xref: /openbmc/linux/net/bluetooth/hci_event.c (revision 4611dfa8)
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 {
463d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
464d5859e22SJohan Hedberg 		return 2;
465d5859e22SJohan Hedberg 
466d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
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 
518d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
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 
524d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_PAUSE_ENC)
525d5859e22SJohan Hedberg 		events[5] |= 0x80; /* Encryption Key Refresh Complete */
526d5859e22SJohan Hedberg 
527d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
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 
533d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_LSTO)
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 
636d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
637d5859e22SJohan Hedberg 		hci_setup_inquiry_mode(hdev);
638d5859e22SJohan Hedberg 
639d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_INQ_TX_PWR)
640d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
641971e3a4bSAndre Guedes 
642971e3a4bSAndre Guedes 	if (hdev->features[7] & LMP_EXTFEATURES) {
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;
689d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_HOLD)
690d5859e22SJohan Hedberg 		link_policy |= HCI_LP_HOLD;
6916eded100SAndre Guedes 	if (lmp_sniff_capable(hdev))
692d5859e22SJohan Hedberg 		link_policy |= HCI_LP_SNIFF;
693d5859e22SJohan Hedberg 	if (hdev->features[1] & LMP_PARK)
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;
7838f984dfaSJohan Hedberg 		cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
7848f984dfaSJohan Hedberg 	}
7858f984dfaSJohan Hedberg 
7868f984dfaSJohan Hedberg 	if (cp.le != !!(hdev->host_features[0] & LMP_HOST_LE))
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;
12908f984dfaSJohan Hedberg 	}
12918f984dfaSJohan Hedberg 
12928f984dfaSJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
12938f984dfaSJohan Hedberg 	    !test_bit(HCI_INIT, &hdev->flags))
12948f984dfaSJohan Hedberg 		mgmt_le_enable_complete(hdev, sent->le, status);
12958f984dfaSJohan Hedberg 
12968f984dfaSJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status);
1297f9b49306SAndre Guedes }
1298f9b49306SAndre Guedes 
129993c284eeSAndrei Emeltchenko static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
130093c284eeSAndrei Emeltchenko 					  struct sk_buff *skb)
130193c284eeSAndrei Emeltchenko {
130293c284eeSAndrei Emeltchenko 	struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data;
130393c284eeSAndrei Emeltchenko 
130493c284eeSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
130593c284eeSAndrei Emeltchenko 	       hdev->name, rp->status, rp->phy_handle);
130693c284eeSAndrei Emeltchenko 
130793c284eeSAndrei Emeltchenko 	if (rp->status)
130893c284eeSAndrei Emeltchenko 		return;
130993c284eeSAndrei Emeltchenko 
131093c284eeSAndrei Emeltchenko 	amp_write_rem_assoc_continue(hdev, rp->phy_handle);
131193c284eeSAndrei Emeltchenko }
131293c284eeSAndrei Emeltchenko 
13136039aa73SGustavo Padovan static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1314a9de9248SMarcel Holtmann {
13159f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1316a9de9248SMarcel Holtmann 
1317a9de9248SMarcel Holtmann 	if (status) {
131823bb5763SJohan Hedberg 		hci_req_complete(hdev, HCI_OP_INQUIRY, status);
1319a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
132056e5cb86SJohan Hedberg 		hci_dev_lock(hdev);
1321a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
13227a135109SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
132356e5cb86SJohan Hedberg 		hci_dev_unlock(hdev);
1324314b2381SJohan Hedberg 		return;
1325314b2381SJohan Hedberg 	}
1326314b2381SJohan Hedberg 
132789352e7dSAndre Guedes 	set_bit(HCI_INQUIRY, &hdev->flags);
132889352e7dSAndre Guedes 
132956e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1330343f935bSAndre Guedes 	hci_discovery_set_state(hdev, DISCOVERY_FINDING);
133156e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1332a9de9248SMarcel Holtmann }
1333a9de9248SMarcel Holtmann 
13346039aa73SGustavo Padovan static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
13351da177e4SLinus Torvalds {
1336a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
13371da177e4SLinus Torvalds 	struct hci_conn *conn;
13381da177e4SLinus Torvalds 
13399f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1340a9de9248SMarcel Holtmann 
1341a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
13421da177e4SLinus Torvalds 	if (!cp)
13431da177e4SLinus Torvalds 		return;
13441da177e4SLinus Torvalds 
13451da177e4SLinus Torvalds 	hci_dev_lock(hdev);
13461da177e4SLinus Torvalds 
13471da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
13481da177e4SLinus Torvalds 
13496ed93dc6SAndrei Emeltchenko 	BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn);
13501da177e4SLinus Torvalds 
13511da177e4SLinus Torvalds 	if (status) {
13521da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
13534c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
13541da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
13551da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
13561da177e4SLinus Torvalds 				hci_conn_del(conn);
13574c67bc74SMarcel Holtmann 			} else
13584c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
13591da177e4SLinus Torvalds 		}
13601da177e4SLinus Torvalds 	} else {
13611da177e4SLinus Torvalds 		if (!conn) {
13621da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
13631da177e4SLinus Torvalds 			if (conn) {
1364a0c808b3SJohan Hedberg 				conn->out = true;
13651da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
13661da177e4SLinus Torvalds 			} else
1367893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
13681da177e4SLinus Torvalds 		}
13691da177e4SLinus Torvalds 	}
13701da177e4SLinus Torvalds 
13711da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
13721da177e4SLinus Torvalds }
13731da177e4SLinus Torvalds 
1374a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
13751da177e4SLinus Torvalds {
1376a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
13771da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
13781da177e4SLinus Torvalds 	__u16 handle;
13791da177e4SLinus Torvalds 
13809f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1381b6a0dc82SMarcel Holtmann 
1382a9de9248SMarcel Holtmann 	if (!status)
1383a9de9248SMarcel Holtmann 		return;
1384a9de9248SMarcel Holtmann 
1385a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
13861da177e4SLinus Torvalds 	if (!cp)
1387a9de9248SMarcel Holtmann 		return;
13881da177e4SLinus Torvalds 
13891da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
13901da177e4SLinus Torvalds 
13919f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
13921da177e4SLinus Torvalds 
13931da177e4SLinus Torvalds 	hci_dev_lock(hdev);
13941da177e4SLinus Torvalds 
13951da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
13965a08ecceSAndrei Emeltchenko 	if (acl) {
13975a08ecceSAndrei Emeltchenko 		sco = acl->link;
13985a08ecceSAndrei Emeltchenko 		if (sco) {
13991da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
14001da177e4SLinus Torvalds 
14011da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
14021da177e4SLinus Torvalds 			hci_conn_del(sco);
14031da177e4SLinus Torvalds 		}
14045a08ecceSAndrei Emeltchenko 	}
14051da177e4SLinus Torvalds 
14061da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
14071da177e4SLinus Torvalds }
14081da177e4SLinus Torvalds 
1409f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1410f8558555SMarcel Holtmann {
1411f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1412f8558555SMarcel Holtmann 	struct hci_conn *conn;
1413f8558555SMarcel Holtmann 
14149f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1415f8558555SMarcel Holtmann 
1416f8558555SMarcel Holtmann 	if (!status)
1417f8558555SMarcel Holtmann 		return;
1418f8558555SMarcel Holtmann 
1419f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1420f8558555SMarcel Holtmann 	if (!cp)
1421f8558555SMarcel Holtmann 		return;
1422f8558555SMarcel Holtmann 
1423f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1424f8558555SMarcel Holtmann 
1425f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1426f8558555SMarcel Holtmann 	if (conn) {
1427f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1428f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1429f8558555SMarcel Holtmann 			hci_conn_put(conn);
1430f8558555SMarcel Holtmann 		}
1431f8558555SMarcel Holtmann 	}
1432f8558555SMarcel Holtmann 
1433f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1434f8558555SMarcel Holtmann }
1435f8558555SMarcel Holtmann 
1436f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1437f8558555SMarcel Holtmann {
1438f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1439f8558555SMarcel Holtmann 	struct hci_conn *conn;
1440f8558555SMarcel Holtmann 
14419f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1442f8558555SMarcel Holtmann 
1443f8558555SMarcel Holtmann 	if (!status)
1444f8558555SMarcel Holtmann 		return;
1445f8558555SMarcel Holtmann 
1446f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1447f8558555SMarcel Holtmann 	if (!cp)
1448f8558555SMarcel Holtmann 		return;
1449f8558555SMarcel Holtmann 
1450f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1451f8558555SMarcel Holtmann 
1452f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1453f8558555SMarcel Holtmann 	if (conn) {
1454f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1455f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1456f8558555SMarcel Holtmann 			hci_conn_put(conn);
1457f8558555SMarcel Holtmann 		}
1458f8558555SMarcel Holtmann 	}
1459f8558555SMarcel Holtmann 
1460f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1461f8558555SMarcel Holtmann }
1462f8558555SMarcel Holtmann 
1463127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1464392599b9SJohan Hedberg 				    struct hci_conn *conn)
1465392599b9SJohan Hedberg {
1466392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1467392599b9SJohan Hedberg 		return 0;
1468392599b9SJohan Hedberg 
1469765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1470392599b9SJohan Hedberg 		return 0;
1471392599b9SJohan Hedberg 
1472392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1473e9bf2bf0SVinicius Costa Gomes 	 * devices with sec_level HIGH or if MITM protection is requested */
1474807deac2SGustavo Padovan 	if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
1475807deac2SGustavo Padovan 	    conn->pending_sec_level != BT_SECURITY_HIGH)
1476392599b9SJohan Hedberg 		return 0;
1477392599b9SJohan Hedberg 
1478392599b9SJohan Hedberg 	return 1;
1479392599b9SJohan Hedberg }
1480392599b9SJohan Hedberg 
14816039aa73SGustavo Padovan static int hci_resolve_name(struct hci_dev *hdev,
148200abfe44SGustavo F. Padovan 				   struct inquiry_entry *e)
148330dc78e1SJohan Hedberg {
148430dc78e1SJohan Hedberg 	struct hci_cp_remote_name_req cp;
148530dc78e1SJohan Hedberg 
148630dc78e1SJohan Hedberg 	memset(&cp, 0, sizeof(cp));
148730dc78e1SJohan Hedberg 
148830dc78e1SJohan Hedberg 	bacpy(&cp.bdaddr, &e->data.bdaddr);
148930dc78e1SJohan Hedberg 	cp.pscan_rep_mode = e->data.pscan_rep_mode;
149030dc78e1SJohan Hedberg 	cp.pscan_mode = e->data.pscan_mode;
149130dc78e1SJohan Hedberg 	cp.clock_offset = e->data.clock_offset;
149230dc78e1SJohan Hedberg 
149330dc78e1SJohan Hedberg 	return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
149430dc78e1SJohan Hedberg }
149530dc78e1SJohan Hedberg 
1496b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev)
149730dc78e1SJohan Hedberg {
149830dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
149930dc78e1SJohan Hedberg 	struct inquiry_entry *e;
150030dc78e1SJohan Hedberg 
1501b644ba33SJohan Hedberg 	if (list_empty(&discov->resolve))
1502b644ba33SJohan Hedberg 		return false;
1503b644ba33SJohan Hedberg 
1504b644ba33SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1505c810089cSRam Malovany 	if (!e)
1506c810089cSRam Malovany 		return false;
1507c810089cSRam Malovany 
1508b644ba33SJohan Hedberg 	if (hci_resolve_name(hdev, e) == 0) {
1509b644ba33SJohan Hedberg 		e->name_state = NAME_PENDING;
1510b644ba33SJohan Hedberg 		return true;
1511b644ba33SJohan Hedberg 	}
1512b644ba33SJohan Hedberg 
1513b644ba33SJohan Hedberg 	return false;
1514b644ba33SJohan Hedberg }
1515b644ba33SJohan Hedberg 
1516b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
1517b644ba33SJohan Hedberg 				   bdaddr_t *bdaddr, u8 *name, u8 name_len)
1518b644ba33SJohan Hedberg {
1519b644ba33SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
1520b644ba33SJohan Hedberg 	struct inquiry_entry *e;
1521b644ba33SJohan Hedberg 
1522b644ba33SJohan Hedberg 	if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
152304124681SGustavo F. Padovan 		mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
152404124681SGustavo F. Padovan 				      name_len, conn->dev_class);
1525b644ba33SJohan Hedberg 
1526b644ba33SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPED)
1527b644ba33SJohan Hedberg 		return;
1528b644ba33SJohan Hedberg 
152930dc78e1SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPING)
153030dc78e1SJohan Hedberg 		goto discov_complete;
153130dc78e1SJohan Hedberg 
153230dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_RESOLVING)
153330dc78e1SJohan Hedberg 		return;
153430dc78e1SJohan Hedberg 
153530dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
15367cc8380eSRam Malovany 	/* If the device was not found in a list of found devices names of which
15377cc8380eSRam Malovany 	 * are pending. there is no need to continue resolving a next name as it
15387cc8380eSRam Malovany 	 * will be done upon receiving another Remote Name Request Complete
15397cc8380eSRam Malovany 	 * Event */
15407cc8380eSRam Malovany 	if (!e)
15417cc8380eSRam Malovany 		return;
15427cc8380eSRam Malovany 
154330dc78e1SJohan Hedberg 	list_del(&e->list);
15447cc8380eSRam Malovany 	if (name) {
15457cc8380eSRam Malovany 		e->name_state = NAME_KNOWN;
1546b644ba33SJohan Hedberg 		mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1547b644ba33SJohan Hedberg 				 e->data.rssi, name, name_len);
1548c3e7c0d9SRam Malovany 	} else {
1549c3e7c0d9SRam Malovany 		e->name_state = NAME_NOT_KNOWN;
155030dc78e1SJohan Hedberg 	}
155130dc78e1SJohan Hedberg 
1552b644ba33SJohan Hedberg 	if (hci_resolve_next_name(hdev))
155330dc78e1SJohan Hedberg 		return;
155430dc78e1SJohan Hedberg 
155530dc78e1SJohan Hedberg discov_complete:
155630dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
155730dc78e1SJohan Hedberg }
155830dc78e1SJohan Hedberg 
1559a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
15601da177e4SLinus Torvalds {
1561127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1562127178d2SJohan Hedberg 	struct hci_conn *conn;
1563127178d2SJohan Hedberg 
15649f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1565127178d2SJohan Hedberg 
1566127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1567127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1568127178d2SJohan Hedberg 	if (!status)
1569127178d2SJohan Hedberg 		return;
1570127178d2SJohan Hedberg 
1571127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1572127178d2SJohan Hedberg 	if (!cp)
1573127178d2SJohan Hedberg 		return;
1574127178d2SJohan Hedberg 
1575127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1576127178d2SJohan Hedberg 
1577127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1578b644ba33SJohan Hedberg 
1579b644ba33SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1580b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1581b644ba33SJohan Hedberg 
158279c6c70cSJohan Hedberg 	if (!conn)
158379c6c70cSJohan Hedberg 		goto unlock;
158479c6c70cSJohan Hedberg 
158579c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
158679c6c70cSJohan Hedberg 		goto unlock;
158779c6c70cSJohan Hedberg 
158851a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1589127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1590127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1591127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1592127178d2SJohan Hedberg 	}
1593127178d2SJohan Hedberg 
159479c6c70cSJohan Hedberg unlock:
1595127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1596a9de9248SMarcel Holtmann }
15971da177e4SLinus Torvalds 
1598769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1599769be974SMarcel Holtmann {
1600769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1601769be974SMarcel Holtmann 	struct hci_conn *conn;
1602769be974SMarcel Holtmann 
16039f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1604769be974SMarcel Holtmann 
1605769be974SMarcel Holtmann 	if (!status)
1606769be974SMarcel Holtmann 		return;
1607769be974SMarcel Holtmann 
1608769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1609769be974SMarcel Holtmann 	if (!cp)
1610769be974SMarcel Holtmann 		return;
1611769be974SMarcel Holtmann 
1612769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1613769be974SMarcel Holtmann 
1614769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1615769be974SMarcel Holtmann 	if (conn) {
1616769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1617769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1618769be974SMarcel Holtmann 			hci_conn_put(conn);
1619769be974SMarcel Holtmann 		}
1620769be974SMarcel Holtmann 	}
1621769be974SMarcel Holtmann 
1622769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1623769be974SMarcel Holtmann }
1624769be974SMarcel Holtmann 
1625769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1626769be974SMarcel Holtmann {
1627769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1628769be974SMarcel Holtmann 	struct hci_conn *conn;
1629769be974SMarcel Holtmann 
16309f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1631769be974SMarcel Holtmann 
1632769be974SMarcel Holtmann 	if (!status)
1633769be974SMarcel Holtmann 		return;
1634769be974SMarcel Holtmann 
1635769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1636769be974SMarcel Holtmann 	if (!cp)
1637769be974SMarcel Holtmann 		return;
1638769be974SMarcel Holtmann 
1639769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1640769be974SMarcel Holtmann 
1641769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1642769be974SMarcel Holtmann 	if (conn) {
1643769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1644769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1645769be974SMarcel Holtmann 			hci_conn_put(conn);
1646769be974SMarcel Holtmann 		}
1647769be974SMarcel Holtmann 	}
1648769be974SMarcel Holtmann 
1649769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1650769be974SMarcel Holtmann }
1651769be974SMarcel Holtmann 
1652a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1653a9de9248SMarcel Holtmann {
1654b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1655b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1656b6a0dc82SMarcel Holtmann 	__u16 handle;
1657b6a0dc82SMarcel Holtmann 
16589f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1659b6a0dc82SMarcel Holtmann 
1660b6a0dc82SMarcel Holtmann 	if (!status)
1661b6a0dc82SMarcel Holtmann 		return;
1662b6a0dc82SMarcel Holtmann 
1663b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1664b6a0dc82SMarcel Holtmann 	if (!cp)
1665b6a0dc82SMarcel Holtmann 		return;
1666b6a0dc82SMarcel Holtmann 
1667b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1668b6a0dc82SMarcel Holtmann 
16699f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
1670b6a0dc82SMarcel Holtmann 
1671b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1672b6a0dc82SMarcel Holtmann 
1673b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
16745a08ecceSAndrei Emeltchenko 	if (acl) {
16755a08ecceSAndrei Emeltchenko 		sco = acl->link;
16765a08ecceSAndrei Emeltchenko 		if (sco) {
1677b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1678b6a0dc82SMarcel Holtmann 
1679b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1680b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1681b6a0dc82SMarcel Holtmann 		}
16825a08ecceSAndrei Emeltchenko 	}
1683b6a0dc82SMarcel Holtmann 
1684b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1685a9de9248SMarcel Holtmann }
1686a9de9248SMarcel Holtmann 
1687a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1688a9de9248SMarcel Holtmann {
1689a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
169004837f64SMarcel Holtmann 	struct hci_conn *conn;
169104837f64SMarcel Holtmann 
16929f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1693a9de9248SMarcel Holtmann 
1694a9de9248SMarcel Holtmann 	if (!status)
1695a9de9248SMarcel Holtmann 		return;
1696a9de9248SMarcel Holtmann 
1697a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
169804837f64SMarcel Holtmann 	if (!cp)
1699a9de9248SMarcel Holtmann 		return;
170004837f64SMarcel Holtmann 
170104837f64SMarcel Holtmann 	hci_dev_lock(hdev);
170204837f64SMarcel Holtmann 
170304837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1704e73439d8SMarcel Holtmann 	if (conn) {
170551a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
170604837f64SMarcel Holtmann 
170751a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1708e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1709e73439d8SMarcel Holtmann 	}
1710e73439d8SMarcel Holtmann 
171104837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
171204837f64SMarcel Holtmann }
171304837f64SMarcel Holtmann 
1714a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1715a9de9248SMarcel Holtmann {
1716a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
171704837f64SMarcel Holtmann 	struct hci_conn *conn;
171804837f64SMarcel Holtmann 
17199f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1720a9de9248SMarcel Holtmann 
1721a9de9248SMarcel Holtmann 	if (!status)
1722a9de9248SMarcel Holtmann 		return;
1723a9de9248SMarcel Holtmann 
1724a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
172504837f64SMarcel Holtmann 	if (!cp)
1726a9de9248SMarcel Holtmann 		return;
172704837f64SMarcel Holtmann 
172804837f64SMarcel Holtmann 	hci_dev_lock(hdev);
172904837f64SMarcel Holtmann 
173004837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1731e73439d8SMarcel Holtmann 	if (conn) {
173251a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
173304837f64SMarcel Holtmann 
173451a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1735e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1736e73439d8SMarcel Holtmann 	}
1737e73439d8SMarcel Holtmann 
173804837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
173904837f64SMarcel Holtmann }
174004837f64SMarcel Holtmann 
174188c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
174288c3df13SJohan Hedberg {
174388c3df13SJohan Hedberg 	struct hci_cp_disconnect *cp;
174488c3df13SJohan Hedberg 	struct hci_conn *conn;
174588c3df13SJohan Hedberg 
174688c3df13SJohan Hedberg 	if (!status)
174788c3df13SJohan Hedberg 		return;
174888c3df13SJohan Hedberg 
174988c3df13SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
175088c3df13SJohan Hedberg 	if (!cp)
175188c3df13SJohan Hedberg 		return;
175288c3df13SJohan Hedberg 
175388c3df13SJohan Hedberg 	hci_dev_lock(hdev);
175488c3df13SJohan Hedberg 
175588c3df13SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
175688c3df13SJohan Hedberg 	if (conn)
175788c3df13SJohan Hedberg 		mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
175888c3df13SJohan Hedberg 				       conn->dst_type, status);
175988c3df13SJohan Hedberg 
176088c3df13SJohan Hedberg 	hci_dev_unlock(hdev);
176188c3df13SJohan Hedberg }
176288c3df13SJohan Hedberg 
1763fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1764fcd89c09SVille Tervo {
1765fcd89c09SVille Tervo 	struct hci_conn *conn;
1766fcd89c09SVille Tervo 
17679f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1768fcd89c09SVille Tervo 
1769f00a06acSAndre Guedes 	if (status) {
1770fcd89c09SVille Tervo 		hci_dev_lock(hdev);
1771fcd89c09SVille Tervo 
17720c95ab78SAndre Guedes 		conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
1773f00a06acSAndre Guedes 		if (!conn) {
1774f00a06acSAndre Guedes 			hci_dev_unlock(hdev);
1775f00a06acSAndre Guedes 			return;
1776f00a06acSAndre Guedes 		}
1777fcd89c09SVille Tervo 
17786ed93dc6SAndrei Emeltchenko 		BT_DBG("%s bdaddr %pMR conn %p", hdev->name, &conn->dst, conn);
1779fcd89c09SVille Tervo 
1780fcd89c09SVille Tervo 		conn->state = BT_CLOSED;
17810c95ab78SAndre Guedes 		mgmt_connect_failed(hdev, &conn->dst, conn->type,
1782328c9248SHemant Gupta 				    conn->dst_type, status);
1783fcd89c09SVille Tervo 		hci_proto_connect_cfm(conn, status);
1784fcd89c09SVille Tervo 		hci_conn_del(conn);
1785fcd89c09SVille Tervo 
1786fcd89c09SVille Tervo 		hci_dev_unlock(hdev);
1787fcd89c09SVille Tervo 	}
1788f00a06acSAndre Guedes }
1789fcd89c09SVille Tervo 
1790a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1791a7a595f6SVinicius Costa Gomes {
17929f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1793a7a595f6SVinicius Costa Gomes }
1794a7a595f6SVinicius Costa Gomes 
1795a02226d6SAndrei Emeltchenko static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
1796a02226d6SAndrei Emeltchenko {
179793c284eeSAndrei Emeltchenko 	struct hci_cp_create_phy_link *cp;
179893c284eeSAndrei Emeltchenko 
1799a02226d6SAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
180093c284eeSAndrei Emeltchenko 
180193c284eeSAndrei Emeltchenko 	if (status)
180293c284eeSAndrei Emeltchenko 		return;
180393c284eeSAndrei Emeltchenko 
180493c284eeSAndrei Emeltchenko 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
180593c284eeSAndrei Emeltchenko 	if (!cp)
180693c284eeSAndrei Emeltchenko 		return;
180793c284eeSAndrei Emeltchenko 
180893c284eeSAndrei Emeltchenko 	amp_write_remote_assoc(hdev, cp->phy_handle);
1809a02226d6SAndrei Emeltchenko }
1810a02226d6SAndrei Emeltchenko 
18110b26ab9dSAndrei Emeltchenko static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
18120b26ab9dSAndrei Emeltchenko {
18130b26ab9dSAndrei Emeltchenko 	struct hci_cp_accept_phy_link *cp;
18140b26ab9dSAndrei Emeltchenko 
18150b26ab9dSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
18160b26ab9dSAndrei Emeltchenko 
18170b26ab9dSAndrei Emeltchenko 	if (status)
18180b26ab9dSAndrei Emeltchenko 		return;
18190b26ab9dSAndrei Emeltchenko 
18200b26ab9dSAndrei Emeltchenko 	cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
18210b26ab9dSAndrei Emeltchenko 	if (!cp)
18220b26ab9dSAndrei Emeltchenko 		return;
18230b26ab9dSAndrei Emeltchenko 
18240b26ab9dSAndrei Emeltchenko 	amp_write_remote_assoc(hdev, cp->phy_handle);
18250b26ab9dSAndrei Emeltchenko }
18260b26ab9dSAndrei Emeltchenko 
18276039aa73SGustavo Padovan static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
18281da177e4SLinus Torvalds {
18291da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
183030dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
183130dc78e1SJohan Hedberg 	struct inquiry_entry *e;
18321da177e4SLinus Torvalds 
18339f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
18341da177e4SLinus Torvalds 
183523bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY, status);
18366bd57416SMarcel Holtmann 
1837a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
183889352e7dSAndre Guedes 
183989352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
184089352e7dSAndre Guedes 		return;
184189352e7dSAndre Guedes 
1842a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
184330dc78e1SJohan Hedberg 		return;
184430dc78e1SJohan Hedberg 
184556e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
184630dc78e1SJohan Hedberg 
1847343f935bSAndre Guedes 	if (discov->state != DISCOVERY_FINDING)
184830dc78e1SJohan Hedberg 		goto unlock;
184930dc78e1SJohan Hedberg 
185030dc78e1SJohan Hedberg 	if (list_empty(&discov->resolve)) {
1851ff9ef578SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
185230dc78e1SJohan Hedberg 		goto unlock;
185330dc78e1SJohan Hedberg 	}
185430dc78e1SJohan Hedberg 
185530dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
185630dc78e1SJohan Hedberg 	if (e && hci_resolve_name(hdev, e) == 0) {
185730dc78e1SJohan Hedberg 		e->name_state = NAME_PENDING;
185830dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
185930dc78e1SJohan Hedberg 	} else {
186030dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
186130dc78e1SJohan Hedberg 	}
186230dc78e1SJohan Hedberg 
186330dc78e1SJohan Hedberg unlock:
186456e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
18651da177e4SLinus Torvalds }
18661da177e4SLinus Torvalds 
18676039aa73SGustavo Padovan static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
18681da177e4SLinus Torvalds {
186945bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1870a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
18711da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
18721da177e4SLinus Torvalds 
18731da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
18741da177e4SLinus Torvalds 
187545bb4bf0SMarcel Holtmann 	if (!num_rsp)
187645bb4bf0SMarcel Holtmann 		return;
187745bb4bf0SMarcel Holtmann 
18781519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
18791519cc17SAndre Guedes 		return;
18801519cc17SAndre Guedes 
18811da177e4SLinus Torvalds 	hci_dev_lock(hdev);
188245bb4bf0SMarcel Holtmann 
1883e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
1884388fc8faSJohan Hedberg 		bool name_known, ssp;
18853175405bSJohan Hedberg 
18861da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
18871da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
18881da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
18891da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
18901da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
18911da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
18921da177e4SLinus Torvalds 		data.rssi		= 0x00;
189341a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
18943175405bSJohan Hedberg 
1895388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
189648264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
189704124681SGustavo F. Padovan 				  info->dev_class, 0, !name_known, ssp, NULL,
189804124681SGustavo F. Padovan 				  0);
18991da177e4SLinus Torvalds 	}
190045bb4bf0SMarcel Holtmann 
19011da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
19021da177e4SLinus Torvalds }
19031da177e4SLinus Torvalds 
19046039aa73SGustavo Padovan static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
19051da177e4SLinus Torvalds {
1906a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
1907a9de9248SMarcel Holtmann 	struct hci_conn *conn;
19081da177e4SLinus Torvalds 
1909a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
191045bb4bf0SMarcel Holtmann 
19111da177e4SLinus Torvalds 	hci_dev_lock(hdev);
191245bb4bf0SMarcel Holtmann 
1913a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
19149499237aSMarcel Holtmann 	if (!conn) {
19159499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
19169499237aSMarcel Holtmann 			goto unlock;
19179499237aSMarcel Holtmann 
19189499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1919a9de9248SMarcel Holtmann 		if (!conn)
1920a9de9248SMarcel Holtmann 			goto unlock;
192145bb4bf0SMarcel Holtmann 
19229499237aSMarcel Holtmann 		conn->type = SCO_LINK;
19239499237aSMarcel Holtmann 	}
19249499237aSMarcel Holtmann 
1925a9de9248SMarcel Holtmann 	if (!ev->status) {
1926a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1927769be974SMarcel Holtmann 
1928769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1929769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
1930769be974SMarcel Holtmann 			hci_conn_hold(conn);
1931a9ea3ed9SSzymon Janc 
1932a9ea3ed9SSzymon Janc 			if (!conn->out && !hci_conn_ssp_enabled(conn) &&
1933a9ea3ed9SSzymon Janc 			    !hci_find_link_key(hdev, &ev->bdaddr))
1934a9ea3ed9SSzymon Janc 				conn->disc_timeout = HCI_PAIRING_TIMEOUT;
1935a9ea3ed9SSzymon Janc 			else
1936052b30b0SMarcel Holtmann 				conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1937769be974SMarcel Holtmann 		} else
1938a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
1939a9de9248SMarcel Holtmann 
19409eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
19417d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
19427d0db0a3SMarcel Holtmann 
1943a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1944a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1945a9de9248SMarcel Holtmann 
1946a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1947a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1948a9de9248SMarcel Holtmann 
1949a9de9248SMarcel Holtmann 		/* Get remote features */
1950a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1951a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1952a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1953769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1954769be974SMarcel Holtmann 				     sizeof(cp), &cp);
195545bb4bf0SMarcel Holtmann 		}
1956a9de9248SMarcel Holtmann 
1957a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1958d095c1ebSAndrei Emeltchenko 		if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
1959a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1960a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1961a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
196204124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
196304124681SGustavo F. Padovan 				     &cp);
1964a9de9248SMarcel Holtmann 		}
196517d5c04cSJohan Hedberg 	} else {
1966a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
196717d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
1968744cf19eSJohan Hedberg 			mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
196948264f06SJohan Hedberg 					    conn->dst_type, ev->status);
197017d5c04cSJohan Hedberg 	}
197145bb4bf0SMarcel Holtmann 
1972e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
1973e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
197445bb4bf0SMarcel Holtmann 
1975769be974SMarcel Holtmann 	if (ev->status) {
1976a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1977a9de9248SMarcel Holtmann 		hci_conn_del(conn);
1978c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
1979c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1980a9de9248SMarcel Holtmann 
1981a9de9248SMarcel Holtmann unlock:
19821da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
1983a9de9248SMarcel Holtmann 
1984a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
19851da177e4SLinus Torvalds }
19861da177e4SLinus Torvalds 
19876039aa73SGustavo Padovan static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
19881da177e4SLinus Torvalds {
1989a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
19901da177e4SLinus Torvalds 	int mask = hdev->link_mode;
19911da177e4SLinus Torvalds 
19926ed93dc6SAndrei Emeltchenko 	BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
1993807deac2SGustavo Padovan 	       ev->link_type);
19941da177e4SLinus Torvalds 
19951da177e4SLinus Torvalds 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
19961da177e4SLinus Torvalds 
1997138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
1998138d22efSSzymon Janc 	    !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
19991da177e4SLinus Torvalds 		/* Connection accepted */
2000c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
20011da177e4SLinus Torvalds 		struct hci_conn *conn;
20021da177e4SLinus Torvalds 
20031da177e4SLinus Torvalds 		hci_dev_lock(hdev);
2004b6a0dc82SMarcel Holtmann 
2005cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2006cc11b9c1SAndrei Emeltchenko 		if (ie)
2007c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
2008c7bdd502SMarcel Holtmann 
20098fc9ced3SGustavo Padovan 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
20108fc9ced3SGustavo Padovan 					       &ev->bdaddr);
20111da177e4SLinus Torvalds 		if (!conn) {
2012cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
2013cc11b9c1SAndrei Emeltchenko 			if (!conn) {
2014893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
20151da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
20161da177e4SLinus Torvalds 				return;
20171da177e4SLinus Torvalds 			}
20181da177e4SLinus Torvalds 		}
2019b6a0dc82SMarcel Holtmann 
20201da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
20211da177e4SLinus Torvalds 		conn->state = BT_CONNECT;
2022b6a0dc82SMarcel Holtmann 
20231da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
20241da177e4SLinus Torvalds 
2025b6a0dc82SMarcel Holtmann 		if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
2026b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
2027b6a0dc82SMarcel Holtmann 
20281da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
20291da177e4SLinus Torvalds 
20301da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
20311da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
20321da177e4SLinus Torvalds 			else
20331da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
20341da177e4SLinus Torvalds 
203504124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
203604124681SGustavo F. Padovan 				     &cp);
2037b6a0dc82SMarcel Holtmann 		} else {
2038b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
2039b6a0dc82SMarcel Holtmann 
2040b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
2041a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
2042b6a0dc82SMarcel Holtmann 
204382781e63SAndrei Emeltchenko 			cp.tx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
204482781e63SAndrei Emeltchenko 			cp.rx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
204582781e63SAndrei Emeltchenko 			cp.max_latency    = __constant_cpu_to_le16(0xffff);
2046b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
2047b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
2048b6a0dc82SMarcel Holtmann 
2049b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
2050b6a0dc82SMarcel Holtmann 				     sizeof(cp), &cp);
2051b6a0dc82SMarcel Holtmann 		}
20521da177e4SLinus Torvalds 	} else {
20531da177e4SLinus Torvalds 		/* Connection rejected */
20541da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
20551da177e4SLinus Torvalds 
20561da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
20579f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_REJ_BAD_ADDR;
2058a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
20591da177e4SLinus Torvalds 	}
20601da177e4SLinus Torvalds }
20611da177e4SLinus Torvalds 
2062f0d6a0eaSMikel Astiz static u8 hci_to_mgmt_reason(u8 err)
2063f0d6a0eaSMikel Astiz {
2064f0d6a0eaSMikel Astiz 	switch (err) {
2065f0d6a0eaSMikel Astiz 	case HCI_ERROR_CONNECTION_TIMEOUT:
2066f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_TIMEOUT;
2067f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_USER_TERM:
2068f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_LOW_RESOURCES:
2069f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_POWER_OFF:
2070f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_REMOTE;
2071f0d6a0eaSMikel Astiz 	case HCI_ERROR_LOCAL_HOST_TERM:
2072f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_LOCAL_HOST;
2073f0d6a0eaSMikel Astiz 	default:
2074f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_UNKNOWN;
2075f0d6a0eaSMikel Astiz 	}
2076f0d6a0eaSMikel Astiz }
2077f0d6a0eaSMikel Astiz 
20786039aa73SGustavo Padovan static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
20791da177e4SLinus Torvalds {
2080a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
208104837f64SMarcel Holtmann 	struct hci_conn *conn;
20821da177e4SLinus Torvalds 
20839f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
20841da177e4SLinus Torvalds 
20851da177e4SLinus Torvalds 	hci_dev_lock(hdev);
20861da177e4SLinus Torvalds 
208704837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2088f7520543SJohan Hedberg 	if (!conn)
2089f7520543SJohan Hedberg 		goto unlock;
2090f7520543SJohan Hedberg 
209137d9ef76SJohan Hedberg 	if (ev->status == 0)
20921da177e4SLinus Torvalds 		conn->state = BT_CLOSED;
20937d0db0a3SMarcel Holtmann 
2094b644ba33SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
2095b644ba33SJohan Hedberg 	    (conn->type == ACL_LINK || conn->type == LE_LINK)) {
2096f0d6a0eaSMikel Astiz 		if (ev->status) {
209788c3df13SJohan Hedberg 			mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
209888c3df13SJohan Hedberg 					       conn->dst_type, ev->status);
2099f0d6a0eaSMikel Astiz 		} else {
2100f0d6a0eaSMikel Astiz 			u8 reason = hci_to_mgmt_reason(ev->reason);
2101f0d6a0eaSMikel Astiz 
2102afc747a6SJohan Hedberg 			mgmt_device_disconnected(hdev, &conn->dst, conn->type,
2103f0d6a0eaSMikel Astiz 						 conn->dst_type, reason);
2104f0d6a0eaSMikel Astiz 		}
210537d9ef76SJohan Hedberg 	}
2106f7520543SJohan Hedberg 
210737d9ef76SJohan Hedberg 	if (ev->status == 0) {
21086ec5bcadSVishal Agarwal 		if (conn->type == ACL_LINK && conn->flush_key)
21096ec5bcadSVishal Agarwal 			hci_remove_link_key(hdev, &conn->dst);
21102950f21aSMarcel Holtmann 		hci_proto_disconn_cfm(conn, ev->reason);
21111da177e4SLinus Torvalds 		hci_conn_del(conn);
211237d9ef76SJohan Hedberg 	}
21131da177e4SLinus Torvalds 
2114f7520543SJohan Hedberg unlock:
21151da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
21161da177e4SLinus Torvalds }
21171da177e4SLinus Torvalds 
21186039aa73SGustavo Padovan static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2119a9de9248SMarcel Holtmann {
2120a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
2121a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2122a9de9248SMarcel Holtmann 
21239f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2124a9de9248SMarcel Holtmann 
2125a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2126a9de9248SMarcel Holtmann 
2127a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2128d7556e20SWaldemar Rymarkiewicz 	if (!conn)
2129d7556e20SWaldemar Rymarkiewicz 		goto unlock;
2130d7556e20SWaldemar Rymarkiewicz 
2131765c2a96SJohan Hedberg 	if (!ev->status) {
2132aa64a8b5SJohan Hedberg 		if (!hci_conn_ssp_enabled(conn) &&
213351a8efd7SJohan Hedberg 		    test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
2134d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
213519f8def0SWaldemar Rymarkiewicz 		} else {
2136a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
2137765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
213819f8def0SWaldemar Rymarkiewicz 		}
21392a611692SJohan Hedberg 	} else {
2140bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
2141bab73cb6SJohan Hedberg 				 ev->status);
21422a611692SJohan Hedberg 	}
2143a9de9248SMarcel Holtmann 
214451a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
214551a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
2146a9de9248SMarcel Holtmann 
2147f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
2148aa64a8b5SJohan Hedberg 		if (!ev->status && hci_conn_ssp_enabled(conn)) {
2149f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
2150f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
2151f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
2152d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
2153d7556e20SWaldemar Rymarkiewicz 				     &cp);
2154f8558555SMarcel Holtmann 		} else {
2155f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
2156f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
2157f8558555SMarcel Holtmann 			hci_conn_put(conn);
2158f8558555SMarcel Holtmann 		}
2159052b30b0SMarcel Holtmann 	} else {
2160a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
2161a9de9248SMarcel Holtmann 
2162052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2163052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2164052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2165052b30b0SMarcel Holtmann 	}
2166052b30b0SMarcel Holtmann 
216751a8efd7SJohan Hedberg 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
2168a9de9248SMarcel Holtmann 		if (!ev->status) {
2169a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
2170f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
2171f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
2172d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
2173d7556e20SWaldemar Rymarkiewicz 				     &cp);
2174a9de9248SMarcel Holtmann 		} else {
217551a8efd7SJohan Hedberg 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2176a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
2177a9de9248SMarcel Holtmann 		}
2178a9de9248SMarcel Holtmann 	}
2179a9de9248SMarcel Holtmann 
2180d7556e20SWaldemar Rymarkiewicz unlock:
2181a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2182a9de9248SMarcel Holtmann }
2183a9de9248SMarcel Holtmann 
21846039aa73SGustavo Padovan static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
2185a9de9248SMarcel Holtmann {
2186127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
2187127178d2SJohan Hedberg 	struct hci_conn *conn;
2188127178d2SJohan Hedberg 
2189a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2190a9de9248SMarcel Holtmann 
2191a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
2192127178d2SJohan Hedberg 
2193127178d2SJohan Hedberg 	hci_dev_lock(hdev);
2194127178d2SJohan Hedberg 
2195127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2196b644ba33SJohan Hedberg 
2197b644ba33SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
2198b644ba33SJohan Hedberg 		goto check_auth;
2199b644ba33SJohan Hedberg 
2200b644ba33SJohan Hedberg 	if (ev->status == 0)
2201b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
2202b644ba33SJohan Hedberg 				       strnlen(ev->name, HCI_MAX_NAME_LENGTH));
2203b644ba33SJohan Hedberg 	else
2204b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
2205b644ba33SJohan Hedberg 
2206b644ba33SJohan Hedberg check_auth:
220779c6c70cSJohan Hedberg 	if (!conn)
220879c6c70cSJohan Hedberg 		goto unlock;
220979c6c70cSJohan Hedberg 
221079c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
221179c6c70cSJohan Hedberg 		goto unlock;
221279c6c70cSJohan Hedberg 
221351a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
2214127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
2215127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
2216127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
2217127178d2SJohan Hedberg 	}
2218127178d2SJohan Hedberg 
221979c6c70cSJohan Hedberg unlock:
2220127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
2221a9de9248SMarcel Holtmann }
2222a9de9248SMarcel Holtmann 
22236039aa73SGustavo Padovan static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2224a9de9248SMarcel Holtmann {
2225a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
2226a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2227a9de9248SMarcel Holtmann 
22289f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2229a9de9248SMarcel Holtmann 
2230a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2231a9de9248SMarcel Holtmann 
2232a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2233a9de9248SMarcel Holtmann 	if (conn) {
2234a9de9248SMarcel Holtmann 		if (!ev->status) {
2235ae293196SMarcel Holtmann 			if (ev->encrypt) {
2236ae293196SMarcel Holtmann 				/* Encryption implies authentication */
2237ae293196SMarcel Holtmann 				conn->link_mode |= HCI_LM_AUTH;
2238a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_ENCRYPT;
2239da85e5e5SVinicius Costa Gomes 				conn->sec_level = conn->pending_sec_level;
2240ae293196SMarcel Holtmann 			} else
2241a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_ENCRYPT;
2242a9de9248SMarcel Holtmann 		}
2243a9de9248SMarcel Holtmann 
224451a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2245a9de9248SMarcel Holtmann 
2246a7d7723aSGustavo Padovan 		if (ev->status && conn->state == BT_CONNECTED) {
2247d839c813SGustavo Padovan 			hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
2248a7d7723aSGustavo Padovan 			hci_conn_put(conn);
2249a7d7723aSGustavo Padovan 			goto unlock;
2250a7d7723aSGustavo Padovan 		}
2251a7d7723aSGustavo Padovan 
2252f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
2253f8558555SMarcel Holtmann 			if (!ev->status)
2254f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
2255f8558555SMarcel Holtmann 
2256f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
2257f8558555SMarcel Holtmann 			hci_conn_put(conn);
2258f8558555SMarcel Holtmann 		} else
2259a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, ev->encrypt);
2260a9de9248SMarcel Holtmann 	}
2261a9de9248SMarcel Holtmann 
2262a7d7723aSGustavo Padovan unlock:
2263a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2264a9de9248SMarcel Holtmann }
2265a9de9248SMarcel Holtmann 
22666039aa73SGustavo Padovan static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
2267807deac2SGustavo Padovan 					     struct sk_buff *skb)
2268a9de9248SMarcel Holtmann {
2269a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2270a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2271a9de9248SMarcel Holtmann 
22729f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2273a9de9248SMarcel Holtmann 
2274a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2275a9de9248SMarcel Holtmann 
2276a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2277a9de9248SMarcel Holtmann 	if (conn) {
2278a9de9248SMarcel Holtmann 		if (!ev->status)
2279a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
2280a9de9248SMarcel Holtmann 
228151a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
2282a9de9248SMarcel Holtmann 
2283a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
2284a9de9248SMarcel Holtmann 	}
2285a9de9248SMarcel Holtmann 
2286a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2287a9de9248SMarcel Holtmann }
2288a9de9248SMarcel Holtmann 
22896039aa73SGustavo Padovan static void hci_remote_features_evt(struct hci_dev *hdev,
2290807deac2SGustavo Padovan 				    struct sk_buff *skb)
2291a9de9248SMarcel Holtmann {
2292a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
2293a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2294a9de9248SMarcel Holtmann 
22959f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2296a9de9248SMarcel Holtmann 
2297a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2298a9de9248SMarcel Holtmann 
2299a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2300ccd556feSJohan Hedberg 	if (!conn)
2301ccd556feSJohan Hedberg 		goto unlock;
2302ccd556feSJohan Hedberg 
2303769be974SMarcel Holtmann 	if (!ev->status)
2304a9de9248SMarcel Holtmann 		memcpy(conn->features, ev->features, 8);
2305a9de9248SMarcel Holtmann 
2306ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2307ccd556feSJohan Hedberg 		goto unlock;
2308ccd556feSJohan Hedberg 
2309ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2310769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
2311769be974SMarcel Holtmann 		cp.handle = ev->handle;
2312769be974SMarcel Holtmann 		cp.page = 0x01;
2313ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
2314769be974SMarcel Holtmann 			     sizeof(cp), &cp);
2315392599b9SJohan Hedberg 		goto unlock;
2316392599b9SJohan Hedberg 	}
2317392599b9SJohan Hedberg 
2318671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
2319127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2320127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2321127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2322127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2323127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2324b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2325b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
232608c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
2327b644ba33SJohan Hedberg 				      conn->dev_class);
2328392599b9SJohan Hedberg 
2329127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2330769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2331769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2332769be974SMarcel Holtmann 		hci_conn_put(conn);
2333769be974SMarcel Holtmann 	}
2334769be974SMarcel Holtmann 
2335ccd556feSJohan Hedberg unlock:
2336a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2337a9de9248SMarcel Holtmann }
2338a9de9248SMarcel Holtmann 
23396039aa73SGustavo Padovan static void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
23406039aa73SGustavo Padovan {
23416039aa73SGustavo Padovan 	BT_DBG("%s", hdev->name);
23426039aa73SGustavo Padovan }
23436039aa73SGustavo Padovan 
23446039aa73SGustavo Padovan static void hci_qos_setup_complete_evt(struct hci_dev *hdev,
2345807deac2SGustavo Padovan 				       struct sk_buff *skb)
2346a9de9248SMarcel Holtmann {
2347a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2348a9de9248SMarcel Holtmann }
2349a9de9248SMarcel Holtmann 
23506039aa73SGustavo Padovan static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2351a9de9248SMarcel Holtmann {
2352a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
2353a9de9248SMarcel Holtmann 	__u16 opcode;
2354a9de9248SMarcel Holtmann 
2355a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2356a9de9248SMarcel Holtmann 
2357a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2358a9de9248SMarcel Holtmann 
2359a9de9248SMarcel Holtmann 	switch (opcode) {
2360a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
2361a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
2362a9de9248SMarcel Holtmann 		break;
2363a9de9248SMarcel Holtmann 
23644d93483bSAndre Guedes 	case HCI_OP_PERIODIC_INQ:
23654d93483bSAndre Guedes 		hci_cc_periodic_inq(hdev, skb);
23664d93483bSAndre Guedes 		break;
23674d93483bSAndre Guedes 
2368a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
2369a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
2370a9de9248SMarcel Holtmann 		break;
2371a9de9248SMarcel Holtmann 
2372a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2373a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
2374a9de9248SMarcel Holtmann 		break;
2375a9de9248SMarcel Holtmann 
2376a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
2377a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
2378a9de9248SMarcel Holtmann 		break;
2379a9de9248SMarcel Holtmann 
2380e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
2381e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
2382e4e8e37cSMarcel Holtmann 		break;
2383e4e8e37cSMarcel Holtmann 
2384a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
2385a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
2386a9de9248SMarcel Holtmann 		break;
2387a9de9248SMarcel Holtmann 
2388e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
2389e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
2390e4e8e37cSMarcel Holtmann 		break;
2391e4e8e37cSMarcel Holtmann 
2392e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
2393e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
2394e4e8e37cSMarcel Holtmann 		break;
2395e4e8e37cSMarcel Holtmann 
2396a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
2397a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
2398a9de9248SMarcel Holtmann 		break;
2399a9de9248SMarcel Holtmann 
2400a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
2401a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
2402a9de9248SMarcel Holtmann 		break;
2403a9de9248SMarcel Holtmann 
2404a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
2405a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
2406a9de9248SMarcel Holtmann 		break;
2407a9de9248SMarcel Holtmann 
2408a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
2409a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
2410a9de9248SMarcel Holtmann 		break;
2411a9de9248SMarcel Holtmann 
2412a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
2413a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
2414a9de9248SMarcel Holtmann 		break;
2415a9de9248SMarcel Holtmann 
2416a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
2417a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
2418a9de9248SMarcel Holtmann 		break;
2419a9de9248SMarcel Holtmann 
2420a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
2421a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
2422a9de9248SMarcel Holtmann 		break;
2423a9de9248SMarcel Holtmann 
2424a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
2425a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
2426a9de9248SMarcel Holtmann 		break;
2427a9de9248SMarcel Holtmann 
2428a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
2429a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
2430a9de9248SMarcel Holtmann 		break;
2431a9de9248SMarcel Holtmann 
2432a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
2433a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
2434a9de9248SMarcel Holtmann 		break;
2435a9de9248SMarcel Holtmann 
2436a9de9248SMarcel Holtmann 	case HCI_OP_HOST_BUFFER_SIZE:
2437a9de9248SMarcel Holtmann 		hci_cc_host_buffer_size(hdev, skb);
2438a9de9248SMarcel Holtmann 		break;
2439a9de9248SMarcel Holtmann 
2440333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
2441333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
2442333140b5SMarcel Holtmann 		break;
2443333140b5SMarcel Holtmann 
2444a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
2445a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
2446a9de9248SMarcel Holtmann 		break;
2447a9de9248SMarcel Holtmann 
2448a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
2449a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
2450a9de9248SMarcel Holtmann 		break;
2451a9de9248SMarcel Holtmann 
2452a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
2453a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
2454a9de9248SMarcel Holtmann 		break;
2455a9de9248SMarcel Holtmann 
2456971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
2457971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
2458971e3a4bSAndre Guedes 		break;
2459971e3a4bSAndre Guedes 
2460a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
2461a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
2462a9de9248SMarcel Holtmann 		break;
2463a9de9248SMarcel Holtmann 
2464a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
2465a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
2466a9de9248SMarcel Holtmann 		break;
2467a9de9248SMarcel Holtmann 
2468350ee4cfSAndrei Emeltchenko 	case HCI_OP_READ_DATA_BLOCK_SIZE:
2469350ee4cfSAndrei Emeltchenko 		hci_cc_read_data_block_size(hdev, skb);
2470350ee4cfSAndrei Emeltchenko 		break;
2471350ee4cfSAndrei Emeltchenko 
247223bb5763SJohan Hedberg 	case HCI_OP_WRITE_CA_TIMEOUT:
247323bb5763SJohan Hedberg 		hci_cc_write_ca_timeout(hdev, skb);
247423bb5763SJohan Hedberg 		break;
247523bb5763SJohan Hedberg 
24761e89cffbSAndrei Emeltchenko 	case HCI_OP_READ_FLOW_CONTROL_MODE:
24771e89cffbSAndrei Emeltchenko 		hci_cc_read_flow_control_mode(hdev, skb);
24781e89cffbSAndrei Emeltchenko 		break;
24791e89cffbSAndrei Emeltchenko 
2480928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
2481928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
2482928abaa7SAndrei Emeltchenko 		break;
2483928abaa7SAndrei Emeltchenko 
2484903e4541SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_ASSOC:
2485903e4541SAndrei Emeltchenko 		hci_cc_read_local_amp_assoc(hdev, skb);
2486903e4541SAndrei Emeltchenko 		break;
2487903e4541SAndrei Emeltchenko 
2488b0916ea0SJohan Hedberg 	case HCI_OP_DELETE_STORED_LINK_KEY:
2489b0916ea0SJohan Hedberg 		hci_cc_delete_stored_link_key(hdev, skb);
2490b0916ea0SJohan Hedberg 		break;
2491b0916ea0SJohan Hedberg 
2492d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_MASK:
2493d5859e22SJohan Hedberg 		hci_cc_set_event_mask(hdev, skb);
2494d5859e22SJohan Hedberg 		break;
2495d5859e22SJohan Hedberg 
2496d5859e22SJohan Hedberg 	case HCI_OP_WRITE_INQUIRY_MODE:
2497d5859e22SJohan Hedberg 		hci_cc_write_inquiry_mode(hdev, skb);
2498d5859e22SJohan Hedberg 		break;
2499d5859e22SJohan Hedberg 
2500d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
2501d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
2502d5859e22SJohan Hedberg 		break;
2503d5859e22SJohan Hedberg 
2504d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_FLT:
2505d5859e22SJohan Hedberg 		hci_cc_set_event_flt(hdev, skb);
2506d5859e22SJohan Hedberg 		break;
2507d5859e22SJohan Hedberg 
2508980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
2509980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
2510980e1a53SJohan Hedberg 		break;
2511980e1a53SJohan Hedberg 
2512980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
2513980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
2514980e1a53SJohan Hedberg 		break;
2515980e1a53SJohan Hedberg 
2516c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
2517c35938b2SSzymon Janc 		hci_cc_read_local_oob_data_reply(hdev, skb);
2518c35938b2SSzymon Janc 		break;
2519c35938b2SSzymon Janc 
25206ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
25216ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
25226ed58ec5SVille Tervo 		break;
25236ed58ec5SVille Tervo 
25248fa19098SJohan Hedberg 	case HCI_OP_LE_READ_ADV_TX_POWER:
25258fa19098SJohan Hedberg 		hci_cc_le_read_adv_tx_power(hdev, skb);
25268fa19098SJohan Hedberg 		break;
25278fa19098SJohan Hedberg 
2528e36b04c8SJohan Hedberg 	case HCI_OP_LE_SET_EVENT_MASK:
2529e36b04c8SJohan Hedberg 		hci_cc_le_set_event_mask(hdev, skb);
2530e36b04c8SJohan Hedberg 		break;
2531e36b04c8SJohan Hedberg 
2532a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
2533a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
2534a5c29683SJohan Hedberg 		break;
2535a5c29683SJohan Hedberg 
2536a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
2537a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
2538a5c29683SJohan Hedberg 		break;
2539a5c29683SJohan Hedberg 
25401143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_REPLY:
25411143d458SBrian Gix 		hci_cc_user_passkey_reply(hdev, skb);
25421143d458SBrian Gix 		break;
25431143d458SBrian Gix 
25441143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_NEG_REPLY:
25451143d458SBrian Gix 		hci_cc_user_passkey_neg_reply(hdev, skb);
254616cde993SSzymon Janc 		break;
254707f7fa5dSAndre Guedes 
254807f7fa5dSAndre Guedes 	case HCI_OP_LE_SET_SCAN_PARAM:
254907f7fa5dSAndre Guedes 		hci_cc_le_set_scan_param(hdev, skb);
25501143d458SBrian Gix 		break;
25511143d458SBrian Gix 
2552eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
2553eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
2554eb9d91f5SAndre Guedes 		break;
2555eb9d91f5SAndre Guedes 
2556a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_REPLY:
2557a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_reply(hdev, skb);
2558a7a595f6SVinicius Costa Gomes 		break;
2559a7a595f6SVinicius Costa Gomes 
2560a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_NEG_REPLY:
2561a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_neg_reply(hdev, skb);
2562a7a595f6SVinicius Costa Gomes 		break;
2563a7a595f6SVinicius Costa Gomes 
2564f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2565f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
2566f9b49306SAndre Guedes 		break;
2567f9b49306SAndre Guedes 
256893c284eeSAndrei Emeltchenko 	case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
256993c284eeSAndrei Emeltchenko 		hci_cc_write_remote_amp_assoc(hdev, skb);
257093c284eeSAndrei Emeltchenko 		break;
257193c284eeSAndrei Emeltchenko 
2572a9de9248SMarcel Holtmann 	default:
25739f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2574a9de9248SMarcel Holtmann 		break;
2575a9de9248SMarcel Holtmann 	}
2576a9de9248SMarcel Holtmann 
25776bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
25786bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
25796bd32326SVille Tervo 
2580a9de9248SMarcel Holtmann 	if (ev->ncmd) {
2581a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2582a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2583c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2584a9de9248SMarcel Holtmann 	}
2585a9de9248SMarcel Holtmann }
2586a9de9248SMarcel Holtmann 
25876039aa73SGustavo Padovan static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2588a9de9248SMarcel Holtmann {
2589a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
2590a9de9248SMarcel Holtmann 	__u16 opcode;
2591a9de9248SMarcel Holtmann 
2592a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2593a9de9248SMarcel Holtmann 
2594a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2595a9de9248SMarcel Holtmann 
2596a9de9248SMarcel Holtmann 	switch (opcode) {
2597a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
2598a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
2599a9de9248SMarcel Holtmann 		break;
2600a9de9248SMarcel Holtmann 
2601a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
2602a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
2603a9de9248SMarcel Holtmann 		break;
2604a9de9248SMarcel Holtmann 
2605a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
2606a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
2607a9de9248SMarcel Holtmann 		break;
2608a9de9248SMarcel Holtmann 
2609f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2610f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2611f8558555SMarcel Holtmann 		break;
2612f8558555SMarcel Holtmann 
2613f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2614f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2615f8558555SMarcel Holtmann 		break;
2616f8558555SMarcel Holtmann 
2617a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2618a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2619a9de9248SMarcel Holtmann 		break;
2620a9de9248SMarcel Holtmann 
2621769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2622769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2623769be974SMarcel Holtmann 		break;
2624769be974SMarcel Holtmann 
2625769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2626769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2627769be974SMarcel Holtmann 		break;
2628769be974SMarcel Holtmann 
2629a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2630a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2631a9de9248SMarcel Holtmann 		break;
2632a9de9248SMarcel Holtmann 
2633a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2634a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2635a9de9248SMarcel Holtmann 		break;
2636a9de9248SMarcel Holtmann 
2637a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2638a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2639a9de9248SMarcel Holtmann 		break;
2640a9de9248SMarcel Holtmann 
26418962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
264288c3df13SJohan Hedberg 		hci_cs_disconnect(hdev, ev->status);
26438962ee74SJohan Hedberg 		break;
26448962ee74SJohan Hedberg 
2645fcd89c09SVille Tervo 	case HCI_OP_LE_CREATE_CONN:
2646fcd89c09SVille Tervo 		hci_cs_le_create_conn(hdev, ev->status);
2647fcd89c09SVille Tervo 		break;
2648fcd89c09SVille Tervo 
2649a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_START_ENC:
2650a7a595f6SVinicius Costa Gomes 		hci_cs_le_start_enc(hdev, ev->status);
2651a7a595f6SVinicius Costa Gomes 		break;
2652a7a595f6SVinicius Costa Gomes 
2653a02226d6SAndrei Emeltchenko 	case HCI_OP_CREATE_PHY_LINK:
2654a02226d6SAndrei Emeltchenko 		hci_cs_create_phylink(hdev, ev->status);
2655a02226d6SAndrei Emeltchenko 		break;
2656a02226d6SAndrei Emeltchenko 
26570b26ab9dSAndrei Emeltchenko 	case HCI_OP_ACCEPT_PHY_LINK:
26580b26ab9dSAndrei Emeltchenko 		hci_cs_accept_phylink(hdev, ev->status);
26590b26ab9dSAndrei Emeltchenko 		break;
26600b26ab9dSAndrei Emeltchenko 
2661a9de9248SMarcel Holtmann 	default:
26629f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2663a9de9248SMarcel Holtmann 		break;
2664a9de9248SMarcel Holtmann 	}
2665a9de9248SMarcel Holtmann 
26666bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
26676bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
26686bd32326SVille Tervo 
266910572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2670a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2671a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2672c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2673a9de9248SMarcel Holtmann 	}
2674a9de9248SMarcel Holtmann }
2675a9de9248SMarcel Holtmann 
26766039aa73SGustavo Padovan static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2677a9de9248SMarcel Holtmann {
2678a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2679a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2680a9de9248SMarcel Holtmann 
26819f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2682a9de9248SMarcel Holtmann 
2683a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2684a9de9248SMarcel Holtmann 
2685a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2686a9de9248SMarcel Holtmann 	if (conn) {
2687a9de9248SMarcel Holtmann 		if (!ev->status) {
2688a9de9248SMarcel Holtmann 			if (ev->role)
2689a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
2690a9de9248SMarcel Holtmann 			else
2691a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
2692a9de9248SMarcel Holtmann 		}
2693a9de9248SMarcel Holtmann 
269451a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
2695a9de9248SMarcel Holtmann 
2696a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2697a9de9248SMarcel Holtmann 	}
2698a9de9248SMarcel Holtmann 
2699a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2700a9de9248SMarcel Holtmann }
2701a9de9248SMarcel Holtmann 
27026039aa73SGustavo Padovan static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
27031da177e4SLinus Torvalds {
2704a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
27051da177e4SLinus Torvalds 	int i;
27061da177e4SLinus Torvalds 
270732ac5b9bSAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
270832ac5b9bSAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
270932ac5b9bSAndrei Emeltchenko 		return;
271032ac5b9bSAndrei Emeltchenko 	}
271132ac5b9bSAndrei Emeltchenko 
2712c5993de8SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2713c5993de8SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
27141da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
27151da177e4SLinus Torvalds 		return;
27161da177e4SLinus Torvalds 	}
27171da177e4SLinus Torvalds 
2718c5993de8SAndrei Emeltchenko 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2719c5993de8SAndrei Emeltchenko 
2720613a1c0cSAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
2721613a1c0cSAndrei Emeltchenko 		struct hci_comp_pkts_info *info = &ev->handles[i];
27221da177e4SLinus Torvalds 		struct hci_conn *conn;
27231da177e4SLinus Torvalds 		__u16  handle, count;
27241da177e4SLinus Torvalds 
2725613a1c0cSAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
2726613a1c0cSAndrei Emeltchenko 		count  = __le16_to_cpu(info->count);
27271da177e4SLinus Torvalds 
27281da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
2729f4280918SAndrei Emeltchenko 		if (!conn)
2730f4280918SAndrei Emeltchenko 			continue;
2731f4280918SAndrei Emeltchenko 
27321da177e4SLinus Torvalds 		conn->sent -= count;
27331da177e4SLinus Torvalds 
2734f4280918SAndrei Emeltchenko 		switch (conn->type) {
2735f4280918SAndrei Emeltchenko 		case ACL_LINK:
273670f23020SAndrei Emeltchenko 			hdev->acl_cnt += count;
273770f23020SAndrei Emeltchenko 			if (hdev->acl_cnt > hdev->acl_pkts)
27381da177e4SLinus Torvalds 				hdev->acl_cnt = hdev->acl_pkts;
2739f4280918SAndrei Emeltchenko 			break;
2740f4280918SAndrei Emeltchenko 
2741f4280918SAndrei Emeltchenko 		case LE_LINK:
27426ed58ec5SVille Tervo 			if (hdev->le_pkts) {
27436ed58ec5SVille Tervo 				hdev->le_cnt += count;
27446ed58ec5SVille Tervo 				if (hdev->le_cnt > hdev->le_pkts)
27456ed58ec5SVille Tervo 					hdev->le_cnt = hdev->le_pkts;
27466ed58ec5SVille Tervo 			} else {
27476ed58ec5SVille Tervo 				hdev->acl_cnt += count;
27486ed58ec5SVille Tervo 				if (hdev->acl_cnt > hdev->acl_pkts)
27496ed58ec5SVille Tervo 					hdev->acl_cnt = hdev->acl_pkts;
27506ed58ec5SVille Tervo 			}
2751f4280918SAndrei Emeltchenko 			break;
2752f4280918SAndrei Emeltchenko 
2753f4280918SAndrei Emeltchenko 		case SCO_LINK:
275470f23020SAndrei Emeltchenko 			hdev->sco_cnt += count;
275570f23020SAndrei Emeltchenko 			if (hdev->sco_cnt > hdev->sco_pkts)
27565b7f9909SMarcel Holtmann 				hdev->sco_cnt = hdev->sco_pkts;
2757f4280918SAndrei Emeltchenko 			break;
2758f4280918SAndrei Emeltchenko 
2759f4280918SAndrei Emeltchenko 		default:
2760f4280918SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
2761f4280918SAndrei Emeltchenko 			break;
27621da177e4SLinus Torvalds 		}
27631da177e4SLinus Torvalds 	}
2764a9de9248SMarcel Holtmann 
27653eff45eaSGustavo F. Padovan 	queue_work(hdev->workqueue, &hdev->tx_work);
27661da177e4SLinus Torvalds }
27671da177e4SLinus Torvalds 
276876ef7cf7SAndrei Emeltchenko static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
276976ef7cf7SAndrei Emeltchenko 						 __u16 handle)
277076ef7cf7SAndrei Emeltchenko {
277176ef7cf7SAndrei Emeltchenko 	struct hci_chan *chan;
277276ef7cf7SAndrei Emeltchenko 
277376ef7cf7SAndrei Emeltchenko 	switch (hdev->dev_type) {
277476ef7cf7SAndrei Emeltchenko 	case HCI_BREDR:
277576ef7cf7SAndrei Emeltchenko 		return hci_conn_hash_lookup_handle(hdev, handle);
277676ef7cf7SAndrei Emeltchenko 	case HCI_AMP:
277776ef7cf7SAndrei Emeltchenko 		chan = hci_chan_lookup_handle(hdev, handle);
277876ef7cf7SAndrei Emeltchenko 		if (chan)
277976ef7cf7SAndrei Emeltchenko 			return chan->conn;
278076ef7cf7SAndrei Emeltchenko 		break;
278176ef7cf7SAndrei Emeltchenko 	default:
278276ef7cf7SAndrei Emeltchenko 		BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type);
278376ef7cf7SAndrei Emeltchenko 		break;
278476ef7cf7SAndrei Emeltchenko 	}
278576ef7cf7SAndrei Emeltchenko 
278676ef7cf7SAndrei Emeltchenko 	return NULL;
278776ef7cf7SAndrei Emeltchenko }
278876ef7cf7SAndrei Emeltchenko 
27896039aa73SGustavo Padovan static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
279025e89e99SAndrei Emeltchenko {
279125e89e99SAndrei Emeltchenko 	struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
279225e89e99SAndrei Emeltchenko 	int i;
279325e89e99SAndrei Emeltchenko 
279425e89e99SAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
279525e89e99SAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
279625e89e99SAndrei Emeltchenko 		return;
279725e89e99SAndrei Emeltchenko 	}
279825e89e99SAndrei Emeltchenko 
279925e89e99SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
280025e89e99SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
280125e89e99SAndrei Emeltchenko 		BT_DBG("%s bad parameters", hdev->name);
280225e89e99SAndrei Emeltchenko 		return;
280325e89e99SAndrei Emeltchenko 	}
280425e89e99SAndrei Emeltchenko 
280525e89e99SAndrei Emeltchenko 	BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
280625e89e99SAndrei Emeltchenko 	       ev->num_hndl);
280725e89e99SAndrei Emeltchenko 
280825e89e99SAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
280925e89e99SAndrei Emeltchenko 		struct hci_comp_blocks_info *info = &ev->handles[i];
281076ef7cf7SAndrei Emeltchenko 		struct hci_conn *conn = NULL;
281125e89e99SAndrei Emeltchenko 		__u16  handle, block_count;
281225e89e99SAndrei Emeltchenko 
281325e89e99SAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
281425e89e99SAndrei Emeltchenko 		block_count = __le16_to_cpu(info->blocks);
281525e89e99SAndrei Emeltchenko 
281676ef7cf7SAndrei Emeltchenko 		conn = __hci_conn_lookup_handle(hdev, handle);
281725e89e99SAndrei Emeltchenko 		if (!conn)
281825e89e99SAndrei Emeltchenko 			continue;
281925e89e99SAndrei Emeltchenko 
282025e89e99SAndrei Emeltchenko 		conn->sent -= block_count;
282125e89e99SAndrei Emeltchenko 
282225e89e99SAndrei Emeltchenko 		switch (conn->type) {
282325e89e99SAndrei Emeltchenko 		case ACL_LINK:
2824bd1eb66bSAndrei Emeltchenko 		case AMP_LINK:
282525e89e99SAndrei Emeltchenko 			hdev->block_cnt += block_count;
282625e89e99SAndrei Emeltchenko 			if (hdev->block_cnt > hdev->num_blocks)
282725e89e99SAndrei Emeltchenko 				hdev->block_cnt = hdev->num_blocks;
282825e89e99SAndrei Emeltchenko 			break;
282925e89e99SAndrei Emeltchenko 
283025e89e99SAndrei Emeltchenko 		default:
283125e89e99SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
283225e89e99SAndrei Emeltchenko 			break;
283325e89e99SAndrei Emeltchenko 		}
283425e89e99SAndrei Emeltchenko 	}
283525e89e99SAndrei Emeltchenko 
283625e89e99SAndrei Emeltchenko 	queue_work(hdev->workqueue, &hdev->tx_work);
283725e89e99SAndrei Emeltchenko }
283825e89e99SAndrei Emeltchenko 
28396039aa73SGustavo Padovan static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
28401da177e4SLinus Torvalds {
2841a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
284204837f64SMarcel Holtmann 	struct hci_conn *conn;
28431da177e4SLinus Torvalds 
28449f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
28451da177e4SLinus Torvalds 
28461da177e4SLinus Torvalds 	hci_dev_lock(hdev);
28471da177e4SLinus Torvalds 
284804837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
284904837f64SMarcel Holtmann 	if (conn) {
285004837f64SMarcel Holtmann 		conn->mode = ev->mode;
285104837f64SMarcel Holtmann 		conn->interval = __le16_to_cpu(ev->interval);
285204837f64SMarcel Holtmann 
28538fc9ced3SGustavo Padovan 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
28548fc9ced3SGustavo Padovan 					&conn->flags)) {
285504837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
285658a681efSJohan Hedberg 				set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
285704837f64SMarcel Holtmann 			else
285858a681efSJohan Hedberg 				clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
285904837f64SMarcel Holtmann 		}
2860e73439d8SMarcel Holtmann 
286151a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
2862e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
286304837f64SMarcel Holtmann 	}
286404837f64SMarcel Holtmann 
286504837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
286604837f64SMarcel Holtmann }
286704837f64SMarcel Holtmann 
28686039aa73SGustavo Padovan static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
28691da177e4SLinus Torvalds {
2870052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
2871052b30b0SMarcel Holtmann 	struct hci_conn *conn;
2872052b30b0SMarcel Holtmann 
2873a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2874052b30b0SMarcel Holtmann 
2875052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2876052b30b0SMarcel Holtmann 
2877052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2878b6f98044SWaldemar Rymarkiewicz 	if (!conn)
2879b6f98044SWaldemar Rymarkiewicz 		goto unlock;
2880b6f98044SWaldemar Rymarkiewicz 
2881b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
2882052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2883052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2884052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2885052b30b0SMarcel Holtmann 	}
2886052b30b0SMarcel Holtmann 
2887a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
288803b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
288903b555e1SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
2890a8b2d5c2SJohan Hedberg 	else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
2891a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
2892a770bb5aSWaldemar Rymarkiewicz 
2893a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
2894a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
2895a770bb5aSWaldemar Rymarkiewicz 		else
2896a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
2897a770bb5aSWaldemar Rymarkiewicz 
2898744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
2899a770bb5aSWaldemar Rymarkiewicz 	}
2900980e1a53SJohan Hedberg 
2901b6f98044SWaldemar Rymarkiewicz unlock:
2902052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
29031da177e4SLinus Torvalds }
29041da177e4SLinus Torvalds 
29056039aa73SGustavo Padovan static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
29061da177e4SLinus Torvalds {
290755ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
290855ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
290955ed8ca1SJohan Hedberg 	struct hci_conn *conn;
291055ed8ca1SJohan Hedberg 	struct link_key *key;
291155ed8ca1SJohan Hedberg 
2912a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
291355ed8ca1SJohan Hedberg 
2914a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
291555ed8ca1SJohan Hedberg 		return;
291655ed8ca1SJohan Hedberg 
291755ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
291855ed8ca1SJohan Hedberg 
291955ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
292055ed8ca1SJohan Hedberg 	if (!key) {
29216ed93dc6SAndrei Emeltchenko 		BT_DBG("%s link key not found for %pMR", hdev->name,
29226ed93dc6SAndrei Emeltchenko 		       &ev->bdaddr);
292355ed8ca1SJohan Hedberg 		goto not_found;
292455ed8ca1SJohan Hedberg 	}
292555ed8ca1SJohan Hedberg 
29266ed93dc6SAndrei Emeltchenko 	BT_DBG("%s found key type %u for %pMR", hdev->name, key->type,
29276ed93dc6SAndrei Emeltchenko 	       &ev->bdaddr);
292855ed8ca1SJohan Hedberg 
2929a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
2930b6020ba0SWaldemar Rymarkiewicz 	    key->type == HCI_LK_DEBUG_COMBINATION) {
293155ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
293255ed8ca1SJohan Hedberg 		goto not_found;
293355ed8ca1SJohan Hedberg 	}
293455ed8ca1SJohan Hedberg 
293555ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
293660b83f57SWaldemar Rymarkiewicz 	if (conn) {
293760b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_UNAUTH_COMBINATION &&
2938807deac2SGustavo Padovan 		    conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
293955ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
294055ed8ca1SJohan Hedberg 			goto not_found;
294155ed8ca1SJohan Hedberg 		}
294255ed8ca1SJohan Hedberg 
294360b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
294460b83f57SWaldemar Rymarkiewicz 		    conn->pending_sec_level == BT_SECURITY_HIGH) {
29458fc9ced3SGustavo Padovan 			BT_DBG("%s ignoring key unauthenticated for high security",
29468fc9ced3SGustavo Padovan 			       hdev->name);
294760b83f57SWaldemar Rymarkiewicz 			goto not_found;
294860b83f57SWaldemar Rymarkiewicz 		}
294960b83f57SWaldemar Rymarkiewicz 
295060b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
295160b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
295260b83f57SWaldemar Rymarkiewicz 	}
295360b83f57SWaldemar Rymarkiewicz 
295455ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
29559b3b4460SAndrei Emeltchenko 	memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
295655ed8ca1SJohan Hedberg 
295755ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
295855ed8ca1SJohan Hedberg 
295955ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
296055ed8ca1SJohan Hedberg 
296155ed8ca1SJohan Hedberg 	return;
296255ed8ca1SJohan Hedberg 
296355ed8ca1SJohan Hedberg not_found:
296455ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
296555ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
29661da177e4SLinus Torvalds }
29671da177e4SLinus Torvalds 
29686039aa73SGustavo Padovan static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
29691da177e4SLinus Torvalds {
2970052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
2971052b30b0SMarcel Holtmann 	struct hci_conn *conn;
297255ed8ca1SJohan Hedberg 	u8 pin_len = 0;
2973052b30b0SMarcel Holtmann 
2974a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2975052b30b0SMarcel Holtmann 
2976052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2977052b30b0SMarcel Holtmann 
2978052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2979052b30b0SMarcel Holtmann 	if (conn) {
2980052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2981052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2982980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
298313d39315SWaldemar Rymarkiewicz 
298413d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
298513d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
298613d39315SWaldemar Rymarkiewicz 
2987052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2988052b30b0SMarcel Holtmann 	}
2989052b30b0SMarcel Holtmann 
2990a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
2991d25e28abSJohan Hedberg 		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
299255ed8ca1SJohan Hedberg 				 ev->key_type, pin_len);
299355ed8ca1SJohan Hedberg 
2994052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
29951da177e4SLinus Torvalds }
29961da177e4SLinus Torvalds 
29976039aa73SGustavo Padovan static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
299804837f64SMarcel Holtmann {
2999a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
300004837f64SMarcel Holtmann 	struct hci_conn *conn;
300104837f64SMarcel Holtmann 
30029f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
300304837f64SMarcel Holtmann 
300404837f64SMarcel Holtmann 	hci_dev_lock(hdev);
300504837f64SMarcel Holtmann 
300604837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
30071da177e4SLinus Torvalds 	if (conn && !ev->status) {
30081da177e4SLinus Torvalds 		struct inquiry_entry *ie;
30091da177e4SLinus Torvalds 
3010cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3011cc11b9c1SAndrei Emeltchenko 		if (ie) {
30121da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
30131da177e4SLinus Torvalds 			ie->timestamp = jiffies;
30141da177e4SLinus Torvalds 		}
30151da177e4SLinus Torvalds 	}
30161da177e4SLinus Torvalds 
30171da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
30181da177e4SLinus Torvalds }
30191da177e4SLinus Torvalds 
30206039aa73SGustavo Padovan static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
3021a8746417SMarcel Holtmann {
3022a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
3023a8746417SMarcel Holtmann 	struct hci_conn *conn;
3024a8746417SMarcel Holtmann 
30259f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3026a8746417SMarcel Holtmann 
3027a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
3028a8746417SMarcel Holtmann 
3029a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3030a8746417SMarcel Holtmann 	if (conn && !ev->status)
3031a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
3032a8746417SMarcel Holtmann 
3033a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
3034a8746417SMarcel Holtmann }
3035a8746417SMarcel Holtmann 
30366039aa73SGustavo Padovan static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
303785a1e930SMarcel Holtmann {
3038a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
303985a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
304085a1e930SMarcel Holtmann 
304185a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
304285a1e930SMarcel Holtmann 
304385a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
304485a1e930SMarcel Holtmann 
3045cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3046cc11b9c1SAndrei Emeltchenko 	if (ie) {
304785a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
304885a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
304985a1e930SMarcel Holtmann 	}
305085a1e930SMarcel Holtmann 
305185a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
305285a1e930SMarcel Holtmann }
305385a1e930SMarcel Holtmann 
30546039aa73SGustavo Padovan static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
3055807deac2SGustavo Padovan 					     struct sk_buff *skb)
3056a9de9248SMarcel Holtmann {
3057a9de9248SMarcel Holtmann 	struct inquiry_data data;
3058a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
3059388fc8faSJohan Hedberg 	bool name_known, ssp;
3060a9de9248SMarcel Holtmann 
3061a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3062a9de9248SMarcel Holtmann 
3063a9de9248SMarcel Holtmann 	if (!num_rsp)
3064a9de9248SMarcel Holtmann 		return;
3065a9de9248SMarcel Holtmann 
30661519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
30671519cc17SAndre Guedes 		return;
30681519cc17SAndre Guedes 
3069a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
3070a9de9248SMarcel Holtmann 
3071a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
3072138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
3073138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
3074a9de9248SMarcel Holtmann 
3075e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
3076a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
3077a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
3078a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
3079a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
3080a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
3081a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
3082a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
308341a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
30843175405bSJohan Hedberg 
30853175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
3086388fc8faSJohan Hedberg 							      false, &ssp);
308748264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
3088e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
3089388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
3090a9de9248SMarcel Holtmann 		}
3091a9de9248SMarcel Holtmann 	} else {
3092a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
3093a9de9248SMarcel Holtmann 
3094e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
3095a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
3096a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
3097a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
3098a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
3099a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
3100a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
3101a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
310241a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
31033175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
3104388fc8faSJohan Hedberg 							      false, &ssp);
310548264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
3106e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
3107388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
3108a9de9248SMarcel Holtmann 		}
3109a9de9248SMarcel Holtmann 	}
3110a9de9248SMarcel Holtmann 
3111a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3112a9de9248SMarcel Holtmann }
3113a9de9248SMarcel Holtmann 
31146039aa73SGustavo Padovan static void hci_remote_ext_features_evt(struct hci_dev *hdev,
3115807deac2SGustavo Padovan 					struct sk_buff *skb)
3116a9de9248SMarcel Holtmann {
311741a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
311841a96212SMarcel Holtmann 	struct hci_conn *conn;
311941a96212SMarcel Holtmann 
3120a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
312141a96212SMarcel Holtmann 
312241a96212SMarcel Holtmann 	hci_dev_lock(hdev);
312341a96212SMarcel Holtmann 
312441a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3125ccd556feSJohan Hedberg 	if (!conn)
3126ccd556feSJohan Hedberg 		goto unlock;
3127ccd556feSJohan Hedberg 
3128769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
312941a96212SMarcel Holtmann 		struct inquiry_entry *ie;
313041a96212SMarcel Holtmann 
3131cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3132cc11b9c1SAndrei Emeltchenko 		if (ie)
313302b7cc62SJohan Hedberg 			ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
313441a96212SMarcel Holtmann 
313502b7cc62SJohan Hedberg 		if (ev->features[0] & LMP_HOST_SSP)
313658a681efSJohan Hedberg 			set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
313741a96212SMarcel Holtmann 	}
313841a96212SMarcel Holtmann 
3139ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
3140ccd556feSJohan Hedberg 		goto unlock;
3141ccd556feSJohan Hedberg 
3142671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
3143127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
3144127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
3145127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
3146127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
3147127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
3148b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3149b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
315008c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
3151b644ba33SJohan Hedberg 				      conn->dev_class);
3152392599b9SJohan Hedberg 
3153127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
3154769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
3155769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
3156769be974SMarcel Holtmann 		hci_conn_put(conn);
3157769be974SMarcel Holtmann 	}
3158769be974SMarcel Holtmann 
3159ccd556feSJohan Hedberg unlock:
316041a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
3161a9de9248SMarcel Holtmann }
3162a9de9248SMarcel Holtmann 
31636039aa73SGustavo Padovan static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
3164807deac2SGustavo Padovan 				       struct sk_buff *skb)
3165a9de9248SMarcel Holtmann {
3166b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
3167b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
3168b6a0dc82SMarcel Holtmann 
31699f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3170b6a0dc82SMarcel Holtmann 
3171b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
3172b6a0dc82SMarcel Holtmann 
3173b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
31749dc0a3afSMarcel Holtmann 	if (!conn) {
31759dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
31769dc0a3afSMarcel Holtmann 			goto unlock;
31779dc0a3afSMarcel Holtmann 
31789dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
3179b6a0dc82SMarcel Holtmann 		if (!conn)
3180b6a0dc82SMarcel Holtmann 			goto unlock;
3181b6a0dc82SMarcel Holtmann 
31829dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
31839dc0a3afSMarcel Holtmann 	}
31849dc0a3afSMarcel Holtmann 
3185732547f9SMarcel Holtmann 	switch (ev->status) {
3186732547f9SMarcel Holtmann 	case 0x00:
3187732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
3188732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
3189732547f9SMarcel Holtmann 
31909eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
3191732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
3192732547f9SMarcel Holtmann 		break;
3193732547f9SMarcel Holtmann 
3194705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
3195732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
31961038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
3197732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
3198732547f9SMarcel Holtmann 		if (conn->out && conn->attempt < 2) {
3199efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
3200efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
3201efc7688bSMarcel Holtmann 			hci_setup_sync(conn, conn->link->handle);
3202efc7688bSMarcel Holtmann 			goto unlock;
3203efc7688bSMarcel Holtmann 		}
3204732547f9SMarcel Holtmann 		/* fall through */
3205efc7688bSMarcel Holtmann 
3206732547f9SMarcel Holtmann 	default:
3207b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
3208732547f9SMarcel Holtmann 		break;
3209732547f9SMarcel Holtmann 	}
3210b6a0dc82SMarcel Holtmann 
3211b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
3212b6a0dc82SMarcel Holtmann 	if (ev->status)
3213b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
3214b6a0dc82SMarcel Holtmann 
3215b6a0dc82SMarcel Holtmann unlock:
3216b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
3217a9de9248SMarcel Holtmann }
3218a9de9248SMarcel Holtmann 
32196039aa73SGustavo Padovan static void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
3220a9de9248SMarcel Holtmann {
3221a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
3222a9de9248SMarcel Holtmann }
3223a9de9248SMarcel Holtmann 
32246039aa73SGustavo Padovan static void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
322504837f64SMarcel Holtmann {
3226a9de9248SMarcel Holtmann 	struct hci_ev_sniff_subrate *ev = (void *) skb->data;
322704837f64SMarcel Holtmann 
32289f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
322904837f64SMarcel Holtmann }
323004837f64SMarcel Holtmann 
32316039aa73SGustavo Padovan static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
3232807deac2SGustavo Padovan 					    struct sk_buff *skb)
3233a9de9248SMarcel Holtmann {
3234a9de9248SMarcel Holtmann 	struct inquiry_data data;
3235a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
3236a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
32379d939d94SVishal Agarwal 	size_t eir_len;
3238a9de9248SMarcel Holtmann 
3239a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3240a9de9248SMarcel Holtmann 
3241a9de9248SMarcel Holtmann 	if (!num_rsp)
3242a9de9248SMarcel Holtmann 		return;
3243a9de9248SMarcel Holtmann 
32441519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
32451519cc17SAndre Guedes 		return;
32461519cc17SAndre Guedes 
3247a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
3248a9de9248SMarcel Holtmann 
3249e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
3250388fc8faSJohan Hedberg 		bool name_known, ssp;
3251561aafbcSJohan Hedberg 
3252a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
3253a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
3254a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
3255a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
3256a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
3257a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
3258a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
325941a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
3260561aafbcSJohan Hedberg 
3261a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
32624ddb1930SJohan Hedberg 			name_known = eir_has_data_type(info->data,
32634ddb1930SJohan Hedberg 						       sizeof(info->data),
32644ddb1930SJohan Hedberg 						       EIR_NAME_COMPLETE);
3265561aafbcSJohan Hedberg 		else
3266561aafbcSJohan Hedberg 			name_known = true;
3267561aafbcSJohan Hedberg 
3268388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, name_known,
3269388fc8faSJohan Hedberg 						      &ssp);
32709d939d94SVishal Agarwal 		eir_len = eir_get_length(info->data, sizeof(info->data));
327148264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
327204124681SGustavo F. Padovan 				  info->dev_class, info->rssi, !name_known,
32739d939d94SVishal Agarwal 				  ssp, info->data, eir_len);
3274a9de9248SMarcel Holtmann 	}
3275a9de9248SMarcel Holtmann 
3276a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3277a9de9248SMarcel Holtmann }
3278a9de9248SMarcel Holtmann 
32791c2e0041SJohan Hedberg static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
32801c2e0041SJohan Hedberg 					 struct sk_buff *skb)
32811c2e0041SJohan Hedberg {
32821c2e0041SJohan Hedberg 	struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
32831c2e0041SJohan Hedberg 	struct hci_conn *conn;
32841c2e0041SJohan Hedberg 
32859f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
32861c2e0041SJohan Hedberg 	       __le16_to_cpu(ev->handle));
32871c2e0041SJohan Hedberg 
32881c2e0041SJohan Hedberg 	hci_dev_lock(hdev);
32891c2e0041SJohan Hedberg 
32901c2e0041SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
32911c2e0041SJohan Hedberg 	if (!conn)
32921c2e0041SJohan Hedberg 		goto unlock;
32931c2e0041SJohan Hedberg 
32941c2e0041SJohan Hedberg 	if (!ev->status)
32951c2e0041SJohan Hedberg 		conn->sec_level = conn->pending_sec_level;
32961c2e0041SJohan Hedberg 
32971c2e0041SJohan Hedberg 	clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
32981c2e0041SJohan Hedberg 
32991c2e0041SJohan Hedberg 	if (ev->status && conn->state == BT_CONNECTED) {
33001c2e0041SJohan Hedberg 		hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
33011c2e0041SJohan Hedberg 		hci_conn_put(conn);
33021c2e0041SJohan Hedberg 		goto unlock;
33031c2e0041SJohan Hedberg 	}
33041c2e0041SJohan Hedberg 
33051c2e0041SJohan Hedberg 	if (conn->state == BT_CONFIG) {
33061c2e0041SJohan Hedberg 		if (!ev->status)
33071c2e0041SJohan Hedberg 			conn->state = BT_CONNECTED;
33081c2e0041SJohan Hedberg 
33091c2e0041SJohan Hedberg 		hci_proto_connect_cfm(conn, ev->status);
33101c2e0041SJohan Hedberg 		hci_conn_put(conn);
33111c2e0041SJohan Hedberg 	} else {
33121c2e0041SJohan Hedberg 		hci_auth_cfm(conn, ev->status);
33131c2e0041SJohan Hedberg 
33141c2e0041SJohan Hedberg 		hci_conn_hold(conn);
33151c2e0041SJohan Hedberg 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
33161c2e0041SJohan Hedberg 		hci_conn_put(conn);
33171c2e0041SJohan Hedberg 	}
33181c2e0041SJohan Hedberg 
33191c2e0041SJohan Hedberg unlock:
33201c2e0041SJohan Hedberg 	hci_dev_unlock(hdev);
33211c2e0041SJohan Hedberg }
33221c2e0041SJohan Hedberg 
33236039aa73SGustavo Padovan static u8 hci_get_auth_req(struct hci_conn *conn)
332417fa4b9dSJohan Hedberg {
332517fa4b9dSJohan Hedberg 	/* If remote requests dedicated bonding follow that lead */
332617fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
332717fa4b9dSJohan Hedberg 		/* If both remote and local IO capabilities allow MITM
332817fa4b9dSJohan Hedberg 		 * protection then require it, otherwise don't */
332917fa4b9dSJohan Hedberg 		if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
333017fa4b9dSJohan Hedberg 			return 0x02;
333117fa4b9dSJohan Hedberg 		else
333217fa4b9dSJohan Hedberg 			return 0x03;
333317fa4b9dSJohan Hedberg 	}
333417fa4b9dSJohan Hedberg 
333517fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
333617fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
333758797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
333817fa4b9dSJohan Hedberg 
333917fa4b9dSJohan Hedberg 	return conn->auth_type;
334017fa4b9dSJohan Hedberg }
334117fa4b9dSJohan Hedberg 
33426039aa73SGustavo Padovan static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
33430493684eSMarcel Holtmann {
33440493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
33450493684eSMarcel Holtmann 	struct hci_conn *conn;
33460493684eSMarcel Holtmann 
33470493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
33480493684eSMarcel Holtmann 
33490493684eSMarcel Holtmann 	hci_dev_lock(hdev);
33500493684eSMarcel Holtmann 
33510493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
335203b555e1SJohan Hedberg 	if (!conn)
335303b555e1SJohan Hedberg 		goto unlock;
335403b555e1SJohan Hedberg 
33550493684eSMarcel Holtmann 	hci_conn_hold(conn);
33560493684eSMarcel Holtmann 
3357a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
335803b555e1SJohan Hedberg 		goto unlock;
335903b555e1SJohan Hedberg 
3360a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
336103b555e1SJohan Hedberg 	    (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
336217fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
336317fa4b9dSJohan Hedberg 
336417fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
33657a7f1e7cSHemant Gupta 		/* Change the IO capability from KeyboardDisplay
33667a7f1e7cSHemant Gupta 		 * to DisplayYesNo as it is not supported by BT spec. */
33677a7f1e7cSHemant Gupta 		cp.capability = (conn->io_capability == 0x04) ?
33687a7f1e7cSHemant Gupta 						0x01 : conn->io_capability;
33697cbc9bd9SJohan Hedberg 		conn->auth_type = hci_get_auth_req(conn);
33707cbc9bd9SJohan Hedberg 		cp.authentication = conn->auth_type;
337117fa4b9dSJohan Hedberg 
33728fc9ced3SGustavo Padovan 		if (hci_find_remote_oob_data(hdev, &conn->dst) &&
33738fc9ced3SGustavo Padovan 		    (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
3374ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
3375ce85ee13SSzymon Janc 		else
3376ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
3377ce85ee13SSzymon Janc 
337817fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
337917fa4b9dSJohan Hedberg 			     sizeof(cp), &cp);
338003b555e1SJohan Hedberg 	} else {
338103b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
338203b555e1SJohan Hedberg 
338303b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
33849f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
338503b555e1SJohan Hedberg 
338603b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
338703b555e1SJohan Hedberg 			     sizeof(cp), &cp);
338803b555e1SJohan Hedberg 	}
338903b555e1SJohan Hedberg 
339003b555e1SJohan Hedberg unlock:
339103b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
339203b555e1SJohan Hedberg }
339303b555e1SJohan Hedberg 
33946039aa73SGustavo Padovan static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
339503b555e1SJohan Hedberg {
339603b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
339703b555e1SJohan Hedberg 	struct hci_conn *conn;
339803b555e1SJohan Hedberg 
339903b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
340003b555e1SJohan Hedberg 
340103b555e1SJohan Hedberg 	hci_dev_lock(hdev);
340203b555e1SJohan Hedberg 
340303b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
340403b555e1SJohan Hedberg 	if (!conn)
340503b555e1SJohan Hedberg 		goto unlock;
340603b555e1SJohan Hedberg 
340703b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
340803b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
340958a681efSJohan Hedberg 	if (ev->oob_data)
341058a681efSJohan Hedberg 		set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
341103b555e1SJohan Hedberg 
341203b555e1SJohan Hedberg unlock:
34130493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
34140493684eSMarcel Holtmann }
34150493684eSMarcel Holtmann 
34166039aa73SGustavo Padovan static void hci_user_confirm_request_evt(struct hci_dev *hdev,
3417a5c29683SJohan Hedberg 					 struct sk_buff *skb)
3418a5c29683SJohan Hedberg {
3419a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
342055bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
34217a828908SJohan Hedberg 	struct hci_conn *conn;
3422a5c29683SJohan Hedberg 
3423a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
3424a5c29683SJohan Hedberg 
3425a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
3426a5c29683SJohan Hedberg 
3427a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
34287a828908SJohan Hedberg 		goto unlock;
34297a828908SJohan Hedberg 
34307a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
34317a828908SJohan Hedberg 	if (!conn)
34327a828908SJohan Hedberg 		goto unlock;
34337a828908SJohan Hedberg 
34347a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
34357a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
34367a828908SJohan Hedberg 
34377a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
34387a828908SJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
34397a828908SJohan Hedberg 	 * request. The only exception is when we're dedicated bonding
34407a828908SJohan Hedberg 	 * initiators (connect_cfm_cb set) since then we always have the MITM
34417a828908SJohan Hedberg 	 * bit set. */
34427a828908SJohan Hedberg 	if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
34437a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
34447a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
34457a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
34467a828908SJohan Hedberg 		goto unlock;
34477a828908SJohan Hedberg 	}
34487a828908SJohan Hedberg 
34497a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
34507a828908SJohan Hedberg 	if ((!loc_mitm || conn->remote_cap == 0x03) &&
34517a828908SJohan Hedberg 	    (!rem_mitm || conn->io_capability == 0x03)) {
345255bc1a37SJohan Hedberg 
345355bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
345455bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
345555bc1a37SJohan Hedberg 		 * confirm_hint set to 1). */
345651a8efd7SJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
345755bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
345855bc1a37SJohan Hedberg 			confirm_hint = 1;
345955bc1a37SJohan Hedberg 			goto confirm;
346055bc1a37SJohan Hedberg 		}
346155bc1a37SJohan Hedberg 
34629f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
34639f61656aSJohan Hedberg 		       hdev->auto_accept_delay);
34649f61656aSJohan Hedberg 
34659f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
34669f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
34679f61656aSJohan Hedberg 			mod_timer(&conn->auto_accept_timer, jiffies + delay);
34689f61656aSJohan Hedberg 			goto unlock;
34699f61656aSJohan Hedberg 		}
34709f61656aSJohan Hedberg 
34717a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
34727a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
34737a828908SJohan Hedberg 		goto unlock;
34747a828908SJohan Hedberg 	}
34757a828908SJohan Hedberg 
347655bc1a37SJohan Hedberg confirm:
3477272d90dfSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
347855bc1a37SJohan Hedberg 				  confirm_hint);
3479a5c29683SJohan Hedberg 
34807a828908SJohan Hedberg unlock:
3481a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
3482a5c29683SJohan Hedberg }
3483a5c29683SJohan Hedberg 
34846039aa73SGustavo Padovan static void hci_user_passkey_request_evt(struct hci_dev *hdev,
34851143d458SBrian Gix 					 struct sk_buff *skb)
34861143d458SBrian Gix {
34871143d458SBrian Gix 	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
34881143d458SBrian Gix 
34891143d458SBrian Gix 	BT_DBG("%s", hdev->name);
34901143d458SBrian Gix 
3491a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3492272d90dfSJohan Hedberg 		mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
34931143d458SBrian Gix }
34941143d458SBrian Gix 
349592a25256SJohan Hedberg static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
349692a25256SJohan Hedberg 					struct sk_buff *skb)
349792a25256SJohan Hedberg {
349892a25256SJohan Hedberg 	struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
349992a25256SJohan Hedberg 	struct hci_conn *conn;
350092a25256SJohan Hedberg 
350192a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
350292a25256SJohan Hedberg 
350392a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
350492a25256SJohan Hedberg 	if (!conn)
350592a25256SJohan Hedberg 		return;
350692a25256SJohan Hedberg 
350792a25256SJohan Hedberg 	conn->passkey_notify = __le32_to_cpu(ev->passkey);
350892a25256SJohan Hedberg 	conn->passkey_entered = 0;
350992a25256SJohan Hedberg 
351092a25256SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
351192a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
351292a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
351392a25256SJohan Hedberg 					 conn->passkey_entered);
351492a25256SJohan Hedberg }
351592a25256SJohan Hedberg 
351692a25256SJohan Hedberg static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
351792a25256SJohan Hedberg {
351892a25256SJohan Hedberg 	struct hci_ev_keypress_notify *ev = (void *) skb->data;
351992a25256SJohan Hedberg 	struct hci_conn *conn;
352092a25256SJohan Hedberg 
352192a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
352292a25256SJohan Hedberg 
352392a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
352492a25256SJohan Hedberg 	if (!conn)
352592a25256SJohan Hedberg 		return;
352692a25256SJohan Hedberg 
352792a25256SJohan Hedberg 	switch (ev->type) {
352892a25256SJohan Hedberg 	case HCI_KEYPRESS_STARTED:
352992a25256SJohan Hedberg 		conn->passkey_entered = 0;
353092a25256SJohan Hedberg 		return;
353192a25256SJohan Hedberg 
353292a25256SJohan Hedberg 	case HCI_KEYPRESS_ENTERED:
353392a25256SJohan Hedberg 		conn->passkey_entered++;
353492a25256SJohan Hedberg 		break;
353592a25256SJohan Hedberg 
353692a25256SJohan Hedberg 	case HCI_KEYPRESS_ERASED:
353792a25256SJohan Hedberg 		conn->passkey_entered--;
353892a25256SJohan Hedberg 		break;
353992a25256SJohan Hedberg 
354092a25256SJohan Hedberg 	case HCI_KEYPRESS_CLEARED:
354192a25256SJohan Hedberg 		conn->passkey_entered = 0;
354292a25256SJohan Hedberg 		break;
354392a25256SJohan Hedberg 
354492a25256SJohan Hedberg 	case HCI_KEYPRESS_COMPLETED:
354592a25256SJohan Hedberg 		return;
354692a25256SJohan Hedberg 	}
354792a25256SJohan Hedberg 
354892a25256SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
354992a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
355092a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
355192a25256SJohan Hedberg 					 conn->passkey_entered);
355292a25256SJohan Hedberg }
355392a25256SJohan Hedberg 
35546039aa73SGustavo Padovan static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
3555807deac2SGustavo Padovan 					 struct sk_buff *skb)
35560493684eSMarcel Holtmann {
35570493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
35580493684eSMarcel Holtmann 	struct hci_conn *conn;
35590493684eSMarcel Holtmann 
35600493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
35610493684eSMarcel Holtmann 
35620493684eSMarcel Holtmann 	hci_dev_lock(hdev);
35630493684eSMarcel Holtmann 
35640493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
35652a611692SJohan Hedberg 	if (!conn)
35662a611692SJohan Hedberg 		goto unlock;
35672a611692SJohan Hedberg 
35682a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
35692a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
35702a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
35712a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
35722a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
3573fa1bd918SMikel Astiz 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status)
3574bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
3575bab73cb6SJohan Hedberg 				 ev->status);
35762a611692SJohan Hedberg 
35770493684eSMarcel Holtmann 	hci_conn_put(conn);
35780493684eSMarcel Holtmann 
35792a611692SJohan Hedberg unlock:
35800493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
35810493684eSMarcel Holtmann }
35820493684eSMarcel Holtmann 
35836039aa73SGustavo Padovan static void hci_remote_host_features_evt(struct hci_dev *hdev,
3584807deac2SGustavo Padovan 					 struct sk_buff *skb)
358541a96212SMarcel Holtmann {
358641a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
358741a96212SMarcel Holtmann 	struct inquiry_entry *ie;
358841a96212SMarcel Holtmann 
358941a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
359041a96212SMarcel Holtmann 
359141a96212SMarcel Holtmann 	hci_dev_lock(hdev);
359241a96212SMarcel Holtmann 
3593cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3594cc11b9c1SAndrei Emeltchenko 	if (ie)
359502b7cc62SJohan Hedberg 		ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
359641a96212SMarcel Holtmann 
359741a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
359841a96212SMarcel Holtmann }
359941a96212SMarcel Holtmann 
36006039aa73SGustavo Padovan static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
36012763eda6SSzymon Janc 					    struct sk_buff *skb)
36022763eda6SSzymon Janc {
36032763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
36042763eda6SSzymon Janc 	struct oob_data *data;
36052763eda6SSzymon Janc 
36062763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
36072763eda6SSzymon Janc 
36082763eda6SSzymon Janc 	hci_dev_lock(hdev);
36092763eda6SSzymon Janc 
3610a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
3611e1ba1f15SSzymon Janc 		goto unlock;
3612e1ba1f15SSzymon Janc 
36132763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
36142763eda6SSzymon Janc 	if (data) {
36152763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_reply cp;
36162763eda6SSzymon Janc 
36172763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
36182763eda6SSzymon Janc 		memcpy(cp.hash, data->hash, sizeof(cp.hash));
36192763eda6SSzymon Janc 		memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
36202763eda6SSzymon Janc 
36212763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
36222763eda6SSzymon Janc 			     &cp);
36232763eda6SSzymon Janc 	} else {
36242763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
36252763eda6SSzymon Janc 
36262763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
36272763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
36282763eda6SSzymon Janc 			     &cp);
36292763eda6SSzymon Janc 	}
36302763eda6SSzymon Janc 
3631e1ba1f15SSzymon Janc unlock:
36322763eda6SSzymon Janc 	hci_dev_unlock(hdev);
36332763eda6SSzymon Janc }
36342763eda6SSzymon Janc 
36356039aa73SGustavo Padovan static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3636fcd89c09SVille Tervo {
3637fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3638fcd89c09SVille Tervo 	struct hci_conn *conn;
3639fcd89c09SVille Tervo 
36409f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3641fcd89c09SVille Tervo 
3642fcd89c09SVille Tervo 	hci_dev_lock(hdev);
3643fcd89c09SVille Tervo 
36444f72b329SAndrzej Kaczmarek 	conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
3645b62f328bSVille Tervo 	if (!conn) {
3646b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3647b62f328bSVille Tervo 		if (!conn) {
3648b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
3649230fd16aSAndre Guedes 			goto unlock;
3650b62f328bSVille Tervo 		}
365129b7988aSAndre Guedes 
365229b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
3653b9b343d2SAndre Guedes 
3654b9b343d2SAndre Guedes 		if (ev->role == LE_CONN_ROLE_MASTER) {
3655b9b343d2SAndre Guedes 			conn->out = true;
3656b9b343d2SAndre Guedes 			conn->link_mode |= HCI_LM_MASTER;
3657b9b343d2SAndre Guedes 		}
3658b62f328bSVille Tervo 	}
3659fcd89c09SVille Tervo 
3660cd17decbSAndre Guedes 	if (ev->status) {
3661cd17decbSAndre Guedes 		mgmt_connect_failed(hdev, &conn->dst, conn->type,
3662cd17decbSAndre Guedes 				    conn->dst_type, ev->status);
3663cd17decbSAndre Guedes 		hci_proto_connect_cfm(conn, ev->status);
3664cd17decbSAndre Guedes 		conn->state = BT_CLOSED;
3665cd17decbSAndre Guedes 		hci_conn_del(conn);
3666cd17decbSAndre Guedes 		goto unlock;
3667cd17decbSAndre Guedes 	}
3668cd17decbSAndre Guedes 
3669b644ba33SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3670b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
367195b23582SSzymon Janc 				      conn->dst_type, 0, NULL, 0, NULL);
367283bc71b4SVinicius Costa Gomes 
36737b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
3674fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
3675fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
3676fcd89c09SVille Tervo 
3677fcd89c09SVille Tervo 	hci_conn_hold_device(conn);
3678fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
3679fcd89c09SVille Tervo 
3680fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
3681fcd89c09SVille Tervo 
3682fcd89c09SVille Tervo unlock:
3683fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
3684fcd89c09SVille Tervo }
3685fcd89c09SVille Tervo 
36866039aa73SGustavo Padovan static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
36879aa04c91SAndre Guedes {
3688e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
3689e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
36903c9e9195SAndre Guedes 	s8 rssi;
36919aa04c91SAndre Guedes 
36929aa04c91SAndre Guedes 	hci_dev_lock(hdev);
36939aa04c91SAndre Guedes 
3694e95beb41SAndre Guedes 	while (num_reports--) {
3695e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
3696e95beb41SAndre Guedes 
36973c9e9195SAndre Guedes 		rssi = ev->data[ev->length];
36983c9e9195SAndre Guedes 		mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
369904124681SGustavo F. Padovan 				  NULL, rssi, 0, 1, ev->data, ev->length);
37003c9e9195SAndre Guedes 
3701e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
37029aa04c91SAndre Guedes 	}
37039aa04c91SAndre Guedes 
37049aa04c91SAndre Guedes 	hci_dev_unlock(hdev);
37059aa04c91SAndre Guedes }
37069aa04c91SAndre Guedes 
37076039aa73SGustavo Padovan static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
3708a7a595f6SVinicius Costa Gomes {
3709a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3710a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
3711bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
3712a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
3713c9839a11SVinicius Costa Gomes 	struct smp_ltk *ltk;
3714a7a595f6SVinicius Costa Gomes 
37159f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
3716a7a595f6SVinicius Costa Gomes 
3717a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
3718a7a595f6SVinicius Costa Gomes 
3719a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3720bea710feSVinicius Costa Gomes 	if (conn == NULL)
3721bea710feSVinicius Costa Gomes 		goto not_found;
3722a7a595f6SVinicius Costa Gomes 
3723bea710feSVinicius Costa Gomes 	ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3724bea710feSVinicius Costa Gomes 	if (ltk == NULL)
3725bea710feSVinicius Costa Gomes 		goto not_found;
3726bea710feSVinicius Costa Gomes 
3727bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
3728a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
3729c9839a11SVinicius Costa Gomes 
3730c9839a11SVinicius Costa Gomes 	if (ltk->authenticated)
3731c9839a11SVinicius Costa Gomes 		conn->sec_level = BT_SECURITY_HIGH;
3732a7a595f6SVinicius Costa Gomes 
3733a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3734a7a595f6SVinicius Costa Gomes 
3735c9839a11SVinicius Costa Gomes 	if (ltk->type & HCI_SMP_STK) {
3736c9839a11SVinicius Costa Gomes 		list_del(&ltk->list);
3737c9839a11SVinicius Costa Gomes 		kfree(ltk);
3738c9839a11SVinicius Costa Gomes 	}
3739c9839a11SVinicius Costa Gomes 
3740a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
3741bea710feSVinicius Costa Gomes 
3742bea710feSVinicius Costa Gomes 	return;
3743bea710feSVinicius Costa Gomes 
3744bea710feSVinicius Costa Gomes not_found:
3745bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
3746bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3747bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
3748a7a595f6SVinicius Costa Gomes }
3749a7a595f6SVinicius Costa Gomes 
37506039aa73SGustavo Padovan static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3751fcd89c09SVille Tervo {
3752fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
3753fcd89c09SVille Tervo 
3754fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
3755fcd89c09SVille Tervo 
3756fcd89c09SVille Tervo 	switch (le_ev->subevent) {
3757fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
3758fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
3759fcd89c09SVille Tervo 		break;
3760fcd89c09SVille Tervo 
37619aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
37629aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
37639aa04c91SAndre Guedes 		break;
37649aa04c91SAndre Guedes 
3765a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
3766a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
3767a7a595f6SVinicius Costa Gomes 		break;
3768a7a595f6SVinicius Costa Gomes 
3769fcd89c09SVille Tervo 	default:
3770fcd89c09SVille Tervo 		break;
3771fcd89c09SVille Tervo 	}
3772fcd89c09SVille Tervo }
3773fcd89c09SVille Tervo 
37749495b2eeSAndrei Emeltchenko static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
37759495b2eeSAndrei Emeltchenko {
37769495b2eeSAndrei Emeltchenko 	struct hci_ev_channel_selected *ev = (void *) skb->data;
37779495b2eeSAndrei Emeltchenko 	struct hci_conn *hcon;
37789495b2eeSAndrei Emeltchenko 
37799495b2eeSAndrei Emeltchenko 	BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
37809495b2eeSAndrei Emeltchenko 
37819495b2eeSAndrei Emeltchenko 	skb_pull(skb, sizeof(*ev));
37829495b2eeSAndrei Emeltchenko 
37839495b2eeSAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
37849495b2eeSAndrei Emeltchenko 	if (!hcon)
37859495b2eeSAndrei Emeltchenko 		return;
37869495b2eeSAndrei Emeltchenko 
37879495b2eeSAndrei Emeltchenko 	amp_read_loc_assoc_final_data(hdev, hcon);
37889495b2eeSAndrei Emeltchenko }
37899495b2eeSAndrei Emeltchenko 
37901da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
37911da177e4SLinus Torvalds {
3792a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
3793a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
37941da177e4SLinus Torvalds 
37951da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
37961da177e4SLinus Torvalds 
3797a9de9248SMarcel Holtmann 	switch (event) {
37981da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
37991da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
38001da177e4SLinus Torvalds 		break;
38011da177e4SLinus Torvalds 
38021da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
38031da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
38041da177e4SLinus Torvalds 		break;
38051da177e4SLinus Torvalds 
3806a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
3807a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
380821d9e30eSMarcel Holtmann 		break;
380921d9e30eSMarcel Holtmann 
38101da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
38111da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
38121da177e4SLinus Torvalds 		break;
38131da177e4SLinus Torvalds 
38141da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
38151da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
38161da177e4SLinus Torvalds 		break;
38171da177e4SLinus Torvalds 
38181da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
38191da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
38201da177e4SLinus Torvalds 		break;
38211da177e4SLinus Torvalds 
3822a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
3823a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
3824a9de9248SMarcel Holtmann 		break;
3825a9de9248SMarcel Holtmann 
38261da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
38271da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
38281da177e4SLinus Torvalds 		break;
38291da177e4SLinus Torvalds 
3830a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3831a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
3832a9de9248SMarcel Holtmann 		break;
3833a9de9248SMarcel Holtmann 
3834a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
3835a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
3836a9de9248SMarcel Holtmann 		break;
3837a9de9248SMarcel Holtmann 
3838a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_VERSION:
3839a9de9248SMarcel Holtmann 		hci_remote_version_evt(hdev, skb);
3840a9de9248SMarcel Holtmann 		break;
3841a9de9248SMarcel Holtmann 
3842a9de9248SMarcel Holtmann 	case HCI_EV_QOS_SETUP_COMPLETE:
3843a9de9248SMarcel Holtmann 		hci_qos_setup_complete_evt(hdev, skb);
3844a9de9248SMarcel Holtmann 		break;
3845a9de9248SMarcel Holtmann 
3846a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
3847a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
3848a9de9248SMarcel Holtmann 		break;
3849a9de9248SMarcel Holtmann 
3850a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
3851a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
3852a9de9248SMarcel Holtmann 		break;
3853a9de9248SMarcel Holtmann 
3854a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
3855a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
3856a9de9248SMarcel Holtmann 		break;
3857a9de9248SMarcel Holtmann 
3858a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
3859a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
3860a9de9248SMarcel Holtmann 		break;
3861a9de9248SMarcel Holtmann 
3862a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
3863a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
38641da177e4SLinus Torvalds 		break;
38651da177e4SLinus Torvalds 
38661da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
38671da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
38681da177e4SLinus Torvalds 		break;
38691da177e4SLinus Torvalds 
38701da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
38711da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
38721da177e4SLinus Torvalds 		break;
38731da177e4SLinus Torvalds 
38741da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
38751da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
38761da177e4SLinus Torvalds 		break;
38771da177e4SLinus Torvalds 
38781da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
38791da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
38801da177e4SLinus Torvalds 		break;
38811da177e4SLinus Torvalds 
3882a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
3883a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
3884a8746417SMarcel Holtmann 		break;
3885a8746417SMarcel Holtmann 
388685a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
388785a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
388885a1e930SMarcel Holtmann 		break;
388985a1e930SMarcel Holtmann 
3890a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3891a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
3892a9de9248SMarcel Holtmann 		break;
3893a9de9248SMarcel Holtmann 
3894a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
3895a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
3896a9de9248SMarcel Holtmann 		break;
3897a9de9248SMarcel Holtmann 
3898a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
3899a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
3900a9de9248SMarcel Holtmann 		break;
3901a9de9248SMarcel Holtmann 
3902a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_CHANGED:
3903a9de9248SMarcel Holtmann 		hci_sync_conn_changed_evt(hdev, skb);
3904a9de9248SMarcel Holtmann 		break;
3905a9de9248SMarcel Holtmann 
390604837f64SMarcel Holtmann 	case HCI_EV_SNIFF_SUBRATE:
390704837f64SMarcel Holtmann 		hci_sniff_subrate_evt(hdev, skb);
390804837f64SMarcel Holtmann 		break;
390904837f64SMarcel Holtmann 
3910a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
3911a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
39121da177e4SLinus Torvalds 		break;
39131da177e4SLinus Torvalds 
39141c2e0041SJohan Hedberg 	case HCI_EV_KEY_REFRESH_COMPLETE:
39151c2e0041SJohan Hedberg 		hci_key_refresh_complete_evt(hdev, skb);
39161c2e0041SJohan Hedberg 		break;
39171c2e0041SJohan Hedberg 
39180493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
39190493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
39200493684eSMarcel Holtmann 		break;
39210493684eSMarcel Holtmann 
392203b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
392303b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
392403b555e1SJohan Hedberg 		break;
392503b555e1SJohan Hedberg 
3926a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
3927a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
3928a5c29683SJohan Hedberg 		break;
3929a5c29683SJohan Hedberg 
39301143d458SBrian Gix 	case HCI_EV_USER_PASSKEY_REQUEST:
39311143d458SBrian Gix 		hci_user_passkey_request_evt(hdev, skb);
39321143d458SBrian Gix 		break;
39331143d458SBrian Gix 
393492a25256SJohan Hedberg 	case HCI_EV_USER_PASSKEY_NOTIFY:
393592a25256SJohan Hedberg 		hci_user_passkey_notify_evt(hdev, skb);
393692a25256SJohan Hedberg 		break;
393792a25256SJohan Hedberg 
393892a25256SJohan Hedberg 	case HCI_EV_KEYPRESS_NOTIFY:
393992a25256SJohan Hedberg 		hci_keypress_notify_evt(hdev, skb);
394092a25256SJohan Hedberg 		break;
394192a25256SJohan Hedberg 
39420493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
39430493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
39440493684eSMarcel Holtmann 		break;
39450493684eSMarcel Holtmann 
394641a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
394741a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
394841a96212SMarcel Holtmann 		break;
394941a96212SMarcel Holtmann 
3950fcd89c09SVille Tervo 	case HCI_EV_LE_META:
3951fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
3952fcd89c09SVille Tervo 		break;
3953fcd89c09SVille Tervo 
39549495b2eeSAndrei Emeltchenko 	case HCI_EV_CHANNEL_SELECTED:
39559495b2eeSAndrei Emeltchenko 		hci_chan_selected_evt(hdev, skb);
39569495b2eeSAndrei Emeltchenko 		break;
39579495b2eeSAndrei Emeltchenko 
39582763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
39592763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
39602763eda6SSzymon Janc 		break;
39612763eda6SSzymon Janc 
396225e89e99SAndrei Emeltchenko 	case HCI_EV_NUM_COMP_BLOCKS:
396325e89e99SAndrei Emeltchenko 		hci_num_comp_blocks_evt(hdev, skb);
396425e89e99SAndrei Emeltchenko 		break;
396525e89e99SAndrei Emeltchenko 
39661da177e4SLinus Torvalds 	default:
39679f1db00cSAndrei Emeltchenko 		BT_DBG("%s event 0x%2.2x", hdev->name, event);
39681da177e4SLinus Torvalds 		break;
39691da177e4SLinus Torvalds 	}
39701da177e4SLinus Torvalds 
39711da177e4SLinus Torvalds 	kfree_skb(skb);
39721da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
39731da177e4SLinus Torvalds }
3974