xref: /openbmc/linux/net/bluetooth/hci_event.c (revision 9495b2ee)
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 
510d5859e22SJohan Hedberg 	events[4] |= 0x01; /* Flow Specification Complete */
511d5859e22SJohan Hedberg 	events[4] |= 0x02; /* Inquiry Result with RSSI */
512d5859e22SJohan Hedberg 	events[4] |= 0x04; /* Read Remote Extended Features Complete */
513d5859e22SJohan Hedberg 	events[5] |= 0x08; /* Synchronous Connection Complete */
514d5859e22SJohan Hedberg 	events[5] |= 0x10; /* Synchronous Connection Changed */
515d5859e22SJohan Hedberg 
516d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
517a24299e6SJohan Hedberg 		events[4] |= 0x02; /* Inquiry Result with RSSI */
518d5859e22SJohan Hedberg 
519999dcd10SAndre Guedes 	if (lmp_sniffsubr_capable(hdev))
520d5859e22SJohan Hedberg 		events[5] |= 0x20; /* Sniff Subrating */
521d5859e22SJohan Hedberg 
522d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_PAUSE_ENC)
523d5859e22SJohan Hedberg 		events[5] |= 0x80; /* Encryption Key Refresh Complete */
524d5859e22SJohan Hedberg 
525d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
526d5859e22SJohan Hedberg 		events[5] |= 0x40; /* Extended Inquiry Result */
527d5859e22SJohan Hedberg 
528c58e810eSAndre Guedes 	if (lmp_no_flush_capable(hdev))
529d5859e22SJohan Hedberg 		events[7] |= 0x01; /* Enhanced Flush Complete */
530d5859e22SJohan Hedberg 
531d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_LSTO)
532d5859e22SJohan Hedberg 		events[6] |= 0x80; /* Link Supervision Timeout Changed */
533d5859e22SJohan Hedberg 
5349a1a1996SAndre Guedes 	if (lmp_ssp_capable(hdev)) {
535d5859e22SJohan Hedberg 		events[6] |= 0x01;	/* IO Capability Request */
536d5859e22SJohan Hedberg 		events[6] |= 0x02;	/* IO Capability Response */
537d5859e22SJohan Hedberg 		events[6] |= 0x04;	/* User Confirmation Request */
538d5859e22SJohan Hedberg 		events[6] |= 0x08;	/* User Passkey Request */
539d5859e22SJohan Hedberg 		events[6] |= 0x10;	/* Remote OOB Data Request */
540d5859e22SJohan Hedberg 		events[6] |= 0x20;	/* Simple Pairing Complete */
541d5859e22SJohan Hedberg 		events[7] |= 0x04;	/* User Passkey Notification */
542d5859e22SJohan Hedberg 		events[7] |= 0x08;	/* Keypress Notification */
543d5859e22SJohan Hedberg 		events[7] |= 0x10;	/* Remote Host Supported
544d5859e22SJohan Hedberg 					 * Features Notification */
545d5859e22SJohan Hedberg 	}
546d5859e22SJohan Hedberg 
547c383ddc4SAndre Guedes 	if (lmp_le_capable(hdev))
548d5859e22SJohan Hedberg 		events[7] |= 0x20;	/* LE Meta-Event */
549d5859e22SJohan Hedberg 
550d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
551d5859e22SJohan Hedberg }
552d5859e22SJohan Hedberg 
553d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev)
554d5859e22SJohan Hedberg {
555e61ef499SAndrei Emeltchenko 	if (hdev->dev_type != HCI_BREDR)
556e61ef499SAndrei Emeltchenko 		return;
557e61ef499SAndrei Emeltchenko 
558d5859e22SJohan Hedberg 	hci_setup_event_mask(hdev);
559d5859e22SJohan Hedberg 
560d095c1ebSAndrei Emeltchenko 	if (hdev->hci_ver > BLUETOOTH_VER_1_1)
561d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
562d5859e22SJohan Hedberg 
5636d3c730fSGustavo Padovan 	if (lmp_ssp_capable(hdev)) {
56454d04dbbSJohan Hedberg 		if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
565d5859e22SJohan Hedberg 			u8 mode = 0x01;
56654d04dbbSJohan Hedberg 			hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE,
56754d04dbbSJohan Hedberg 				     sizeof(mode), &mode);
56854d04dbbSJohan Hedberg 		} else {
56954d04dbbSJohan Hedberg 			struct hci_cp_write_eir cp;
57054d04dbbSJohan Hedberg 
57154d04dbbSJohan Hedberg 			memset(hdev->eir, 0, sizeof(hdev->eir));
57254d04dbbSJohan Hedberg 			memset(&cp, 0, sizeof(cp));
57354d04dbbSJohan Hedberg 
57454d04dbbSJohan Hedberg 			hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
57554d04dbbSJohan Hedberg 		}
576d5859e22SJohan Hedberg 	}
577d5859e22SJohan Hedberg 
578d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
579d5859e22SJohan Hedberg 		hci_setup_inquiry_mode(hdev);
580d5859e22SJohan Hedberg 
581d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_INQ_TX_PWR)
582d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
583971e3a4bSAndre Guedes 
584971e3a4bSAndre Guedes 	if (hdev->features[7] & LMP_EXTFEATURES) {
585971e3a4bSAndre Guedes 		struct hci_cp_read_local_ext_features cp;
586971e3a4bSAndre Guedes 
587971e3a4bSAndre Guedes 		cp.page = 0x01;
58804124681SGustavo F. Padovan 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp),
58904124681SGustavo F. Padovan 			     &cp);
590971e3a4bSAndre Guedes 	}
591e6100a25SAndre Guedes 
59247990ea0SJohan Hedberg 	if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) {
59347990ea0SJohan Hedberg 		u8 enable = 1;
59404124681SGustavo F. Padovan 		hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable),
59504124681SGustavo F. Padovan 			     &enable);
59647990ea0SJohan Hedberg 	}
597d5859e22SJohan Hedberg }
598d5859e22SJohan Hedberg 
599a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
600a9de9248SMarcel Holtmann {
601a9de9248SMarcel Holtmann 	struct hci_rp_read_local_version *rp = (void *) skb->data;
6021143e5a6SMarcel Holtmann 
6039f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
6041143e5a6SMarcel Holtmann 
605a9de9248SMarcel Holtmann 	if (rp->status)
60628b8df77SAndrei Emeltchenko 		goto done;
6071143e5a6SMarcel Holtmann 
608a9de9248SMarcel Holtmann 	hdev->hci_ver = rp->hci_ver;
609e4e8e37cSMarcel Holtmann 	hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
610d5859e22SJohan Hedberg 	hdev->lmp_ver = rp->lmp_ver;
611e4e8e37cSMarcel Holtmann 	hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
612d5859e22SJohan Hedberg 	hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
6131da177e4SLinus Torvalds 
6149f1db00cSAndrei Emeltchenko 	BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name,
615807deac2SGustavo Padovan 	       hdev->manufacturer, hdev->hci_ver, hdev->hci_rev);
616d5859e22SJohan Hedberg 
617d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags))
618d5859e22SJohan Hedberg 		hci_setup(hdev);
61928b8df77SAndrei Emeltchenko 
62028b8df77SAndrei Emeltchenko done:
62128b8df77SAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_VERSION, rp->status);
622d5859e22SJohan Hedberg }
623d5859e22SJohan Hedberg 
624d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev)
625d5859e22SJohan Hedberg {
626035100c8SAndrei Emeltchenko 	struct hci_cp_write_def_link_policy cp;
627d5859e22SJohan Hedberg 	u16 link_policy = 0;
628d5859e22SJohan Hedberg 
6299f92ebf6SAndre Guedes 	if (lmp_rswitch_capable(hdev))
630d5859e22SJohan Hedberg 		link_policy |= HCI_LP_RSWITCH;
631d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_HOLD)
632d5859e22SJohan Hedberg 		link_policy |= HCI_LP_HOLD;
6336eded100SAndre Guedes 	if (lmp_sniff_capable(hdev))
634d5859e22SJohan Hedberg 		link_policy |= HCI_LP_SNIFF;
635d5859e22SJohan Hedberg 	if (hdev->features[1] & LMP_PARK)
636d5859e22SJohan Hedberg 		link_policy |= HCI_LP_PARK;
637d5859e22SJohan Hedberg 
638035100c8SAndrei Emeltchenko 	cp.policy = cpu_to_le16(link_policy);
639035100c8SAndrei Emeltchenko 	hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp);
6401da177e4SLinus Torvalds }
6411da177e4SLinus Torvalds 
6428fc9ced3SGustavo Padovan static void hci_cc_read_local_commands(struct hci_dev *hdev,
6438fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
644a9de9248SMarcel Holtmann {
645a9de9248SMarcel Holtmann 	struct hci_rp_read_local_commands *rp = (void *) skb->data;
646a9de9248SMarcel Holtmann 
6479f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
648a9de9248SMarcel Holtmann 
649a9de9248SMarcel Holtmann 	if (rp->status)
650d5859e22SJohan Hedberg 		goto done;
651a9de9248SMarcel Holtmann 
652a9de9248SMarcel Holtmann 	memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
653d5859e22SJohan Hedberg 
654d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
655d5859e22SJohan Hedberg 		hci_setup_link_policy(hdev);
656d5859e22SJohan Hedberg 
657d5859e22SJohan Hedberg done:
658d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
659a9de9248SMarcel Holtmann }
660a9de9248SMarcel Holtmann 
6618fc9ced3SGustavo Padovan static void hci_cc_read_local_features(struct hci_dev *hdev,
6628fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
663a9de9248SMarcel Holtmann {
664a9de9248SMarcel Holtmann 	struct hci_rp_read_local_features *rp = (void *) skb->data;
665a9de9248SMarcel Holtmann 
6669f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
667a9de9248SMarcel Holtmann 
668a9de9248SMarcel Holtmann 	if (rp->status)
669a9de9248SMarcel Holtmann 		return;
670a9de9248SMarcel Holtmann 
671a9de9248SMarcel Holtmann 	memcpy(hdev->features, rp->features, 8);
6721da177e4SLinus Torvalds 
6731da177e4SLinus Torvalds 	/* Adjust default settings according to features
6741da177e4SLinus Torvalds 	 * supported by device. */
675a9de9248SMarcel Holtmann 
6761da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_3SLOT)
6771da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
6781da177e4SLinus Torvalds 
6791da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_5SLOT)
6801da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
6811da177e4SLinus Torvalds 
6825b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV2) {
6831da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV2);
6845b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV2);
6855b7f9909SMarcel Holtmann 	}
6861da177e4SLinus Torvalds 
6875b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV3) {
6881da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV3);
6895b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV3);
6905b7f9909SMarcel Holtmann 	}
6915b7f9909SMarcel Holtmann 
69245db810fSAndre Guedes 	if (lmp_esco_capable(hdev))
6935b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV3);
6945b7f9909SMarcel Holtmann 
6955b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV4)
6965b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV4);
6975b7f9909SMarcel Holtmann 
6985b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV5)
6995b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV5);
7001da177e4SLinus Torvalds 
701efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_2M)
702efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV3);
703efc7688bSMarcel Holtmann 
704efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_3M)
705efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_3EV3);
706efc7688bSMarcel Holtmann 
707efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_3S_ESCO)
708efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
709efc7688bSMarcel Holtmann 
710a9de9248SMarcel Holtmann 	BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
711a9de9248SMarcel Holtmann 	       hdev->features[0], hdev->features[1],
712a9de9248SMarcel Holtmann 	       hdev->features[2], hdev->features[3],
713a9de9248SMarcel Holtmann 	       hdev->features[4], hdev->features[5],
714a9de9248SMarcel Holtmann 	       hdev->features[6], hdev->features[7]);
7151da177e4SLinus Torvalds }
7161da177e4SLinus Torvalds 
7178f984dfaSJohan Hedberg static void hci_set_le_support(struct hci_dev *hdev)
7188f984dfaSJohan Hedberg {
7198f984dfaSJohan Hedberg 	struct hci_cp_write_le_host_supported cp;
7208f984dfaSJohan Hedberg 
7218f984dfaSJohan Hedberg 	memset(&cp, 0, sizeof(cp));
7228f984dfaSJohan Hedberg 
7239d42820fSMarcel Holtmann 	if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
7248f984dfaSJohan Hedberg 		cp.le = 1;
7258f984dfaSJohan Hedberg 		cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
7268f984dfaSJohan Hedberg 	}
7278f984dfaSJohan Hedberg 
7288f984dfaSJohan Hedberg 	if (cp.le != !!(hdev->host_features[0] & LMP_HOST_LE))
72904124681SGustavo F. Padovan 		hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp),
73004124681SGustavo F. Padovan 			     &cp);
7318f984dfaSJohan Hedberg }
7328f984dfaSJohan Hedberg 
733971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
734971e3a4bSAndre Guedes 					   struct sk_buff *skb)
735971e3a4bSAndre Guedes {
736971e3a4bSAndre Guedes 	struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
737971e3a4bSAndre Guedes 
7389f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
739971e3a4bSAndre Guedes 
740971e3a4bSAndre Guedes 	if (rp->status)
7418f984dfaSJohan Hedberg 		goto done;
742971e3a4bSAndre Guedes 
743b5b32b65SAndre Guedes 	switch (rp->page) {
744b5b32b65SAndre Guedes 	case 0:
745b5b32b65SAndre Guedes 		memcpy(hdev->features, rp->features, 8);
746b5b32b65SAndre Guedes 		break;
747b5b32b65SAndre Guedes 	case 1:
74859e29406SAndre Guedes 		memcpy(hdev->host_features, rp->features, 8);
749b5b32b65SAndre Guedes 		break;
750b5b32b65SAndre Guedes 	}
751971e3a4bSAndre Guedes 
752c383ddc4SAndre Guedes 	if (test_bit(HCI_INIT, &hdev->flags) && lmp_le_capable(hdev))
7538f984dfaSJohan Hedberg 		hci_set_le_support(hdev);
7548f984dfaSJohan Hedberg 
7558f984dfaSJohan Hedberg done:
756971e3a4bSAndre Guedes 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
757971e3a4bSAndre Guedes }
758971e3a4bSAndre Guedes 
7591e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
7601e89cffbSAndrei Emeltchenko 					  struct sk_buff *skb)
7611e89cffbSAndrei Emeltchenko {
7621e89cffbSAndrei Emeltchenko 	struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
7631e89cffbSAndrei Emeltchenko 
7649f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
7651e89cffbSAndrei Emeltchenko 
7661e89cffbSAndrei Emeltchenko 	if (rp->status)
7671e89cffbSAndrei Emeltchenko 		return;
7681e89cffbSAndrei Emeltchenko 
7691e89cffbSAndrei Emeltchenko 	hdev->flow_ctl_mode = rp->mode;
7701e89cffbSAndrei Emeltchenko 
7711e89cffbSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
7721e89cffbSAndrei Emeltchenko }
7731e89cffbSAndrei Emeltchenko 
774a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
775a9de9248SMarcel Holtmann {
776a9de9248SMarcel Holtmann 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
777a9de9248SMarcel Holtmann 
7789f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
779a9de9248SMarcel Holtmann 
780a9de9248SMarcel Holtmann 	if (rp->status)
781a9de9248SMarcel Holtmann 		return;
782a9de9248SMarcel Holtmann 
783a9de9248SMarcel Holtmann 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
784a9de9248SMarcel Holtmann 	hdev->sco_mtu  = rp->sco_mtu;
785a9de9248SMarcel Holtmann 	hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
786a9de9248SMarcel Holtmann 	hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
787da1f5198SMarcel Holtmann 
788da1f5198SMarcel Holtmann 	if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
789da1f5198SMarcel Holtmann 		hdev->sco_mtu  = 64;
790da1f5198SMarcel Holtmann 		hdev->sco_pkts = 8;
791da1f5198SMarcel Holtmann 	}
792da1f5198SMarcel Holtmann 
793da1f5198SMarcel Holtmann 	hdev->acl_cnt = hdev->acl_pkts;
794da1f5198SMarcel Holtmann 	hdev->sco_cnt = hdev->sco_pkts;
7951da177e4SLinus Torvalds 
796807deac2SGustavo Padovan 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
797807deac2SGustavo Padovan 	       hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
7981da177e4SLinus Torvalds }
7991da177e4SLinus Torvalds 
800a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
801a9de9248SMarcel Holtmann {
802a9de9248SMarcel Holtmann 	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
8031da177e4SLinus Torvalds 
8049f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
805a9de9248SMarcel Holtmann 
806a9de9248SMarcel Holtmann 	if (!rp->status)
807a9de9248SMarcel Holtmann 		bacpy(&hdev->bdaddr, &rp->bdaddr);
808a9de9248SMarcel Holtmann 
80923bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
81023bb5763SJohan Hedberg }
81123bb5763SJohan Hedberg 
812350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev,
813350ee4cfSAndrei Emeltchenko 					struct sk_buff *skb)
814350ee4cfSAndrei Emeltchenko {
815350ee4cfSAndrei Emeltchenko 	struct hci_rp_read_data_block_size *rp = (void *) skb->data;
816350ee4cfSAndrei Emeltchenko 
8179f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
818350ee4cfSAndrei Emeltchenko 
819350ee4cfSAndrei Emeltchenko 	if (rp->status)
820350ee4cfSAndrei Emeltchenko 		return;
821350ee4cfSAndrei Emeltchenko 
822350ee4cfSAndrei Emeltchenko 	hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
823350ee4cfSAndrei Emeltchenko 	hdev->block_len = __le16_to_cpu(rp->block_len);
824350ee4cfSAndrei Emeltchenko 	hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
825350ee4cfSAndrei Emeltchenko 
826350ee4cfSAndrei Emeltchenko 	hdev->block_cnt = hdev->num_blocks;
827350ee4cfSAndrei Emeltchenko 
828350ee4cfSAndrei Emeltchenko 	BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
829350ee4cfSAndrei Emeltchenko 	       hdev->block_cnt, hdev->block_len);
830350ee4cfSAndrei Emeltchenko 
831350ee4cfSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
832350ee4cfSAndrei Emeltchenko }
833350ee4cfSAndrei Emeltchenko 
83423bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
83523bb5763SJohan Hedberg {
83623bb5763SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
83723bb5763SJohan Hedberg 
8389f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
83923bb5763SJohan Hedberg 
84023bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
8411da177e4SLinus Torvalds }
8421da177e4SLinus Torvalds 
843928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
844928abaa7SAndrei Emeltchenko 				       struct sk_buff *skb)
845928abaa7SAndrei Emeltchenko {
846928abaa7SAndrei Emeltchenko 	struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
847928abaa7SAndrei Emeltchenko 
8489f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
849928abaa7SAndrei Emeltchenko 
850928abaa7SAndrei Emeltchenko 	if (rp->status)
8518e2a0d92SAndrei Emeltchenko 		goto a2mp_rsp;
852928abaa7SAndrei Emeltchenko 
853928abaa7SAndrei Emeltchenko 	hdev->amp_status = rp->amp_status;
854928abaa7SAndrei Emeltchenko 	hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
855928abaa7SAndrei Emeltchenko 	hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
856928abaa7SAndrei Emeltchenko 	hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
857928abaa7SAndrei Emeltchenko 	hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
858928abaa7SAndrei Emeltchenko 	hdev->amp_type = rp->amp_type;
859928abaa7SAndrei Emeltchenko 	hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
860928abaa7SAndrei Emeltchenko 	hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
861928abaa7SAndrei Emeltchenko 	hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
862928abaa7SAndrei Emeltchenko 	hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
863928abaa7SAndrei Emeltchenko 
864928abaa7SAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
8658e2a0d92SAndrei Emeltchenko 
8668e2a0d92SAndrei Emeltchenko a2mp_rsp:
8678e2a0d92SAndrei Emeltchenko 	a2mp_send_getinfo_rsp(hdev);
868928abaa7SAndrei Emeltchenko }
869928abaa7SAndrei Emeltchenko 
870903e4541SAndrei Emeltchenko static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev,
871903e4541SAndrei Emeltchenko 					struct sk_buff *skb)
872903e4541SAndrei Emeltchenko {
873903e4541SAndrei Emeltchenko 	struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data;
874903e4541SAndrei Emeltchenko 	struct amp_assoc *assoc = &hdev->loc_assoc;
875903e4541SAndrei Emeltchenko 	size_t rem_len, frag_len;
876903e4541SAndrei Emeltchenko 
877903e4541SAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
878903e4541SAndrei Emeltchenko 
879903e4541SAndrei Emeltchenko 	if (rp->status)
880903e4541SAndrei Emeltchenko 		goto a2mp_rsp;
881903e4541SAndrei Emeltchenko 
882903e4541SAndrei Emeltchenko 	frag_len = skb->len - sizeof(*rp);
883903e4541SAndrei Emeltchenko 	rem_len = __le16_to_cpu(rp->rem_len);
884903e4541SAndrei Emeltchenko 
885903e4541SAndrei Emeltchenko 	if (rem_len > frag_len) {
886903e4541SAndrei Emeltchenko 		BT_DBG("frag_len %d rem_len %d", frag_len, rem_len);
887903e4541SAndrei Emeltchenko 
888903e4541SAndrei Emeltchenko 		memcpy(assoc->data + assoc->offset, rp->frag, frag_len);
889903e4541SAndrei Emeltchenko 		assoc->offset += frag_len;
890903e4541SAndrei Emeltchenko 
891903e4541SAndrei Emeltchenko 		/* Read other fragments */
892903e4541SAndrei Emeltchenko 		amp_read_loc_assoc_frag(hdev, rp->phy_handle);
893903e4541SAndrei Emeltchenko 
894903e4541SAndrei Emeltchenko 		return;
895903e4541SAndrei Emeltchenko 	}
896903e4541SAndrei Emeltchenko 
897903e4541SAndrei Emeltchenko 	memcpy(assoc->data + assoc->offset, rp->frag, rem_len);
898903e4541SAndrei Emeltchenko 	assoc->len = assoc->offset + rem_len;
899903e4541SAndrei Emeltchenko 	assoc->offset = 0;
900903e4541SAndrei Emeltchenko 
901903e4541SAndrei Emeltchenko a2mp_rsp:
902903e4541SAndrei Emeltchenko 	/* Send A2MP Rsp when all fragments are received */
903903e4541SAndrei Emeltchenko 	a2mp_send_getampassoc_rsp(hdev, rp->status);
9049495b2eeSAndrei Emeltchenko 	a2mp_send_create_phy_link_req(hdev, rp->status);
905903e4541SAndrei Emeltchenko }
906903e4541SAndrei Emeltchenko 
907b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
908b0916ea0SJohan Hedberg 					  struct sk_buff *skb)
909b0916ea0SJohan Hedberg {
910b0916ea0SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
911b0916ea0SJohan Hedberg 
9129f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
913b0916ea0SJohan Hedberg 
914b0916ea0SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
915b0916ea0SJohan Hedberg }
916b0916ea0SJohan Hedberg 
917d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
918d5859e22SJohan Hedberg {
919d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
920d5859e22SJohan Hedberg 
9219f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
922d5859e22SJohan Hedberg 
923d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
924d5859e22SJohan Hedberg }
925d5859e22SJohan Hedberg 
926d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
927d5859e22SJohan Hedberg 				      struct sk_buff *skb)
928d5859e22SJohan Hedberg {
929d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
930d5859e22SJohan Hedberg 
9319f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
932d5859e22SJohan Hedberg 
933d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
934d5859e22SJohan Hedberg }
935d5859e22SJohan Hedberg 
936d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
937d5859e22SJohan Hedberg 					 struct sk_buff *skb)
938d5859e22SJohan Hedberg {
93991c4e9b1SMarcel Holtmann 	struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
940d5859e22SJohan Hedberg 
9419f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
942d5859e22SJohan Hedberg 
94391c4e9b1SMarcel Holtmann 	if (!rp->status)
94491c4e9b1SMarcel Holtmann 		hdev->inq_tx_power = rp->tx_power;
94591c4e9b1SMarcel Holtmann 
94691c4e9b1SMarcel Holtmann 	hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, rp->status);
947d5859e22SJohan Hedberg }
948d5859e22SJohan Hedberg 
949d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
950d5859e22SJohan Hedberg {
951d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
952d5859e22SJohan Hedberg 
9539f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
954d5859e22SJohan Hedberg 
955d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
956d5859e22SJohan Hedberg }
957d5859e22SJohan Hedberg 
958980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
959980e1a53SJohan Hedberg {
960980e1a53SJohan Hedberg 	struct hci_rp_pin_code_reply *rp = (void *) skb->data;
961980e1a53SJohan Hedberg 	struct hci_cp_pin_code_reply *cp;
962980e1a53SJohan Hedberg 	struct hci_conn *conn;
963980e1a53SJohan Hedberg 
9649f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
965980e1a53SJohan Hedberg 
96656e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
96756e5cb86SJohan Hedberg 
968a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
969744cf19eSJohan Hedberg 		mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
970980e1a53SJohan Hedberg 
971fa1bd918SMikel Astiz 	if (rp->status)
97256e5cb86SJohan Hedberg 		goto unlock;
973980e1a53SJohan Hedberg 
974980e1a53SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
975980e1a53SJohan Hedberg 	if (!cp)
97656e5cb86SJohan Hedberg 		goto unlock;
977980e1a53SJohan Hedberg 
978980e1a53SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
979980e1a53SJohan Hedberg 	if (conn)
980980e1a53SJohan Hedberg 		conn->pin_length = cp->pin_len;
98156e5cb86SJohan Hedberg 
98256e5cb86SJohan Hedberg unlock:
98356e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
984980e1a53SJohan Hedberg }
985980e1a53SJohan Hedberg 
986980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
987980e1a53SJohan Hedberg {
988980e1a53SJohan Hedberg 	struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
989980e1a53SJohan Hedberg 
9909f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
991980e1a53SJohan Hedberg 
99256e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
99356e5cb86SJohan Hedberg 
994a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
995744cf19eSJohan Hedberg 		mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
996980e1a53SJohan Hedberg 						 rp->status);
99756e5cb86SJohan Hedberg 
99856e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
999980e1a53SJohan Hedberg }
100056e5cb86SJohan Hedberg 
10016ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
10026ed58ec5SVille Tervo 				       struct sk_buff *skb)
10036ed58ec5SVille Tervo {
10046ed58ec5SVille Tervo 	struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
10056ed58ec5SVille Tervo 
10069f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
10076ed58ec5SVille Tervo 
10086ed58ec5SVille Tervo 	if (rp->status)
10096ed58ec5SVille Tervo 		return;
10106ed58ec5SVille Tervo 
10116ed58ec5SVille Tervo 	hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
10126ed58ec5SVille Tervo 	hdev->le_pkts = rp->le_max_pkt;
10136ed58ec5SVille Tervo 
10146ed58ec5SVille Tervo 	hdev->le_cnt = hdev->le_pkts;
10156ed58ec5SVille Tervo 
10166ed58ec5SVille Tervo 	BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
10176ed58ec5SVille Tervo 
10186ed58ec5SVille Tervo 	hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
10196ed58ec5SVille Tervo }
1020980e1a53SJohan Hedberg 
1021a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
1022a5c29683SJohan Hedberg {
1023a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1024a5c29683SJohan Hedberg 
10259f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1026a5c29683SJohan Hedberg 
102756e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
102856e5cb86SJohan Hedberg 
1029a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
103004124681SGustavo F. Padovan 		mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
103104124681SGustavo F. Padovan 						 rp->status);
103256e5cb86SJohan Hedberg 
103356e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1034a5c29683SJohan Hedberg }
1035a5c29683SJohan Hedberg 
1036a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
1037a5c29683SJohan Hedberg 					  struct sk_buff *skb)
1038a5c29683SJohan Hedberg {
1039a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1040a5c29683SJohan Hedberg 
10419f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1042a5c29683SJohan Hedberg 
104356e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
104456e5cb86SJohan Hedberg 
1045a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1046744cf19eSJohan Hedberg 		mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
104704124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
104856e5cb86SJohan Hedberg 
104956e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1050a5c29683SJohan Hedberg }
1051a5c29683SJohan Hedberg 
10521143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
10531143d458SBrian Gix {
10541143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
10551143d458SBrian Gix 
10569f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
10571143d458SBrian Gix 
10581143d458SBrian Gix 	hci_dev_lock(hdev);
10591143d458SBrian Gix 
1060a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1061272d90dfSJohan Hedberg 		mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
1062272d90dfSJohan Hedberg 						 0, rp->status);
10631143d458SBrian Gix 
10641143d458SBrian Gix 	hci_dev_unlock(hdev);
10651143d458SBrian Gix }
10661143d458SBrian Gix 
10671143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
10681143d458SBrian Gix 					  struct sk_buff *skb)
10691143d458SBrian Gix {
10701143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
10711143d458SBrian Gix 
10729f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
10731143d458SBrian Gix 
10741143d458SBrian Gix 	hci_dev_lock(hdev);
10751143d458SBrian Gix 
1076a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
10771143d458SBrian Gix 		mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
107804124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
10791143d458SBrian Gix 
10801143d458SBrian Gix 	hci_dev_unlock(hdev);
10811143d458SBrian Gix }
10821143d458SBrian Gix 
1083c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
1084c35938b2SSzymon Janc 					     struct sk_buff *skb)
1085c35938b2SSzymon Janc {
1086c35938b2SSzymon Janc 	struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
1087c35938b2SSzymon Janc 
10889f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1089c35938b2SSzymon Janc 
109056e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1091744cf19eSJohan Hedberg 	mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
1092c35938b2SSzymon Janc 						rp->randomizer, rp->status);
109356e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1094c35938b2SSzymon Janc }
1095c35938b2SSzymon Janc 
109607f7fa5dSAndre Guedes static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
109707f7fa5dSAndre Guedes {
109807f7fa5dSAndre Guedes 	__u8 status = *((__u8 *) skb->data);
109907f7fa5dSAndre Guedes 
11009f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
11017ba8b4beSAndre Guedes 
11027ba8b4beSAndre Guedes 	hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status);
11033fd24153SAndre Guedes 
11043fd24153SAndre Guedes 	if (status) {
11053fd24153SAndre Guedes 		hci_dev_lock(hdev);
11063fd24153SAndre Guedes 		mgmt_start_discovery_failed(hdev, status);
11073fd24153SAndre Guedes 		hci_dev_unlock(hdev);
11083fd24153SAndre Guedes 		return;
11093fd24153SAndre Guedes 	}
111007f7fa5dSAndre Guedes }
111107f7fa5dSAndre Guedes 
1112eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
1113eb9d91f5SAndre Guedes 				      struct sk_buff *skb)
1114eb9d91f5SAndre Guedes {
1115eb9d91f5SAndre Guedes 	struct hci_cp_le_set_scan_enable *cp;
1116eb9d91f5SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1117eb9d91f5SAndre Guedes 
11189f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1119eb9d91f5SAndre Guedes 
1120eb9d91f5SAndre Guedes 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1121eb9d91f5SAndre Guedes 	if (!cp)
1122eb9d91f5SAndre Guedes 		return;
1123eb9d91f5SAndre Guedes 
112468a8aea4SAndrei Emeltchenko 	switch (cp->enable) {
112568a8aea4SAndrei Emeltchenko 	case LE_SCANNING_ENABLED:
11267ba8b4beSAndre Guedes 		hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status);
11277ba8b4beSAndre Guedes 
11283fd24153SAndre Guedes 		if (status) {
11293fd24153SAndre Guedes 			hci_dev_lock(hdev);
11303fd24153SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
11313fd24153SAndre Guedes 			hci_dev_unlock(hdev);
11327ba8b4beSAndre Guedes 			return;
11333fd24153SAndre Guedes 		}
11347ba8b4beSAndre Guedes 
1135d23264a8SAndre Guedes 		set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1136d23264a8SAndre Guedes 
1137a8f13c8cSAndre Guedes 		hci_dev_lock(hdev);
1138343f935bSAndre Guedes 		hci_discovery_set_state(hdev, DISCOVERY_FINDING);
1139a8f13c8cSAndre Guedes 		hci_dev_unlock(hdev);
114068a8aea4SAndrei Emeltchenko 		break;
114168a8aea4SAndrei Emeltchenko 
114268a8aea4SAndrei Emeltchenko 	case LE_SCANNING_DISABLED:
1143c9ecc48eSAndre Guedes 		if (status) {
1144c9ecc48eSAndre Guedes 			hci_dev_lock(hdev);
1145c9ecc48eSAndre Guedes 			mgmt_stop_discovery_failed(hdev, status);
1146c9ecc48eSAndre Guedes 			hci_dev_unlock(hdev);
11477ba8b4beSAndre Guedes 			return;
1148c9ecc48eSAndre Guedes 		}
11497ba8b4beSAndre Guedes 
1150d23264a8SAndre Guedes 		clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1151d23264a8SAndre Guedes 
1152bc3dd33cSAndre Guedes 		if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
1153bc3dd33cSAndre Guedes 		    hdev->discovery.state == DISCOVERY_FINDING) {
11545e0452c0SAndre Guedes 			mgmt_interleaved_discovery(hdev);
11555e0452c0SAndre Guedes 		} else {
1156c599008fSAndre Guedes 			hci_dev_lock(hdev);
1157c599008fSAndre Guedes 			hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1158c599008fSAndre Guedes 			hci_dev_unlock(hdev);
11595e0452c0SAndre Guedes 		}
1160c599008fSAndre Guedes 
116168a8aea4SAndrei Emeltchenko 		break;
116268a8aea4SAndrei Emeltchenko 
116368a8aea4SAndrei Emeltchenko 	default:
116468a8aea4SAndrei Emeltchenko 		BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
116568a8aea4SAndrei Emeltchenko 		break;
116635815085SAndre Guedes 	}
1167eb9d91f5SAndre Guedes }
1168eb9d91f5SAndre Guedes 
1169a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1170a7a595f6SVinicius Costa Gomes {
1171a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1172a7a595f6SVinicius Costa Gomes 
11739f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1174a7a595f6SVinicius Costa Gomes 
1175a7a595f6SVinicius Costa Gomes 	if (rp->status)
1176a7a595f6SVinicius Costa Gomes 		return;
1177a7a595f6SVinicius Costa Gomes 
1178a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1179a7a595f6SVinicius Costa Gomes }
1180a7a595f6SVinicius Costa Gomes 
1181a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1182a7a595f6SVinicius Costa Gomes {
1183a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1184a7a595f6SVinicius Costa Gomes 
11859f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1186a7a595f6SVinicius Costa Gomes 
1187a7a595f6SVinicius Costa Gomes 	if (rp->status)
1188a7a595f6SVinicius Costa Gomes 		return;
1189a7a595f6SVinicius Costa Gomes 
1190a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1191a7a595f6SVinicius Costa Gomes }
1192a7a595f6SVinicius Costa Gomes 
11936039aa73SGustavo Padovan static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1194f9b49306SAndre Guedes 					   struct sk_buff *skb)
1195f9b49306SAndre Guedes {
119606199cf8SJohan Hedberg 	struct hci_cp_write_le_host_supported *sent;
1197f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1198f9b49306SAndre Guedes 
11999f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1200f9b49306SAndre Guedes 
120106199cf8SJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
12028f984dfaSJohan Hedberg 	if (!sent)
1203f9b49306SAndre Guedes 		return;
1204f9b49306SAndre Guedes 
12058f984dfaSJohan Hedberg 	if (!status) {
12068f984dfaSJohan Hedberg 		if (sent->le)
12078f984dfaSJohan Hedberg 			hdev->host_features[0] |= LMP_HOST_LE;
12088f984dfaSJohan Hedberg 		else
12098f984dfaSJohan Hedberg 			hdev->host_features[0] &= ~LMP_HOST_LE;
12108f984dfaSJohan Hedberg 	}
12118f984dfaSJohan Hedberg 
12128f984dfaSJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
12138f984dfaSJohan Hedberg 	    !test_bit(HCI_INIT, &hdev->flags))
12148f984dfaSJohan Hedberg 		mgmt_le_enable_complete(hdev, sent->le, status);
12158f984dfaSJohan Hedberg 
12168f984dfaSJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status);
1217f9b49306SAndre Guedes }
1218f9b49306SAndre Guedes 
121993c284eeSAndrei Emeltchenko static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
122093c284eeSAndrei Emeltchenko 					  struct sk_buff *skb)
122193c284eeSAndrei Emeltchenko {
122293c284eeSAndrei Emeltchenko 	struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data;
122393c284eeSAndrei Emeltchenko 
122493c284eeSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
122593c284eeSAndrei Emeltchenko 	       hdev->name, rp->status, rp->phy_handle);
122693c284eeSAndrei Emeltchenko 
122793c284eeSAndrei Emeltchenko 	if (rp->status)
122893c284eeSAndrei Emeltchenko 		return;
122993c284eeSAndrei Emeltchenko 
123093c284eeSAndrei Emeltchenko 	amp_write_rem_assoc_continue(hdev, rp->phy_handle);
123193c284eeSAndrei Emeltchenko }
123293c284eeSAndrei Emeltchenko 
12336039aa73SGustavo Padovan static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1234a9de9248SMarcel Holtmann {
12359f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1236a9de9248SMarcel Holtmann 
1237a9de9248SMarcel Holtmann 	if (status) {
123823bb5763SJohan Hedberg 		hci_req_complete(hdev, HCI_OP_INQUIRY, status);
1239a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
124056e5cb86SJohan Hedberg 		hci_dev_lock(hdev);
1241a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
12427a135109SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
124356e5cb86SJohan Hedberg 		hci_dev_unlock(hdev);
1244314b2381SJohan Hedberg 		return;
1245314b2381SJohan Hedberg 	}
1246314b2381SJohan Hedberg 
124789352e7dSAndre Guedes 	set_bit(HCI_INQUIRY, &hdev->flags);
124889352e7dSAndre Guedes 
124956e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1250343f935bSAndre Guedes 	hci_discovery_set_state(hdev, DISCOVERY_FINDING);
125156e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1252a9de9248SMarcel Holtmann }
1253a9de9248SMarcel Holtmann 
12546039aa73SGustavo Padovan static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
12551da177e4SLinus Torvalds {
1256a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
12571da177e4SLinus Torvalds 	struct hci_conn *conn;
12581da177e4SLinus Torvalds 
12599f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1260a9de9248SMarcel Holtmann 
1261a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
12621da177e4SLinus Torvalds 	if (!cp)
12631da177e4SLinus Torvalds 		return;
12641da177e4SLinus Torvalds 
12651da177e4SLinus Torvalds 	hci_dev_lock(hdev);
12661da177e4SLinus Torvalds 
12671da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
12681da177e4SLinus Torvalds 
12699f1db00cSAndrei Emeltchenko 	BT_DBG("%s bdaddr %s hcon %p", hdev->name, batostr(&cp->bdaddr), conn);
12701da177e4SLinus Torvalds 
12711da177e4SLinus Torvalds 	if (status) {
12721da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
12734c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
12741da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
12751da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
12761da177e4SLinus Torvalds 				hci_conn_del(conn);
12774c67bc74SMarcel Holtmann 			} else
12784c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
12791da177e4SLinus Torvalds 		}
12801da177e4SLinus Torvalds 	} else {
12811da177e4SLinus Torvalds 		if (!conn) {
12821da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
12831da177e4SLinus Torvalds 			if (conn) {
1284a0c808b3SJohan Hedberg 				conn->out = true;
12851da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
12861da177e4SLinus Torvalds 			} else
1287893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
12881da177e4SLinus Torvalds 		}
12891da177e4SLinus Torvalds 	}
12901da177e4SLinus Torvalds 
12911da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
12921da177e4SLinus Torvalds }
12931da177e4SLinus Torvalds 
1294a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
12951da177e4SLinus Torvalds {
1296a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
12971da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
12981da177e4SLinus Torvalds 	__u16 handle;
12991da177e4SLinus Torvalds 
13009f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1301b6a0dc82SMarcel Holtmann 
1302a9de9248SMarcel Holtmann 	if (!status)
1303a9de9248SMarcel Holtmann 		return;
1304a9de9248SMarcel Holtmann 
1305a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
13061da177e4SLinus Torvalds 	if (!cp)
1307a9de9248SMarcel Holtmann 		return;
13081da177e4SLinus Torvalds 
13091da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
13101da177e4SLinus Torvalds 
13119f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
13121da177e4SLinus Torvalds 
13131da177e4SLinus Torvalds 	hci_dev_lock(hdev);
13141da177e4SLinus Torvalds 
13151da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
13165a08ecceSAndrei Emeltchenko 	if (acl) {
13175a08ecceSAndrei Emeltchenko 		sco = acl->link;
13185a08ecceSAndrei Emeltchenko 		if (sco) {
13191da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
13201da177e4SLinus Torvalds 
13211da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
13221da177e4SLinus Torvalds 			hci_conn_del(sco);
13231da177e4SLinus Torvalds 		}
13245a08ecceSAndrei Emeltchenko 	}
13251da177e4SLinus Torvalds 
13261da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
13271da177e4SLinus Torvalds }
13281da177e4SLinus Torvalds 
1329f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1330f8558555SMarcel Holtmann {
1331f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1332f8558555SMarcel Holtmann 	struct hci_conn *conn;
1333f8558555SMarcel Holtmann 
13349f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1335f8558555SMarcel Holtmann 
1336f8558555SMarcel Holtmann 	if (!status)
1337f8558555SMarcel Holtmann 		return;
1338f8558555SMarcel Holtmann 
1339f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1340f8558555SMarcel Holtmann 	if (!cp)
1341f8558555SMarcel Holtmann 		return;
1342f8558555SMarcel Holtmann 
1343f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1344f8558555SMarcel Holtmann 
1345f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1346f8558555SMarcel Holtmann 	if (conn) {
1347f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1348f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1349f8558555SMarcel Holtmann 			hci_conn_put(conn);
1350f8558555SMarcel Holtmann 		}
1351f8558555SMarcel Holtmann 	}
1352f8558555SMarcel Holtmann 
1353f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1354f8558555SMarcel Holtmann }
1355f8558555SMarcel Holtmann 
1356f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1357f8558555SMarcel Holtmann {
1358f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1359f8558555SMarcel Holtmann 	struct hci_conn *conn;
1360f8558555SMarcel Holtmann 
13619f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1362f8558555SMarcel Holtmann 
1363f8558555SMarcel Holtmann 	if (!status)
1364f8558555SMarcel Holtmann 		return;
1365f8558555SMarcel Holtmann 
1366f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1367f8558555SMarcel Holtmann 	if (!cp)
1368f8558555SMarcel Holtmann 		return;
1369f8558555SMarcel Holtmann 
1370f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1371f8558555SMarcel Holtmann 
1372f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1373f8558555SMarcel Holtmann 	if (conn) {
1374f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1375f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1376f8558555SMarcel Holtmann 			hci_conn_put(conn);
1377f8558555SMarcel Holtmann 		}
1378f8558555SMarcel Holtmann 	}
1379f8558555SMarcel Holtmann 
1380f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1381f8558555SMarcel Holtmann }
1382f8558555SMarcel Holtmann 
1383127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1384392599b9SJohan Hedberg 				    struct hci_conn *conn)
1385392599b9SJohan Hedberg {
1386392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1387392599b9SJohan Hedberg 		return 0;
1388392599b9SJohan Hedberg 
1389765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1390392599b9SJohan Hedberg 		return 0;
1391392599b9SJohan Hedberg 
1392392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1393e9bf2bf0SVinicius Costa Gomes 	 * devices with sec_level HIGH or if MITM protection is requested */
1394807deac2SGustavo Padovan 	if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
1395807deac2SGustavo Padovan 	    conn->pending_sec_level != BT_SECURITY_HIGH)
1396392599b9SJohan Hedberg 		return 0;
1397392599b9SJohan Hedberg 
1398392599b9SJohan Hedberg 	return 1;
1399392599b9SJohan Hedberg }
1400392599b9SJohan Hedberg 
14016039aa73SGustavo Padovan static int hci_resolve_name(struct hci_dev *hdev,
140200abfe44SGustavo F. Padovan 				   struct inquiry_entry *e)
140330dc78e1SJohan Hedberg {
140430dc78e1SJohan Hedberg 	struct hci_cp_remote_name_req cp;
140530dc78e1SJohan Hedberg 
140630dc78e1SJohan Hedberg 	memset(&cp, 0, sizeof(cp));
140730dc78e1SJohan Hedberg 
140830dc78e1SJohan Hedberg 	bacpy(&cp.bdaddr, &e->data.bdaddr);
140930dc78e1SJohan Hedberg 	cp.pscan_rep_mode = e->data.pscan_rep_mode;
141030dc78e1SJohan Hedberg 	cp.pscan_mode = e->data.pscan_mode;
141130dc78e1SJohan Hedberg 	cp.clock_offset = e->data.clock_offset;
141230dc78e1SJohan Hedberg 
141330dc78e1SJohan Hedberg 	return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
141430dc78e1SJohan Hedberg }
141530dc78e1SJohan Hedberg 
1416b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev)
141730dc78e1SJohan Hedberg {
141830dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
141930dc78e1SJohan Hedberg 	struct inquiry_entry *e;
142030dc78e1SJohan Hedberg 
1421b644ba33SJohan Hedberg 	if (list_empty(&discov->resolve))
1422b644ba33SJohan Hedberg 		return false;
1423b644ba33SJohan Hedberg 
1424b644ba33SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1425c810089cSRam Malovany 	if (!e)
1426c810089cSRam Malovany 		return false;
1427c810089cSRam Malovany 
1428b644ba33SJohan Hedberg 	if (hci_resolve_name(hdev, e) == 0) {
1429b644ba33SJohan Hedberg 		e->name_state = NAME_PENDING;
1430b644ba33SJohan Hedberg 		return true;
1431b644ba33SJohan Hedberg 	}
1432b644ba33SJohan Hedberg 
1433b644ba33SJohan Hedberg 	return false;
1434b644ba33SJohan Hedberg }
1435b644ba33SJohan Hedberg 
1436b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
1437b644ba33SJohan Hedberg 				   bdaddr_t *bdaddr, u8 *name, u8 name_len)
1438b644ba33SJohan Hedberg {
1439b644ba33SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
1440b644ba33SJohan Hedberg 	struct inquiry_entry *e;
1441b644ba33SJohan Hedberg 
1442b644ba33SJohan Hedberg 	if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
144304124681SGustavo F. Padovan 		mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
144404124681SGustavo F. Padovan 				      name_len, conn->dev_class);
1445b644ba33SJohan Hedberg 
1446b644ba33SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPED)
1447b644ba33SJohan Hedberg 		return;
1448b644ba33SJohan Hedberg 
144930dc78e1SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPING)
145030dc78e1SJohan Hedberg 		goto discov_complete;
145130dc78e1SJohan Hedberg 
145230dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_RESOLVING)
145330dc78e1SJohan Hedberg 		return;
145430dc78e1SJohan Hedberg 
145530dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
14567cc8380eSRam Malovany 	/* If the device was not found in a list of found devices names of which
14577cc8380eSRam Malovany 	 * are pending. there is no need to continue resolving a next name as it
14587cc8380eSRam Malovany 	 * will be done upon receiving another Remote Name Request Complete
14597cc8380eSRam Malovany 	 * Event */
14607cc8380eSRam Malovany 	if (!e)
14617cc8380eSRam Malovany 		return;
14627cc8380eSRam Malovany 
146330dc78e1SJohan Hedberg 	list_del(&e->list);
14647cc8380eSRam Malovany 	if (name) {
14657cc8380eSRam Malovany 		e->name_state = NAME_KNOWN;
1466b644ba33SJohan Hedberg 		mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1467b644ba33SJohan Hedberg 				 e->data.rssi, name, name_len);
1468c3e7c0d9SRam Malovany 	} else {
1469c3e7c0d9SRam Malovany 		e->name_state = NAME_NOT_KNOWN;
147030dc78e1SJohan Hedberg 	}
147130dc78e1SJohan Hedberg 
1472b644ba33SJohan Hedberg 	if (hci_resolve_next_name(hdev))
147330dc78e1SJohan Hedberg 		return;
147430dc78e1SJohan Hedberg 
147530dc78e1SJohan Hedberg discov_complete:
147630dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
147730dc78e1SJohan Hedberg }
147830dc78e1SJohan Hedberg 
1479a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
14801da177e4SLinus Torvalds {
1481127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1482127178d2SJohan Hedberg 	struct hci_conn *conn;
1483127178d2SJohan Hedberg 
14849f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1485127178d2SJohan Hedberg 
1486127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1487127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1488127178d2SJohan Hedberg 	if (!status)
1489127178d2SJohan Hedberg 		return;
1490127178d2SJohan Hedberg 
1491127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1492127178d2SJohan Hedberg 	if (!cp)
1493127178d2SJohan Hedberg 		return;
1494127178d2SJohan Hedberg 
1495127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1496127178d2SJohan Hedberg 
1497127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1498b644ba33SJohan Hedberg 
1499b644ba33SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1500b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1501b644ba33SJohan Hedberg 
150279c6c70cSJohan Hedberg 	if (!conn)
150379c6c70cSJohan Hedberg 		goto unlock;
150479c6c70cSJohan Hedberg 
150579c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
150679c6c70cSJohan Hedberg 		goto unlock;
150779c6c70cSJohan Hedberg 
150851a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1509127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1510127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1511127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1512127178d2SJohan Hedberg 	}
1513127178d2SJohan Hedberg 
151479c6c70cSJohan Hedberg unlock:
1515127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1516a9de9248SMarcel Holtmann }
15171da177e4SLinus Torvalds 
1518769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1519769be974SMarcel Holtmann {
1520769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1521769be974SMarcel Holtmann 	struct hci_conn *conn;
1522769be974SMarcel Holtmann 
15239f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1524769be974SMarcel Holtmann 
1525769be974SMarcel Holtmann 	if (!status)
1526769be974SMarcel Holtmann 		return;
1527769be974SMarcel Holtmann 
1528769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1529769be974SMarcel Holtmann 	if (!cp)
1530769be974SMarcel Holtmann 		return;
1531769be974SMarcel Holtmann 
1532769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1533769be974SMarcel Holtmann 
1534769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1535769be974SMarcel Holtmann 	if (conn) {
1536769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1537769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1538769be974SMarcel Holtmann 			hci_conn_put(conn);
1539769be974SMarcel Holtmann 		}
1540769be974SMarcel Holtmann 	}
1541769be974SMarcel Holtmann 
1542769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1543769be974SMarcel Holtmann }
1544769be974SMarcel Holtmann 
1545769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1546769be974SMarcel Holtmann {
1547769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1548769be974SMarcel Holtmann 	struct hci_conn *conn;
1549769be974SMarcel Holtmann 
15509f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1551769be974SMarcel Holtmann 
1552769be974SMarcel Holtmann 	if (!status)
1553769be974SMarcel Holtmann 		return;
1554769be974SMarcel Holtmann 
1555769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1556769be974SMarcel Holtmann 	if (!cp)
1557769be974SMarcel Holtmann 		return;
1558769be974SMarcel Holtmann 
1559769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1560769be974SMarcel Holtmann 
1561769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1562769be974SMarcel Holtmann 	if (conn) {
1563769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1564769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1565769be974SMarcel Holtmann 			hci_conn_put(conn);
1566769be974SMarcel Holtmann 		}
1567769be974SMarcel Holtmann 	}
1568769be974SMarcel Holtmann 
1569769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1570769be974SMarcel Holtmann }
1571769be974SMarcel Holtmann 
1572a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1573a9de9248SMarcel Holtmann {
1574b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1575b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1576b6a0dc82SMarcel Holtmann 	__u16 handle;
1577b6a0dc82SMarcel Holtmann 
15789f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1579b6a0dc82SMarcel Holtmann 
1580b6a0dc82SMarcel Holtmann 	if (!status)
1581b6a0dc82SMarcel Holtmann 		return;
1582b6a0dc82SMarcel Holtmann 
1583b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1584b6a0dc82SMarcel Holtmann 	if (!cp)
1585b6a0dc82SMarcel Holtmann 		return;
1586b6a0dc82SMarcel Holtmann 
1587b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1588b6a0dc82SMarcel Holtmann 
15899f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
1590b6a0dc82SMarcel Holtmann 
1591b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1592b6a0dc82SMarcel Holtmann 
1593b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
15945a08ecceSAndrei Emeltchenko 	if (acl) {
15955a08ecceSAndrei Emeltchenko 		sco = acl->link;
15965a08ecceSAndrei Emeltchenko 		if (sco) {
1597b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1598b6a0dc82SMarcel Holtmann 
1599b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1600b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1601b6a0dc82SMarcel Holtmann 		}
16025a08ecceSAndrei Emeltchenko 	}
1603b6a0dc82SMarcel Holtmann 
1604b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1605a9de9248SMarcel Holtmann }
1606a9de9248SMarcel Holtmann 
1607a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1608a9de9248SMarcel Holtmann {
1609a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
161004837f64SMarcel Holtmann 	struct hci_conn *conn;
161104837f64SMarcel Holtmann 
16129f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1613a9de9248SMarcel Holtmann 
1614a9de9248SMarcel Holtmann 	if (!status)
1615a9de9248SMarcel Holtmann 		return;
1616a9de9248SMarcel Holtmann 
1617a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
161804837f64SMarcel Holtmann 	if (!cp)
1619a9de9248SMarcel Holtmann 		return;
162004837f64SMarcel Holtmann 
162104837f64SMarcel Holtmann 	hci_dev_lock(hdev);
162204837f64SMarcel Holtmann 
162304837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1624e73439d8SMarcel Holtmann 	if (conn) {
162551a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
162604837f64SMarcel Holtmann 
162751a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1628e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1629e73439d8SMarcel Holtmann 	}
1630e73439d8SMarcel Holtmann 
163104837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
163204837f64SMarcel Holtmann }
163304837f64SMarcel Holtmann 
1634a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1635a9de9248SMarcel Holtmann {
1636a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
163704837f64SMarcel Holtmann 	struct hci_conn *conn;
163804837f64SMarcel Holtmann 
16399f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1640a9de9248SMarcel Holtmann 
1641a9de9248SMarcel Holtmann 	if (!status)
1642a9de9248SMarcel Holtmann 		return;
1643a9de9248SMarcel Holtmann 
1644a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
164504837f64SMarcel Holtmann 	if (!cp)
1646a9de9248SMarcel Holtmann 		return;
164704837f64SMarcel Holtmann 
164804837f64SMarcel Holtmann 	hci_dev_lock(hdev);
164904837f64SMarcel Holtmann 
165004837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1651e73439d8SMarcel Holtmann 	if (conn) {
165251a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
165304837f64SMarcel Holtmann 
165451a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1655e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1656e73439d8SMarcel Holtmann 	}
1657e73439d8SMarcel Holtmann 
165804837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
165904837f64SMarcel Holtmann }
166004837f64SMarcel Holtmann 
166188c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
166288c3df13SJohan Hedberg {
166388c3df13SJohan Hedberg 	struct hci_cp_disconnect *cp;
166488c3df13SJohan Hedberg 	struct hci_conn *conn;
166588c3df13SJohan Hedberg 
166688c3df13SJohan Hedberg 	if (!status)
166788c3df13SJohan Hedberg 		return;
166888c3df13SJohan Hedberg 
166988c3df13SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
167088c3df13SJohan Hedberg 	if (!cp)
167188c3df13SJohan Hedberg 		return;
167288c3df13SJohan Hedberg 
167388c3df13SJohan Hedberg 	hci_dev_lock(hdev);
167488c3df13SJohan Hedberg 
167588c3df13SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
167688c3df13SJohan Hedberg 	if (conn)
167788c3df13SJohan Hedberg 		mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
167888c3df13SJohan Hedberg 				       conn->dst_type, status);
167988c3df13SJohan Hedberg 
168088c3df13SJohan Hedberg 	hci_dev_unlock(hdev);
168188c3df13SJohan Hedberg }
168288c3df13SJohan Hedberg 
1683fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1684fcd89c09SVille Tervo {
1685fcd89c09SVille Tervo 	struct hci_conn *conn;
1686fcd89c09SVille Tervo 
16879f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1688fcd89c09SVille Tervo 
1689f00a06acSAndre Guedes 	if (status) {
1690fcd89c09SVille Tervo 		hci_dev_lock(hdev);
1691fcd89c09SVille Tervo 
16920c95ab78SAndre Guedes 		conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
1693f00a06acSAndre Guedes 		if (!conn) {
1694f00a06acSAndre Guedes 			hci_dev_unlock(hdev);
1695f00a06acSAndre Guedes 			return;
1696f00a06acSAndre Guedes 		}
1697fcd89c09SVille Tervo 
16980c95ab78SAndre Guedes 		BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&conn->dst),
1699fcd89c09SVille Tervo 		       conn);
1700fcd89c09SVille Tervo 
1701fcd89c09SVille Tervo 		conn->state = BT_CLOSED;
17020c95ab78SAndre Guedes 		mgmt_connect_failed(hdev, &conn->dst, conn->type,
1703328c9248SHemant Gupta 				    conn->dst_type, status);
1704fcd89c09SVille Tervo 		hci_proto_connect_cfm(conn, status);
1705fcd89c09SVille Tervo 		hci_conn_del(conn);
1706fcd89c09SVille Tervo 
1707fcd89c09SVille Tervo 		hci_dev_unlock(hdev);
1708fcd89c09SVille Tervo 	}
1709f00a06acSAndre Guedes }
1710fcd89c09SVille Tervo 
1711a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1712a7a595f6SVinicius Costa Gomes {
17139f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1714a7a595f6SVinicius Costa Gomes }
1715a7a595f6SVinicius Costa Gomes 
1716a02226d6SAndrei Emeltchenko static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
1717a02226d6SAndrei Emeltchenko {
171893c284eeSAndrei Emeltchenko 	struct hci_cp_create_phy_link *cp;
171993c284eeSAndrei Emeltchenko 
1720a02226d6SAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
172193c284eeSAndrei Emeltchenko 
172293c284eeSAndrei Emeltchenko 	if (status)
172393c284eeSAndrei Emeltchenko 		return;
172493c284eeSAndrei Emeltchenko 
172593c284eeSAndrei Emeltchenko 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
172693c284eeSAndrei Emeltchenko 	if (!cp)
172793c284eeSAndrei Emeltchenko 		return;
172893c284eeSAndrei Emeltchenko 
172993c284eeSAndrei Emeltchenko 	amp_write_remote_assoc(hdev, cp->phy_handle);
1730a02226d6SAndrei Emeltchenko }
1731a02226d6SAndrei Emeltchenko 
17326039aa73SGustavo Padovan static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
17331da177e4SLinus Torvalds {
17341da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
173530dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
173630dc78e1SJohan Hedberg 	struct inquiry_entry *e;
17371da177e4SLinus Torvalds 
17389f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
17391da177e4SLinus Torvalds 
174023bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY, status);
17416bd57416SMarcel Holtmann 
1742a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
174389352e7dSAndre Guedes 
174489352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
174589352e7dSAndre Guedes 		return;
174689352e7dSAndre Guedes 
1747a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
174830dc78e1SJohan Hedberg 		return;
174930dc78e1SJohan Hedberg 
175056e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
175130dc78e1SJohan Hedberg 
1752343f935bSAndre Guedes 	if (discov->state != DISCOVERY_FINDING)
175330dc78e1SJohan Hedberg 		goto unlock;
175430dc78e1SJohan Hedberg 
175530dc78e1SJohan Hedberg 	if (list_empty(&discov->resolve)) {
1756ff9ef578SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
175730dc78e1SJohan Hedberg 		goto unlock;
175830dc78e1SJohan Hedberg 	}
175930dc78e1SJohan Hedberg 
176030dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
176130dc78e1SJohan Hedberg 	if (e && hci_resolve_name(hdev, e) == 0) {
176230dc78e1SJohan Hedberg 		e->name_state = NAME_PENDING;
176330dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
176430dc78e1SJohan Hedberg 	} else {
176530dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
176630dc78e1SJohan Hedberg 	}
176730dc78e1SJohan Hedberg 
176830dc78e1SJohan Hedberg unlock:
176956e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
17701da177e4SLinus Torvalds }
17711da177e4SLinus Torvalds 
17726039aa73SGustavo Padovan static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
17731da177e4SLinus Torvalds {
177445bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1775a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
17761da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
17771da177e4SLinus Torvalds 
17781da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
17791da177e4SLinus Torvalds 
178045bb4bf0SMarcel Holtmann 	if (!num_rsp)
178145bb4bf0SMarcel Holtmann 		return;
178245bb4bf0SMarcel Holtmann 
17831519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
17841519cc17SAndre Guedes 		return;
17851519cc17SAndre Guedes 
17861da177e4SLinus Torvalds 	hci_dev_lock(hdev);
178745bb4bf0SMarcel Holtmann 
1788e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
1789388fc8faSJohan Hedberg 		bool name_known, ssp;
17903175405bSJohan Hedberg 
17911da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
17921da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
17931da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
17941da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
17951da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
17961da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
17971da177e4SLinus Torvalds 		data.rssi		= 0x00;
179841a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
17993175405bSJohan Hedberg 
1800388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
180148264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
180204124681SGustavo F. Padovan 				  info->dev_class, 0, !name_known, ssp, NULL,
180304124681SGustavo F. Padovan 				  0);
18041da177e4SLinus Torvalds 	}
180545bb4bf0SMarcel Holtmann 
18061da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
18071da177e4SLinus Torvalds }
18081da177e4SLinus Torvalds 
18096039aa73SGustavo Padovan static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
18101da177e4SLinus Torvalds {
1811a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
1812a9de9248SMarcel Holtmann 	struct hci_conn *conn;
18131da177e4SLinus Torvalds 
1814a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
181545bb4bf0SMarcel Holtmann 
18161da177e4SLinus Torvalds 	hci_dev_lock(hdev);
181745bb4bf0SMarcel Holtmann 
1818a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
18199499237aSMarcel Holtmann 	if (!conn) {
18209499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
18219499237aSMarcel Holtmann 			goto unlock;
18229499237aSMarcel Holtmann 
18239499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1824a9de9248SMarcel Holtmann 		if (!conn)
1825a9de9248SMarcel Holtmann 			goto unlock;
182645bb4bf0SMarcel Holtmann 
18279499237aSMarcel Holtmann 		conn->type = SCO_LINK;
18289499237aSMarcel Holtmann 	}
18299499237aSMarcel Holtmann 
1830a9de9248SMarcel Holtmann 	if (!ev->status) {
1831a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1832769be974SMarcel Holtmann 
1833769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1834769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
1835769be974SMarcel Holtmann 			hci_conn_hold(conn);
1836a9ea3ed9SSzymon Janc 
1837a9ea3ed9SSzymon Janc 			if (!conn->out && !hci_conn_ssp_enabled(conn) &&
1838a9ea3ed9SSzymon Janc 			    !hci_find_link_key(hdev, &ev->bdaddr))
1839a9ea3ed9SSzymon Janc 				conn->disc_timeout = HCI_PAIRING_TIMEOUT;
1840a9ea3ed9SSzymon Janc 			else
1841052b30b0SMarcel Holtmann 				conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1842769be974SMarcel Holtmann 		} else
1843a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
1844a9de9248SMarcel Holtmann 
18459eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
18467d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
18477d0db0a3SMarcel Holtmann 
1848a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1849a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1850a9de9248SMarcel Holtmann 
1851a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1852a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1853a9de9248SMarcel Holtmann 
1854a9de9248SMarcel Holtmann 		/* Get remote features */
1855a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1856a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1857a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1858769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1859769be974SMarcel Holtmann 				     sizeof(cp), &cp);
186045bb4bf0SMarcel Holtmann 		}
1861a9de9248SMarcel Holtmann 
1862a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1863d095c1ebSAndrei Emeltchenko 		if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
1864a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1865a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1866a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
186704124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
186804124681SGustavo F. Padovan 				     &cp);
1869a9de9248SMarcel Holtmann 		}
187017d5c04cSJohan Hedberg 	} else {
1871a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
187217d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
1873744cf19eSJohan Hedberg 			mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
187448264f06SJohan Hedberg 					    conn->dst_type, ev->status);
187517d5c04cSJohan Hedberg 	}
187645bb4bf0SMarcel Holtmann 
1877e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
1878e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
187945bb4bf0SMarcel Holtmann 
1880769be974SMarcel Holtmann 	if (ev->status) {
1881a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1882a9de9248SMarcel Holtmann 		hci_conn_del(conn);
1883c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
1884c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1885a9de9248SMarcel Holtmann 
1886a9de9248SMarcel Holtmann unlock:
18871da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
1888a9de9248SMarcel Holtmann 
1889a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
18901da177e4SLinus Torvalds }
18911da177e4SLinus Torvalds 
18926039aa73SGustavo Padovan static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
18931da177e4SLinus Torvalds {
1894a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
18951da177e4SLinus Torvalds 	int mask = hdev->link_mode;
18961da177e4SLinus Torvalds 
1897807deac2SGustavo Padovan 	BT_DBG("%s bdaddr %s type 0x%x", hdev->name, batostr(&ev->bdaddr),
1898807deac2SGustavo Padovan 	       ev->link_type);
18991da177e4SLinus Torvalds 
19001da177e4SLinus Torvalds 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
19011da177e4SLinus Torvalds 
1902138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
1903138d22efSSzymon Janc 	    !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
19041da177e4SLinus Torvalds 		/* Connection accepted */
1905c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
19061da177e4SLinus Torvalds 		struct hci_conn *conn;
19071da177e4SLinus Torvalds 
19081da177e4SLinus Torvalds 		hci_dev_lock(hdev);
1909b6a0dc82SMarcel Holtmann 
1910cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1911cc11b9c1SAndrei Emeltchenko 		if (ie)
1912c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
1913c7bdd502SMarcel Holtmann 
19148fc9ced3SGustavo Padovan 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
19158fc9ced3SGustavo Padovan 					       &ev->bdaddr);
19161da177e4SLinus Torvalds 		if (!conn) {
1917cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1918cc11b9c1SAndrei Emeltchenko 			if (!conn) {
1919893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
19201da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
19211da177e4SLinus Torvalds 				return;
19221da177e4SLinus Torvalds 			}
19231da177e4SLinus Torvalds 		}
1924b6a0dc82SMarcel Holtmann 
19251da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
19261da177e4SLinus Torvalds 		conn->state = BT_CONNECT;
1927b6a0dc82SMarcel Holtmann 
19281da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
19291da177e4SLinus Torvalds 
1930b6a0dc82SMarcel Holtmann 		if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1931b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
1932b6a0dc82SMarcel Holtmann 
19331da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
19341da177e4SLinus Torvalds 
19351da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
19361da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
19371da177e4SLinus Torvalds 			else
19381da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
19391da177e4SLinus Torvalds 
194004124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
194104124681SGustavo F. Padovan 				     &cp);
1942b6a0dc82SMarcel Holtmann 		} else {
1943b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
1944b6a0dc82SMarcel Holtmann 
1945b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
1946a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1947b6a0dc82SMarcel Holtmann 
194882781e63SAndrei Emeltchenko 			cp.tx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
194982781e63SAndrei Emeltchenko 			cp.rx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
195082781e63SAndrei Emeltchenko 			cp.max_latency    = __constant_cpu_to_le16(0xffff);
1951b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
1952b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
1953b6a0dc82SMarcel Holtmann 
1954b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1955b6a0dc82SMarcel Holtmann 				     sizeof(cp), &cp);
1956b6a0dc82SMarcel Holtmann 		}
19571da177e4SLinus Torvalds 	} else {
19581da177e4SLinus Torvalds 		/* Connection rejected */
19591da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
19601da177e4SLinus Torvalds 
19611da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
19629f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_REJ_BAD_ADDR;
1963a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
19641da177e4SLinus Torvalds 	}
19651da177e4SLinus Torvalds }
19661da177e4SLinus Torvalds 
1967f0d6a0eaSMikel Astiz static u8 hci_to_mgmt_reason(u8 err)
1968f0d6a0eaSMikel Astiz {
1969f0d6a0eaSMikel Astiz 	switch (err) {
1970f0d6a0eaSMikel Astiz 	case HCI_ERROR_CONNECTION_TIMEOUT:
1971f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_TIMEOUT;
1972f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_USER_TERM:
1973f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_LOW_RESOURCES:
1974f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_POWER_OFF:
1975f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_REMOTE;
1976f0d6a0eaSMikel Astiz 	case HCI_ERROR_LOCAL_HOST_TERM:
1977f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_LOCAL_HOST;
1978f0d6a0eaSMikel Astiz 	default:
1979f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_UNKNOWN;
1980f0d6a0eaSMikel Astiz 	}
1981f0d6a0eaSMikel Astiz }
1982f0d6a0eaSMikel Astiz 
19836039aa73SGustavo Padovan static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
19841da177e4SLinus Torvalds {
1985a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
198604837f64SMarcel Holtmann 	struct hci_conn *conn;
19871da177e4SLinus Torvalds 
19889f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
19891da177e4SLinus Torvalds 
19901da177e4SLinus Torvalds 	hci_dev_lock(hdev);
19911da177e4SLinus Torvalds 
199204837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1993f7520543SJohan Hedberg 	if (!conn)
1994f7520543SJohan Hedberg 		goto unlock;
1995f7520543SJohan Hedberg 
199637d9ef76SJohan Hedberg 	if (ev->status == 0)
19971da177e4SLinus Torvalds 		conn->state = BT_CLOSED;
19987d0db0a3SMarcel Holtmann 
1999b644ba33SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
2000b644ba33SJohan Hedberg 	    (conn->type == ACL_LINK || conn->type == LE_LINK)) {
2001f0d6a0eaSMikel Astiz 		if (ev->status) {
200288c3df13SJohan Hedberg 			mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
200388c3df13SJohan Hedberg 					       conn->dst_type, ev->status);
2004f0d6a0eaSMikel Astiz 		} else {
2005f0d6a0eaSMikel Astiz 			u8 reason = hci_to_mgmt_reason(ev->reason);
2006f0d6a0eaSMikel Astiz 
2007afc747a6SJohan Hedberg 			mgmt_device_disconnected(hdev, &conn->dst, conn->type,
2008f0d6a0eaSMikel Astiz 						 conn->dst_type, reason);
2009f0d6a0eaSMikel Astiz 		}
201037d9ef76SJohan Hedberg 	}
2011f7520543SJohan Hedberg 
201237d9ef76SJohan Hedberg 	if (ev->status == 0) {
20136ec5bcadSVishal Agarwal 		if (conn->type == ACL_LINK && conn->flush_key)
20146ec5bcadSVishal Agarwal 			hci_remove_link_key(hdev, &conn->dst);
20152950f21aSMarcel Holtmann 		hci_proto_disconn_cfm(conn, ev->reason);
20161da177e4SLinus Torvalds 		hci_conn_del(conn);
201737d9ef76SJohan Hedberg 	}
20181da177e4SLinus Torvalds 
2019f7520543SJohan Hedberg unlock:
20201da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
20211da177e4SLinus Torvalds }
20221da177e4SLinus Torvalds 
20236039aa73SGustavo Padovan static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2024a9de9248SMarcel Holtmann {
2025a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
2026a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2027a9de9248SMarcel Holtmann 
20289f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2029a9de9248SMarcel Holtmann 
2030a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2031a9de9248SMarcel Holtmann 
2032a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2033d7556e20SWaldemar Rymarkiewicz 	if (!conn)
2034d7556e20SWaldemar Rymarkiewicz 		goto unlock;
2035d7556e20SWaldemar Rymarkiewicz 
2036765c2a96SJohan Hedberg 	if (!ev->status) {
2037aa64a8b5SJohan Hedberg 		if (!hci_conn_ssp_enabled(conn) &&
203851a8efd7SJohan Hedberg 		    test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
2039d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
204019f8def0SWaldemar Rymarkiewicz 		} else {
2041a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
2042765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
204319f8def0SWaldemar Rymarkiewicz 		}
20442a611692SJohan Hedberg 	} else {
2045bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
2046bab73cb6SJohan Hedberg 				 ev->status);
20472a611692SJohan Hedberg 	}
2048a9de9248SMarcel Holtmann 
204951a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
205051a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
2051a9de9248SMarcel Holtmann 
2052f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
2053aa64a8b5SJohan Hedberg 		if (!ev->status && hci_conn_ssp_enabled(conn)) {
2054f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
2055f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
2056f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
2057d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
2058d7556e20SWaldemar Rymarkiewicz 				     &cp);
2059f8558555SMarcel Holtmann 		} else {
2060f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
2061f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
2062f8558555SMarcel Holtmann 			hci_conn_put(conn);
2063f8558555SMarcel Holtmann 		}
2064052b30b0SMarcel Holtmann 	} else {
2065a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
2066a9de9248SMarcel Holtmann 
2067052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2068052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2069052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2070052b30b0SMarcel Holtmann 	}
2071052b30b0SMarcel Holtmann 
207251a8efd7SJohan Hedberg 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
2073a9de9248SMarcel Holtmann 		if (!ev->status) {
2074a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
2075f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
2076f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
2077d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
2078d7556e20SWaldemar Rymarkiewicz 				     &cp);
2079a9de9248SMarcel Holtmann 		} else {
208051a8efd7SJohan Hedberg 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2081a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
2082a9de9248SMarcel Holtmann 		}
2083a9de9248SMarcel Holtmann 	}
2084a9de9248SMarcel Holtmann 
2085d7556e20SWaldemar Rymarkiewicz unlock:
2086a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2087a9de9248SMarcel Holtmann }
2088a9de9248SMarcel Holtmann 
20896039aa73SGustavo Padovan static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
2090a9de9248SMarcel Holtmann {
2091127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
2092127178d2SJohan Hedberg 	struct hci_conn *conn;
2093127178d2SJohan Hedberg 
2094a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2095a9de9248SMarcel Holtmann 
2096a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
2097127178d2SJohan Hedberg 
2098127178d2SJohan Hedberg 	hci_dev_lock(hdev);
2099127178d2SJohan Hedberg 
2100127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2101b644ba33SJohan Hedberg 
2102b644ba33SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
2103b644ba33SJohan Hedberg 		goto check_auth;
2104b644ba33SJohan Hedberg 
2105b644ba33SJohan Hedberg 	if (ev->status == 0)
2106b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
2107b644ba33SJohan Hedberg 				       strnlen(ev->name, HCI_MAX_NAME_LENGTH));
2108b644ba33SJohan Hedberg 	else
2109b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
2110b644ba33SJohan Hedberg 
2111b644ba33SJohan Hedberg check_auth:
211279c6c70cSJohan Hedberg 	if (!conn)
211379c6c70cSJohan Hedberg 		goto unlock;
211479c6c70cSJohan Hedberg 
211579c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
211679c6c70cSJohan Hedberg 		goto unlock;
211779c6c70cSJohan Hedberg 
211851a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
2119127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
2120127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
2121127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
2122127178d2SJohan Hedberg 	}
2123127178d2SJohan Hedberg 
212479c6c70cSJohan Hedberg unlock:
2125127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
2126a9de9248SMarcel Holtmann }
2127a9de9248SMarcel Holtmann 
21286039aa73SGustavo Padovan static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2129a9de9248SMarcel Holtmann {
2130a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
2131a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2132a9de9248SMarcel Holtmann 
21339f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2134a9de9248SMarcel Holtmann 
2135a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2136a9de9248SMarcel Holtmann 
2137a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2138a9de9248SMarcel Holtmann 	if (conn) {
2139a9de9248SMarcel Holtmann 		if (!ev->status) {
2140ae293196SMarcel Holtmann 			if (ev->encrypt) {
2141ae293196SMarcel Holtmann 				/* Encryption implies authentication */
2142ae293196SMarcel Holtmann 				conn->link_mode |= HCI_LM_AUTH;
2143a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_ENCRYPT;
2144da85e5e5SVinicius Costa Gomes 				conn->sec_level = conn->pending_sec_level;
2145ae293196SMarcel Holtmann 			} else
2146a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_ENCRYPT;
2147a9de9248SMarcel Holtmann 		}
2148a9de9248SMarcel Holtmann 
214951a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2150a9de9248SMarcel Holtmann 
2151a7d7723aSGustavo Padovan 		if (ev->status && conn->state == BT_CONNECTED) {
2152d839c813SGustavo Padovan 			hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
2153a7d7723aSGustavo Padovan 			hci_conn_put(conn);
2154a7d7723aSGustavo Padovan 			goto unlock;
2155a7d7723aSGustavo Padovan 		}
2156a7d7723aSGustavo Padovan 
2157f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
2158f8558555SMarcel Holtmann 			if (!ev->status)
2159f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
2160f8558555SMarcel Holtmann 
2161f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
2162f8558555SMarcel Holtmann 			hci_conn_put(conn);
2163f8558555SMarcel Holtmann 		} else
2164a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, ev->encrypt);
2165a9de9248SMarcel Holtmann 	}
2166a9de9248SMarcel Holtmann 
2167a7d7723aSGustavo Padovan unlock:
2168a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2169a9de9248SMarcel Holtmann }
2170a9de9248SMarcel Holtmann 
21716039aa73SGustavo Padovan static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
2172807deac2SGustavo Padovan 					     struct sk_buff *skb)
2173a9de9248SMarcel Holtmann {
2174a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2175a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2176a9de9248SMarcel Holtmann 
21779f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2178a9de9248SMarcel Holtmann 
2179a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2180a9de9248SMarcel Holtmann 
2181a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2182a9de9248SMarcel Holtmann 	if (conn) {
2183a9de9248SMarcel Holtmann 		if (!ev->status)
2184a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
2185a9de9248SMarcel Holtmann 
218651a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
2187a9de9248SMarcel Holtmann 
2188a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
2189a9de9248SMarcel Holtmann 	}
2190a9de9248SMarcel Holtmann 
2191a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2192a9de9248SMarcel Holtmann }
2193a9de9248SMarcel Holtmann 
21946039aa73SGustavo Padovan static void hci_remote_features_evt(struct hci_dev *hdev,
2195807deac2SGustavo Padovan 				    struct sk_buff *skb)
2196a9de9248SMarcel Holtmann {
2197a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
2198a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2199a9de9248SMarcel Holtmann 
22009f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2201a9de9248SMarcel Holtmann 
2202a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2203a9de9248SMarcel Holtmann 
2204a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2205ccd556feSJohan Hedberg 	if (!conn)
2206ccd556feSJohan Hedberg 		goto unlock;
2207ccd556feSJohan Hedberg 
2208769be974SMarcel Holtmann 	if (!ev->status)
2209a9de9248SMarcel Holtmann 		memcpy(conn->features, ev->features, 8);
2210a9de9248SMarcel Holtmann 
2211ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2212ccd556feSJohan Hedberg 		goto unlock;
2213ccd556feSJohan Hedberg 
2214ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2215769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
2216769be974SMarcel Holtmann 		cp.handle = ev->handle;
2217769be974SMarcel Holtmann 		cp.page = 0x01;
2218ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
2219769be974SMarcel Holtmann 			     sizeof(cp), &cp);
2220392599b9SJohan Hedberg 		goto unlock;
2221392599b9SJohan Hedberg 	}
2222392599b9SJohan Hedberg 
2223671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
2224127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2225127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2226127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2227127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2228127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2229b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2230b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
223108c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
2232b644ba33SJohan Hedberg 				      conn->dev_class);
2233392599b9SJohan Hedberg 
2234127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2235769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2236769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2237769be974SMarcel Holtmann 		hci_conn_put(conn);
2238769be974SMarcel Holtmann 	}
2239769be974SMarcel Holtmann 
2240ccd556feSJohan Hedberg unlock:
2241a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2242a9de9248SMarcel Holtmann }
2243a9de9248SMarcel Holtmann 
22446039aa73SGustavo Padovan static void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
22456039aa73SGustavo Padovan {
22466039aa73SGustavo Padovan 	BT_DBG("%s", hdev->name);
22476039aa73SGustavo Padovan }
22486039aa73SGustavo Padovan 
22496039aa73SGustavo Padovan static void hci_qos_setup_complete_evt(struct hci_dev *hdev,
2250807deac2SGustavo Padovan 				       struct sk_buff *skb)
2251a9de9248SMarcel Holtmann {
2252a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2253a9de9248SMarcel Holtmann }
2254a9de9248SMarcel Holtmann 
22556039aa73SGustavo Padovan static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2256a9de9248SMarcel Holtmann {
2257a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
2258a9de9248SMarcel Holtmann 	__u16 opcode;
2259a9de9248SMarcel Holtmann 
2260a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2261a9de9248SMarcel Holtmann 
2262a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2263a9de9248SMarcel Holtmann 
2264a9de9248SMarcel Holtmann 	switch (opcode) {
2265a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
2266a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
2267a9de9248SMarcel Holtmann 		break;
2268a9de9248SMarcel Holtmann 
22694d93483bSAndre Guedes 	case HCI_OP_PERIODIC_INQ:
22704d93483bSAndre Guedes 		hci_cc_periodic_inq(hdev, skb);
22714d93483bSAndre Guedes 		break;
22724d93483bSAndre Guedes 
2273a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
2274a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
2275a9de9248SMarcel Holtmann 		break;
2276a9de9248SMarcel Holtmann 
2277a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2278a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
2279a9de9248SMarcel Holtmann 		break;
2280a9de9248SMarcel Holtmann 
2281a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
2282a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
2283a9de9248SMarcel Holtmann 		break;
2284a9de9248SMarcel Holtmann 
2285e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
2286e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
2287e4e8e37cSMarcel Holtmann 		break;
2288e4e8e37cSMarcel Holtmann 
2289a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
2290a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
2291a9de9248SMarcel Holtmann 		break;
2292a9de9248SMarcel Holtmann 
2293e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
2294e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
2295e4e8e37cSMarcel Holtmann 		break;
2296e4e8e37cSMarcel Holtmann 
2297e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
2298e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
2299e4e8e37cSMarcel Holtmann 		break;
2300e4e8e37cSMarcel Holtmann 
2301a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
2302a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
2303a9de9248SMarcel Holtmann 		break;
2304a9de9248SMarcel Holtmann 
2305a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
2306a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
2307a9de9248SMarcel Holtmann 		break;
2308a9de9248SMarcel Holtmann 
2309a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
2310a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
2311a9de9248SMarcel Holtmann 		break;
2312a9de9248SMarcel Holtmann 
2313a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
2314a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
2315a9de9248SMarcel Holtmann 		break;
2316a9de9248SMarcel Holtmann 
2317a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
2318a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
2319a9de9248SMarcel Holtmann 		break;
2320a9de9248SMarcel Holtmann 
2321a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
2322a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
2323a9de9248SMarcel Holtmann 		break;
2324a9de9248SMarcel Holtmann 
2325a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
2326a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
2327a9de9248SMarcel Holtmann 		break;
2328a9de9248SMarcel Holtmann 
2329a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
2330a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
2331a9de9248SMarcel Holtmann 		break;
2332a9de9248SMarcel Holtmann 
2333a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
2334a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
2335a9de9248SMarcel Holtmann 		break;
2336a9de9248SMarcel Holtmann 
2337a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
2338a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
2339a9de9248SMarcel Holtmann 		break;
2340a9de9248SMarcel Holtmann 
2341a9de9248SMarcel Holtmann 	case HCI_OP_HOST_BUFFER_SIZE:
2342a9de9248SMarcel Holtmann 		hci_cc_host_buffer_size(hdev, skb);
2343a9de9248SMarcel Holtmann 		break;
2344a9de9248SMarcel Holtmann 
2345333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
2346333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
2347333140b5SMarcel Holtmann 		break;
2348333140b5SMarcel Holtmann 
2349a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
2350a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
2351a9de9248SMarcel Holtmann 		break;
2352a9de9248SMarcel Holtmann 
2353a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
2354a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
2355a9de9248SMarcel Holtmann 		break;
2356a9de9248SMarcel Holtmann 
2357a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
2358a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
2359a9de9248SMarcel Holtmann 		break;
2360a9de9248SMarcel Holtmann 
2361971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
2362971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
2363971e3a4bSAndre Guedes 		break;
2364971e3a4bSAndre Guedes 
2365a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
2366a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
2367a9de9248SMarcel Holtmann 		break;
2368a9de9248SMarcel Holtmann 
2369a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
2370a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
2371a9de9248SMarcel Holtmann 		break;
2372a9de9248SMarcel Holtmann 
2373350ee4cfSAndrei Emeltchenko 	case HCI_OP_READ_DATA_BLOCK_SIZE:
2374350ee4cfSAndrei Emeltchenko 		hci_cc_read_data_block_size(hdev, skb);
2375350ee4cfSAndrei Emeltchenko 		break;
2376350ee4cfSAndrei Emeltchenko 
237723bb5763SJohan Hedberg 	case HCI_OP_WRITE_CA_TIMEOUT:
237823bb5763SJohan Hedberg 		hci_cc_write_ca_timeout(hdev, skb);
237923bb5763SJohan Hedberg 		break;
238023bb5763SJohan Hedberg 
23811e89cffbSAndrei Emeltchenko 	case HCI_OP_READ_FLOW_CONTROL_MODE:
23821e89cffbSAndrei Emeltchenko 		hci_cc_read_flow_control_mode(hdev, skb);
23831e89cffbSAndrei Emeltchenko 		break;
23841e89cffbSAndrei Emeltchenko 
2385928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
2386928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
2387928abaa7SAndrei Emeltchenko 		break;
2388928abaa7SAndrei Emeltchenko 
2389903e4541SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_ASSOC:
2390903e4541SAndrei Emeltchenko 		hci_cc_read_local_amp_assoc(hdev, skb);
2391903e4541SAndrei Emeltchenko 		break;
2392903e4541SAndrei Emeltchenko 
2393b0916ea0SJohan Hedberg 	case HCI_OP_DELETE_STORED_LINK_KEY:
2394b0916ea0SJohan Hedberg 		hci_cc_delete_stored_link_key(hdev, skb);
2395b0916ea0SJohan Hedberg 		break;
2396b0916ea0SJohan Hedberg 
2397d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_MASK:
2398d5859e22SJohan Hedberg 		hci_cc_set_event_mask(hdev, skb);
2399d5859e22SJohan Hedberg 		break;
2400d5859e22SJohan Hedberg 
2401d5859e22SJohan Hedberg 	case HCI_OP_WRITE_INQUIRY_MODE:
2402d5859e22SJohan Hedberg 		hci_cc_write_inquiry_mode(hdev, skb);
2403d5859e22SJohan Hedberg 		break;
2404d5859e22SJohan Hedberg 
2405d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
2406d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
2407d5859e22SJohan Hedberg 		break;
2408d5859e22SJohan Hedberg 
2409d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_FLT:
2410d5859e22SJohan Hedberg 		hci_cc_set_event_flt(hdev, skb);
2411d5859e22SJohan Hedberg 		break;
2412d5859e22SJohan Hedberg 
2413980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
2414980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
2415980e1a53SJohan Hedberg 		break;
2416980e1a53SJohan Hedberg 
2417980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
2418980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
2419980e1a53SJohan Hedberg 		break;
2420980e1a53SJohan Hedberg 
2421c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
2422c35938b2SSzymon Janc 		hci_cc_read_local_oob_data_reply(hdev, skb);
2423c35938b2SSzymon Janc 		break;
2424c35938b2SSzymon Janc 
24256ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
24266ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
24276ed58ec5SVille Tervo 		break;
24286ed58ec5SVille Tervo 
2429a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
2430a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
2431a5c29683SJohan Hedberg 		break;
2432a5c29683SJohan Hedberg 
2433a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
2434a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
2435a5c29683SJohan Hedberg 		break;
2436a5c29683SJohan Hedberg 
24371143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_REPLY:
24381143d458SBrian Gix 		hci_cc_user_passkey_reply(hdev, skb);
24391143d458SBrian Gix 		break;
24401143d458SBrian Gix 
24411143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_NEG_REPLY:
24421143d458SBrian Gix 		hci_cc_user_passkey_neg_reply(hdev, skb);
244316cde993SSzymon Janc 		break;
244407f7fa5dSAndre Guedes 
244507f7fa5dSAndre Guedes 	case HCI_OP_LE_SET_SCAN_PARAM:
244607f7fa5dSAndre Guedes 		hci_cc_le_set_scan_param(hdev, skb);
24471143d458SBrian Gix 		break;
24481143d458SBrian Gix 
2449eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
2450eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
2451eb9d91f5SAndre Guedes 		break;
2452eb9d91f5SAndre Guedes 
2453a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_REPLY:
2454a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_reply(hdev, skb);
2455a7a595f6SVinicius Costa Gomes 		break;
2456a7a595f6SVinicius Costa Gomes 
2457a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_NEG_REPLY:
2458a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_neg_reply(hdev, skb);
2459a7a595f6SVinicius Costa Gomes 		break;
2460a7a595f6SVinicius Costa Gomes 
2461f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2462f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
2463f9b49306SAndre Guedes 		break;
2464f9b49306SAndre Guedes 
246593c284eeSAndrei Emeltchenko 	case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
246693c284eeSAndrei Emeltchenko 		hci_cc_write_remote_amp_assoc(hdev, skb);
246793c284eeSAndrei Emeltchenko 		break;
246893c284eeSAndrei Emeltchenko 
2469a9de9248SMarcel Holtmann 	default:
24709f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2471a9de9248SMarcel Holtmann 		break;
2472a9de9248SMarcel Holtmann 	}
2473a9de9248SMarcel Holtmann 
24746bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
24756bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
24766bd32326SVille Tervo 
2477a9de9248SMarcel Holtmann 	if (ev->ncmd) {
2478a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2479a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2480c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2481a9de9248SMarcel Holtmann 	}
2482a9de9248SMarcel Holtmann }
2483a9de9248SMarcel Holtmann 
24846039aa73SGustavo Padovan static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2485a9de9248SMarcel Holtmann {
2486a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
2487a9de9248SMarcel Holtmann 	__u16 opcode;
2488a9de9248SMarcel Holtmann 
2489a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2490a9de9248SMarcel Holtmann 
2491a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2492a9de9248SMarcel Holtmann 
2493a9de9248SMarcel Holtmann 	switch (opcode) {
2494a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
2495a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
2496a9de9248SMarcel Holtmann 		break;
2497a9de9248SMarcel Holtmann 
2498a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
2499a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
2500a9de9248SMarcel Holtmann 		break;
2501a9de9248SMarcel Holtmann 
2502a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
2503a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
2504a9de9248SMarcel Holtmann 		break;
2505a9de9248SMarcel Holtmann 
2506f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2507f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2508f8558555SMarcel Holtmann 		break;
2509f8558555SMarcel Holtmann 
2510f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2511f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2512f8558555SMarcel Holtmann 		break;
2513f8558555SMarcel Holtmann 
2514a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2515a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2516a9de9248SMarcel Holtmann 		break;
2517a9de9248SMarcel Holtmann 
2518769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2519769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2520769be974SMarcel Holtmann 		break;
2521769be974SMarcel Holtmann 
2522769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2523769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2524769be974SMarcel Holtmann 		break;
2525769be974SMarcel Holtmann 
2526a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2527a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2528a9de9248SMarcel Holtmann 		break;
2529a9de9248SMarcel Holtmann 
2530a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2531a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2532a9de9248SMarcel Holtmann 		break;
2533a9de9248SMarcel Holtmann 
2534a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2535a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2536a9de9248SMarcel Holtmann 		break;
2537a9de9248SMarcel Holtmann 
25388962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
253988c3df13SJohan Hedberg 		hci_cs_disconnect(hdev, ev->status);
25408962ee74SJohan Hedberg 		break;
25418962ee74SJohan Hedberg 
2542fcd89c09SVille Tervo 	case HCI_OP_LE_CREATE_CONN:
2543fcd89c09SVille Tervo 		hci_cs_le_create_conn(hdev, ev->status);
2544fcd89c09SVille Tervo 		break;
2545fcd89c09SVille Tervo 
2546a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_START_ENC:
2547a7a595f6SVinicius Costa Gomes 		hci_cs_le_start_enc(hdev, ev->status);
2548a7a595f6SVinicius Costa Gomes 		break;
2549a7a595f6SVinicius Costa Gomes 
2550a02226d6SAndrei Emeltchenko 	case HCI_OP_CREATE_PHY_LINK:
2551a02226d6SAndrei Emeltchenko 		hci_cs_create_phylink(hdev, ev->status);
2552a02226d6SAndrei Emeltchenko 		break;
2553a02226d6SAndrei Emeltchenko 
2554a9de9248SMarcel Holtmann 	default:
25559f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2556a9de9248SMarcel Holtmann 		break;
2557a9de9248SMarcel Holtmann 	}
2558a9de9248SMarcel Holtmann 
25596bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
25606bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
25616bd32326SVille Tervo 
256210572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2563a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2564a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2565c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2566a9de9248SMarcel Holtmann 	}
2567a9de9248SMarcel Holtmann }
2568a9de9248SMarcel Holtmann 
25696039aa73SGustavo Padovan static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2570a9de9248SMarcel Holtmann {
2571a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2572a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2573a9de9248SMarcel Holtmann 
25749f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2575a9de9248SMarcel Holtmann 
2576a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2577a9de9248SMarcel Holtmann 
2578a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2579a9de9248SMarcel Holtmann 	if (conn) {
2580a9de9248SMarcel Holtmann 		if (!ev->status) {
2581a9de9248SMarcel Holtmann 			if (ev->role)
2582a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
2583a9de9248SMarcel Holtmann 			else
2584a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
2585a9de9248SMarcel Holtmann 		}
2586a9de9248SMarcel Holtmann 
258751a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
2588a9de9248SMarcel Holtmann 
2589a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2590a9de9248SMarcel Holtmann 	}
2591a9de9248SMarcel Holtmann 
2592a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2593a9de9248SMarcel Holtmann }
2594a9de9248SMarcel Holtmann 
25956039aa73SGustavo Padovan static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
25961da177e4SLinus Torvalds {
2597a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
25981da177e4SLinus Torvalds 	int i;
25991da177e4SLinus Torvalds 
260032ac5b9bSAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
260132ac5b9bSAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
260232ac5b9bSAndrei Emeltchenko 		return;
260332ac5b9bSAndrei Emeltchenko 	}
260432ac5b9bSAndrei Emeltchenko 
2605c5993de8SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2606c5993de8SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
26071da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
26081da177e4SLinus Torvalds 		return;
26091da177e4SLinus Torvalds 	}
26101da177e4SLinus Torvalds 
2611c5993de8SAndrei Emeltchenko 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2612c5993de8SAndrei Emeltchenko 
2613613a1c0cSAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
2614613a1c0cSAndrei Emeltchenko 		struct hci_comp_pkts_info *info = &ev->handles[i];
26151da177e4SLinus Torvalds 		struct hci_conn *conn;
26161da177e4SLinus Torvalds 		__u16  handle, count;
26171da177e4SLinus Torvalds 
2618613a1c0cSAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
2619613a1c0cSAndrei Emeltchenko 		count  = __le16_to_cpu(info->count);
26201da177e4SLinus Torvalds 
26211da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
2622f4280918SAndrei Emeltchenko 		if (!conn)
2623f4280918SAndrei Emeltchenko 			continue;
2624f4280918SAndrei Emeltchenko 
26251da177e4SLinus Torvalds 		conn->sent -= count;
26261da177e4SLinus Torvalds 
2627f4280918SAndrei Emeltchenko 		switch (conn->type) {
2628f4280918SAndrei Emeltchenko 		case ACL_LINK:
262970f23020SAndrei Emeltchenko 			hdev->acl_cnt += count;
263070f23020SAndrei Emeltchenko 			if (hdev->acl_cnt > hdev->acl_pkts)
26311da177e4SLinus Torvalds 				hdev->acl_cnt = hdev->acl_pkts;
2632f4280918SAndrei Emeltchenko 			break;
2633f4280918SAndrei Emeltchenko 
2634f4280918SAndrei Emeltchenko 		case LE_LINK:
26356ed58ec5SVille Tervo 			if (hdev->le_pkts) {
26366ed58ec5SVille Tervo 				hdev->le_cnt += count;
26376ed58ec5SVille Tervo 				if (hdev->le_cnt > hdev->le_pkts)
26386ed58ec5SVille Tervo 					hdev->le_cnt = hdev->le_pkts;
26396ed58ec5SVille Tervo 			} else {
26406ed58ec5SVille Tervo 				hdev->acl_cnt += count;
26416ed58ec5SVille Tervo 				if (hdev->acl_cnt > hdev->acl_pkts)
26426ed58ec5SVille Tervo 					hdev->acl_cnt = hdev->acl_pkts;
26436ed58ec5SVille Tervo 			}
2644f4280918SAndrei Emeltchenko 			break;
2645f4280918SAndrei Emeltchenko 
2646f4280918SAndrei Emeltchenko 		case SCO_LINK:
264770f23020SAndrei Emeltchenko 			hdev->sco_cnt += count;
264870f23020SAndrei Emeltchenko 			if (hdev->sco_cnt > hdev->sco_pkts)
26495b7f9909SMarcel Holtmann 				hdev->sco_cnt = hdev->sco_pkts;
2650f4280918SAndrei Emeltchenko 			break;
2651f4280918SAndrei Emeltchenko 
2652f4280918SAndrei Emeltchenko 		default:
2653f4280918SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
2654f4280918SAndrei Emeltchenko 			break;
26551da177e4SLinus Torvalds 		}
26561da177e4SLinus Torvalds 	}
2657a9de9248SMarcel Holtmann 
26583eff45eaSGustavo F. Padovan 	queue_work(hdev->workqueue, &hdev->tx_work);
26591da177e4SLinus Torvalds }
26601da177e4SLinus Torvalds 
26616039aa73SGustavo Padovan static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
266225e89e99SAndrei Emeltchenko {
266325e89e99SAndrei Emeltchenko 	struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
266425e89e99SAndrei Emeltchenko 	int i;
266525e89e99SAndrei Emeltchenko 
266625e89e99SAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
266725e89e99SAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
266825e89e99SAndrei Emeltchenko 		return;
266925e89e99SAndrei Emeltchenko 	}
267025e89e99SAndrei Emeltchenko 
267125e89e99SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
267225e89e99SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
267325e89e99SAndrei Emeltchenko 		BT_DBG("%s bad parameters", hdev->name);
267425e89e99SAndrei Emeltchenko 		return;
267525e89e99SAndrei Emeltchenko 	}
267625e89e99SAndrei Emeltchenko 
267725e89e99SAndrei Emeltchenko 	BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
267825e89e99SAndrei Emeltchenko 	       ev->num_hndl);
267925e89e99SAndrei Emeltchenko 
268025e89e99SAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
268125e89e99SAndrei Emeltchenko 		struct hci_comp_blocks_info *info = &ev->handles[i];
268225e89e99SAndrei Emeltchenko 		struct hci_conn *conn;
268325e89e99SAndrei Emeltchenko 		__u16  handle, block_count;
268425e89e99SAndrei Emeltchenko 
268525e89e99SAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
268625e89e99SAndrei Emeltchenko 		block_count = __le16_to_cpu(info->blocks);
268725e89e99SAndrei Emeltchenko 
268825e89e99SAndrei Emeltchenko 		conn = hci_conn_hash_lookup_handle(hdev, handle);
268925e89e99SAndrei Emeltchenko 		if (!conn)
269025e89e99SAndrei Emeltchenko 			continue;
269125e89e99SAndrei Emeltchenko 
269225e89e99SAndrei Emeltchenko 		conn->sent -= block_count;
269325e89e99SAndrei Emeltchenko 
269425e89e99SAndrei Emeltchenko 		switch (conn->type) {
269525e89e99SAndrei Emeltchenko 		case ACL_LINK:
269625e89e99SAndrei Emeltchenko 			hdev->block_cnt += block_count;
269725e89e99SAndrei Emeltchenko 			if (hdev->block_cnt > hdev->num_blocks)
269825e89e99SAndrei Emeltchenko 				hdev->block_cnt = hdev->num_blocks;
269925e89e99SAndrei Emeltchenko 			break;
270025e89e99SAndrei Emeltchenko 
270125e89e99SAndrei Emeltchenko 		default:
270225e89e99SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
270325e89e99SAndrei Emeltchenko 			break;
270425e89e99SAndrei Emeltchenko 		}
270525e89e99SAndrei Emeltchenko 	}
270625e89e99SAndrei Emeltchenko 
270725e89e99SAndrei Emeltchenko 	queue_work(hdev->workqueue, &hdev->tx_work);
270825e89e99SAndrei Emeltchenko }
270925e89e99SAndrei Emeltchenko 
27106039aa73SGustavo Padovan static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
27111da177e4SLinus Torvalds {
2712a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
271304837f64SMarcel Holtmann 	struct hci_conn *conn;
27141da177e4SLinus Torvalds 
27159f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
27161da177e4SLinus Torvalds 
27171da177e4SLinus Torvalds 	hci_dev_lock(hdev);
27181da177e4SLinus Torvalds 
271904837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
272004837f64SMarcel Holtmann 	if (conn) {
272104837f64SMarcel Holtmann 		conn->mode = ev->mode;
272204837f64SMarcel Holtmann 		conn->interval = __le16_to_cpu(ev->interval);
272304837f64SMarcel Holtmann 
27248fc9ced3SGustavo Padovan 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
27258fc9ced3SGustavo Padovan 					&conn->flags)) {
272604837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
272758a681efSJohan Hedberg 				set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
272804837f64SMarcel Holtmann 			else
272958a681efSJohan Hedberg 				clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
273004837f64SMarcel Holtmann 		}
2731e73439d8SMarcel Holtmann 
273251a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
2733e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
273404837f64SMarcel Holtmann 	}
273504837f64SMarcel Holtmann 
273604837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
273704837f64SMarcel Holtmann }
273804837f64SMarcel Holtmann 
27396039aa73SGustavo Padovan static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
27401da177e4SLinus Torvalds {
2741052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
2742052b30b0SMarcel Holtmann 	struct hci_conn *conn;
2743052b30b0SMarcel Holtmann 
2744a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2745052b30b0SMarcel Holtmann 
2746052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2747052b30b0SMarcel Holtmann 
2748052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2749b6f98044SWaldemar Rymarkiewicz 	if (!conn)
2750b6f98044SWaldemar Rymarkiewicz 		goto unlock;
2751b6f98044SWaldemar Rymarkiewicz 
2752b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
2753052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2754052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2755052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2756052b30b0SMarcel Holtmann 	}
2757052b30b0SMarcel Holtmann 
2758a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
275903b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
276003b555e1SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
2761a8b2d5c2SJohan Hedberg 	else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
2762a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
2763a770bb5aSWaldemar Rymarkiewicz 
2764a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
2765a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
2766a770bb5aSWaldemar Rymarkiewicz 		else
2767a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
2768a770bb5aSWaldemar Rymarkiewicz 
2769744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
2770a770bb5aSWaldemar Rymarkiewicz 	}
2771980e1a53SJohan Hedberg 
2772b6f98044SWaldemar Rymarkiewicz unlock:
2773052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
27741da177e4SLinus Torvalds }
27751da177e4SLinus Torvalds 
27766039aa73SGustavo Padovan static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
27771da177e4SLinus Torvalds {
277855ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
277955ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
278055ed8ca1SJohan Hedberg 	struct hci_conn *conn;
278155ed8ca1SJohan Hedberg 	struct link_key *key;
278255ed8ca1SJohan Hedberg 
2783a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
278455ed8ca1SJohan Hedberg 
2785a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
278655ed8ca1SJohan Hedberg 		return;
278755ed8ca1SJohan Hedberg 
278855ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
278955ed8ca1SJohan Hedberg 
279055ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
279155ed8ca1SJohan Hedberg 	if (!key) {
279255ed8ca1SJohan Hedberg 		BT_DBG("%s link key not found for %s", hdev->name,
279355ed8ca1SJohan Hedberg 		       batostr(&ev->bdaddr));
279455ed8ca1SJohan Hedberg 		goto not_found;
279555ed8ca1SJohan Hedberg 	}
279655ed8ca1SJohan Hedberg 
279755ed8ca1SJohan Hedberg 	BT_DBG("%s found key type %u for %s", hdev->name, key->type,
279855ed8ca1SJohan Hedberg 	       batostr(&ev->bdaddr));
279955ed8ca1SJohan Hedberg 
2800a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
2801b6020ba0SWaldemar Rymarkiewicz 	    key->type == HCI_LK_DEBUG_COMBINATION) {
280255ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
280355ed8ca1SJohan Hedberg 		goto not_found;
280455ed8ca1SJohan Hedberg 	}
280555ed8ca1SJohan Hedberg 
280655ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
280760b83f57SWaldemar Rymarkiewicz 	if (conn) {
280860b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_UNAUTH_COMBINATION &&
2809807deac2SGustavo Padovan 		    conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
281055ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
281155ed8ca1SJohan Hedberg 			goto not_found;
281255ed8ca1SJohan Hedberg 		}
281355ed8ca1SJohan Hedberg 
281460b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
281560b83f57SWaldemar Rymarkiewicz 		    conn->pending_sec_level == BT_SECURITY_HIGH) {
28168fc9ced3SGustavo Padovan 			BT_DBG("%s ignoring key unauthenticated for high security",
28178fc9ced3SGustavo Padovan 			       hdev->name);
281860b83f57SWaldemar Rymarkiewicz 			goto not_found;
281960b83f57SWaldemar Rymarkiewicz 		}
282060b83f57SWaldemar Rymarkiewicz 
282160b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
282260b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
282360b83f57SWaldemar Rymarkiewicz 	}
282460b83f57SWaldemar Rymarkiewicz 
282555ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
28269b3b4460SAndrei Emeltchenko 	memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
282755ed8ca1SJohan Hedberg 
282855ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
282955ed8ca1SJohan Hedberg 
283055ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
283155ed8ca1SJohan Hedberg 
283255ed8ca1SJohan Hedberg 	return;
283355ed8ca1SJohan Hedberg 
283455ed8ca1SJohan Hedberg not_found:
283555ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
283655ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
28371da177e4SLinus Torvalds }
28381da177e4SLinus Torvalds 
28396039aa73SGustavo Padovan static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
28401da177e4SLinus Torvalds {
2841052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
2842052b30b0SMarcel Holtmann 	struct hci_conn *conn;
284355ed8ca1SJohan Hedberg 	u8 pin_len = 0;
2844052b30b0SMarcel Holtmann 
2845a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2846052b30b0SMarcel Holtmann 
2847052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2848052b30b0SMarcel Holtmann 
2849052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2850052b30b0SMarcel Holtmann 	if (conn) {
2851052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2852052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2853980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
285413d39315SWaldemar Rymarkiewicz 
285513d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
285613d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
285713d39315SWaldemar Rymarkiewicz 
2858052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2859052b30b0SMarcel Holtmann 	}
2860052b30b0SMarcel Holtmann 
2861a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
2862d25e28abSJohan Hedberg 		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
286355ed8ca1SJohan Hedberg 				 ev->key_type, pin_len);
286455ed8ca1SJohan Hedberg 
2865052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
28661da177e4SLinus Torvalds }
28671da177e4SLinus Torvalds 
28686039aa73SGustavo Padovan static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
286904837f64SMarcel Holtmann {
2870a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
287104837f64SMarcel Holtmann 	struct hci_conn *conn;
287204837f64SMarcel Holtmann 
28739f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
287404837f64SMarcel Holtmann 
287504837f64SMarcel Holtmann 	hci_dev_lock(hdev);
287604837f64SMarcel Holtmann 
287704837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
28781da177e4SLinus Torvalds 	if (conn && !ev->status) {
28791da177e4SLinus Torvalds 		struct inquiry_entry *ie;
28801da177e4SLinus Torvalds 
2881cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2882cc11b9c1SAndrei Emeltchenko 		if (ie) {
28831da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
28841da177e4SLinus Torvalds 			ie->timestamp = jiffies;
28851da177e4SLinus Torvalds 		}
28861da177e4SLinus Torvalds 	}
28871da177e4SLinus Torvalds 
28881da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
28891da177e4SLinus Torvalds }
28901da177e4SLinus Torvalds 
28916039aa73SGustavo Padovan static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2892a8746417SMarcel Holtmann {
2893a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2894a8746417SMarcel Holtmann 	struct hci_conn *conn;
2895a8746417SMarcel Holtmann 
28969f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2897a8746417SMarcel Holtmann 
2898a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
2899a8746417SMarcel Holtmann 
2900a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2901a8746417SMarcel Holtmann 	if (conn && !ev->status)
2902a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2903a8746417SMarcel Holtmann 
2904a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
2905a8746417SMarcel Holtmann }
2906a8746417SMarcel Holtmann 
29076039aa73SGustavo Padovan static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
290885a1e930SMarcel Holtmann {
2909a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
291085a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
291185a1e930SMarcel Holtmann 
291285a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
291385a1e930SMarcel Holtmann 
291485a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
291585a1e930SMarcel Holtmann 
2916cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2917cc11b9c1SAndrei Emeltchenko 	if (ie) {
291885a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
291985a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
292085a1e930SMarcel Holtmann 	}
292185a1e930SMarcel Holtmann 
292285a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
292385a1e930SMarcel Holtmann }
292485a1e930SMarcel Holtmann 
29256039aa73SGustavo Padovan static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
2926807deac2SGustavo Padovan 					     struct sk_buff *skb)
2927a9de9248SMarcel Holtmann {
2928a9de9248SMarcel Holtmann 	struct inquiry_data data;
2929a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2930388fc8faSJohan Hedberg 	bool name_known, ssp;
2931a9de9248SMarcel Holtmann 
2932a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2933a9de9248SMarcel Holtmann 
2934a9de9248SMarcel Holtmann 	if (!num_rsp)
2935a9de9248SMarcel Holtmann 		return;
2936a9de9248SMarcel Holtmann 
29371519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
29381519cc17SAndre Guedes 		return;
29391519cc17SAndre Guedes 
2940a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2941a9de9248SMarcel Holtmann 
2942a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
2943138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
2944138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
2945a9de9248SMarcel Holtmann 
2946e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2947a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2948a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2949a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2950a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
2951a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2952a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2953a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
295441a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
29553175405bSJohan Hedberg 
29563175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
2957388fc8faSJohan Hedberg 							      false, &ssp);
295848264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2959e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
2960388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
2961a9de9248SMarcel Holtmann 		}
2962a9de9248SMarcel Holtmann 	} else {
2963a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2964a9de9248SMarcel Holtmann 
2965e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2966a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2967a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2968a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2969a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
2970a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2971a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2972a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
297341a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
29743175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
2975388fc8faSJohan Hedberg 							      false, &ssp);
297648264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2977e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
2978388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
2979a9de9248SMarcel Holtmann 		}
2980a9de9248SMarcel Holtmann 	}
2981a9de9248SMarcel Holtmann 
2982a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2983a9de9248SMarcel Holtmann }
2984a9de9248SMarcel Holtmann 
29856039aa73SGustavo Padovan static void hci_remote_ext_features_evt(struct hci_dev *hdev,
2986807deac2SGustavo Padovan 					struct sk_buff *skb)
2987a9de9248SMarcel Holtmann {
298841a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
298941a96212SMarcel Holtmann 	struct hci_conn *conn;
299041a96212SMarcel Holtmann 
2991a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
299241a96212SMarcel Holtmann 
299341a96212SMarcel Holtmann 	hci_dev_lock(hdev);
299441a96212SMarcel Holtmann 
299541a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2996ccd556feSJohan Hedberg 	if (!conn)
2997ccd556feSJohan Hedberg 		goto unlock;
2998ccd556feSJohan Hedberg 
2999769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
300041a96212SMarcel Holtmann 		struct inquiry_entry *ie;
300141a96212SMarcel Holtmann 
3002cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3003cc11b9c1SAndrei Emeltchenko 		if (ie)
300402b7cc62SJohan Hedberg 			ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
300541a96212SMarcel Holtmann 
300602b7cc62SJohan Hedberg 		if (ev->features[0] & LMP_HOST_SSP)
300758a681efSJohan Hedberg 			set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
300841a96212SMarcel Holtmann 	}
300941a96212SMarcel Holtmann 
3010ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
3011ccd556feSJohan Hedberg 		goto unlock;
3012ccd556feSJohan Hedberg 
3013671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
3014127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
3015127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
3016127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
3017127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
3018127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
3019b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3020b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
302108c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
3022b644ba33SJohan Hedberg 				      conn->dev_class);
3023392599b9SJohan Hedberg 
3024127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
3025769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
3026769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
3027769be974SMarcel Holtmann 		hci_conn_put(conn);
3028769be974SMarcel Holtmann 	}
3029769be974SMarcel Holtmann 
3030ccd556feSJohan Hedberg unlock:
303141a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
3032a9de9248SMarcel Holtmann }
3033a9de9248SMarcel Holtmann 
30346039aa73SGustavo Padovan static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
3035807deac2SGustavo Padovan 				       struct sk_buff *skb)
3036a9de9248SMarcel Holtmann {
3037b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
3038b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
3039b6a0dc82SMarcel Holtmann 
30409f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3041b6a0dc82SMarcel Holtmann 
3042b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
3043b6a0dc82SMarcel Holtmann 
3044b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
30459dc0a3afSMarcel Holtmann 	if (!conn) {
30469dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
30479dc0a3afSMarcel Holtmann 			goto unlock;
30489dc0a3afSMarcel Holtmann 
30499dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
3050b6a0dc82SMarcel Holtmann 		if (!conn)
3051b6a0dc82SMarcel Holtmann 			goto unlock;
3052b6a0dc82SMarcel Holtmann 
30539dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
30549dc0a3afSMarcel Holtmann 	}
30559dc0a3afSMarcel Holtmann 
3056732547f9SMarcel Holtmann 	switch (ev->status) {
3057732547f9SMarcel Holtmann 	case 0x00:
3058732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
3059732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
3060732547f9SMarcel Holtmann 
30619eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
3062732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
3063732547f9SMarcel Holtmann 		break;
3064732547f9SMarcel Holtmann 
3065705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
3066732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
30671038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
3068732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
3069732547f9SMarcel Holtmann 		if (conn->out && conn->attempt < 2) {
3070efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
3071efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
3072efc7688bSMarcel Holtmann 			hci_setup_sync(conn, conn->link->handle);
3073efc7688bSMarcel Holtmann 			goto unlock;
3074efc7688bSMarcel Holtmann 		}
3075732547f9SMarcel Holtmann 		/* fall through */
3076efc7688bSMarcel Holtmann 
3077732547f9SMarcel Holtmann 	default:
3078b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
3079732547f9SMarcel Holtmann 		break;
3080732547f9SMarcel Holtmann 	}
3081b6a0dc82SMarcel Holtmann 
3082b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
3083b6a0dc82SMarcel Holtmann 	if (ev->status)
3084b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
3085b6a0dc82SMarcel Holtmann 
3086b6a0dc82SMarcel Holtmann unlock:
3087b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
3088a9de9248SMarcel Holtmann }
3089a9de9248SMarcel Holtmann 
30906039aa73SGustavo Padovan static void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
3091a9de9248SMarcel Holtmann {
3092a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
3093a9de9248SMarcel Holtmann }
3094a9de9248SMarcel Holtmann 
30956039aa73SGustavo Padovan static void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
309604837f64SMarcel Holtmann {
3097a9de9248SMarcel Holtmann 	struct hci_ev_sniff_subrate *ev = (void *) skb->data;
309804837f64SMarcel Holtmann 
30999f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
310004837f64SMarcel Holtmann }
310104837f64SMarcel Holtmann 
31026039aa73SGustavo Padovan static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
3103807deac2SGustavo Padovan 					    struct sk_buff *skb)
3104a9de9248SMarcel Holtmann {
3105a9de9248SMarcel Holtmann 	struct inquiry_data data;
3106a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
3107a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
31089d939d94SVishal Agarwal 	size_t eir_len;
3109a9de9248SMarcel Holtmann 
3110a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3111a9de9248SMarcel Holtmann 
3112a9de9248SMarcel Holtmann 	if (!num_rsp)
3113a9de9248SMarcel Holtmann 		return;
3114a9de9248SMarcel Holtmann 
31151519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
31161519cc17SAndre Guedes 		return;
31171519cc17SAndre Guedes 
3118a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
3119a9de9248SMarcel Holtmann 
3120e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
3121388fc8faSJohan Hedberg 		bool name_known, ssp;
3122561aafbcSJohan Hedberg 
3123a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
3124a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
3125a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
3126a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
3127a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
3128a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
3129a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
313041a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
3131561aafbcSJohan Hedberg 
3132a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
31334ddb1930SJohan Hedberg 			name_known = eir_has_data_type(info->data,
31344ddb1930SJohan Hedberg 						       sizeof(info->data),
31354ddb1930SJohan Hedberg 						       EIR_NAME_COMPLETE);
3136561aafbcSJohan Hedberg 		else
3137561aafbcSJohan Hedberg 			name_known = true;
3138561aafbcSJohan Hedberg 
3139388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, name_known,
3140388fc8faSJohan Hedberg 						      &ssp);
31419d939d94SVishal Agarwal 		eir_len = eir_get_length(info->data, sizeof(info->data));
314248264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
314304124681SGustavo F. Padovan 				  info->dev_class, info->rssi, !name_known,
31449d939d94SVishal Agarwal 				  ssp, info->data, eir_len);
3145a9de9248SMarcel Holtmann 	}
3146a9de9248SMarcel Holtmann 
3147a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3148a9de9248SMarcel Holtmann }
3149a9de9248SMarcel Holtmann 
31501c2e0041SJohan Hedberg static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
31511c2e0041SJohan Hedberg 					 struct sk_buff *skb)
31521c2e0041SJohan Hedberg {
31531c2e0041SJohan Hedberg 	struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
31541c2e0041SJohan Hedberg 	struct hci_conn *conn;
31551c2e0041SJohan Hedberg 
31569f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
31571c2e0041SJohan Hedberg 	       __le16_to_cpu(ev->handle));
31581c2e0041SJohan Hedberg 
31591c2e0041SJohan Hedberg 	hci_dev_lock(hdev);
31601c2e0041SJohan Hedberg 
31611c2e0041SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
31621c2e0041SJohan Hedberg 	if (!conn)
31631c2e0041SJohan Hedberg 		goto unlock;
31641c2e0041SJohan Hedberg 
31651c2e0041SJohan Hedberg 	if (!ev->status)
31661c2e0041SJohan Hedberg 		conn->sec_level = conn->pending_sec_level;
31671c2e0041SJohan Hedberg 
31681c2e0041SJohan Hedberg 	clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
31691c2e0041SJohan Hedberg 
31701c2e0041SJohan Hedberg 	if (ev->status && conn->state == BT_CONNECTED) {
31711c2e0041SJohan Hedberg 		hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
31721c2e0041SJohan Hedberg 		hci_conn_put(conn);
31731c2e0041SJohan Hedberg 		goto unlock;
31741c2e0041SJohan Hedberg 	}
31751c2e0041SJohan Hedberg 
31761c2e0041SJohan Hedberg 	if (conn->state == BT_CONFIG) {
31771c2e0041SJohan Hedberg 		if (!ev->status)
31781c2e0041SJohan Hedberg 			conn->state = BT_CONNECTED;
31791c2e0041SJohan Hedberg 
31801c2e0041SJohan Hedberg 		hci_proto_connect_cfm(conn, ev->status);
31811c2e0041SJohan Hedberg 		hci_conn_put(conn);
31821c2e0041SJohan Hedberg 	} else {
31831c2e0041SJohan Hedberg 		hci_auth_cfm(conn, ev->status);
31841c2e0041SJohan Hedberg 
31851c2e0041SJohan Hedberg 		hci_conn_hold(conn);
31861c2e0041SJohan Hedberg 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
31871c2e0041SJohan Hedberg 		hci_conn_put(conn);
31881c2e0041SJohan Hedberg 	}
31891c2e0041SJohan Hedberg 
31901c2e0041SJohan Hedberg unlock:
31911c2e0041SJohan Hedberg 	hci_dev_unlock(hdev);
31921c2e0041SJohan Hedberg }
31931c2e0041SJohan Hedberg 
31946039aa73SGustavo Padovan static u8 hci_get_auth_req(struct hci_conn *conn)
319517fa4b9dSJohan Hedberg {
319617fa4b9dSJohan Hedberg 	/* If remote requests dedicated bonding follow that lead */
319717fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
319817fa4b9dSJohan Hedberg 		/* If both remote and local IO capabilities allow MITM
319917fa4b9dSJohan Hedberg 		 * protection then require it, otherwise don't */
320017fa4b9dSJohan Hedberg 		if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
320117fa4b9dSJohan Hedberg 			return 0x02;
320217fa4b9dSJohan Hedberg 		else
320317fa4b9dSJohan Hedberg 			return 0x03;
320417fa4b9dSJohan Hedberg 	}
320517fa4b9dSJohan Hedberg 
320617fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
320717fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
320858797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
320917fa4b9dSJohan Hedberg 
321017fa4b9dSJohan Hedberg 	return conn->auth_type;
321117fa4b9dSJohan Hedberg }
321217fa4b9dSJohan Hedberg 
32136039aa73SGustavo Padovan static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
32140493684eSMarcel Holtmann {
32150493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
32160493684eSMarcel Holtmann 	struct hci_conn *conn;
32170493684eSMarcel Holtmann 
32180493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
32190493684eSMarcel Holtmann 
32200493684eSMarcel Holtmann 	hci_dev_lock(hdev);
32210493684eSMarcel Holtmann 
32220493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
322303b555e1SJohan Hedberg 	if (!conn)
322403b555e1SJohan Hedberg 		goto unlock;
322503b555e1SJohan Hedberg 
32260493684eSMarcel Holtmann 	hci_conn_hold(conn);
32270493684eSMarcel Holtmann 
3228a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
322903b555e1SJohan Hedberg 		goto unlock;
323003b555e1SJohan Hedberg 
3231a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
323203b555e1SJohan Hedberg 	    (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
323317fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
323417fa4b9dSJohan Hedberg 
323517fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
32367a7f1e7cSHemant Gupta 		/* Change the IO capability from KeyboardDisplay
32377a7f1e7cSHemant Gupta 		 * to DisplayYesNo as it is not supported by BT spec. */
32387a7f1e7cSHemant Gupta 		cp.capability = (conn->io_capability == 0x04) ?
32397a7f1e7cSHemant Gupta 						0x01 : conn->io_capability;
32407cbc9bd9SJohan Hedberg 		conn->auth_type = hci_get_auth_req(conn);
32417cbc9bd9SJohan Hedberg 		cp.authentication = conn->auth_type;
324217fa4b9dSJohan Hedberg 
32438fc9ced3SGustavo Padovan 		if (hci_find_remote_oob_data(hdev, &conn->dst) &&
32448fc9ced3SGustavo Padovan 		    (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
3245ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
3246ce85ee13SSzymon Janc 		else
3247ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
3248ce85ee13SSzymon Janc 
324917fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
325017fa4b9dSJohan Hedberg 			     sizeof(cp), &cp);
325103b555e1SJohan Hedberg 	} else {
325203b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
325303b555e1SJohan Hedberg 
325403b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
32559f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
325603b555e1SJohan Hedberg 
325703b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
325803b555e1SJohan Hedberg 			     sizeof(cp), &cp);
325903b555e1SJohan Hedberg 	}
326003b555e1SJohan Hedberg 
326103b555e1SJohan Hedberg unlock:
326203b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
326303b555e1SJohan Hedberg }
326403b555e1SJohan Hedberg 
32656039aa73SGustavo Padovan static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
326603b555e1SJohan Hedberg {
326703b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
326803b555e1SJohan Hedberg 	struct hci_conn *conn;
326903b555e1SJohan Hedberg 
327003b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
327103b555e1SJohan Hedberg 
327203b555e1SJohan Hedberg 	hci_dev_lock(hdev);
327303b555e1SJohan Hedberg 
327403b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
327503b555e1SJohan Hedberg 	if (!conn)
327603b555e1SJohan Hedberg 		goto unlock;
327703b555e1SJohan Hedberg 
327803b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
327903b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
328058a681efSJohan Hedberg 	if (ev->oob_data)
328158a681efSJohan Hedberg 		set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
328203b555e1SJohan Hedberg 
328303b555e1SJohan Hedberg unlock:
32840493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
32850493684eSMarcel Holtmann }
32860493684eSMarcel Holtmann 
32876039aa73SGustavo Padovan static void hci_user_confirm_request_evt(struct hci_dev *hdev,
3288a5c29683SJohan Hedberg 					 struct sk_buff *skb)
3289a5c29683SJohan Hedberg {
3290a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
329155bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
32927a828908SJohan Hedberg 	struct hci_conn *conn;
3293a5c29683SJohan Hedberg 
3294a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
3295a5c29683SJohan Hedberg 
3296a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
3297a5c29683SJohan Hedberg 
3298a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
32997a828908SJohan Hedberg 		goto unlock;
33007a828908SJohan Hedberg 
33017a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
33027a828908SJohan Hedberg 	if (!conn)
33037a828908SJohan Hedberg 		goto unlock;
33047a828908SJohan Hedberg 
33057a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
33067a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
33077a828908SJohan Hedberg 
33087a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
33097a828908SJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
33107a828908SJohan Hedberg 	 * request. The only exception is when we're dedicated bonding
33117a828908SJohan Hedberg 	 * initiators (connect_cfm_cb set) since then we always have the MITM
33127a828908SJohan Hedberg 	 * bit set. */
33137a828908SJohan Hedberg 	if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
33147a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
33157a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
33167a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
33177a828908SJohan Hedberg 		goto unlock;
33187a828908SJohan Hedberg 	}
33197a828908SJohan Hedberg 
33207a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
33217a828908SJohan Hedberg 	if ((!loc_mitm || conn->remote_cap == 0x03) &&
33227a828908SJohan Hedberg 	    (!rem_mitm || conn->io_capability == 0x03)) {
332355bc1a37SJohan Hedberg 
332455bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
332555bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
332655bc1a37SJohan Hedberg 		 * confirm_hint set to 1). */
332751a8efd7SJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
332855bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
332955bc1a37SJohan Hedberg 			confirm_hint = 1;
333055bc1a37SJohan Hedberg 			goto confirm;
333155bc1a37SJohan Hedberg 		}
333255bc1a37SJohan Hedberg 
33339f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
33349f61656aSJohan Hedberg 		       hdev->auto_accept_delay);
33359f61656aSJohan Hedberg 
33369f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
33379f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
33389f61656aSJohan Hedberg 			mod_timer(&conn->auto_accept_timer, jiffies + delay);
33399f61656aSJohan Hedberg 			goto unlock;
33409f61656aSJohan Hedberg 		}
33419f61656aSJohan Hedberg 
33427a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
33437a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
33447a828908SJohan Hedberg 		goto unlock;
33457a828908SJohan Hedberg 	}
33467a828908SJohan Hedberg 
334755bc1a37SJohan Hedberg confirm:
3348272d90dfSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
334955bc1a37SJohan Hedberg 				  confirm_hint);
3350a5c29683SJohan Hedberg 
33517a828908SJohan Hedberg unlock:
3352a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
3353a5c29683SJohan Hedberg }
3354a5c29683SJohan Hedberg 
33556039aa73SGustavo Padovan static void hci_user_passkey_request_evt(struct hci_dev *hdev,
33561143d458SBrian Gix 					 struct sk_buff *skb)
33571143d458SBrian Gix {
33581143d458SBrian Gix 	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
33591143d458SBrian Gix 
33601143d458SBrian Gix 	BT_DBG("%s", hdev->name);
33611143d458SBrian Gix 
3362a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3363272d90dfSJohan Hedberg 		mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
33641143d458SBrian Gix }
33651143d458SBrian Gix 
336692a25256SJohan Hedberg static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
336792a25256SJohan Hedberg 					struct sk_buff *skb)
336892a25256SJohan Hedberg {
336992a25256SJohan Hedberg 	struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
337092a25256SJohan Hedberg 	struct hci_conn *conn;
337192a25256SJohan Hedberg 
337292a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
337392a25256SJohan Hedberg 
337492a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
337592a25256SJohan Hedberg 	if (!conn)
337692a25256SJohan Hedberg 		return;
337792a25256SJohan Hedberg 
337892a25256SJohan Hedberg 	conn->passkey_notify = __le32_to_cpu(ev->passkey);
337992a25256SJohan Hedberg 	conn->passkey_entered = 0;
338092a25256SJohan Hedberg 
338192a25256SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
338292a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
338392a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
338492a25256SJohan Hedberg 					 conn->passkey_entered);
338592a25256SJohan Hedberg }
338692a25256SJohan Hedberg 
338792a25256SJohan Hedberg static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
338892a25256SJohan Hedberg {
338992a25256SJohan Hedberg 	struct hci_ev_keypress_notify *ev = (void *) skb->data;
339092a25256SJohan Hedberg 	struct hci_conn *conn;
339192a25256SJohan Hedberg 
339292a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
339392a25256SJohan Hedberg 
339492a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
339592a25256SJohan Hedberg 	if (!conn)
339692a25256SJohan Hedberg 		return;
339792a25256SJohan Hedberg 
339892a25256SJohan Hedberg 	switch (ev->type) {
339992a25256SJohan Hedberg 	case HCI_KEYPRESS_STARTED:
340092a25256SJohan Hedberg 		conn->passkey_entered = 0;
340192a25256SJohan Hedberg 		return;
340292a25256SJohan Hedberg 
340392a25256SJohan Hedberg 	case HCI_KEYPRESS_ENTERED:
340492a25256SJohan Hedberg 		conn->passkey_entered++;
340592a25256SJohan Hedberg 		break;
340692a25256SJohan Hedberg 
340792a25256SJohan Hedberg 	case HCI_KEYPRESS_ERASED:
340892a25256SJohan Hedberg 		conn->passkey_entered--;
340992a25256SJohan Hedberg 		break;
341092a25256SJohan Hedberg 
341192a25256SJohan Hedberg 	case HCI_KEYPRESS_CLEARED:
341292a25256SJohan Hedberg 		conn->passkey_entered = 0;
341392a25256SJohan Hedberg 		break;
341492a25256SJohan Hedberg 
341592a25256SJohan Hedberg 	case HCI_KEYPRESS_COMPLETED:
341692a25256SJohan Hedberg 		return;
341792a25256SJohan Hedberg 	}
341892a25256SJohan Hedberg 
341992a25256SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
342092a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
342192a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
342292a25256SJohan Hedberg 					 conn->passkey_entered);
342392a25256SJohan Hedberg }
342492a25256SJohan Hedberg 
34256039aa73SGustavo Padovan static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
3426807deac2SGustavo Padovan 					 struct sk_buff *skb)
34270493684eSMarcel Holtmann {
34280493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
34290493684eSMarcel Holtmann 	struct hci_conn *conn;
34300493684eSMarcel Holtmann 
34310493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
34320493684eSMarcel Holtmann 
34330493684eSMarcel Holtmann 	hci_dev_lock(hdev);
34340493684eSMarcel Holtmann 
34350493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
34362a611692SJohan Hedberg 	if (!conn)
34372a611692SJohan Hedberg 		goto unlock;
34382a611692SJohan Hedberg 
34392a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
34402a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
34412a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
34422a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
34432a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
3444fa1bd918SMikel Astiz 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status)
3445bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
3446bab73cb6SJohan Hedberg 				 ev->status);
34472a611692SJohan Hedberg 
34480493684eSMarcel Holtmann 	hci_conn_put(conn);
34490493684eSMarcel Holtmann 
34502a611692SJohan Hedberg unlock:
34510493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
34520493684eSMarcel Holtmann }
34530493684eSMarcel Holtmann 
34546039aa73SGustavo Padovan static void hci_remote_host_features_evt(struct hci_dev *hdev,
3455807deac2SGustavo Padovan 					 struct sk_buff *skb)
345641a96212SMarcel Holtmann {
345741a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
345841a96212SMarcel Holtmann 	struct inquiry_entry *ie;
345941a96212SMarcel Holtmann 
346041a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
346141a96212SMarcel Holtmann 
346241a96212SMarcel Holtmann 	hci_dev_lock(hdev);
346341a96212SMarcel Holtmann 
3464cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3465cc11b9c1SAndrei Emeltchenko 	if (ie)
346602b7cc62SJohan Hedberg 		ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
346741a96212SMarcel Holtmann 
346841a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
346941a96212SMarcel Holtmann }
347041a96212SMarcel Holtmann 
34716039aa73SGustavo Padovan static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
34722763eda6SSzymon Janc 					    struct sk_buff *skb)
34732763eda6SSzymon Janc {
34742763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
34752763eda6SSzymon Janc 	struct oob_data *data;
34762763eda6SSzymon Janc 
34772763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
34782763eda6SSzymon Janc 
34792763eda6SSzymon Janc 	hci_dev_lock(hdev);
34802763eda6SSzymon Janc 
3481a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
3482e1ba1f15SSzymon Janc 		goto unlock;
3483e1ba1f15SSzymon Janc 
34842763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
34852763eda6SSzymon Janc 	if (data) {
34862763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_reply cp;
34872763eda6SSzymon Janc 
34882763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
34892763eda6SSzymon Janc 		memcpy(cp.hash, data->hash, sizeof(cp.hash));
34902763eda6SSzymon Janc 		memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
34912763eda6SSzymon Janc 
34922763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
34932763eda6SSzymon Janc 			     &cp);
34942763eda6SSzymon Janc 	} else {
34952763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
34962763eda6SSzymon Janc 
34972763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
34982763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
34992763eda6SSzymon Janc 			     &cp);
35002763eda6SSzymon Janc 	}
35012763eda6SSzymon Janc 
3502e1ba1f15SSzymon Janc unlock:
35032763eda6SSzymon Janc 	hci_dev_unlock(hdev);
35042763eda6SSzymon Janc }
35052763eda6SSzymon Janc 
35066039aa73SGustavo Padovan static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3507fcd89c09SVille Tervo {
3508fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3509fcd89c09SVille Tervo 	struct hci_conn *conn;
3510fcd89c09SVille Tervo 
35119f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3512fcd89c09SVille Tervo 
3513fcd89c09SVille Tervo 	hci_dev_lock(hdev);
3514fcd89c09SVille Tervo 
35154f72b329SAndrzej Kaczmarek 	conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
3516b62f328bSVille Tervo 	if (!conn) {
3517b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3518b62f328bSVille Tervo 		if (!conn) {
3519b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
3520230fd16aSAndre Guedes 			goto unlock;
3521b62f328bSVille Tervo 		}
352229b7988aSAndre Guedes 
352329b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
3524b9b343d2SAndre Guedes 
3525b9b343d2SAndre Guedes 		if (ev->role == LE_CONN_ROLE_MASTER) {
3526b9b343d2SAndre Guedes 			conn->out = true;
3527b9b343d2SAndre Guedes 			conn->link_mode |= HCI_LM_MASTER;
3528b9b343d2SAndre Guedes 		}
3529b62f328bSVille Tervo 	}
3530fcd89c09SVille Tervo 
3531cd17decbSAndre Guedes 	if (ev->status) {
3532cd17decbSAndre Guedes 		mgmt_connect_failed(hdev, &conn->dst, conn->type,
3533cd17decbSAndre Guedes 				    conn->dst_type, ev->status);
3534cd17decbSAndre Guedes 		hci_proto_connect_cfm(conn, ev->status);
3535cd17decbSAndre Guedes 		conn->state = BT_CLOSED;
3536cd17decbSAndre Guedes 		hci_conn_del(conn);
3537cd17decbSAndre Guedes 		goto unlock;
3538cd17decbSAndre Guedes 	}
3539cd17decbSAndre Guedes 
3540b644ba33SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3541b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
354295b23582SSzymon Janc 				      conn->dst_type, 0, NULL, 0, NULL);
354383bc71b4SVinicius Costa Gomes 
35447b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
3545fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
3546fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
3547fcd89c09SVille Tervo 
3548fcd89c09SVille Tervo 	hci_conn_hold_device(conn);
3549fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
3550fcd89c09SVille Tervo 
3551fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
3552fcd89c09SVille Tervo 
3553fcd89c09SVille Tervo unlock:
3554fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
3555fcd89c09SVille Tervo }
3556fcd89c09SVille Tervo 
35576039aa73SGustavo Padovan static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
35589aa04c91SAndre Guedes {
3559e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
3560e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
35613c9e9195SAndre Guedes 	s8 rssi;
35629aa04c91SAndre Guedes 
35639aa04c91SAndre Guedes 	hci_dev_lock(hdev);
35649aa04c91SAndre Guedes 
3565e95beb41SAndre Guedes 	while (num_reports--) {
3566e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
3567e95beb41SAndre Guedes 
35683c9e9195SAndre Guedes 		rssi = ev->data[ev->length];
35693c9e9195SAndre Guedes 		mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
357004124681SGustavo F. Padovan 				  NULL, rssi, 0, 1, ev->data, ev->length);
35713c9e9195SAndre Guedes 
3572e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
35739aa04c91SAndre Guedes 	}
35749aa04c91SAndre Guedes 
35759aa04c91SAndre Guedes 	hci_dev_unlock(hdev);
35769aa04c91SAndre Guedes }
35779aa04c91SAndre Guedes 
35786039aa73SGustavo Padovan static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
3579a7a595f6SVinicius Costa Gomes {
3580a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3581a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
3582bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
3583a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
3584c9839a11SVinicius Costa Gomes 	struct smp_ltk *ltk;
3585a7a595f6SVinicius Costa Gomes 
35869f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
3587a7a595f6SVinicius Costa Gomes 
3588a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
3589a7a595f6SVinicius Costa Gomes 
3590a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3591bea710feSVinicius Costa Gomes 	if (conn == NULL)
3592bea710feSVinicius Costa Gomes 		goto not_found;
3593a7a595f6SVinicius Costa Gomes 
3594bea710feSVinicius Costa Gomes 	ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3595bea710feSVinicius Costa Gomes 	if (ltk == NULL)
3596bea710feSVinicius Costa Gomes 		goto not_found;
3597bea710feSVinicius Costa Gomes 
3598bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
3599a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
3600c9839a11SVinicius Costa Gomes 
3601c9839a11SVinicius Costa Gomes 	if (ltk->authenticated)
3602c9839a11SVinicius Costa Gomes 		conn->sec_level = BT_SECURITY_HIGH;
3603a7a595f6SVinicius Costa Gomes 
3604a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3605a7a595f6SVinicius Costa Gomes 
3606c9839a11SVinicius Costa Gomes 	if (ltk->type & HCI_SMP_STK) {
3607c9839a11SVinicius Costa Gomes 		list_del(&ltk->list);
3608c9839a11SVinicius Costa Gomes 		kfree(ltk);
3609c9839a11SVinicius Costa Gomes 	}
3610c9839a11SVinicius Costa Gomes 
3611a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
3612bea710feSVinicius Costa Gomes 
3613bea710feSVinicius Costa Gomes 	return;
3614bea710feSVinicius Costa Gomes 
3615bea710feSVinicius Costa Gomes not_found:
3616bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
3617bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3618bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
3619a7a595f6SVinicius Costa Gomes }
3620a7a595f6SVinicius Costa Gomes 
36216039aa73SGustavo Padovan static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3622fcd89c09SVille Tervo {
3623fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
3624fcd89c09SVille Tervo 
3625fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
3626fcd89c09SVille Tervo 
3627fcd89c09SVille Tervo 	switch (le_ev->subevent) {
3628fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
3629fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
3630fcd89c09SVille Tervo 		break;
3631fcd89c09SVille Tervo 
36329aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
36339aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
36349aa04c91SAndre Guedes 		break;
36359aa04c91SAndre Guedes 
3636a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
3637a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
3638a7a595f6SVinicius Costa Gomes 		break;
3639a7a595f6SVinicius Costa Gomes 
3640fcd89c09SVille Tervo 	default:
3641fcd89c09SVille Tervo 		break;
3642fcd89c09SVille Tervo 	}
3643fcd89c09SVille Tervo }
3644fcd89c09SVille Tervo 
36459495b2eeSAndrei Emeltchenko static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
36469495b2eeSAndrei Emeltchenko {
36479495b2eeSAndrei Emeltchenko 	struct hci_ev_channel_selected *ev = (void *) skb->data;
36489495b2eeSAndrei Emeltchenko 	struct hci_conn *hcon;
36499495b2eeSAndrei Emeltchenko 
36509495b2eeSAndrei Emeltchenko 	BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
36519495b2eeSAndrei Emeltchenko 
36529495b2eeSAndrei Emeltchenko 	skb_pull(skb, sizeof(*ev));
36539495b2eeSAndrei Emeltchenko 
36549495b2eeSAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
36559495b2eeSAndrei Emeltchenko 	if (!hcon)
36569495b2eeSAndrei Emeltchenko 		return;
36579495b2eeSAndrei Emeltchenko 
36589495b2eeSAndrei Emeltchenko 	amp_read_loc_assoc_final_data(hdev, hcon);
36599495b2eeSAndrei Emeltchenko }
36609495b2eeSAndrei Emeltchenko 
36611da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
36621da177e4SLinus Torvalds {
3663a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
3664a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
36651da177e4SLinus Torvalds 
36661da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
36671da177e4SLinus Torvalds 
3668a9de9248SMarcel Holtmann 	switch (event) {
36691da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
36701da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
36711da177e4SLinus Torvalds 		break;
36721da177e4SLinus Torvalds 
36731da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
36741da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
36751da177e4SLinus Torvalds 		break;
36761da177e4SLinus Torvalds 
3677a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
3678a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
367921d9e30eSMarcel Holtmann 		break;
368021d9e30eSMarcel Holtmann 
36811da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
36821da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
36831da177e4SLinus Torvalds 		break;
36841da177e4SLinus Torvalds 
36851da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
36861da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
36871da177e4SLinus Torvalds 		break;
36881da177e4SLinus Torvalds 
36891da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
36901da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
36911da177e4SLinus Torvalds 		break;
36921da177e4SLinus Torvalds 
3693a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
3694a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
3695a9de9248SMarcel Holtmann 		break;
3696a9de9248SMarcel Holtmann 
36971da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
36981da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
36991da177e4SLinus Torvalds 		break;
37001da177e4SLinus Torvalds 
3701a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3702a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
3703a9de9248SMarcel Holtmann 		break;
3704a9de9248SMarcel Holtmann 
3705a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
3706a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
3707a9de9248SMarcel Holtmann 		break;
3708a9de9248SMarcel Holtmann 
3709a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_VERSION:
3710a9de9248SMarcel Holtmann 		hci_remote_version_evt(hdev, skb);
3711a9de9248SMarcel Holtmann 		break;
3712a9de9248SMarcel Holtmann 
3713a9de9248SMarcel Holtmann 	case HCI_EV_QOS_SETUP_COMPLETE:
3714a9de9248SMarcel Holtmann 		hci_qos_setup_complete_evt(hdev, skb);
3715a9de9248SMarcel Holtmann 		break;
3716a9de9248SMarcel Holtmann 
3717a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
3718a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
3719a9de9248SMarcel Holtmann 		break;
3720a9de9248SMarcel Holtmann 
3721a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
3722a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
3723a9de9248SMarcel Holtmann 		break;
3724a9de9248SMarcel Holtmann 
3725a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
3726a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
3727a9de9248SMarcel Holtmann 		break;
3728a9de9248SMarcel Holtmann 
3729a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
3730a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
3731a9de9248SMarcel Holtmann 		break;
3732a9de9248SMarcel Holtmann 
3733a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
3734a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
37351da177e4SLinus Torvalds 		break;
37361da177e4SLinus Torvalds 
37371da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
37381da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
37391da177e4SLinus Torvalds 		break;
37401da177e4SLinus Torvalds 
37411da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
37421da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
37431da177e4SLinus Torvalds 		break;
37441da177e4SLinus Torvalds 
37451da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
37461da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
37471da177e4SLinus Torvalds 		break;
37481da177e4SLinus Torvalds 
37491da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
37501da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
37511da177e4SLinus Torvalds 		break;
37521da177e4SLinus Torvalds 
3753a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
3754a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
3755a8746417SMarcel Holtmann 		break;
3756a8746417SMarcel Holtmann 
375785a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
375885a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
375985a1e930SMarcel Holtmann 		break;
376085a1e930SMarcel Holtmann 
3761a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3762a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
3763a9de9248SMarcel Holtmann 		break;
3764a9de9248SMarcel Holtmann 
3765a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
3766a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
3767a9de9248SMarcel Holtmann 		break;
3768a9de9248SMarcel Holtmann 
3769a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
3770a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
3771a9de9248SMarcel Holtmann 		break;
3772a9de9248SMarcel Holtmann 
3773a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_CHANGED:
3774a9de9248SMarcel Holtmann 		hci_sync_conn_changed_evt(hdev, skb);
3775a9de9248SMarcel Holtmann 		break;
3776a9de9248SMarcel Holtmann 
377704837f64SMarcel Holtmann 	case HCI_EV_SNIFF_SUBRATE:
377804837f64SMarcel Holtmann 		hci_sniff_subrate_evt(hdev, skb);
377904837f64SMarcel Holtmann 		break;
378004837f64SMarcel Holtmann 
3781a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
3782a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
37831da177e4SLinus Torvalds 		break;
37841da177e4SLinus Torvalds 
37851c2e0041SJohan Hedberg 	case HCI_EV_KEY_REFRESH_COMPLETE:
37861c2e0041SJohan Hedberg 		hci_key_refresh_complete_evt(hdev, skb);
37871c2e0041SJohan Hedberg 		break;
37881c2e0041SJohan Hedberg 
37890493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
37900493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
37910493684eSMarcel Holtmann 		break;
37920493684eSMarcel Holtmann 
379303b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
379403b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
379503b555e1SJohan Hedberg 		break;
379603b555e1SJohan Hedberg 
3797a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
3798a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
3799a5c29683SJohan Hedberg 		break;
3800a5c29683SJohan Hedberg 
38011143d458SBrian Gix 	case HCI_EV_USER_PASSKEY_REQUEST:
38021143d458SBrian Gix 		hci_user_passkey_request_evt(hdev, skb);
38031143d458SBrian Gix 		break;
38041143d458SBrian Gix 
380592a25256SJohan Hedberg 	case HCI_EV_USER_PASSKEY_NOTIFY:
380692a25256SJohan Hedberg 		hci_user_passkey_notify_evt(hdev, skb);
380792a25256SJohan Hedberg 		break;
380892a25256SJohan Hedberg 
380992a25256SJohan Hedberg 	case HCI_EV_KEYPRESS_NOTIFY:
381092a25256SJohan Hedberg 		hci_keypress_notify_evt(hdev, skb);
381192a25256SJohan Hedberg 		break;
381292a25256SJohan Hedberg 
38130493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
38140493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
38150493684eSMarcel Holtmann 		break;
38160493684eSMarcel Holtmann 
381741a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
381841a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
381941a96212SMarcel Holtmann 		break;
382041a96212SMarcel Holtmann 
3821fcd89c09SVille Tervo 	case HCI_EV_LE_META:
3822fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
3823fcd89c09SVille Tervo 		break;
3824fcd89c09SVille Tervo 
38259495b2eeSAndrei Emeltchenko 	case HCI_EV_CHANNEL_SELECTED:
38269495b2eeSAndrei Emeltchenko 		hci_chan_selected_evt(hdev, skb);
38279495b2eeSAndrei Emeltchenko 		break;
38289495b2eeSAndrei Emeltchenko 
38292763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
38302763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
38312763eda6SSzymon Janc 		break;
38322763eda6SSzymon Janc 
383325e89e99SAndrei Emeltchenko 	case HCI_EV_NUM_COMP_BLOCKS:
383425e89e99SAndrei Emeltchenko 		hci_num_comp_blocks_evt(hdev, skb);
383525e89e99SAndrei Emeltchenko 		break;
383625e89e99SAndrei Emeltchenko 
38371da177e4SLinus Torvalds 	default:
38389f1db00cSAndrei Emeltchenko 		BT_DBG("%s event 0x%2.2x", hdev->name, event);
38391da177e4SLinus Torvalds 		break;
38401da177e4SLinus Torvalds 	}
38411da177e4SLinus Torvalds 
38421da177e4SLinus Torvalds 	kfree_skb(skb);
38431da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
38441da177e4SLinus Torvalds }
3845