xref: /openbmc/linux/net/bluetooth/hci_event.c (revision c3e7c0d9)
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>
321da177e4SLinus Torvalds 
331da177e4SLinus Torvalds /* Handle HCI Event packets */
341da177e4SLinus Torvalds 
35a9de9248SMarcel Holtmann static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
361da177e4SLinus Torvalds {
37a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
381da177e4SLinus Torvalds 
399f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
401da177e4SLinus Torvalds 
41e6d465cbSAndre Guedes 	if (status) {
42e6d465cbSAndre Guedes 		hci_dev_lock(hdev);
43e6d465cbSAndre Guedes 		mgmt_stop_discovery_failed(hdev, status);
44e6d465cbSAndre Guedes 		hci_dev_unlock(hdev);
45a9de9248SMarcel Holtmann 		return;
46e6d465cbSAndre Guedes 	}
471da177e4SLinus Torvalds 
4889352e7dSAndre Guedes 	clear_bit(HCI_INQUIRY, &hdev->flags);
4989352e7dSAndre Guedes 
5056e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
51ff9ef578SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
5256e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
53a9de9248SMarcel Holtmann 
5423bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status);
55a9de9248SMarcel Holtmann 
56a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
571da177e4SLinus Torvalds }
586bd57416SMarcel Holtmann 
594d93483bSAndre Guedes static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
604d93483bSAndre Guedes {
614d93483bSAndre Guedes 	__u8 status = *((__u8 *) skb->data);
624d93483bSAndre Guedes 
639f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
64ae854a70SAndre Guedes 
65ae854a70SAndre Guedes 	if (status)
66ae854a70SAndre Guedes 		return;
67ae854a70SAndre Guedes 
68ae854a70SAndre Guedes 	set_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
694d93483bSAndre Guedes }
704d93483bSAndre Guedes 
71a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
721da177e4SLinus Torvalds {
73a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
74a9de9248SMarcel Holtmann 
759f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
76a9de9248SMarcel Holtmann 
77a9de9248SMarcel Holtmann 	if (status)
78a9de9248SMarcel Holtmann 		return;
79a9de9248SMarcel Holtmann 
80ae854a70SAndre Guedes 	clear_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
81ae854a70SAndre Guedes 
82a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
83a9de9248SMarcel Holtmann }
84a9de9248SMarcel Holtmann 
85807deac2SGustavo Padovan static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev,
86807deac2SGustavo Padovan 					  struct sk_buff *skb)
87a9de9248SMarcel Holtmann {
88a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
89a9de9248SMarcel Holtmann }
90a9de9248SMarcel Holtmann 
91a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
92a9de9248SMarcel Holtmann {
93a9de9248SMarcel Holtmann 	struct hci_rp_role_discovery *rp = (void *) skb->data;
941da177e4SLinus Torvalds 	struct hci_conn *conn;
951da177e4SLinus Torvalds 
969f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
971da177e4SLinus Torvalds 
98a9de9248SMarcel Holtmann 	if (rp->status)
99a9de9248SMarcel Holtmann 		return;
1001da177e4SLinus Torvalds 
1011da177e4SLinus Torvalds 	hci_dev_lock(hdev);
1021da177e4SLinus Torvalds 
103a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
1041da177e4SLinus Torvalds 	if (conn) {
105a9de9248SMarcel Holtmann 		if (rp->role)
1061da177e4SLinus Torvalds 			conn->link_mode &= ~HCI_LM_MASTER;
1071da177e4SLinus Torvalds 		else
1081da177e4SLinus Torvalds 			conn->link_mode |= HCI_LM_MASTER;
1091da177e4SLinus Torvalds 	}
1101da177e4SLinus Torvalds 
1111da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
112a9de9248SMarcel Holtmann }
1131da177e4SLinus Torvalds 
114e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
115e4e8e37cSMarcel Holtmann {
116e4e8e37cSMarcel Holtmann 	struct hci_rp_read_link_policy *rp = (void *) skb->data;
117e4e8e37cSMarcel Holtmann 	struct hci_conn *conn;
118e4e8e37cSMarcel Holtmann 
1199f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
120e4e8e37cSMarcel Holtmann 
121e4e8e37cSMarcel Holtmann 	if (rp->status)
122e4e8e37cSMarcel Holtmann 		return;
123e4e8e37cSMarcel Holtmann 
124e4e8e37cSMarcel Holtmann 	hci_dev_lock(hdev);
125e4e8e37cSMarcel Holtmann 
126e4e8e37cSMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
127e4e8e37cSMarcel Holtmann 	if (conn)
128e4e8e37cSMarcel Holtmann 		conn->link_policy = __le16_to_cpu(rp->policy);
129e4e8e37cSMarcel Holtmann 
130e4e8e37cSMarcel Holtmann 	hci_dev_unlock(hdev);
131e4e8e37cSMarcel Holtmann }
132e4e8e37cSMarcel Holtmann 
133a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
134a9de9248SMarcel Holtmann {
135a9de9248SMarcel Holtmann 	struct hci_rp_write_link_policy *rp = (void *) skb->data;
136a9de9248SMarcel Holtmann 	struct hci_conn *conn;
137a9de9248SMarcel Holtmann 	void *sent;
138a9de9248SMarcel Holtmann 
1399f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
140a9de9248SMarcel Holtmann 
141a9de9248SMarcel Holtmann 	if (rp->status)
142a9de9248SMarcel Holtmann 		return;
143a9de9248SMarcel Holtmann 
144a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
14504837f64SMarcel Holtmann 	if (!sent)
146a9de9248SMarcel Holtmann 		return;
14704837f64SMarcel Holtmann 
14804837f64SMarcel Holtmann 	hci_dev_lock(hdev);
14904837f64SMarcel Holtmann 
150a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
151e4e8e37cSMarcel Holtmann 	if (conn)
15283985319SHarvey Harrison 		conn->link_policy = get_unaligned_le16(sent + 2);
15304837f64SMarcel Holtmann 
15404837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
1551da177e4SLinus Torvalds }
1561da177e4SLinus Torvalds 
157807deac2SGustavo Padovan static void hci_cc_read_def_link_policy(struct hci_dev *hdev,
158807deac2SGustavo Padovan 					struct sk_buff *skb)
159e4e8e37cSMarcel Holtmann {
160e4e8e37cSMarcel Holtmann 	struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
161e4e8e37cSMarcel Holtmann 
1629f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
163e4e8e37cSMarcel Holtmann 
164e4e8e37cSMarcel Holtmann 	if (rp->status)
165e4e8e37cSMarcel Holtmann 		return;
166e4e8e37cSMarcel Holtmann 
167e4e8e37cSMarcel Holtmann 	hdev->link_policy = __le16_to_cpu(rp->policy);
168e4e8e37cSMarcel Holtmann }
169e4e8e37cSMarcel Holtmann 
170807deac2SGustavo Padovan static void hci_cc_write_def_link_policy(struct hci_dev *hdev,
171807deac2SGustavo Padovan 					 struct sk_buff *skb)
172e4e8e37cSMarcel Holtmann {
173e4e8e37cSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
174e4e8e37cSMarcel Holtmann 	void *sent;
175e4e8e37cSMarcel Holtmann 
1769f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
177e4e8e37cSMarcel Holtmann 
178e4e8e37cSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
179e4e8e37cSMarcel Holtmann 	if (!sent)
180e4e8e37cSMarcel Holtmann 		return;
181e4e8e37cSMarcel Holtmann 
182e4e8e37cSMarcel Holtmann 	if (!status)
183e4e8e37cSMarcel Holtmann 		hdev->link_policy = get_unaligned_le16(sent);
184e4e8e37cSMarcel Holtmann 
18523bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status);
186e4e8e37cSMarcel Holtmann }
187e4e8e37cSMarcel Holtmann 
188a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
1891da177e4SLinus Torvalds {
190a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
191a9de9248SMarcel Holtmann 
1929f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
193a9de9248SMarcel Holtmann 
19410572132SGustavo F. Padovan 	clear_bit(HCI_RESET, &hdev->flags);
19510572132SGustavo F. Padovan 
19623bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_RESET, status);
197d23264a8SAndre Guedes 
198a297e97cSJohan Hedberg 	/* Reset all non-persistent flags */
199ae854a70SAndre Guedes 	hdev->dev_flags &= ~(BIT(HCI_LE_SCAN) | BIT(HCI_PENDING_CLASS) |
200ae854a70SAndre Guedes 			     BIT(HCI_PERIODIC_INQ));
20169775ff6SAndre Guedes 
20269775ff6SAndre Guedes 	hdev->discovery.state = DISCOVERY_STOPPED;
203a9de9248SMarcel Holtmann }
204a9de9248SMarcel Holtmann 
205a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
206a9de9248SMarcel Holtmann {
207a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
2081da177e4SLinus Torvalds 	void *sent;
2091da177e4SLinus Torvalds 
2109f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
2111da177e4SLinus Torvalds 
212a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
2131da177e4SLinus Torvalds 	if (!sent)
214a9de9248SMarcel Holtmann 		return;
2151da177e4SLinus Torvalds 
21656e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
21756e5cb86SJohan Hedberg 
218f51d5b24SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
219f51d5b24SJohan Hedberg 		mgmt_set_local_name_complete(hdev, sent, status);
22028cc7bdeSJohan Hedberg 	else if (!status)
22128cc7bdeSJohan Hedberg 		memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
222f51d5b24SJohan Hedberg 
22356e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
2243159d384SJohan Hedberg 
2253159d384SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_LOCAL_NAME, status);
226a9de9248SMarcel Holtmann }
227a9de9248SMarcel Holtmann 
228a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
229a9de9248SMarcel Holtmann {
230a9de9248SMarcel Holtmann 	struct hci_rp_read_local_name *rp = (void *) skb->data;
231a9de9248SMarcel Holtmann 
2329f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
233a9de9248SMarcel Holtmann 
234a9de9248SMarcel Holtmann 	if (rp->status)
235a9de9248SMarcel Holtmann 		return;
236a9de9248SMarcel Holtmann 
237db99b5fcSJohan Hedberg 	if (test_bit(HCI_SETUP, &hdev->dev_flags))
2381f6c6378SJohan Hedberg 		memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
239a9de9248SMarcel Holtmann }
240a9de9248SMarcel Holtmann 
241a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
242a9de9248SMarcel Holtmann {
243a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
244a9de9248SMarcel Holtmann 	void *sent;
245a9de9248SMarcel Holtmann 
2469f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
247a9de9248SMarcel Holtmann 
248a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
249a9de9248SMarcel Holtmann 	if (!sent)
250a9de9248SMarcel Holtmann 		return;
2511da177e4SLinus Torvalds 
2521da177e4SLinus Torvalds 	if (!status) {
253a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
254a9de9248SMarcel Holtmann 
2551da177e4SLinus Torvalds 		if (param == AUTH_ENABLED)
2561da177e4SLinus Torvalds 			set_bit(HCI_AUTH, &hdev->flags);
2571da177e4SLinus Torvalds 		else
2581da177e4SLinus Torvalds 			clear_bit(HCI_AUTH, &hdev->flags);
2591da177e4SLinus Torvalds 	}
260a9de9248SMarcel Holtmann 
26133ef95edSJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
26233ef95edSJohan Hedberg 		mgmt_auth_enable_complete(hdev, status);
26333ef95edSJohan Hedberg 
26423bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status);
265a9de9248SMarcel Holtmann }
2661da177e4SLinus Torvalds 
267a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
268a9de9248SMarcel Holtmann {
269a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
270a9de9248SMarcel Holtmann 	void *sent;
271a9de9248SMarcel Holtmann 
2729f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
273a9de9248SMarcel Holtmann 
274a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
2751da177e4SLinus Torvalds 	if (!sent)
276a9de9248SMarcel Holtmann 		return;
2771da177e4SLinus Torvalds 
2781da177e4SLinus Torvalds 	if (!status) {
279a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
280a9de9248SMarcel Holtmann 
2811da177e4SLinus Torvalds 		if (param)
2821da177e4SLinus Torvalds 			set_bit(HCI_ENCRYPT, &hdev->flags);
2831da177e4SLinus Torvalds 		else
2841da177e4SLinus Torvalds 			clear_bit(HCI_ENCRYPT, &hdev->flags);
2851da177e4SLinus Torvalds 	}
286a9de9248SMarcel Holtmann 
28723bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status);
2881da177e4SLinus Torvalds }
2891da177e4SLinus Torvalds 
290a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
291a9de9248SMarcel Holtmann {
29236f7fc7eSJohan Hedberg 	__u8 param, status = *((__u8 *) skb->data);
29336f7fc7eSJohan Hedberg 	int old_pscan, old_iscan;
294a9de9248SMarcel Holtmann 	void *sent;
2951da177e4SLinus Torvalds 
2969f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
297a9de9248SMarcel Holtmann 
298a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
2991da177e4SLinus Torvalds 	if (!sent)
300a9de9248SMarcel Holtmann 		return;
3011da177e4SLinus Torvalds 
30236f7fc7eSJohan Hedberg 	param = *((__u8 *) sent);
303a9de9248SMarcel Holtmann 
30456e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
30556e5cb86SJohan Hedberg 
3062d7cee58SJohan Hedberg 	if (status != 0) {
307744cf19eSJohan Hedberg 		mgmt_write_scan_failed(hdev, param, status);
3082d7cee58SJohan Hedberg 		hdev->discov_timeout = 0;
3092d7cee58SJohan Hedberg 		goto done;
3102d7cee58SJohan Hedberg 	}
3112d7cee58SJohan Hedberg 
3129fbcbb45SJohan Hedberg 	old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
3139fbcbb45SJohan Hedberg 	old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
314a9de9248SMarcel Holtmann 
31573f22f62SJohan Hedberg 	if (param & SCAN_INQUIRY) {
3161da177e4SLinus Torvalds 		set_bit(HCI_ISCAN, &hdev->flags);
3179fbcbb45SJohan Hedberg 		if (!old_iscan)
318744cf19eSJohan Hedberg 			mgmt_discoverable(hdev, 1);
31916ab91abSJohan Hedberg 		if (hdev->discov_timeout > 0) {
32016ab91abSJohan Hedberg 			int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
32116ab91abSJohan Hedberg 			queue_delayed_work(hdev->workqueue, &hdev->discov_off,
32216ab91abSJohan Hedberg 					   to);
32316ab91abSJohan Hedberg 		}
3249fbcbb45SJohan Hedberg 	} else if (old_iscan)
325744cf19eSJohan Hedberg 		mgmt_discoverable(hdev, 0);
3261da177e4SLinus Torvalds 
3279fbcbb45SJohan Hedberg 	if (param & SCAN_PAGE) {
3281da177e4SLinus Torvalds 		set_bit(HCI_PSCAN, &hdev->flags);
3299fbcbb45SJohan Hedberg 		if (!old_pscan)
330744cf19eSJohan Hedberg 			mgmt_connectable(hdev, 1);
3319fbcbb45SJohan Hedberg 	} else if (old_pscan)
332744cf19eSJohan Hedberg 		mgmt_connectable(hdev, 0);
333a9de9248SMarcel Holtmann 
33436f7fc7eSJohan Hedberg done:
33556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
33623bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
3371da177e4SLinus Torvalds }
3381da177e4SLinus Torvalds 
339a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
340a9de9248SMarcel Holtmann {
341a9de9248SMarcel Holtmann 	struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
342a9de9248SMarcel Holtmann 
3439f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
344a9de9248SMarcel Holtmann 
345a9de9248SMarcel Holtmann 	if (rp->status)
346a9de9248SMarcel Holtmann 		return;
347a9de9248SMarcel Holtmann 
348a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, rp->dev_class, 3);
349a9de9248SMarcel Holtmann 
350a9de9248SMarcel Holtmann 	BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
351a9de9248SMarcel Holtmann 	       hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
352a9de9248SMarcel Holtmann }
353a9de9248SMarcel Holtmann 
354a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
355a9de9248SMarcel Holtmann {
356a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
357a9de9248SMarcel Holtmann 	void *sent;
358a9de9248SMarcel Holtmann 
3599f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
360a9de9248SMarcel Holtmann 
361a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
362a9de9248SMarcel Holtmann 	if (!sent)
363a9de9248SMarcel Holtmann 		return;
364a9de9248SMarcel Holtmann 
3657f9a903cSMarcel Holtmann 	hci_dev_lock(hdev);
3667f9a903cSMarcel Holtmann 
3677f9a903cSMarcel Holtmann 	if (status == 0)
368a9de9248SMarcel Holtmann 		memcpy(hdev->dev_class, sent, 3);
3697f9a903cSMarcel Holtmann 
3707f9a903cSMarcel Holtmann 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3717f9a903cSMarcel Holtmann 		mgmt_set_class_of_dev_complete(hdev, sent, status);
3727f9a903cSMarcel Holtmann 
3737f9a903cSMarcel Holtmann 	hci_dev_unlock(hdev);
374a9de9248SMarcel Holtmann }
375a9de9248SMarcel Holtmann 
376a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
377a9de9248SMarcel Holtmann {
378a9de9248SMarcel Holtmann 	struct hci_rp_read_voice_setting *rp = (void *) skb->data;
379a9de9248SMarcel Holtmann 	__u16 setting;
380a9de9248SMarcel Holtmann 
3819f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
382a9de9248SMarcel Holtmann 
383a9de9248SMarcel Holtmann 	if (rp->status)
384a9de9248SMarcel Holtmann 		return;
385a9de9248SMarcel Holtmann 
386a9de9248SMarcel Holtmann 	setting = __le16_to_cpu(rp->voice_setting);
387a9de9248SMarcel Holtmann 
388a9de9248SMarcel Holtmann 	if (hdev->voice_setting == setting)
389a9de9248SMarcel Holtmann 		return;
390a9de9248SMarcel Holtmann 
391a9de9248SMarcel Holtmann 	hdev->voice_setting = setting;
392a9de9248SMarcel Holtmann 
3939f1db00cSAndrei Emeltchenko 	BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
394a9de9248SMarcel Holtmann 
3953c54711cSGustavo F. Padovan 	if (hdev->notify)
396a9de9248SMarcel Holtmann 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
397a9de9248SMarcel Holtmann }
398a9de9248SMarcel Holtmann 
3998fc9ced3SGustavo Padovan static void hci_cc_write_voice_setting(struct hci_dev *hdev,
4008fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
401a9de9248SMarcel Holtmann {
402a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
403f383f275SMarcel Holtmann 	__u16 setting;
404a9de9248SMarcel Holtmann 	void *sent;
405a9de9248SMarcel Holtmann 
4069f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
407a9de9248SMarcel Holtmann 
408f383f275SMarcel Holtmann 	if (status)
409f383f275SMarcel Holtmann 		return;
410f383f275SMarcel Holtmann 
411a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
412a9de9248SMarcel Holtmann 	if (!sent)
413a9de9248SMarcel Holtmann 		return;
414a9de9248SMarcel Holtmann 
415f383f275SMarcel Holtmann 	setting = get_unaligned_le16(sent);
4161da177e4SLinus Torvalds 
417f383f275SMarcel Holtmann 	if (hdev->voice_setting == setting)
418f383f275SMarcel Holtmann 		return;
419f383f275SMarcel Holtmann 
4201da177e4SLinus Torvalds 	hdev->voice_setting = setting;
4211da177e4SLinus Torvalds 
4229f1db00cSAndrei Emeltchenko 	BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
4231da177e4SLinus Torvalds 
4243c54711cSGustavo F. Padovan 	if (hdev->notify)
4251da177e4SLinus Torvalds 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
4261da177e4SLinus Torvalds }
4271da177e4SLinus Torvalds 
428a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
4291da177e4SLinus Torvalds {
430a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
4311da177e4SLinus Torvalds 
4329f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
4331da177e4SLinus Torvalds 
43423bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
4351143e5a6SMarcel Holtmann }
4361143e5a6SMarcel Holtmann 
437333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
438333140b5SMarcel Holtmann {
439333140b5SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
440333140b5SMarcel Holtmann 	void *sent;
441333140b5SMarcel Holtmann 
4429f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
443333140b5SMarcel Holtmann 
444333140b5SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
445333140b5SMarcel Holtmann 	if (!sent)
446333140b5SMarcel Holtmann 		return;
447333140b5SMarcel Holtmann 
448c0ecddc2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
449c0ecddc2SJohan Hedberg 		mgmt_ssp_enable_complete(hdev, *((u8 *) sent), status);
450c0ecddc2SJohan Hedberg 	else if (!status) {
45184bde9d6SJohan Hedberg 		if (*((u8 *) sent))
45284bde9d6SJohan Hedberg 			set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
45384bde9d6SJohan Hedberg 		else
45484bde9d6SJohan Hedberg 			clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
455c0ecddc2SJohan Hedberg 	}
456333140b5SMarcel Holtmann }
457333140b5SMarcel Holtmann 
458d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
459d5859e22SJohan Hedberg {
460d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
461d5859e22SJohan Hedberg 		return 2;
462d5859e22SJohan Hedberg 
463d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
464d5859e22SJohan Hedberg 		return 1;
465d5859e22SJohan Hedberg 
466d5859e22SJohan Hedberg 	if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
467d5859e22SJohan Hedberg 	    hdev->lmp_subver == 0x0757)
468d5859e22SJohan Hedberg 		return 1;
469d5859e22SJohan Hedberg 
470d5859e22SJohan Hedberg 	if (hdev->manufacturer == 15) {
471d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
472d5859e22SJohan Hedberg 			return 1;
473d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
474d5859e22SJohan Hedberg 			return 1;
475d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
476d5859e22SJohan Hedberg 			return 1;
477d5859e22SJohan Hedberg 	}
478d5859e22SJohan Hedberg 
479d5859e22SJohan Hedberg 	if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
480d5859e22SJohan Hedberg 	    hdev->lmp_subver == 0x1805)
481d5859e22SJohan Hedberg 		return 1;
482d5859e22SJohan Hedberg 
483d5859e22SJohan Hedberg 	return 0;
484d5859e22SJohan Hedberg }
485d5859e22SJohan Hedberg 
486d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev)
487d5859e22SJohan Hedberg {
488d5859e22SJohan Hedberg 	u8 mode;
489d5859e22SJohan Hedberg 
490d5859e22SJohan Hedberg 	mode = hci_get_inquiry_mode(hdev);
491d5859e22SJohan Hedberg 
492d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
493d5859e22SJohan Hedberg }
494d5859e22SJohan Hedberg 
495d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev)
496d5859e22SJohan Hedberg {
497d5859e22SJohan Hedberg 	/* The second byte is 0xff instead of 0x9f (two reserved bits
498d5859e22SJohan Hedberg 	 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
499d5859e22SJohan Hedberg 	 * command otherwise */
500d5859e22SJohan Hedberg 	u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
501d5859e22SJohan Hedberg 
5026de6c18dSVille Tervo 	/* CSR 1.1 dongles does not accept any bitfield so don't try to set
5036de6c18dSVille Tervo 	 * any event mask for pre 1.2 devices */
5045a13b095SAndrei Emeltchenko 	if (hdev->hci_ver < BLUETOOTH_VER_1_2)
5056de6c18dSVille Tervo 		return;
5066de6c18dSVille Tervo 
507d5859e22SJohan Hedberg 	events[4] |= 0x01; /* Flow Specification Complete */
508d5859e22SJohan Hedberg 	events[4] |= 0x02; /* Inquiry Result with RSSI */
509d5859e22SJohan Hedberg 	events[4] |= 0x04; /* Read Remote Extended Features Complete */
510d5859e22SJohan Hedberg 	events[5] |= 0x08; /* Synchronous Connection Complete */
511d5859e22SJohan Hedberg 	events[5] |= 0x10; /* Synchronous Connection Changed */
512d5859e22SJohan Hedberg 
513d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
514a24299e6SJohan Hedberg 		events[4] |= 0x02; /* Inquiry Result with RSSI */
515d5859e22SJohan Hedberg 
516d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_SNIFF_SUBR)
517d5859e22SJohan Hedberg 		events[5] |= 0x20; /* Sniff Subrating */
518d5859e22SJohan Hedberg 
519d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_PAUSE_ENC)
520d5859e22SJohan Hedberg 		events[5] |= 0x80; /* Encryption Key Refresh Complete */
521d5859e22SJohan Hedberg 
522d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
523d5859e22SJohan Hedberg 		events[5] |= 0x40; /* Extended Inquiry Result */
524d5859e22SJohan Hedberg 
525d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_NO_FLUSH)
526d5859e22SJohan Hedberg 		events[7] |= 0x01; /* Enhanced Flush Complete */
527d5859e22SJohan Hedberg 
528d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_LSTO)
529d5859e22SJohan Hedberg 		events[6] |= 0x80; /* Link Supervision Timeout Changed */
530d5859e22SJohan Hedberg 
531d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_SIMPLE_PAIR) {
532d5859e22SJohan Hedberg 		events[6] |= 0x01;	/* IO Capability Request */
533d5859e22SJohan Hedberg 		events[6] |= 0x02;	/* IO Capability Response */
534d5859e22SJohan Hedberg 		events[6] |= 0x04;	/* User Confirmation Request */
535d5859e22SJohan Hedberg 		events[6] |= 0x08;	/* User Passkey Request */
536d5859e22SJohan Hedberg 		events[6] |= 0x10;	/* Remote OOB Data Request */
537d5859e22SJohan Hedberg 		events[6] |= 0x20;	/* Simple Pairing Complete */
538d5859e22SJohan Hedberg 		events[7] |= 0x04;	/* User Passkey Notification */
539d5859e22SJohan Hedberg 		events[7] |= 0x08;	/* Keypress Notification */
540d5859e22SJohan Hedberg 		events[7] |= 0x10;	/* Remote Host Supported
541d5859e22SJohan Hedberg 					 * Features Notification */
542d5859e22SJohan Hedberg 	}
543d5859e22SJohan Hedberg 
544d5859e22SJohan Hedberg 	if (hdev->features[4] & LMP_LE)
545d5859e22SJohan Hedberg 		events[7] |= 0x20;	/* LE Meta-Event */
546d5859e22SJohan Hedberg 
547d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
548d5859e22SJohan Hedberg }
549d5859e22SJohan Hedberg 
550d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev)
551d5859e22SJohan Hedberg {
552e61ef499SAndrei Emeltchenko 	if (hdev->dev_type != HCI_BREDR)
553e61ef499SAndrei Emeltchenko 		return;
554e61ef499SAndrei Emeltchenko 
555d5859e22SJohan Hedberg 	hci_setup_event_mask(hdev);
556d5859e22SJohan Hedberg 
557d095c1ebSAndrei Emeltchenko 	if (hdev->hci_ver > BLUETOOTH_VER_1_1)
558d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
559d5859e22SJohan Hedberg 
5606d3c730fSGustavo Padovan 	if (lmp_ssp_capable(hdev)) {
56154d04dbbSJohan Hedberg 		if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
562d5859e22SJohan Hedberg 			u8 mode = 0x01;
56354d04dbbSJohan Hedberg 			hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE,
56454d04dbbSJohan Hedberg 				     sizeof(mode), &mode);
56554d04dbbSJohan Hedberg 		} else {
56654d04dbbSJohan Hedberg 			struct hci_cp_write_eir cp;
56754d04dbbSJohan Hedberg 
56854d04dbbSJohan Hedberg 			memset(hdev->eir, 0, sizeof(hdev->eir));
56954d04dbbSJohan Hedberg 			memset(&cp, 0, sizeof(cp));
57054d04dbbSJohan Hedberg 
57154d04dbbSJohan Hedberg 			hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
57254d04dbbSJohan Hedberg 		}
573d5859e22SJohan Hedberg 	}
574d5859e22SJohan Hedberg 
575d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
576d5859e22SJohan Hedberg 		hci_setup_inquiry_mode(hdev);
577d5859e22SJohan Hedberg 
578d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_INQ_TX_PWR)
579d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
580971e3a4bSAndre Guedes 
581971e3a4bSAndre Guedes 	if (hdev->features[7] & LMP_EXTFEATURES) {
582971e3a4bSAndre Guedes 		struct hci_cp_read_local_ext_features cp;
583971e3a4bSAndre Guedes 
584971e3a4bSAndre Guedes 		cp.page = 0x01;
58504124681SGustavo F. Padovan 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp),
58604124681SGustavo F. Padovan 			     &cp);
587971e3a4bSAndre Guedes 	}
588e6100a25SAndre Guedes 
58947990ea0SJohan Hedberg 	if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) {
59047990ea0SJohan Hedberg 		u8 enable = 1;
59104124681SGustavo F. Padovan 		hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable),
59204124681SGustavo F. Padovan 			     &enable);
59347990ea0SJohan Hedberg 	}
594d5859e22SJohan Hedberg }
595d5859e22SJohan Hedberg 
596a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
597a9de9248SMarcel Holtmann {
598a9de9248SMarcel Holtmann 	struct hci_rp_read_local_version *rp = (void *) skb->data;
5991143e5a6SMarcel Holtmann 
6009f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
6011143e5a6SMarcel Holtmann 
602a9de9248SMarcel Holtmann 	if (rp->status)
60328b8df77SAndrei Emeltchenko 		goto done;
6041143e5a6SMarcel Holtmann 
605a9de9248SMarcel Holtmann 	hdev->hci_ver = rp->hci_ver;
606e4e8e37cSMarcel Holtmann 	hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
607d5859e22SJohan Hedberg 	hdev->lmp_ver = rp->lmp_ver;
608e4e8e37cSMarcel Holtmann 	hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
609d5859e22SJohan Hedberg 	hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
6101da177e4SLinus Torvalds 
6119f1db00cSAndrei Emeltchenko 	BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name,
612807deac2SGustavo Padovan 	       hdev->manufacturer, hdev->hci_ver, hdev->hci_rev);
613d5859e22SJohan Hedberg 
614d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags))
615d5859e22SJohan Hedberg 		hci_setup(hdev);
61628b8df77SAndrei Emeltchenko 
61728b8df77SAndrei Emeltchenko done:
61828b8df77SAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_VERSION, rp->status);
619d5859e22SJohan Hedberg }
620d5859e22SJohan Hedberg 
621d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev)
622d5859e22SJohan Hedberg {
623035100c8SAndrei Emeltchenko 	struct hci_cp_write_def_link_policy cp;
624d5859e22SJohan Hedberg 	u16 link_policy = 0;
625d5859e22SJohan Hedberg 
626d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_RSWITCH)
627d5859e22SJohan Hedberg 		link_policy |= HCI_LP_RSWITCH;
628d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_HOLD)
629d5859e22SJohan Hedberg 		link_policy |= HCI_LP_HOLD;
630d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_SNIFF)
631d5859e22SJohan Hedberg 		link_policy |= HCI_LP_SNIFF;
632d5859e22SJohan Hedberg 	if (hdev->features[1] & LMP_PARK)
633d5859e22SJohan Hedberg 		link_policy |= HCI_LP_PARK;
634d5859e22SJohan Hedberg 
635035100c8SAndrei Emeltchenko 	cp.policy = cpu_to_le16(link_policy);
636035100c8SAndrei Emeltchenko 	hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp);
6371da177e4SLinus Torvalds }
6381da177e4SLinus Torvalds 
6398fc9ced3SGustavo Padovan static void hci_cc_read_local_commands(struct hci_dev *hdev,
6408fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
641a9de9248SMarcel Holtmann {
642a9de9248SMarcel Holtmann 	struct hci_rp_read_local_commands *rp = (void *) skb->data;
643a9de9248SMarcel Holtmann 
6449f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
645a9de9248SMarcel Holtmann 
646a9de9248SMarcel Holtmann 	if (rp->status)
647d5859e22SJohan Hedberg 		goto done;
648a9de9248SMarcel Holtmann 
649a9de9248SMarcel Holtmann 	memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
650d5859e22SJohan Hedberg 
651d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
652d5859e22SJohan Hedberg 		hci_setup_link_policy(hdev);
653d5859e22SJohan Hedberg 
654d5859e22SJohan Hedberg done:
655d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
656a9de9248SMarcel Holtmann }
657a9de9248SMarcel Holtmann 
6588fc9ced3SGustavo Padovan static void hci_cc_read_local_features(struct hci_dev *hdev,
6598fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
660a9de9248SMarcel Holtmann {
661a9de9248SMarcel Holtmann 	struct hci_rp_read_local_features *rp = (void *) skb->data;
662a9de9248SMarcel Holtmann 
6639f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
664a9de9248SMarcel Holtmann 
665a9de9248SMarcel Holtmann 	if (rp->status)
666a9de9248SMarcel Holtmann 		return;
667a9de9248SMarcel Holtmann 
668a9de9248SMarcel Holtmann 	memcpy(hdev->features, rp->features, 8);
6691da177e4SLinus Torvalds 
6701da177e4SLinus Torvalds 	/* Adjust default settings according to features
6711da177e4SLinus Torvalds 	 * supported by device. */
672a9de9248SMarcel Holtmann 
6731da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_3SLOT)
6741da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
6751da177e4SLinus Torvalds 
6761da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_5SLOT)
6771da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
6781da177e4SLinus Torvalds 
6795b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV2) {
6801da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV2);
6815b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV2);
6825b7f9909SMarcel Holtmann 	}
6831da177e4SLinus Torvalds 
6845b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV3) {
6851da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV3);
6865b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV3);
6875b7f9909SMarcel Holtmann 	}
6885b7f9909SMarcel Holtmann 
6895b7f9909SMarcel Holtmann 	if (hdev->features[3] & LMP_ESCO)
6905b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV3);
6915b7f9909SMarcel Holtmann 
6925b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV4)
6935b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV4);
6945b7f9909SMarcel Holtmann 
6955b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV5)
6965b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV5);
6971da177e4SLinus Torvalds 
698efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_2M)
699efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV3);
700efc7688bSMarcel Holtmann 
701efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_3M)
702efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_3EV3);
703efc7688bSMarcel Holtmann 
704efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_3S_ESCO)
705efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
706efc7688bSMarcel Holtmann 
707a9de9248SMarcel Holtmann 	BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
708a9de9248SMarcel Holtmann 	       hdev->features[0], hdev->features[1],
709a9de9248SMarcel Holtmann 	       hdev->features[2], hdev->features[3],
710a9de9248SMarcel Holtmann 	       hdev->features[4], hdev->features[5],
711a9de9248SMarcel Holtmann 	       hdev->features[6], hdev->features[7]);
7121da177e4SLinus Torvalds }
7131da177e4SLinus Torvalds 
7148f984dfaSJohan Hedberg static void hci_set_le_support(struct hci_dev *hdev)
7158f984dfaSJohan Hedberg {
7168f984dfaSJohan Hedberg 	struct hci_cp_write_le_host_supported cp;
7178f984dfaSJohan Hedberg 
7188f984dfaSJohan Hedberg 	memset(&cp, 0, sizeof(cp));
7198f984dfaSJohan Hedberg 
7209d42820fSMarcel Holtmann 	if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
7218f984dfaSJohan Hedberg 		cp.le = 1;
7228f984dfaSJohan Hedberg 		cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
7238f984dfaSJohan Hedberg 	}
7248f984dfaSJohan Hedberg 
7258f984dfaSJohan Hedberg 	if (cp.le != !!(hdev->host_features[0] & LMP_HOST_LE))
72604124681SGustavo F. Padovan 		hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp),
72704124681SGustavo F. Padovan 			     &cp);
7288f984dfaSJohan Hedberg }
7298f984dfaSJohan Hedberg 
730971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
731971e3a4bSAndre Guedes 					   struct sk_buff *skb)
732971e3a4bSAndre Guedes {
733971e3a4bSAndre Guedes 	struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
734971e3a4bSAndre Guedes 
7359f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
736971e3a4bSAndre Guedes 
737971e3a4bSAndre Guedes 	if (rp->status)
7388f984dfaSJohan Hedberg 		goto done;
739971e3a4bSAndre Guedes 
740b5b32b65SAndre Guedes 	switch (rp->page) {
741b5b32b65SAndre Guedes 	case 0:
742b5b32b65SAndre Guedes 		memcpy(hdev->features, rp->features, 8);
743b5b32b65SAndre Guedes 		break;
744b5b32b65SAndre Guedes 	case 1:
74559e29406SAndre Guedes 		memcpy(hdev->host_features, rp->features, 8);
746b5b32b65SAndre Guedes 		break;
747b5b32b65SAndre Guedes 	}
748971e3a4bSAndre Guedes 
7498f984dfaSJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags) && hdev->features[4] & LMP_LE)
7508f984dfaSJohan Hedberg 		hci_set_le_support(hdev);
7518f984dfaSJohan Hedberg 
7528f984dfaSJohan Hedberg done:
753971e3a4bSAndre Guedes 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
754971e3a4bSAndre Guedes }
755971e3a4bSAndre Guedes 
7561e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
7571e89cffbSAndrei Emeltchenko 					  struct sk_buff *skb)
7581e89cffbSAndrei Emeltchenko {
7591e89cffbSAndrei Emeltchenko 	struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
7601e89cffbSAndrei Emeltchenko 
7619f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
7621e89cffbSAndrei Emeltchenko 
7631e89cffbSAndrei Emeltchenko 	if (rp->status)
7641e89cffbSAndrei Emeltchenko 		return;
7651e89cffbSAndrei Emeltchenko 
7661e89cffbSAndrei Emeltchenko 	hdev->flow_ctl_mode = rp->mode;
7671e89cffbSAndrei Emeltchenko 
7681e89cffbSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
7691e89cffbSAndrei Emeltchenko }
7701e89cffbSAndrei Emeltchenko 
771a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
772a9de9248SMarcel Holtmann {
773a9de9248SMarcel Holtmann 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
774a9de9248SMarcel Holtmann 
7759f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
776a9de9248SMarcel Holtmann 
777a9de9248SMarcel Holtmann 	if (rp->status)
778a9de9248SMarcel Holtmann 		return;
779a9de9248SMarcel Holtmann 
780a9de9248SMarcel Holtmann 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
781a9de9248SMarcel Holtmann 	hdev->sco_mtu  = rp->sco_mtu;
782a9de9248SMarcel Holtmann 	hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
783a9de9248SMarcel Holtmann 	hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
784da1f5198SMarcel Holtmann 
785da1f5198SMarcel Holtmann 	if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
786da1f5198SMarcel Holtmann 		hdev->sco_mtu  = 64;
787da1f5198SMarcel Holtmann 		hdev->sco_pkts = 8;
788da1f5198SMarcel Holtmann 	}
789da1f5198SMarcel Holtmann 
790da1f5198SMarcel Holtmann 	hdev->acl_cnt = hdev->acl_pkts;
791da1f5198SMarcel Holtmann 	hdev->sco_cnt = hdev->sco_pkts;
7921da177e4SLinus Torvalds 
793807deac2SGustavo Padovan 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
794807deac2SGustavo Padovan 	       hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
7951da177e4SLinus Torvalds }
7961da177e4SLinus Torvalds 
797a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
798a9de9248SMarcel Holtmann {
799a9de9248SMarcel Holtmann 	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
8001da177e4SLinus Torvalds 
8019f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
802a9de9248SMarcel Holtmann 
803a9de9248SMarcel Holtmann 	if (!rp->status)
804a9de9248SMarcel Holtmann 		bacpy(&hdev->bdaddr, &rp->bdaddr);
805a9de9248SMarcel Holtmann 
80623bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
80723bb5763SJohan Hedberg }
80823bb5763SJohan Hedberg 
809350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev,
810350ee4cfSAndrei Emeltchenko 					struct sk_buff *skb)
811350ee4cfSAndrei Emeltchenko {
812350ee4cfSAndrei Emeltchenko 	struct hci_rp_read_data_block_size *rp = (void *) skb->data;
813350ee4cfSAndrei Emeltchenko 
8149f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
815350ee4cfSAndrei Emeltchenko 
816350ee4cfSAndrei Emeltchenko 	if (rp->status)
817350ee4cfSAndrei Emeltchenko 		return;
818350ee4cfSAndrei Emeltchenko 
819350ee4cfSAndrei Emeltchenko 	hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
820350ee4cfSAndrei Emeltchenko 	hdev->block_len = __le16_to_cpu(rp->block_len);
821350ee4cfSAndrei Emeltchenko 	hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
822350ee4cfSAndrei Emeltchenko 
823350ee4cfSAndrei Emeltchenko 	hdev->block_cnt = hdev->num_blocks;
824350ee4cfSAndrei Emeltchenko 
825350ee4cfSAndrei Emeltchenko 	BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
826350ee4cfSAndrei Emeltchenko 	       hdev->block_cnt, hdev->block_len);
827350ee4cfSAndrei Emeltchenko 
828350ee4cfSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
829350ee4cfSAndrei Emeltchenko }
830350ee4cfSAndrei Emeltchenko 
83123bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
83223bb5763SJohan Hedberg {
83323bb5763SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
83423bb5763SJohan Hedberg 
8359f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
83623bb5763SJohan Hedberg 
83723bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
8381da177e4SLinus Torvalds }
8391da177e4SLinus Torvalds 
840928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
841928abaa7SAndrei Emeltchenko 				       struct sk_buff *skb)
842928abaa7SAndrei Emeltchenko {
843928abaa7SAndrei Emeltchenko 	struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
844928abaa7SAndrei Emeltchenko 
8459f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
846928abaa7SAndrei Emeltchenko 
847928abaa7SAndrei Emeltchenko 	if (rp->status)
848928abaa7SAndrei Emeltchenko 		return;
849928abaa7SAndrei Emeltchenko 
850928abaa7SAndrei Emeltchenko 	hdev->amp_status = rp->amp_status;
851928abaa7SAndrei Emeltchenko 	hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
852928abaa7SAndrei Emeltchenko 	hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
853928abaa7SAndrei Emeltchenko 	hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
854928abaa7SAndrei Emeltchenko 	hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
855928abaa7SAndrei Emeltchenko 	hdev->amp_type = rp->amp_type;
856928abaa7SAndrei Emeltchenko 	hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
857928abaa7SAndrei Emeltchenko 	hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
858928abaa7SAndrei Emeltchenko 	hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
859928abaa7SAndrei Emeltchenko 	hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
860928abaa7SAndrei Emeltchenko 
861928abaa7SAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
862928abaa7SAndrei Emeltchenko }
863928abaa7SAndrei Emeltchenko 
864b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
865b0916ea0SJohan Hedberg 					  struct sk_buff *skb)
866b0916ea0SJohan Hedberg {
867b0916ea0SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
868b0916ea0SJohan Hedberg 
8699f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
870b0916ea0SJohan Hedberg 
871b0916ea0SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
872b0916ea0SJohan Hedberg }
873b0916ea0SJohan Hedberg 
874d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
875d5859e22SJohan Hedberg {
876d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
877d5859e22SJohan Hedberg 
8789f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
879d5859e22SJohan Hedberg 
880d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
881d5859e22SJohan Hedberg }
882d5859e22SJohan Hedberg 
883d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
884d5859e22SJohan Hedberg 				      struct sk_buff *skb)
885d5859e22SJohan Hedberg {
886d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
887d5859e22SJohan Hedberg 
8889f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
889d5859e22SJohan Hedberg 
890d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
891d5859e22SJohan Hedberg }
892d5859e22SJohan Hedberg 
893d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
894d5859e22SJohan Hedberg 					 struct sk_buff *skb)
895d5859e22SJohan Hedberg {
89691c4e9b1SMarcel Holtmann 	struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
897d5859e22SJohan Hedberg 
8989f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
899d5859e22SJohan Hedberg 
90091c4e9b1SMarcel Holtmann 	if (!rp->status)
90191c4e9b1SMarcel Holtmann 		hdev->inq_tx_power = rp->tx_power;
90291c4e9b1SMarcel Holtmann 
90391c4e9b1SMarcel Holtmann 	hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, rp->status);
904d5859e22SJohan Hedberg }
905d5859e22SJohan Hedberg 
906d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
907d5859e22SJohan Hedberg {
908d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
909d5859e22SJohan Hedberg 
9109f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
911d5859e22SJohan Hedberg 
912d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
913d5859e22SJohan Hedberg }
914d5859e22SJohan Hedberg 
915980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
916980e1a53SJohan Hedberg {
917980e1a53SJohan Hedberg 	struct hci_rp_pin_code_reply *rp = (void *) skb->data;
918980e1a53SJohan Hedberg 	struct hci_cp_pin_code_reply *cp;
919980e1a53SJohan Hedberg 	struct hci_conn *conn;
920980e1a53SJohan Hedberg 
9219f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
922980e1a53SJohan Hedberg 
92356e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
92456e5cb86SJohan Hedberg 
925a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
926744cf19eSJohan Hedberg 		mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
927980e1a53SJohan Hedberg 
928980e1a53SJohan Hedberg 	if (rp->status != 0)
92956e5cb86SJohan Hedberg 		goto unlock;
930980e1a53SJohan Hedberg 
931980e1a53SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
932980e1a53SJohan Hedberg 	if (!cp)
93356e5cb86SJohan Hedberg 		goto unlock;
934980e1a53SJohan Hedberg 
935980e1a53SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
936980e1a53SJohan Hedberg 	if (conn)
937980e1a53SJohan Hedberg 		conn->pin_length = cp->pin_len;
93856e5cb86SJohan Hedberg 
93956e5cb86SJohan Hedberg unlock:
94056e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
941980e1a53SJohan Hedberg }
942980e1a53SJohan Hedberg 
943980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
944980e1a53SJohan Hedberg {
945980e1a53SJohan Hedberg 	struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
946980e1a53SJohan Hedberg 
9479f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
948980e1a53SJohan Hedberg 
94956e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
95056e5cb86SJohan Hedberg 
951a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
952744cf19eSJohan Hedberg 		mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
953980e1a53SJohan Hedberg 						 rp->status);
95456e5cb86SJohan Hedberg 
95556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
956980e1a53SJohan Hedberg }
95756e5cb86SJohan Hedberg 
9586ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
9596ed58ec5SVille Tervo 				       struct sk_buff *skb)
9606ed58ec5SVille Tervo {
9616ed58ec5SVille Tervo 	struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
9626ed58ec5SVille Tervo 
9639f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
9646ed58ec5SVille Tervo 
9656ed58ec5SVille Tervo 	if (rp->status)
9666ed58ec5SVille Tervo 		return;
9676ed58ec5SVille Tervo 
9686ed58ec5SVille Tervo 	hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
9696ed58ec5SVille Tervo 	hdev->le_pkts = rp->le_max_pkt;
9706ed58ec5SVille Tervo 
9716ed58ec5SVille Tervo 	hdev->le_cnt = hdev->le_pkts;
9726ed58ec5SVille Tervo 
9736ed58ec5SVille Tervo 	BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
9746ed58ec5SVille Tervo 
9756ed58ec5SVille Tervo 	hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
9766ed58ec5SVille Tervo }
977980e1a53SJohan Hedberg 
978a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
979a5c29683SJohan Hedberg {
980a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
981a5c29683SJohan Hedberg 
9829f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
983a5c29683SJohan Hedberg 
98456e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
98556e5cb86SJohan Hedberg 
986a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
98704124681SGustavo F. Padovan 		mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
98804124681SGustavo F. Padovan 						 rp->status);
98956e5cb86SJohan Hedberg 
99056e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
991a5c29683SJohan Hedberg }
992a5c29683SJohan Hedberg 
993a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
994a5c29683SJohan Hedberg 					  struct sk_buff *skb)
995a5c29683SJohan Hedberg {
996a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
997a5c29683SJohan Hedberg 
9989f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
999a5c29683SJohan Hedberg 
100056e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
100156e5cb86SJohan Hedberg 
1002a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1003744cf19eSJohan Hedberg 		mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
100404124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
100556e5cb86SJohan Hedberg 
100656e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1007a5c29683SJohan Hedberg }
1008a5c29683SJohan Hedberg 
10091143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
10101143d458SBrian Gix {
10111143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
10121143d458SBrian Gix 
10139f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
10141143d458SBrian Gix 
10151143d458SBrian Gix 	hci_dev_lock(hdev);
10161143d458SBrian Gix 
1017a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1018272d90dfSJohan Hedberg 		mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
1019272d90dfSJohan Hedberg 						 0, rp->status);
10201143d458SBrian Gix 
10211143d458SBrian Gix 	hci_dev_unlock(hdev);
10221143d458SBrian Gix }
10231143d458SBrian Gix 
10241143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
10251143d458SBrian Gix 					  struct sk_buff *skb)
10261143d458SBrian Gix {
10271143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
10281143d458SBrian Gix 
10299f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
10301143d458SBrian Gix 
10311143d458SBrian Gix 	hci_dev_lock(hdev);
10321143d458SBrian Gix 
1033a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
10341143d458SBrian Gix 		mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
103504124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
10361143d458SBrian Gix 
10371143d458SBrian Gix 	hci_dev_unlock(hdev);
10381143d458SBrian Gix }
10391143d458SBrian Gix 
1040c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
1041c35938b2SSzymon Janc 					     struct sk_buff *skb)
1042c35938b2SSzymon Janc {
1043c35938b2SSzymon Janc 	struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
1044c35938b2SSzymon Janc 
10459f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1046c35938b2SSzymon Janc 
104756e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1048744cf19eSJohan Hedberg 	mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
1049c35938b2SSzymon Janc 						rp->randomizer, rp->status);
105056e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1051c35938b2SSzymon Janc }
1052c35938b2SSzymon Janc 
105307f7fa5dSAndre Guedes static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
105407f7fa5dSAndre Guedes {
105507f7fa5dSAndre Guedes 	__u8 status = *((__u8 *) skb->data);
105607f7fa5dSAndre Guedes 
10579f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
10587ba8b4beSAndre Guedes 
10597ba8b4beSAndre Guedes 	hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status);
10603fd24153SAndre Guedes 
10613fd24153SAndre Guedes 	if (status) {
10623fd24153SAndre Guedes 		hci_dev_lock(hdev);
10633fd24153SAndre Guedes 		mgmt_start_discovery_failed(hdev, status);
10643fd24153SAndre Guedes 		hci_dev_unlock(hdev);
10653fd24153SAndre Guedes 		return;
10663fd24153SAndre Guedes 	}
106707f7fa5dSAndre Guedes }
106807f7fa5dSAndre Guedes 
1069eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
1070eb9d91f5SAndre Guedes 				      struct sk_buff *skb)
1071eb9d91f5SAndre Guedes {
1072eb9d91f5SAndre Guedes 	struct hci_cp_le_set_scan_enable *cp;
1073eb9d91f5SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1074eb9d91f5SAndre Guedes 
10759f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1076eb9d91f5SAndre Guedes 
1077eb9d91f5SAndre Guedes 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1078eb9d91f5SAndre Guedes 	if (!cp)
1079eb9d91f5SAndre Guedes 		return;
1080eb9d91f5SAndre Guedes 
108168a8aea4SAndrei Emeltchenko 	switch (cp->enable) {
108268a8aea4SAndrei Emeltchenko 	case LE_SCANNING_ENABLED:
10837ba8b4beSAndre Guedes 		hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status);
10847ba8b4beSAndre Guedes 
10853fd24153SAndre Guedes 		if (status) {
10863fd24153SAndre Guedes 			hci_dev_lock(hdev);
10873fd24153SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
10883fd24153SAndre Guedes 			hci_dev_unlock(hdev);
10897ba8b4beSAndre Guedes 			return;
10903fd24153SAndre Guedes 		}
10917ba8b4beSAndre Guedes 
1092d23264a8SAndre Guedes 		set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1093d23264a8SAndre Guedes 
1094a8f13c8cSAndre Guedes 		hci_dev_lock(hdev);
1095343f935bSAndre Guedes 		hci_discovery_set_state(hdev, DISCOVERY_FINDING);
1096a8f13c8cSAndre Guedes 		hci_dev_unlock(hdev);
109768a8aea4SAndrei Emeltchenko 		break;
109868a8aea4SAndrei Emeltchenko 
109968a8aea4SAndrei Emeltchenko 	case LE_SCANNING_DISABLED:
1100c9ecc48eSAndre Guedes 		if (status) {
1101c9ecc48eSAndre Guedes 			hci_dev_lock(hdev);
1102c9ecc48eSAndre Guedes 			mgmt_stop_discovery_failed(hdev, status);
1103c9ecc48eSAndre Guedes 			hci_dev_unlock(hdev);
11047ba8b4beSAndre Guedes 			return;
1105c9ecc48eSAndre Guedes 		}
11067ba8b4beSAndre Guedes 
1107d23264a8SAndre Guedes 		clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1108d23264a8SAndre Guedes 
1109bc3dd33cSAndre Guedes 		if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
1110bc3dd33cSAndre Guedes 		    hdev->discovery.state == DISCOVERY_FINDING) {
11115e0452c0SAndre Guedes 			mgmt_interleaved_discovery(hdev);
11125e0452c0SAndre Guedes 		} else {
1113c599008fSAndre Guedes 			hci_dev_lock(hdev);
1114c599008fSAndre Guedes 			hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1115c599008fSAndre Guedes 			hci_dev_unlock(hdev);
11165e0452c0SAndre Guedes 		}
1117c599008fSAndre Guedes 
111868a8aea4SAndrei Emeltchenko 		break;
111968a8aea4SAndrei Emeltchenko 
112068a8aea4SAndrei Emeltchenko 	default:
112168a8aea4SAndrei Emeltchenko 		BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
112268a8aea4SAndrei Emeltchenko 		break;
112335815085SAndre Guedes 	}
1124eb9d91f5SAndre Guedes }
1125eb9d91f5SAndre Guedes 
1126a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1127a7a595f6SVinicius Costa Gomes {
1128a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1129a7a595f6SVinicius Costa Gomes 
11309f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1131a7a595f6SVinicius Costa Gomes 
1132a7a595f6SVinicius Costa Gomes 	if (rp->status)
1133a7a595f6SVinicius Costa Gomes 		return;
1134a7a595f6SVinicius Costa Gomes 
1135a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1136a7a595f6SVinicius Costa Gomes }
1137a7a595f6SVinicius Costa Gomes 
1138a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1139a7a595f6SVinicius Costa Gomes {
1140a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1141a7a595f6SVinicius Costa Gomes 
11429f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1143a7a595f6SVinicius Costa Gomes 
1144a7a595f6SVinicius Costa Gomes 	if (rp->status)
1145a7a595f6SVinicius Costa Gomes 		return;
1146a7a595f6SVinicius Costa Gomes 
1147a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1148a7a595f6SVinicius Costa Gomes }
1149a7a595f6SVinicius Costa Gomes 
11506039aa73SGustavo Padovan static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1151f9b49306SAndre Guedes 					   struct sk_buff *skb)
1152f9b49306SAndre Guedes {
115306199cf8SJohan Hedberg 	struct hci_cp_write_le_host_supported *sent;
1154f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1155f9b49306SAndre Guedes 
11569f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1157f9b49306SAndre Guedes 
115806199cf8SJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
11598f984dfaSJohan Hedberg 	if (!sent)
1160f9b49306SAndre Guedes 		return;
1161f9b49306SAndre Guedes 
11628f984dfaSJohan Hedberg 	if (!status) {
11638f984dfaSJohan Hedberg 		if (sent->le)
11648f984dfaSJohan Hedberg 			hdev->host_features[0] |= LMP_HOST_LE;
11658f984dfaSJohan Hedberg 		else
11668f984dfaSJohan Hedberg 			hdev->host_features[0] &= ~LMP_HOST_LE;
11678f984dfaSJohan Hedberg 	}
11688f984dfaSJohan Hedberg 
11698f984dfaSJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
11708f984dfaSJohan Hedberg 	    !test_bit(HCI_INIT, &hdev->flags))
11718f984dfaSJohan Hedberg 		mgmt_le_enable_complete(hdev, sent->le, status);
11728f984dfaSJohan Hedberg 
11738f984dfaSJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status);
1174f9b49306SAndre Guedes }
1175f9b49306SAndre Guedes 
11766039aa73SGustavo Padovan static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1177a9de9248SMarcel Holtmann {
11789f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1179a9de9248SMarcel Holtmann 
1180a9de9248SMarcel Holtmann 	if (status) {
118123bb5763SJohan Hedberg 		hci_req_complete(hdev, HCI_OP_INQUIRY, status);
1182a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
118356e5cb86SJohan Hedberg 		hci_dev_lock(hdev);
1184a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
11857a135109SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
118656e5cb86SJohan Hedberg 		hci_dev_unlock(hdev);
1187314b2381SJohan Hedberg 		return;
1188314b2381SJohan Hedberg 	}
1189314b2381SJohan Hedberg 
119089352e7dSAndre Guedes 	set_bit(HCI_INQUIRY, &hdev->flags);
119189352e7dSAndre Guedes 
119256e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1193343f935bSAndre Guedes 	hci_discovery_set_state(hdev, DISCOVERY_FINDING);
119456e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1195a9de9248SMarcel Holtmann }
1196a9de9248SMarcel Holtmann 
11976039aa73SGustavo Padovan static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
11981da177e4SLinus Torvalds {
1199a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
12001da177e4SLinus Torvalds 	struct hci_conn *conn;
12011da177e4SLinus Torvalds 
12029f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1203a9de9248SMarcel Holtmann 
1204a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
12051da177e4SLinus Torvalds 	if (!cp)
12061da177e4SLinus Torvalds 		return;
12071da177e4SLinus Torvalds 
12081da177e4SLinus Torvalds 	hci_dev_lock(hdev);
12091da177e4SLinus Torvalds 
12101da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
12111da177e4SLinus Torvalds 
12129f1db00cSAndrei Emeltchenko 	BT_DBG("%s bdaddr %s hcon %p", hdev->name, batostr(&cp->bdaddr), conn);
12131da177e4SLinus Torvalds 
12141da177e4SLinus Torvalds 	if (status) {
12151da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
12164c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
12171da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
12181da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
12191da177e4SLinus Torvalds 				hci_conn_del(conn);
12204c67bc74SMarcel Holtmann 			} else
12214c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
12221da177e4SLinus Torvalds 		}
12231da177e4SLinus Torvalds 	} else {
12241da177e4SLinus Torvalds 		if (!conn) {
12251da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
12261da177e4SLinus Torvalds 			if (conn) {
1227a0c808b3SJohan Hedberg 				conn->out = true;
12281da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
12291da177e4SLinus Torvalds 			} else
1230893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
12311da177e4SLinus Torvalds 		}
12321da177e4SLinus Torvalds 	}
12331da177e4SLinus Torvalds 
12341da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
12351da177e4SLinus Torvalds }
12361da177e4SLinus Torvalds 
1237a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
12381da177e4SLinus Torvalds {
1239a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
12401da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
12411da177e4SLinus Torvalds 	__u16 handle;
12421da177e4SLinus Torvalds 
12439f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1244b6a0dc82SMarcel Holtmann 
1245a9de9248SMarcel Holtmann 	if (!status)
1246a9de9248SMarcel Holtmann 		return;
1247a9de9248SMarcel Holtmann 
1248a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
12491da177e4SLinus Torvalds 	if (!cp)
1250a9de9248SMarcel Holtmann 		return;
12511da177e4SLinus Torvalds 
12521da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
12531da177e4SLinus Torvalds 
12549f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
12551da177e4SLinus Torvalds 
12561da177e4SLinus Torvalds 	hci_dev_lock(hdev);
12571da177e4SLinus Torvalds 
12581da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
12595a08ecceSAndrei Emeltchenko 	if (acl) {
12605a08ecceSAndrei Emeltchenko 		sco = acl->link;
12615a08ecceSAndrei Emeltchenko 		if (sco) {
12621da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
12631da177e4SLinus Torvalds 
12641da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
12651da177e4SLinus Torvalds 			hci_conn_del(sco);
12661da177e4SLinus Torvalds 		}
12675a08ecceSAndrei Emeltchenko 	}
12681da177e4SLinus Torvalds 
12691da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
12701da177e4SLinus Torvalds }
12711da177e4SLinus Torvalds 
1272f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1273f8558555SMarcel Holtmann {
1274f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1275f8558555SMarcel Holtmann 	struct hci_conn *conn;
1276f8558555SMarcel Holtmann 
12779f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1278f8558555SMarcel Holtmann 
1279f8558555SMarcel Holtmann 	if (!status)
1280f8558555SMarcel Holtmann 		return;
1281f8558555SMarcel Holtmann 
1282f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1283f8558555SMarcel Holtmann 	if (!cp)
1284f8558555SMarcel Holtmann 		return;
1285f8558555SMarcel Holtmann 
1286f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1287f8558555SMarcel Holtmann 
1288f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1289f8558555SMarcel Holtmann 	if (conn) {
1290f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1291f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1292f8558555SMarcel Holtmann 			hci_conn_put(conn);
1293f8558555SMarcel Holtmann 		}
1294f8558555SMarcel Holtmann 	}
1295f8558555SMarcel Holtmann 
1296f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1297f8558555SMarcel Holtmann }
1298f8558555SMarcel Holtmann 
1299f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1300f8558555SMarcel Holtmann {
1301f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1302f8558555SMarcel Holtmann 	struct hci_conn *conn;
1303f8558555SMarcel Holtmann 
13049f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1305f8558555SMarcel Holtmann 
1306f8558555SMarcel Holtmann 	if (!status)
1307f8558555SMarcel Holtmann 		return;
1308f8558555SMarcel Holtmann 
1309f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1310f8558555SMarcel Holtmann 	if (!cp)
1311f8558555SMarcel Holtmann 		return;
1312f8558555SMarcel Holtmann 
1313f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1314f8558555SMarcel Holtmann 
1315f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1316f8558555SMarcel Holtmann 	if (conn) {
1317f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1318f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1319f8558555SMarcel Holtmann 			hci_conn_put(conn);
1320f8558555SMarcel Holtmann 		}
1321f8558555SMarcel Holtmann 	}
1322f8558555SMarcel Holtmann 
1323f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1324f8558555SMarcel Holtmann }
1325f8558555SMarcel Holtmann 
1326127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1327392599b9SJohan Hedberg 				    struct hci_conn *conn)
1328392599b9SJohan Hedberg {
1329392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1330392599b9SJohan Hedberg 		return 0;
1331392599b9SJohan Hedberg 
1332765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1333392599b9SJohan Hedberg 		return 0;
1334392599b9SJohan Hedberg 
1335392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1336e9bf2bf0SVinicius Costa Gomes 	 * devices with sec_level HIGH or if MITM protection is requested */
1337807deac2SGustavo Padovan 	if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
1338807deac2SGustavo Padovan 	    conn->pending_sec_level != BT_SECURITY_HIGH)
1339392599b9SJohan Hedberg 		return 0;
1340392599b9SJohan Hedberg 
1341392599b9SJohan Hedberg 	return 1;
1342392599b9SJohan Hedberg }
1343392599b9SJohan Hedberg 
13446039aa73SGustavo Padovan static int hci_resolve_name(struct hci_dev *hdev,
134500abfe44SGustavo F. Padovan 				   struct inquiry_entry *e)
134630dc78e1SJohan Hedberg {
134730dc78e1SJohan Hedberg 	struct hci_cp_remote_name_req cp;
134830dc78e1SJohan Hedberg 
134930dc78e1SJohan Hedberg 	memset(&cp, 0, sizeof(cp));
135030dc78e1SJohan Hedberg 
135130dc78e1SJohan Hedberg 	bacpy(&cp.bdaddr, &e->data.bdaddr);
135230dc78e1SJohan Hedberg 	cp.pscan_rep_mode = e->data.pscan_rep_mode;
135330dc78e1SJohan Hedberg 	cp.pscan_mode = e->data.pscan_mode;
135430dc78e1SJohan Hedberg 	cp.clock_offset = e->data.clock_offset;
135530dc78e1SJohan Hedberg 
135630dc78e1SJohan Hedberg 	return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
135730dc78e1SJohan Hedberg }
135830dc78e1SJohan Hedberg 
1359b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev)
136030dc78e1SJohan Hedberg {
136130dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
136230dc78e1SJohan Hedberg 	struct inquiry_entry *e;
136330dc78e1SJohan Hedberg 
1364b644ba33SJohan Hedberg 	if (list_empty(&discov->resolve))
1365b644ba33SJohan Hedberg 		return false;
1366b644ba33SJohan Hedberg 
1367b644ba33SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1368c810089cSRam Malovany 	if (!e)
1369c810089cSRam Malovany 		return false;
1370c810089cSRam Malovany 
1371b644ba33SJohan Hedberg 	if (hci_resolve_name(hdev, e) == 0) {
1372b644ba33SJohan Hedberg 		e->name_state = NAME_PENDING;
1373b644ba33SJohan Hedberg 		return true;
1374b644ba33SJohan Hedberg 	}
1375b644ba33SJohan Hedberg 
1376b644ba33SJohan Hedberg 	return false;
1377b644ba33SJohan Hedberg }
1378b644ba33SJohan Hedberg 
1379b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
1380b644ba33SJohan Hedberg 				   bdaddr_t *bdaddr, u8 *name, u8 name_len)
1381b644ba33SJohan Hedberg {
1382b644ba33SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
1383b644ba33SJohan Hedberg 	struct inquiry_entry *e;
1384b644ba33SJohan Hedberg 
1385b644ba33SJohan Hedberg 	if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
138604124681SGustavo F. Padovan 		mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
138704124681SGustavo F. Padovan 				      name_len, conn->dev_class);
1388b644ba33SJohan Hedberg 
1389b644ba33SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPED)
1390b644ba33SJohan Hedberg 		return;
1391b644ba33SJohan Hedberg 
139230dc78e1SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPING)
139330dc78e1SJohan Hedberg 		goto discov_complete;
139430dc78e1SJohan Hedberg 
139530dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_RESOLVING)
139630dc78e1SJohan Hedberg 		return;
139730dc78e1SJohan Hedberg 
139830dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
13997cc8380eSRam Malovany 	/* If the device was not found in a list of found devices names of which
14007cc8380eSRam Malovany 	 * are pending. there is no need to continue resolving a next name as it
14017cc8380eSRam Malovany 	 * will be done upon receiving another Remote Name Request Complete
14027cc8380eSRam Malovany 	 * Event */
14037cc8380eSRam Malovany 	if (!e)
14047cc8380eSRam Malovany 		return;
14057cc8380eSRam Malovany 
140630dc78e1SJohan Hedberg 	list_del(&e->list);
14077cc8380eSRam Malovany 	if (name) {
14087cc8380eSRam Malovany 		e->name_state = NAME_KNOWN;
1409b644ba33SJohan Hedberg 		mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1410b644ba33SJohan Hedberg 				 e->data.rssi, name, name_len);
1411*c3e7c0d9SRam Malovany 	} else {
1412*c3e7c0d9SRam Malovany 		e->name_state = NAME_NOT_KNOWN;
141330dc78e1SJohan Hedberg 	}
141430dc78e1SJohan Hedberg 
1415b644ba33SJohan Hedberg 	if (hci_resolve_next_name(hdev))
141630dc78e1SJohan Hedberg 		return;
141730dc78e1SJohan Hedberg 
141830dc78e1SJohan Hedberg discov_complete:
141930dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
142030dc78e1SJohan Hedberg }
142130dc78e1SJohan Hedberg 
1422a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
14231da177e4SLinus Torvalds {
1424127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1425127178d2SJohan Hedberg 	struct hci_conn *conn;
1426127178d2SJohan Hedberg 
14279f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1428127178d2SJohan Hedberg 
1429127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1430127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1431127178d2SJohan Hedberg 	if (!status)
1432127178d2SJohan Hedberg 		return;
1433127178d2SJohan Hedberg 
1434127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1435127178d2SJohan Hedberg 	if (!cp)
1436127178d2SJohan Hedberg 		return;
1437127178d2SJohan Hedberg 
1438127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1439127178d2SJohan Hedberg 
1440127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1441b644ba33SJohan Hedberg 
1442b644ba33SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1443b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1444b644ba33SJohan Hedberg 
144579c6c70cSJohan Hedberg 	if (!conn)
144679c6c70cSJohan Hedberg 		goto unlock;
144779c6c70cSJohan Hedberg 
144879c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
144979c6c70cSJohan Hedberg 		goto unlock;
145079c6c70cSJohan Hedberg 
145151a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1452127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1453127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1454127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1455127178d2SJohan Hedberg 	}
1456127178d2SJohan Hedberg 
145779c6c70cSJohan Hedberg unlock:
1458127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1459a9de9248SMarcel Holtmann }
14601da177e4SLinus Torvalds 
1461769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1462769be974SMarcel Holtmann {
1463769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1464769be974SMarcel Holtmann 	struct hci_conn *conn;
1465769be974SMarcel Holtmann 
14669f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1467769be974SMarcel Holtmann 
1468769be974SMarcel Holtmann 	if (!status)
1469769be974SMarcel Holtmann 		return;
1470769be974SMarcel Holtmann 
1471769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1472769be974SMarcel Holtmann 	if (!cp)
1473769be974SMarcel Holtmann 		return;
1474769be974SMarcel Holtmann 
1475769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1476769be974SMarcel Holtmann 
1477769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1478769be974SMarcel Holtmann 	if (conn) {
1479769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1480769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1481769be974SMarcel Holtmann 			hci_conn_put(conn);
1482769be974SMarcel Holtmann 		}
1483769be974SMarcel Holtmann 	}
1484769be974SMarcel Holtmann 
1485769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1486769be974SMarcel Holtmann }
1487769be974SMarcel Holtmann 
1488769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1489769be974SMarcel Holtmann {
1490769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1491769be974SMarcel Holtmann 	struct hci_conn *conn;
1492769be974SMarcel Holtmann 
14939f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1494769be974SMarcel Holtmann 
1495769be974SMarcel Holtmann 	if (!status)
1496769be974SMarcel Holtmann 		return;
1497769be974SMarcel Holtmann 
1498769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1499769be974SMarcel Holtmann 	if (!cp)
1500769be974SMarcel Holtmann 		return;
1501769be974SMarcel Holtmann 
1502769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1503769be974SMarcel Holtmann 
1504769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1505769be974SMarcel Holtmann 	if (conn) {
1506769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1507769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1508769be974SMarcel Holtmann 			hci_conn_put(conn);
1509769be974SMarcel Holtmann 		}
1510769be974SMarcel Holtmann 	}
1511769be974SMarcel Holtmann 
1512769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1513769be974SMarcel Holtmann }
1514769be974SMarcel Holtmann 
1515a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1516a9de9248SMarcel Holtmann {
1517b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1518b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1519b6a0dc82SMarcel Holtmann 	__u16 handle;
1520b6a0dc82SMarcel Holtmann 
15219f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1522b6a0dc82SMarcel Holtmann 
1523b6a0dc82SMarcel Holtmann 	if (!status)
1524b6a0dc82SMarcel Holtmann 		return;
1525b6a0dc82SMarcel Holtmann 
1526b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1527b6a0dc82SMarcel Holtmann 	if (!cp)
1528b6a0dc82SMarcel Holtmann 		return;
1529b6a0dc82SMarcel Holtmann 
1530b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1531b6a0dc82SMarcel Holtmann 
15329f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
1533b6a0dc82SMarcel Holtmann 
1534b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1535b6a0dc82SMarcel Holtmann 
1536b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
15375a08ecceSAndrei Emeltchenko 	if (acl) {
15385a08ecceSAndrei Emeltchenko 		sco = acl->link;
15395a08ecceSAndrei Emeltchenko 		if (sco) {
1540b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1541b6a0dc82SMarcel Holtmann 
1542b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1543b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1544b6a0dc82SMarcel Holtmann 		}
15455a08ecceSAndrei Emeltchenko 	}
1546b6a0dc82SMarcel Holtmann 
1547b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1548a9de9248SMarcel Holtmann }
1549a9de9248SMarcel Holtmann 
1550a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1551a9de9248SMarcel Holtmann {
1552a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
155304837f64SMarcel Holtmann 	struct hci_conn *conn;
155404837f64SMarcel Holtmann 
15559f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1556a9de9248SMarcel Holtmann 
1557a9de9248SMarcel Holtmann 	if (!status)
1558a9de9248SMarcel Holtmann 		return;
1559a9de9248SMarcel Holtmann 
1560a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
156104837f64SMarcel Holtmann 	if (!cp)
1562a9de9248SMarcel Holtmann 		return;
156304837f64SMarcel Holtmann 
156404837f64SMarcel Holtmann 	hci_dev_lock(hdev);
156504837f64SMarcel Holtmann 
156604837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1567e73439d8SMarcel Holtmann 	if (conn) {
156851a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
156904837f64SMarcel Holtmann 
157051a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1571e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1572e73439d8SMarcel Holtmann 	}
1573e73439d8SMarcel Holtmann 
157404837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
157504837f64SMarcel Holtmann }
157604837f64SMarcel Holtmann 
1577a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1578a9de9248SMarcel Holtmann {
1579a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
158004837f64SMarcel Holtmann 	struct hci_conn *conn;
158104837f64SMarcel Holtmann 
15829f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1583a9de9248SMarcel Holtmann 
1584a9de9248SMarcel Holtmann 	if (!status)
1585a9de9248SMarcel Holtmann 		return;
1586a9de9248SMarcel Holtmann 
1587a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
158804837f64SMarcel Holtmann 	if (!cp)
1589a9de9248SMarcel Holtmann 		return;
159004837f64SMarcel Holtmann 
159104837f64SMarcel Holtmann 	hci_dev_lock(hdev);
159204837f64SMarcel Holtmann 
159304837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1594e73439d8SMarcel Holtmann 	if (conn) {
159551a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
159604837f64SMarcel Holtmann 
159751a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1598e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1599e73439d8SMarcel Holtmann 	}
1600e73439d8SMarcel Holtmann 
160104837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
160204837f64SMarcel Holtmann }
160304837f64SMarcel Holtmann 
160488c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
160588c3df13SJohan Hedberg {
160688c3df13SJohan Hedberg 	struct hci_cp_disconnect *cp;
160788c3df13SJohan Hedberg 	struct hci_conn *conn;
160888c3df13SJohan Hedberg 
160988c3df13SJohan Hedberg 	if (!status)
161088c3df13SJohan Hedberg 		return;
161188c3df13SJohan Hedberg 
161288c3df13SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
161388c3df13SJohan Hedberg 	if (!cp)
161488c3df13SJohan Hedberg 		return;
161588c3df13SJohan Hedberg 
161688c3df13SJohan Hedberg 	hci_dev_lock(hdev);
161788c3df13SJohan Hedberg 
161888c3df13SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
161988c3df13SJohan Hedberg 	if (conn)
162088c3df13SJohan Hedberg 		mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
162188c3df13SJohan Hedberg 				       conn->dst_type, status);
162288c3df13SJohan Hedberg 
162388c3df13SJohan Hedberg 	hci_dev_unlock(hdev);
162488c3df13SJohan Hedberg }
162588c3df13SJohan Hedberg 
1626fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1627fcd89c09SVille Tervo {
1628fcd89c09SVille Tervo 	struct hci_cp_le_create_conn *cp;
1629fcd89c09SVille Tervo 	struct hci_conn *conn;
1630fcd89c09SVille Tervo 
16319f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1632fcd89c09SVille Tervo 
1633fcd89c09SVille Tervo 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
1634fcd89c09SVille Tervo 	if (!cp)
1635fcd89c09SVille Tervo 		return;
1636fcd89c09SVille Tervo 
1637fcd89c09SVille Tervo 	hci_dev_lock(hdev);
1638fcd89c09SVille Tervo 
1639fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
1640fcd89c09SVille Tervo 
1641fcd89c09SVille Tervo 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
1642fcd89c09SVille Tervo 	       conn);
1643fcd89c09SVille Tervo 
1644fcd89c09SVille Tervo 	if (status) {
1645fcd89c09SVille Tervo 		if (conn && conn->state == BT_CONNECT) {
1646fcd89c09SVille Tervo 			conn->state = BT_CLOSED;
1647328c9248SHemant Gupta 			mgmt_connect_failed(hdev, &cp->peer_addr, conn->type,
1648328c9248SHemant Gupta 					    conn->dst_type, status);
1649fcd89c09SVille Tervo 			hci_proto_connect_cfm(conn, status);
1650fcd89c09SVille Tervo 			hci_conn_del(conn);
1651fcd89c09SVille Tervo 		}
1652fcd89c09SVille Tervo 	} else {
1653fcd89c09SVille Tervo 		if (!conn) {
1654fcd89c09SVille Tervo 			conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
165529b7988aSAndre Guedes 			if (conn) {
165629b7988aSAndre Guedes 				conn->dst_type = cp->peer_addr_type;
1657a0c808b3SJohan Hedberg 				conn->out = true;
165829b7988aSAndre Guedes 			} else {
1659fcd89c09SVille Tervo 				BT_ERR("No memory for new connection");
1660fcd89c09SVille Tervo 			}
1661fcd89c09SVille Tervo 		}
166229b7988aSAndre Guedes 	}
1663fcd89c09SVille Tervo 
1664fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
1665fcd89c09SVille Tervo }
1666fcd89c09SVille Tervo 
1667a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1668a7a595f6SVinicius Costa Gomes {
16699f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1670a7a595f6SVinicius Costa Gomes }
1671a7a595f6SVinicius Costa Gomes 
16726039aa73SGustavo Padovan static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
16731da177e4SLinus Torvalds {
16741da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
167530dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
167630dc78e1SJohan Hedberg 	struct inquiry_entry *e;
16771da177e4SLinus Torvalds 
16789f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
16791da177e4SLinus Torvalds 
168023bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY, status);
16816bd57416SMarcel Holtmann 
1682a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
168389352e7dSAndre Guedes 
168489352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
168589352e7dSAndre Guedes 		return;
168689352e7dSAndre Guedes 
1687a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
168830dc78e1SJohan Hedberg 		return;
168930dc78e1SJohan Hedberg 
169056e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
169130dc78e1SJohan Hedberg 
1692343f935bSAndre Guedes 	if (discov->state != DISCOVERY_FINDING)
169330dc78e1SJohan Hedberg 		goto unlock;
169430dc78e1SJohan Hedberg 
169530dc78e1SJohan Hedberg 	if (list_empty(&discov->resolve)) {
1696ff9ef578SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
169730dc78e1SJohan Hedberg 		goto unlock;
169830dc78e1SJohan Hedberg 	}
169930dc78e1SJohan Hedberg 
170030dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
170130dc78e1SJohan Hedberg 	if (e && hci_resolve_name(hdev, e) == 0) {
170230dc78e1SJohan Hedberg 		e->name_state = NAME_PENDING;
170330dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
170430dc78e1SJohan Hedberg 	} else {
170530dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
170630dc78e1SJohan Hedberg 	}
170730dc78e1SJohan Hedberg 
170830dc78e1SJohan Hedberg unlock:
170956e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
17101da177e4SLinus Torvalds }
17111da177e4SLinus Torvalds 
17126039aa73SGustavo Padovan static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
17131da177e4SLinus Torvalds {
171445bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1715a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
17161da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
17171da177e4SLinus Torvalds 
17181da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
17191da177e4SLinus Torvalds 
172045bb4bf0SMarcel Holtmann 	if (!num_rsp)
172145bb4bf0SMarcel Holtmann 		return;
172245bb4bf0SMarcel Holtmann 
17231519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
17241519cc17SAndre Guedes 		return;
17251519cc17SAndre Guedes 
17261da177e4SLinus Torvalds 	hci_dev_lock(hdev);
172745bb4bf0SMarcel Holtmann 
1728e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
1729388fc8faSJohan Hedberg 		bool name_known, ssp;
17303175405bSJohan Hedberg 
17311da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
17321da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
17331da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
17341da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
17351da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
17361da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
17371da177e4SLinus Torvalds 		data.rssi		= 0x00;
173841a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
17393175405bSJohan Hedberg 
1740388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
174148264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
174204124681SGustavo F. Padovan 				  info->dev_class, 0, !name_known, ssp, NULL,
174304124681SGustavo F. Padovan 				  0);
17441da177e4SLinus Torvalds 	}
174545bb4bf0SMarcel Holtmann 
17461da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
17471da177e4SLinus Torvalds }
17481da177e4SLinus Torvalds 
17496039aa73SGustavo Padovan static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
17501da177e4SLinus Torvalds {
1751a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
1752a9de9248SMarcel Holtmann 	struct hci_conn *conn;
17531da177e4SLinus Torvalds 
1754a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
175545bb4bf0SMarcel Holtmann 
17561da177e4SLinus Torvalds 	hci_dev_lock(hdev);
175745bb4bf0SMarcel Holtmann 
1758a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
17599499237aSMarcel Holtmann 	if (!conn) {
17609499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
17619499237aSMarcel Holtmann 			goto unlock;
17629499237aSMarcel Holtmann 
17639499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1764a9de9248SMarcel Holtmann 		if (!conn)
1765a9de9248SMarcel Holtmann 			goto unlock;
176645bb4bf0SMarcel Holtmann 
17679499237aSMarcel Holtmann 		conn->type = SCO_LINK;
17689499237aSMarcel Holtmann 	}
17699499237aSMarcel Holtmann 
1770a9de9248SMarcel Holtmann 	if (!ev->status) {
1771a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1772769be974SMarcel Holtmann 
1773769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1774769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
1775769be974SMarcel Holtmann 			hci_conn_hold(conn);
1776a9ea3ed9SSzymon Janc 
1777a9ea3ed9SSzymon Janc 			if (!conn->out && !hci_conn_ssp_enabled(conn) &&
1778a9ea3ed9SSzymon Janc 			    !hci_find_link_key(hdev, &ev->bdaddr))
1779a9ea3ed9SSzymon Janc 				conn->disc_timeout = HCI_PAIRING_TIMEOUT;
1780a9ea3ed9SSzymon Janc 			else
1781052b30b0SMarcel Holtmann 				conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1782769be974SMarcel Holtmann 		} else
1783a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
1784a9de9248SMarcel Holtmann 
17859eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
17867d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
17877d0db0a3SMarcel Holtmann 
1788a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1789a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1790a9de9248SMarcel Holtmann 
1791a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1792a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1793a9de9248SMarcel Holtmann 
1794a9de9248SMarcel Holtmann 		/* Get remote features */
1795a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1796a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1797a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1798769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1799769be974SMarcel Holtmann 				     sizeof(cp), &cp);
180045bb4bf0SMarcel Holtmann 		}
1801a9de9248SMarcel Holtmann 
1802a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1803d095c1ebSAndrei Emeltchenko 		if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
1804a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1805a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1806a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
180704124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
180804124681SGustavo F. Padovan 				     &cp);
1809a9de9248SMarcel Holtmann 		}
181017d5c04cSJohan Hedberg 	} else {
1811a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
181217d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
1813744cf19eSJohan Hedberg 			mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
181448264f06SJohan Hedberg 					    conn->dst_type, ev->status);
181517d5c04cSJohan Hedberg 	}
181645bb4bf0SMarcel Holtmann 
1817e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
1818e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
181945bb4bf0SMarcel Holtmann 
1820769be974SMarcel Holtmann 	if (ev->status) {
1821a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1822a9de9248SMarcel Holtmann 		hci_conn_del(conn);
1823c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
1824c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1825a9de9248SMarcel Holtmann 
1826a9de9248SMarcel Holtmann unlock:
18271da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
1828a9de9248SMarcel Holtmann 
1829a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
18301da177e4SLinus Torvalds }
18311da177e4SLinus Torvalds 
18326039aa73SGustavo Padovan static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
18331da177e4SLinus Torvalds {
1834a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
18351da177e4SLinus Torvalds 	int mask = hdev->link_mode;
18361da177e4SLinus Torvalds 
1837807deac2SGustavo Padovan 	BT_DBG("%s bdaddr %s type 0x%x", hdev->name, batostr(&ev->bdaddr),
1838807deac2SGustavo Padovan 	       ev->link_type);
18391da177e4SLinus Torvalds 
18401da177e4SLinus Torvalds 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
18411da177e4SLinus Torvalds 
1842138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
1843138d22efSSzymon Janc 	    !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
18441da177e4SLinus Torvalds 		/* Connection accepted */
1845c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
18461da177e4SLinus Torvalds 		struct hci_conn *conn;
18471da177e4SLinus Torvalds 
18481da177e4SLinus Torvalds 		hci_dev_lock(hdev);
1849b6a0dc82SMarcel Holtmann 
1850cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1851cc11b9c1SAndrei Emeltchenko 		if (ie)
1852c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
1853c7bdd502SMarcel Holtmann 
18548fc9ced3SGustavo Padovan 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
18558fc9ced3SGustavo Padovan 					       &ev->bdaddr);
18561da177e4SLinus Torvalds 		if (!conn) {
1857cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1858cc11b9c1SAndrei Emeltchenko 			if (!conn) {
1859893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
18601da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
18611da177e4SLinus Torvalds 				return;
18621da177e4SLinus Torvalds 			}
18631da177e4SLinus Torvalds 		}
1864b6a0dc82SMarcel Holtmann 
18651da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
18661da177e4SLinus Torvalds 		conn->state = BT_CONNECT;
1867b6a0dc82SMarcel Holtmann 
18681da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
18691da177e4SLinus Torvalds 
1870b6a0dc82SMarcel Holtmann 		if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1871b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
1872b6a0dc82SMarcel Holtmann 
18731da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
18741da177e4SLinus Torvalds 
18751da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
18761da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
18771da177e4SLinus Torvalds 			else
18781da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
18791da177e4SLinus Torvalds 
188004124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
188104124681SGustavo F. Padovan 				     &cp);
1882b6a0dc82SMarcel Holtmann 		} else {
1883b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
1884b6a0dc82SMarcel Holtmann 
1885b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
1886a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1887b6a0dc82SMarcel Holtmann 
188882781e63SAndrei Emeltchenko 			cp.tx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
188982781e63SAndrei Emeltchenko 			cp.rx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
189082781e63SAndrei Emeltchenko 			cp.max_latency    = __constant_cpu_to_le16(0xffff);
1891b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
1892b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
1893b6a0dc82SMarcel Holtmann 
1894b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1895b6a0dc82SMarcel Holtmann 				     sizeof(cp), &cp);
1896b6a0dc82SMarcel Holtmann 		}
18971da177e4SLinus Torvalds 	} else {
18981da177e4SLinus Torvalds 		/* Connection rejected */
18991da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
19001da177e4SLinus Torvalds 
19011da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
19029f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_REJ_BAD_ADDR;
1903a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
19041da177e4SLinus Torvalds 	}
19051da177e4SLinus Torvalds }
19061da177e4SLinus Torvalds 
19076039aa73SGustavo Padovan static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
19081da177e4SLinus Torvalds {
1909a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
191004837f64SMarcel Holtmann 	struct hci_conn *conn;
19111da177e4SLinus Torvalds 
19129f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
19131da177e4SLinus Torvalds 
19141da177e4SLinus Torvalds 	hci_dev_lock(hdev);
19151da177e4SLinus Torvalds 
191604837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1917f7520543SJohan Hedberg 	if (!conn)
1918f7520543SJohan Hedberg 		goto unlock;
1919f7520543SJohan Hedberg 
192037d9ef76SJohan Hedberg 	if (ev->status == 0)
19211da177e4SLinus Torvalds 		conn->state = BT_CLOSED;
19227d0db0a3SMarcel Holtmann 
1923b644ba33SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
1924b644ba33SJohan Hedberg 	    (conn->type == ACL_LINK || conn->type == LE_LINK)) {
192537d9ef76SJohan Hedberg 		if (ev->status != 0)
192688c3df13SJohan Hedberg 			mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
192788c3df13SJohan Hedberg 					       conn->dst_type, ev->status);
192837d9ef76SJohan Hedberg 		else
1929afc747a6SJohan Hedberg 			mgmt_device_disconnected(hdev, &conn->dst, conn->type,
193048264f06SJohan Hedberg 						 conn->dst_type);
193137d9ef76SJohan Hedberg 	}
1932f7520543SJohan Hedberg 
193337d9ef76SJohan Hedberg 	if (ev->status == 0) {
19346ec5bcadSVishal Agarwal 		if (conn->type == ACL_LINK && conn->flush_key)
19356ec5bcadSVishal Agarwal 			hci_remove_link_key(hdev, &conn->dst);
19362950f21aSMarcel Holtmann 		hci_proto_disconn_cfm(conn, ev->reason);
19371da177e4SLinus Torvalds 		hci_conn_del(conn);
193837d9ef76SJohan Hedberg 	}
19391da177e4SLinus Torvalds 
1940f7520543SJohan Hedberg unlock:
19411da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
19421da177e4SLinus Torvalds }
19431da177e4SLinus Torvalds 
19446039aa73SGustavo Padovan static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1945a9de9248SMarcel Holtmann {
1946a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
1947a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1948a9de9248SMarcel Holtmann 
19499f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
1950a9de9248SMarcel Holtmann 
1951a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1952a9de9248SMarcel Holtmann 
1953a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1954d7556e20SWaldemar Rymarkiewicz 	if (!conn)
1955d7556e20SWaldemar Rymarkiewicz 		goto unlock;
1956d7556e20SWaldemar Rymarkiewicz 
1957765c2a96SJohan Hedberg 	if (!ev->status) {
1958aa64a8b5SJohan Hedberg 		if (!hci_conn_ssp_enabled(conn) &&
195951a8efd7SJohan Hedberg 		    test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
1960d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
196119f8def0SWaldemar Rymarkiewicz 		} else {
1962a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1963765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
196419f8def0SWaldemar Rymarkiewicz 		}
19652a611692SJohan Hedberg 	} else {
1966bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
1967bab73cb6SJohan Hedberg 				 ev->status);
19682a611692SJohan Hedberg 	}
1969a9de9248SMarcel Holtmann 
197051a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
197151a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
1972a9de9248SMarcel Holtmann 
1973f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
1974aa64a8b5SJohan Hedberg 		if (!ev->status && hci_conn_ssp_enabled(conn)) {
1975f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1976f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1977f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1978d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1979d7556e20SWaldemar Rymarkiewicz 				     &cp);
1980f8558555SMarcel Holtmann 		} else {
1981f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
1982f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1983f8558555SMarcel Holtmann 			hci_conn_put(conn);
1984f8558555SMarcel Holtmann 		}
1985052b30b0SMarcel Holtmann 	} else {
1986a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
1987a9de9248SMarcel Holtmann 
1988052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
1989052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1990052b30b0SMarcel Holtmann 		hci_conn_put(conn);
1991052b30b0SMarcel Holtmann 	}
1992052b30b0SMarcel Holtmann 
199351a8efd7SJohan Hedberg 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
1994a9de9248SMarcel Holtmann 		if (!ev->status) {
1995a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1996f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1997f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1998d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1999d7556e20SWaldemar Rymarkiewicz 				     &cp);
2000a9de9248SMarcel Holtmann 		} else {
200151a8efd7SJohan Hedberg 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2002a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
2003a9de9248SMarcel Holtmann 		}
2004a9de9248SMarcel Holtmann 	}
2005a9de9248SMarcel Holtmann 
2006d7556e20SWaldemar Rymarkiewicz unlock:
2007a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2008a9de9248SMarcel Holtmann }
2009a9de9248SMarcel Holtmann 
20106039aa73SGustavo Padovan static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
2011a9de9248SMarcel Holtmann {
2012127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
2013127178d2SJohan Hedberg 	struct hci_conn *conn;
2014127178d2SJohan Hedberg 
2015a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2016a9de9248SMarcel Holtmann 
2017a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
2018127178d2SJohan Hedberg 
2019127178d2SJohan Hedberg 	hci_dev_lock(hdev);
2020127178d2SJohan Hedberg 
2021127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2022b644ba33SJohan Hedberg 
2023b644ba33SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
2024b644ba33SJohan Hedberg 		goto check_auth;
2025b644ba33SJohan Hedberg 
2026b644ba33SJohan Hedberg 	if (ev->status == 0)
2027b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
2028b644ba33SJohan Hedberg 				       strnlen(ev->name, HCI_MAX_NAME_LENGTH));
2029b644ba33SJohan Hedberg 	else
2030b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
2031b644ba33SJohan Hedberg 
2032b644ba33SJohan Hedberg check_auth:
203379c6c70cSJohan Hedberg 	if (!conn)
203479c6c70cSJohan Hedberg 		goto unlock;
203579c6c70cSJohan Hedberg 
203679c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
203779c6c70cSJohan Hedberg 		goto unlock;
203879c6c70cSJohan Hedberg 
203951a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
2040127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
2041127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
2042127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
2043127178d2SJohan Hedberg 	}
2044127178d2SJohan Hedberg 
204579c6c70cSJohan Hedberg unlock:
2046127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
2047a9de9248SMarcel Holtmann }
2048a9de9248SMarcel Holtmann 
20496039aa73SGustavo Padovan static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2050a9de9248SMarcel Holtmann {
2051a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
2052a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2053a9de9248SMarcel Holtmann 
20549f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2055a9de9248SMarcel Holtmann 
2056a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2057a9de9248SMarcel Holtmann 
2058a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2059a9de9248SMarcel Holtmann 	if (conn) {
2060a9de9248SMarcel Holtmann 		if (!ev->status) {
2061ae293196SMarcel Holtmann 			if (ev->encrypt) {
2062ae293196SMarcel Holtmann 				/* Encryption implies authentication */
2063ae293196SMarcel Holtmann 				conn->link_mode |= HCI_LM_AUTH;
2064a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_ENCRYPT;
2065da85e5e5SVinicius Costa Gomes 				conn->sec_level = conn->pending_sec_level;
2066ae293196SMarcel Holtmann 			} else
2067a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_ENCRYPT;
2068a9de9248SMarcel Holtmann 		}
2069a9de9248SMarcel Holtmann 
207051a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2071a9de9248SMarcel Holtmann 
2072a7d7723aSGustavo Padovan 		if (ev->status && conn->state == BT_CONNECTED) {
2073d839c813SGustavo Padovan 			hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
2074a7d7723aSGustavo Padovan 			hci_conn_put(conn);
2075a7d7723aSGustavo Padovan 			goto unlock;
2076a7d7723aSGustavo Padovan 		}
2077a7d7723aSGustavo Padovan 
2078f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
2079f8558555SMarcel Holtmann 			if (!ev->status)
2080f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
2081f8558555SMarcel Holtmann 
2082f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
2083f8558555SMarcel Holtmann 			hci_conn_put(conn);
2084f8558555SMarcel Holtmann 		} else
2085a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, ev->encrypt);
2086a9de9248SMarcel Holtmann 	}
2087a9de9248SMarcel Holtmann 
2088a7d7723aSGustavo Padovan unlock:
2089a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2090a9de9248SMarcel Holtmann }
2091a9de9248SMarcel Holtmann 
20926039aa73SGustavo Padovan static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
2093807deac2SGustavo Padovan 					     struct sk_buff *skb)
2094a9de9248SMarcel Holtmann {
2095a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2096a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2097a9de9248SMarcel Holtmann 
20989f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2099a9de9248SMarcel Holtmann 
2100a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2101a9de9248SMarcel Holtmann 
2102a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2103a9de9248SMarcel Holtmann 	if (conn) {
2104a9de9248SMarcel Holtmann 		if (!ev->status)
2105a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
2106a9de9248SMarcel Holtmann 
210751a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
2108a9de9248SMarcel Holtmann 
2109a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
2110a9de9248SMarcel Holtmann 	}
2111a9de9248SMarcel Holtmann 
2112a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2113a9de9248SMarcel Holtmann }
2114a9de9248SMarcel Holtmann 
21156039aa73SGustavo Padovan static void hci_remote_features_evt(struct hci_dev *hdev,
2116807deac2SGustavo Padovan 				    struct sk_buff *skb)
2117a9de9248SMarcel Holtmann {
2118a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
2119a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2120a9de9248SMarcel Holtmann 
21219f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2122a9de9248SMarcel Holtmann 
2123a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2124a9de9248SMarcel Holtmann 
2125a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2126ccd556feSJohan Hedberg 	if (!conn)
2127ccd556feSJohan Hedberg 		goto unlock;
2128ccd556feSJohan Hedberg 
2129769be974SMarcel Holtmann 	if (!ev->status)
2130a9de9248SMarcel Holtmann 		memcpy(conn->features, ev->features, 8);
2131a9de9248SMarcel Holtmann 
2132ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2133ccd556feSJohan Hedberg 		goto unlock;
2134ccd556feSJohan Hedberg 
2135ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2136769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
2137769be974SMarcel Holtmann 		cp.handle = ev->handle;
2138769be974SMarcel Holtmann 		cp.page = 0x01;
2139ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
2140769be974SMarcel Holtmann 			     sizeof(cp), &cp);
2141392599b9SJohan Hedberg 		goto unlock;
2142392599b9SJohan Hedberg 	}
2143392599b9SJohan Hedberg 
2144671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
2145127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2146127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2147127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2148127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2149127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2150b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2151b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
215208c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
2153b644ba33SJohan Hedberg 				      conn->dev_class);
2154392599b9SJohan Hedberg 
2155127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2156769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2157769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2158769be974SMarcel Holtmann 		hci_conn_put(conn);
2159769be974SMarcel Holtmann 	}
2160769be974SMarcel Holtmann 
2161ccd556feSJohan Hedberg unlock:
2162a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2163a9de9248SMarcel Holtmann }
2164a9de9248SMarcel Holtmann 
21656039aa73SGustavo Padovan static void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
21666039aa73SGustavo Padovan {
21676039aa73SGustavo Padovan 	BT_DBG("%s", hdev->name);
21686039aa73SGustavo Padovan }
21696039aa73SGustavo Padovan 
21706039aa73SGustavo Padovan static void hci_qos_setup_complete_evt(struct hci_dev *hdev,
2171807deac2SGustavo Padovan 				       struct sk_buff *skb)
2172a9de9248SMarcel Holtmann {
2173a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2174a9de9248SMarcel Holtmann }
2175a9de9248SMarcel Holtmann 
21766039aa73SGustavo Padovan static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2177a9de9248SMarcel Holtmann {
2178a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
2179a9de9248SMarcel Holtmann 	__u16 opcode;
2180a9de9248SMarcel Holtmann 
2181a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2182a9de9248SMarcel Holtmann 
2183a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2184a9de9248SMarcel Holtmann 
2185a9de9248SMarcel Holtmann 	switch (opcode) {
2186a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
2187a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
2188a9de9248SMarcel Holtmann 		break;
2189a9de9248SMarcel Holtmann 
21904d93483bSAndre Guedes 	case HCI_OP_PERIODIC_INQ:
21914d93483bSAndre Guedes 		hci_cc_periodic_inq(hdev, skb);
21924d93483bSAndre Guedes 		break;
21934d93483bSAndre Guedes 
2194a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
2195a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
2196a9de9248SMarcel Holtmann 		break;
2197a9de9248SMarcel Holtmann 
2198a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2199a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
2200a9de9248SMarcel Holtmann 		break;
2201a9de9248SMarcel Holtmann 
2202a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
2203a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
2204a9de9248SMarcel Holtmann 		break;
2205a9de9248SMarcel Holtmann 
2206e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
2207e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
2208e4e8e37cSMarcel Holtmann 		break;
2209e4e8e37cSMarcel Holtmann 
2210a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
2211a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
2212a9de9248SMarcel Holtmann 		break;
2213a9de9248SMarcel Holtmann 
2214e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
2215e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
2216e4e8e37cSMarcel Holtmann 		break;
2217e4e8e37cSMarcel Holtmann 
2218e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
2219e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
2220e4e8e37cSMarcel Holtmann 		break;
2221e4e8e37cSMarcel Holtmann 
2222a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
2223a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
2224a9de9248SMarcel Holtmann 		break;
2225a9de9248SMarcel Holtmann 
2226a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
2227a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
2228a9de9248SMarcel Holtmann 		break;
2229a9de9248SMarcel Holtmann 
2230a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
2231a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
2232a9de9248SMarcel Holtmann 		break;
2233a9de9248SMarcel Holtmann 
2234a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
2235a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
2236a9de9248SMarcel Holtmann 		break;
2237a9de9248SMarcel Holtmann 
2238a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
2239a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
2240a9de9248SMarcel Holtmann 		break;
2241a9de9248SMarcel Holtmann 
2242a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
2243a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
2244a9de9248SMarcel Holtmann 		break;
2245a9de9248SMarcel Holtmann 
2246a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
2247a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
2248a9de9248SMarcel Holtmann 		break;
2249a9de9248SMarcel Holtmann 
2250a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
2251a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
2252a9de9248SMarcel Holtmann 		break;
2253a9de9248SMarcel Holtmann 
2254a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
2255a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
2256a9de9248SMarcel Holtmann 		break;
2257a9de9248SMarcel Holtmann 
2258a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
2259a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
2260a9de9248SMarcel Holtmann 		break;
2261a9de9248SMarcel Holtmann 
2262a9de9248SMarcel Holtmann 	case HCI_OP_HOST_BUFFER_SIZE:
2263a9de9248SMarcel Holtmann 		hci_cc_host_buffer_size(hdev, skb);
2264a9de9248SMarcel Holtmann 		break;
2265a9de9248SMarcel Holtmann 
2266333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
2267333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
2268333140b5SMarcel Holtmann 		break;
2269333140b5SMarcel Holtmann 
2270a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
2271a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
2272a9de9248SMarcel Holtmann 		break;
2273a9de9248SMarcel Holtmann 
2274a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
2275a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
2276a9de9248SMarcel Holtmann 		break;
2277a9de9248SMarcel Holtmann 
2278a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
2279a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
2280a9de9248SMarcel Holtmann 		break;
2281a9de9248SMarcel Holtmann 
2282971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
2283971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
2284971e3a4bSAndre Guedes 		break;
2285971e3a4bSAndre Guedes 
2286a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
2287a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
2288a9de9248SMarcel Holtmann 		break;
2289a9de9248SMarcel Holtmann 
2290a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
2291a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
2292a9de9248SMarcel Holtmann 		break;
2293a9de9248SMarcel Holtmann 
2294350ee4cfSAndrei Emeltchenko 	case HCI_OP_READ_DATA_BLOCK_SIZE:
2295350ee4cfSAndrei Emeltchenko 		hci_cc_read_data_block_size(hdev, skb);
2296350ee4cfSAndrei Emeltchenko 		break;
2297350ee4cfSAndrei Emeltchenko 
229823bb5763SJohan Hedberg 	case HCI_OP_WRITE_CA_TIMEOUT:
229923bb5763SJohan Hedberg 		hci_cc_write_ca_timeout(hdev, skb);
230023bb5763SJohan Hedberg 		break;
230123bb5763SJohan Hedberg 
23021e89cffbSAndrei Emeltchenko 	case HCI_OP_READ_FLOW_CONTROL_MODE:
23031e89cffbSAndrei Emeltchenko 		hci_cc_read_flow_control_mode(hdev, skb);
23041e89cffbSAndrei Emeltchenko 		break;
23051e89cffbSAndrei Emeltchenko 
2306928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
2307928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
2308928abaa7SAndrei Emeltchenko 		break;
2309928abaa7SAndrei Emeltchenko 
2310b0916ea0SJohan Hedberg 	case HCI_OP_DELETE_STORED_LINK_KEY:
2311b0916ea0SJohan Hedberg 		hci_cc_delete_stored_link_key(hdev, skb);
2312b0916ea0SJohan Hedberg 		break;
2313b0916ea0SJohan Hedberg 
2314d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_MASK:
2315d5859e22SJohan Hedberg 		hci_cc_set_event_mask(hdev, skb);
2316d5859e22SJohan Hedberg 		break;
2317d5859e22SJohan Hedberg 
2318d5859e22SJohan Hedberg 	case HCI_OP_WRITE_INQUIRY_MODE:
2319d5859e22SJohan Hedberg 		hci_cc_write_inquiry_mode(hdev, skb);
2320d5859e22SJohan Hedberg 		break;
2321d5859e22SJohan Hedberg 
2322d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
2323d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
2324d5859e22SJohan Hedberg 		break;
2325d5859e22SJohan Hedberg 
2326d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_FLT:
2327d5859e22SJohan Hedberg 		hci_cc_set_event_flt(hdev, skb);
2328d5859e22SJohan Hedberg 		break;
2329d5859e22SJohan Hedberg 
2330980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
2331980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
2332980e1a53SJohan Hedberg 		break;
2333980e1a53SJohan Hedberg 
2334980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
2335980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
2336980e1a53SJohan Hedberg 		break;
2337980e1a53SJohan Hedberg 
2338c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
2339c35938b2SSzymon Janc 		hci_cc_read_local_oob_data_reply(hdev, skb);
2340c35938b2SSzymon Janc 		break;
2341c35938b2SSzymon Janc 
23426ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
23436ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
23446ed58ec5SVille Tervo 		break;
23456ed58ec5SVille Tervo 
2346a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
2347a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
2348a5c29683SJohan Hedberg 		break;
2349a5c29683SJohan Hedberg 
2350a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
2351a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
2352a5c29683SJohan Hedberg 		break;
2353a5c29683SJohan Hedberg 
23541143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_REPLY:
23551143d458SBrian Gix 		hci_cc_user_passkey_reply(hdev, skb);
23561143d458SBrian Gix 		break;
23571143d458SBrian Gix 
23581143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_NEG_REPLY:
23591143d458SBrian Gix 		hci_cc_user_passkey_neg_reply(hdev, skb);
236016cde993SSzymon Janc 		break;
236107f7fa5dSAndre Guedes 
236207f7fa5dSAndre Guedes 	case HCI_OP_LE_SET_SCAN_PARAM:
236307f7fa5dSAndre Guedes 		hci_cc_le_set_scan_param(hdev, skb);
23641143d458SBrian Gix 		break;
23651143d458SBrian Gix 
2366eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
2367eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
2368eb9d91f5SAndre Guedes 		break;
2369eb9d91f5SAndre Guedes 
2370a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_REPLY:
2371a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_reply(hdev, skb);
2372a7a595f6SVinicius Costa Gomes 		break;
2373a7a595f6SVinicius Costa Gomes 
2374a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_NEG_REPLY:
2375a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_neg_reply(hdev, skb);
2376a7a595f6SVinicius Costa Gomes 		break;
2377a7a595f6SVinicius Costa Gomes 
2378f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2379f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
2380f9b49306SAndre Guedes 		break;
2381f9b49306SAndre Guedes 
2382a9de9248SMarcel Holtmann 	default:
23839f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2384a9de9248SMarcel Holtmann 		break;
2385a9de9248SMarcel Holtmann 	}
2386a9de9248SMarcel Holtmann 
23876bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
23886bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
23896bd32326SVille Tervo 
2390a9de9248SMarcel Holtmann 	if (ev->ncmd) {
2391a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2392a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2393c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2394a9de9248SMarcel Holtmann 	}
2395a9de9248SMarcel Holtmann }
2396a9de9248SMarcel Holtmann 
23976039aa73SGustavo Padovan static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2398a9de9248SMarcel Holtmann {
2399a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
2400a9de9248SMarcel Holtmann 	__u16 opcode;
2401a9de9248SMarcel Holtmann 
2402a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2403a9de9248SMarcel Holtmann 
2404a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2405a9de9248SMarcel Holtmann 
2406a9de9248SMarcel Holtmann 	switch (opcode) {
2407a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
2408a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
2409a9de9248SMarcel Holtmann 		break;
2410a9de9248SMarcel Holtmann 
2411a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
2412a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
2413a9de9248SMarcel Holtmann 		break;
2414a9de9248SMarcel Holtmann 
2415a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
2416a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
2417a9de9248SMarcel Holtmann 		break;
2418a9de9248SMarcel Holtmann 
2419f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2420f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2421f8558555SMarcel Holtmann 		break;
2422f8558555SMarcel Holtmann 
2423f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2424f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2425f8558555SMarcel Holtmann 		break;
2426f8558555SMarcel Holtmann 
2427a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2428a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2429a9de9248SMarcel Holtmann 		break;
2430a9de9248SMarcel Holtmann 
2431769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2432769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2433769be974SMarcel Holtmann 		break;
2434769be974SMarcel Holtmann 
2435769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2436769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2437769be974SMarcel Holtmann 		break;
2438769be974SMarcel Holtmann 
2439a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2440a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2441a9de9248SMarcel Holtmann 		break;
2442a9de9248SMarcel Holtmann 
2443a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2444a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2445a9de9248SMarcel Holtmann 		break;
2446a9de9248SMarcel Holtmann 
2447a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2448a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2449a9de9248SMarcel Holtmann 		break;
2450a9de9248SMarcel Holtmann 
24518962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
245288c3df13SJohan Hedberg 		hci_cs_disconnect(hdev, ev->status);
24538962ee74SJohan Hedberg 		break;
24548962ee74SJohan Hedberg 
2455fcd89c09SVille Tervo 	case HCI_OP_LE_CREATE_CONN:
2456fcd89c09SVille Tervo 		hci_cs_le_create_conn(hdev, ev->status);
2457fcd89c09SVille Tervo 		break;
2458fcd89c09SVille Tervo 
2459a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_START_ENC:
2460a7a595f6SVinicius Costa Gomes 		hci_cs_le_start_enc(hdev, ev->status);
2461a7a595f6SVinicius Costa Gomes 		break;
2462a7a595f6SVinicius Costa Gomes 
2463a9de9248SMarcel Holtmann 	default:
24649f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2465a9de9248SMarcel Holtmann 		break;
2466a9de9248SMarcel Holtmann 	}
2467a9de9248SMarcel Holtmann 
24686bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
24696bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
24706bd32326SVille Tervo 
247110572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2472a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2473a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2474c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2475a9de9248SMarcel Holtmann 	}
2476a9de9248SMarcel Holtmann }
2477a9de9248SMarcel Holtmann 
24786039aa73SGustavo Padovan static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2479a9de9248SMarcel Holtmann {
2480a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2481a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2482a9de9248SMarcel Holtmann 
24839f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2484a9de9248SMarcel Holtmann 
2485a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2486a9de9248SMarcel Holtmann 
2487a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2488a9de9248SMarcel Holtmann 	if (conn) {
2489a9de9248SMarcel Holtmann 		if (!ev->status) {
2490a9de9248SMarcel Holtmann 			if (ev->role)
2491a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
2492a9de9248SMarcel Holtmann 			else
2493a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
2494a9de9248SMarcel Holtmann 		}
2495a9de9248SMarcel Holtmann 
249651a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
2497a9de9248SMarcel Holtmann 
2498a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2499a9de9248SMarcel Holtmann 	}
2500a9de9248SMarcel Holtmann 
2501a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2502a9de9248SMarcel Holtmann }
2503a9de9248SMarcel Holtmann 
25046039aa73SGustavo Padovan static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
25051da177e4SLinus Torvalds {
2506a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
25071da177e4SLinus Torvalds 	int i;
25081da177e4SLinus Torvalds 
250932ac5b9bSAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
251032ac5b9bSAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
251132ac5b9bSAndrei Emeltchenko 		return;
251232ac5b9bSAndrei Emeltchenko 	}
251332ac5b9bSAndrei Emeltchenko 
2514c5993de8SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2515c5993de8SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
25161da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
25171da177e4SLinus Torvalds 		return;
25181da177e4SLinus Torvalds 	}
25191da177e4SLinus Torvalds 
2520c5993de8SAndrei Emeltchenko 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2521c5993de8SAndrei Emeltchenko 
2522613a1c0cSAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
2523613a1c0cSAndrei Emeltchenko 		struct hci_comp_pkts_info *info = &ev->handles[i];
25241da177e4SLinus Torvalds 		struct hci_conn *conn;
25251da177e4SLinus Torvalds 		__u16  handle, count;
25261da177e4SLinus Torvalds 
2527613a1c0cSAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
2528613a1c0cSAndrei Emeltchenko 		count  = __le16_to_cpu(info->count);
25291da177e4SLinus Torvalds 
25301da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
2531f4280918SAndrei Emeltchenko 		if (!conn)
2532f4280918SAndrei Emeltchenko 			continue;
2533f4280918SAndrei Emeltchenko 
25341da177e4SLinus Torvalds 		conn->sent -= count;
25351da177e4SLinus Torvalds 
2536f4280918SAndrei Emeltchenko 		switch (conn->type) {
2537f4280918SAndrei Emeltchenko 		case ACL_LINK:
253870f23020SAndrei Emeltchenko 			hdev->acl_cnt += count;
253970f23020SAndrei Emeltchenko 			if (hdev->acl_cnt > hdev->acl_pkts)
25401da177e4SLinus Torvalds 				hdev->acl_cnt = hdev->acl_pkts;
2541f4280918SAndrei Emeltchenko 			break;
2542f4280918SAndrei Emeltchenko 
2543f4280918SAndrei Emeltchenko 		case LE_LINK:
25446ed58ec5SVille Tervo 			if (hdev->le_pkts) {
25456ed58ec5SVille Tervo 				hdev->le_cnt += count;
25466ed58ec5SVille Tervo 				if (hdev->le_cnt > hdev->le_pkts)
25476ed58ec5SVille Tervo 					hdev->le_cnt = hdev->le_pkts;
25486ed58ec5SVille Tervo 			} else {
25496ed58ec5SVille Tervo 				hdev->acl_cnt += count;
25506ed58ec5SVille Tervo 				if (hdev->acl_cnt > hdev->acl_pkts)
25516ed58ec5SVille Tervo 					hdev->acl_cnt = hdev->acl_pkts;
25526ed58ec5SVille Tervo 			}
2553f4280918SAndrei Emeltchenko 			break;
2554f4280918SAndrei Emeltchenko 
2555f4280918SAndrei Emeltchenko 		case SCO_LINK:
255670f23020SAndrei Emeltchenko 			hdev->sco_cnt += count;
255770f23020SAndrei Emeltchenko 			if (hdev->sco_cnt > hdev->sco_pkts)
25585b7f9909SMarcel Holtmann 				hdev->sco_cnt = hdev->sco_pkts;
2559f4280918SAndrei Emeltchenko 			break;
2560f4280918SAndrei Emeltchenko 
2561f4280918SAndrei Emeltchenko 		default:
2562f4280918SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
2563f4280918SAndrei Emeltchenko 			break;
25641da177e4SLinus Torvalds 		}
25651da177e4SLinus Torvalds 	}
2566a9de9248SMarcel Holtmann 
25673eff45eaSGustavo F. Padovan 	queue_work(hdev->workqueue, &hdev->tx_work);
25681da177e4SLinus Torvalds }
25691da177e4SLinus Torvalds 
25706039aa73SGustavo Padovan static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
257125e89e99SAndrei Emeltchenko {
257225e89e99SAndrei Emeltchenko 	struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
257325e89e99SAndrei Emeltchenko 	int i;
257425e89e99SAndrei Emeltchenko 
257525e89e99SAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
257625e89e99SAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
257725e89e99SAndrei Emeltchenko 		return;
257825e89e99SAndrei Emeltchenko 	}
257925e89e99SAndrei Emeltchenko 
258025e89e99SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
258125e89e99SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
258225e89e99SAndrei Emeltchenko 		BT_DBG("%s bad parameters", hdev->name);
258325e89e99SAndrei Emeltchenko 		return;
258425e89e99SAndrei Emeltchenko 	}
258525e89e99SAndrei Emeltchenko 
258625e89e99SAndrei Emeltchenko 	BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
258725e89e99SAndrei Emeltchenko 	       ev->num_hndl);
258825e89e99SAndrei Emeltchenko 
258925e89e99SAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
259025e89e99SAndrei Emeltchenko 		struct hci_comp_blocks_info *info = &ev->handles[i];
259125e89e99SAndrei Emeltchenko 		struct hci_conn *conn;
259225e89e99SAndrei Emeltchenko 		__u16  handle, block_count;
259325e89e99SAndrei Emeltchenko 
259425e89e99SAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
259525e89e99SAndrei Emeltchenko 		block_count = __le16_to_cpu(info->blocks);
259625e89e99SAndrei Emeltchenko 
259725e89e99SAndrei Emeltchenko 		conn = hci_conn_hash_lookup_handle(hdev, handle);
259825e89e99SAndrei Emeltchenko 		if (!conn)
259925e89e99SAndrei Emeltchenko 			continue;
260025e89e99SAndrei Emeltchenko 
260125e89e99SAndrei Emeltchenko 		conn->sent -= block_count;
260225e89e99SAndrei Emeltchenko 
260325e89e99SAndrei Emeltchenko 		switch (conn->type) {
260425e89e99SAndrei Emeltchenko 		case ACL_LINK:
260525e89e99SAndrei Emeltchenko 			hdev->block_cnt += block_count;
260625e89e99SAndrei Emeltchenko 			if (hdev->block_cnt > hdev->num_blocks)
260725e89e99SAndrei Emeltchenko 				hdev->block_cnt = hdev->num_blocks;
260825e89e99SAndrei Emeltchenko 			break;
260925e89e99SAndrei Emeltchenko 
261025e89e99SAndrei Emeltchenko 		default:
261125e89e99SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
261225e89e99SAndrei Emeltchenko 			break;
261325e89e99SAndrei Emeltchenko 		}
261425e89e99SAndrei Emeltchenko 	}
261525e89e99SAndrei Emeltchenko 
261625e89e99SAndrei Emeltchenko 	queue_work(hdev->workqueue, &hdev->tx_work);
261725e89e99SAndrei Emeltchenko }
261825e89e99SAndrei Emeltchenko 
26196039aa73SGustavo Padovan static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
26201da177e4SLinus Torvalds {
2621a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
262204837f64SMarcel Holtmann 	struct hci_conn *conn;
26231da177e4SLinus Torvalds 
26249f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
26251da177e4SLinus Torvalds 
26261da177e4SLinus Torvalds 	hci_dev_lock(hdev);
26271da177e4SLinus Torvalds 
262804837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
262904837f64SMarcel Holtmann 	if (conn) {
263004837f64SMarcel Holtmann 		conn->mode = ev->mode;
263104837f64SMarcel Holtmann 		conn->interval = __le16_to_cpu(ev->interval);
263204837f64SMarcel Holtmann 
26338fc9ced3SGustavo Padovan 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
26348fc9ced3SGustavo Padovan 					&conn->flags)) {
263504837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
263658a681efSJohan Hedberg 				set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
263704837f64SMarcel Holtmann 			else
263858a681efSJohan Hedberg 				clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
263904837f64SMarcel Holtmann 		}
2640e73439d8SMarcel Holtmann 
264151a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
2642e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
264304837f64SMarcel Holtmann 	}
264404837f64SMarcel Holtmann 
264504837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
264604837f64SMarcel Holtmann }
264704837f64SMarcel Holtmann 
26486039aa73SGustavo Padovan static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
26491da177e4SLinus Torvalds {
2650052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
2651052b30b0SMarcel Holtmann 	struct hci_conn *conn;
2652052b30b0SMarcel Holtmann 
2653a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2654052b30b0SMarcel Holtmann 
2655052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2656052b30b0SMarcel Holtmann 
2657052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2658b6f98044SWaldemar Rymarkiewicz 	if (!conn)
2659b6f98044SWaldemar Rymarkiewicz 		goto unlock;
2660b6f98044SWaldemar Rymarkiewicz 
2661b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
2662052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2663052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2664052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2665052b30b0SMarcel Holtmann 	}
2666052b30b0SMarcel Holtmann 
2667a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
266803b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
266903b555e1SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
2670a8b2d5c2SJohan Hedberg 	else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
2671a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
2672a770bb5aSWaldemar Rymarkiewicz 
2673a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
2674a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
2675a770bb5aSWaldemar Rymarkiewicz 		else
2676a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
2677a770bb5aSWaldemar Rymarkiewicz 
2678744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
2679a770bb5aSWaldemar Rymarkiewicz 	}
2680980e1a53SJohan Hedberg 
2681b6f98044SWaldemar Rymarkiewicz unlock:
2682052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
26831da177e4SLinus Torvalds }
26841da177e4SLinus Torvalds 
26856039aa73SGustavo Padovan static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
26861da177e4SLinus Torvalds {
268755ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
268855ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
268955ed8ca1SJohan Hedberg 	struct hci_conn *conn;
269055ed8ca1SJohan Hedberg 	struct link_key *key;
269155ed8ca1SJohan Hedberg 
2692a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
269355ed8ca1SJohan Hedberg 
2694a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
269555ed8ca1SJohan Hedberg 		return;
269655ed8ca1SJohan Hedberg 
269755ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
269855ed8ca1SJohan Hedberg 
269955ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
270055ed8ca1SJohan Hedberg 	if (!key) {
270155ed8ca1SJohan Hedberg 		BT_DBG("%s link key not found for %s", hdev->name,
270255ed8ca1SJohan Hedberg 		       batostr(&ev->bdaddr));
270355ed8ca1SJohan Hedberg 		goto not_found;
270455ed8ca1SJohan Hedberg 	}
270555ed8ca1SJohan Hedberg 
270655ed8ca1SJohan Hedberg 	BT_DBG("%s found key type %u for %s", hdev->name, key->type,
270755ed8ca1SJohan Hedberg 	       batostr(&ev->bdaddr));
270855ed8ca1SJohan Hedberg 
2709a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
2710b6020ba0SWaldemar Rymarkiewicz 	    key->type == HCI_LK_DEBUG_COMBINATION) {
271155ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
271255ed8ca1SJohan Hedberg 		goto not_found;
271355ed8ca1SJohan Hedberg 	}
271455ed8ca1SJohan Hedberg 
271555ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
271660b83f57SWaldemar Rymarkiewicz 	if (conn) {
271760b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_UNAUTH_COMBINATION &&
2718807deac2SGustavo Padovan 		    conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
271955ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
272055ed8ca1SJohan Hedberg 			goto not_found;
272155ed8ca1SJohan Hedberg 		}
272255ed8ca1SJohan Hedberg 
272360b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
272460b83f57SWaldemar Rymarkiewicz 		    conn->pending_sec_level == BT_SECURITY_HIGH) {
27258fc9ced3SGustavo Padovan 			BT_DBG("%s ignoring key unauthenticated for high security",
27268fc9ced3SGustavo Padovan 			       hdev->name);
272760b83f57SWaldemar Rymarkiewicz 			goto not_found;
272860b83f57SWaldemar Rymarkiewicz 		}
272960b83f57SWaldemar Rymarkiewicz 
273060b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
273160b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
273260b83f57SWaldemar Rymarkiewicz 	}
273360b83f57SWaldemar Rymarkiewicz 
273455ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
27359b3b4460SAndrei Emeltchenko 	memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
273655ed8ca1SJohan Hedberg 
273755ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
273855ed8ca1SJohan Hedberg 
273955ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
274055ed8ca1SJohan Hedberg 
274155ed8ca1SJohan Hedberg 	return;
274255ed8ca1SJohan Hedberg 
274355ed8ca1SJohan Hedberg not_found:
274455ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
274555ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
27461da177e4SLinus Torvalds }
27471da177e4SLinus Torvalds 
27486039aa73SGustavo Padovan static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
27491da177e4SLinus Torvalds {
2750052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
2751052b30b0SMarcel Holtmann 	struct hci_conn *conn;
275255ed8ca1SJohan Hedberg 	u8 pin_len = 0;
2753052b30b0SMarcel Holtmann 
2754a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2755052b30b0SMarcel Holtmann 
2756052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2757052b30b0SMarcel Holtmann 
2758052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2759052b30b0SMarcel Holtmann 	if (conn) {
2760052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2761052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2762980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
276313d39315SWaldemar Rymarkiewicz 
276413d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
276513d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
276613d39315SWaldemar Rymarkiewicz 
2767052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2768052b30b0SMarcel Holtmann 	}
2769052b30b0SMarcel Holtmann 
2770a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
2771d25e28abSJohan Hedberg 		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
277255ed8ca1SJohan Hedberg 				 ev->key_type, pin_len);
277355ed8ca1SJohan Hedberg 
2774052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
27751da177e4SLinus Torvalds }
27761da177e4SLinus Torvalds 
27776039aa73SGustavo Padovan static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
277804837f64SMarcel Holtmann {
2779a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
278004837f64SMarcel Holtmann 	struct hci_conn *conn;
278104837f64SMarcel Holtmann 
27829f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
278304837f64SMarcel Holtmann 
278404837f64SMarcel Holtmann 	hci_dev_lock(hdev);
278504837f64SMarcel Holtmann 
278604837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
27871da177e4SLinus Torvalds 	if (conn && !ev->status) {
27881da177e4SLinus Torvalds 		struct inquiry_entry *ie;
27891da177e4SLinus Torvalds 
2790cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2791cc11b9c1SAndrei Emeltchenko 		if (ie) {
27921da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
27931da177e4SLinus Torvalds 			ie->timestamp = jiffies;
27941da177e4SLinus Torvalds 		}
27951da177e4SLinus Torvalds 	}
27961da177e4SLinus Torvalds 
27971da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
27981da177e4SLinus Torvalds }
27991da177e4SLinus Torvalds 
28006039aa73SGustavo Padovan static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2801a8746417SMarcel Holtmann {
2802a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2803a8746417SMarcel Holtmann 	struct hci_conn *conn;
2804a8746417SMarcel Holtmann 
28059f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2806a8746417SMarcel Holtmann 
2807a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
2808a8746417SMarcel Holtmann 
2809a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2810a8746417SMarcel Holtmann 	if (conn && !ev->status)
2811a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2812a8746417SMarcel Holtmann 
2813a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
2814a8746417SMarcel Holtmann }
2815a8746417SMarcel Holtmann 
28166039aa73SGustavo Padovan static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
281785a1e930SMarcel Holtmann {
2818a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
281985a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
282085a1e930SMarcel Holtmann 
282185a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
282285a1e930SMarcel Holtmann 
282385a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
282485a1e930SMarcel Holtmann 
2825cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2826cc11b9c1SAndrei Emeltchenko 	if (ie) {
282785a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
282885a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
282985a1e930SMarcel Holtmann 	}
283085a1e930SMarcel Holtmann 
283185a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
283285a1e930SMarcel Holtmann }
283385a1e930SMarcel Holtmann 
28346039aa73SGustavo Padovan static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
2835807deac2SGustavo Padovan 					     struct sk_buff *skb)
2836a9de9248SMarcel Holtmann {
2837a9de9248SMarcel Holtmann 	struct inquiry_data data;
2838a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2839388fc8faSJohan Hedberg 	bool name_known, ssp;
2840a9de9248SMarcel Holtmann 
2841a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2842a9de9248SMarcel Holtmann 
2843a9de9248SMarcel Holtmann 	if (!num_rsp)
2844a9de9248SMarcel Holtmann 		return;
2845a9de9248SMarcel Holtmann 
28461519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
28471519cc17SAndre Guedes 		return;
28481519cc17SAndre Guedes 
2849a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2850a9de9248SMarcel Holtmann 
2851a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
2852138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
2853138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
2854a9de9248SMarcel Holtmann 
2855e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2856a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2857a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2858a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2859a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
2860a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2861a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2862a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
286341a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
28643175405bSJohan Hedberg 
28653175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
2866388fc8faSJohan Hedberg 							      false, &ssp);
286748264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2868e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
2869388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
2870a9de9248SMarcel Holtmann 		}
2871a9de9248SMarcel Holtmann 	} else {
2872a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2873a9de9248SMarcel Holtmann 
2874e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2875a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2876a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2877a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2878a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
2879a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2880a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2881a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
288241a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
28833175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
2884388fc8faSJohan Hedberg 							      false, &ssp);
288548264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2886e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
2887388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
2888a9de9248SMarcel Holtmann 		}
2889a9de9248SMarcel Holtmann 	}
2890a9de9248SMarcel Holtmann 
2891a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2892a9de9248SMarcel Holtmann }
2893a9de9248SMarcel Holtmann 
28946039aa73SGustavo Padovan static void hci_remote_ext_features_evt(struct hci_dev *hdev,
2895807deac2SGustavo Padovan 					struct sk_buff *skb)
2896a9de9248SMarcel Holtmann {
289741a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
289841a96212SMarcel Holtmann 	struct hci_conn *conn;
289941a96212SMarcel Holtmann 
2900a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
290141a96212SMarcel Holtmann 
290241a96212SMarcel Holtmann 	hci_dev_lock(hdev);
290341a96212SMarcel Holtmann 
290441a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2905ccd556feSJohan Hedberg 	if (!conn)
2906ccd556feSJohan Hedberg 		goto unlock;
2907ccd556feSJohan Hedberg 
2908769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
290941a96212SMarcel Holtmann 		struct inquiry_entry *ie;
291041a96212SMarcel Holtmann 
2911cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2912cc11b9c1SAndrei Emeltchenko 		if (ie)
291302b7cc62SJohan Hedberg 			ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
291441a96212SMarcel Holtmann 
291502b7cc62SJohan Hedberg 		if (ev->features[0] & LMP_HOST_SSP)
291658a681efSJohan Hedberg 			set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
291741a96212SMarcel Holtmann 	}
291841a96212SMarcel Holtmann 
2919ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2920ccd556feSJohan Hedberg 		goto unlock;
2921ccd556feSJohan Hedberg 
2922671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
2923127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2924127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2925127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2926127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2927127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2928b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2929b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
293008c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
2931b644ba33SJohan Hedberg 				      conn->dev_class);
2932392599b9SJohan Hedberg 
2933127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2934769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2935769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2936769be974SMarcel Holtmann 		hci_conn_put(conn);
2937769be974SMarcel Holtmann 	}
2938769be974SMarcel Holtmann 
2939ccd556feSJohan Hedberg unlock:
294041a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
2941a9de9248SMarcel Holtmann }
2942a9de9248SMarcel Holtmann 
29436039aa73SGustavo Padovan static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
2944807deac2SGustavo Padovan 				       struct sk_buff *skb)
2945a9de9248SMarcel Holtmann {
2946b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2947b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
2948b6a0dc82SMarcel Holtmann 
29499f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2950b6a0dc82SMarcel Holtmann 
2951b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
2952b6a0dc82SMarcel Holtmann 
2953b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
29549dc0a3afSMarcel Holtmann 	if (!conn) {
29559dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
29569dc0a3afSMarcel Holtmann 			goto unlock;
29579dc0a3afSMarcel Holtmann 
29589dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2959b6a0dc82SMarcel Holtmann 		if (!conn)
2960b6a0dc82SMarcel Holtmann 			goto unlock;
2961b6a0dc82SMarcel Holtmann 
29629dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
29639dc0a3afSMarcel Holtmann 	}
29649dc0a3afSMarcel Holtmann 
2965732547f9SMarcel Holtmann 	switch (ev->status) {
2966732547f9SMarcel Holtmann 	case 0x00:
2967732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
2968732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
2969732547f9SMarcel Holtmann 
29709eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
2971732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
2972732547f9SMarcel Holtmann 		break;
2973732547f9SMarcel Holtmann 
2974705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
2975732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
29761038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
2977732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
2978732547f9SMarcel Holtmann 		if (conn->out && conn->attempt < 2) {
2979efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2980efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
2981efc7688bSMarcel Holtmann 			hci_setup_sync(conn, conn->link->handle);
2982efc7688bSMarcel Holtmann 			goto unlock;
2983efc7688bSMarcel Holtmann 		}
2984732547f9SMarcel Holtmann 		/* fall through */
2985efc7688bSMarcel Holtmann 
2986732547f9SMarcel Holtmann 	default:
2987b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
2988732547f9SMarcel Holtmann 		break;
2989732547f9SMarcel Holtmann 	}
2990b6a0dc82SMarcel Holtmann 
2991b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
2992b6a0dc82SMarcel Holtmann 	if (ev->status)
2993b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
2994b6a0dc82SMarcel Holtmann 
2995b6a0dc82SMarcel Holtmann unlock:
2996b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
2997a9de9248SMarcel Holtmann }
2998a9de9248SMarcel Holtmann 
29996039aa73SGustavo Padovan static void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
3000a9de9248SMarcel Holtmann {
3001a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
3002a9de9248SMarcel Holtmann }
3003a9de9248SMarcel Holtmann 
30046039aa73SGustavo Padovan static void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
300504837f64SMarcel Holtmann {
3006a9de9248SMarcel Holtmann 	struct hci_ev_sniff_subrate *ev = (void *) skb->data;
300704837f64SMarcel Holtmann 
30089f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
300904837f64SMarcel Holtmann }
301004837f64SMarcel Holtmann 
30116039aa73SGustavo Padovan static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
3012807deac2SGustavo Padovan 					    struct sk_buff *skb)
3013a9de9248SMarcel Holtmann {
3014a9de9248SMarcel Holtmann 	struct inquiry_data data;
3015a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
3016a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
30179d939d94SVishal Agarwal 	size_t eir_len;
3018a9de9248SMarcel Holtmann 
3019a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3020a9de9248SMarcel Holtmann 
3021a9de9248SMarcel Holtmann 	if (!num_rsp)
3022a9de9248SMarcel Holtmann 		return;
3023a9de9248SMarcel Holtmann 
30241519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
30251519cc17SAndre Guedes 		return;
30261519cc17SAndre Guedes 
3027a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
3028a9de9248SMarcel Holtmann 
3029e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
3030388fc8faSJohan Hedberg 		bool name_known, ssp;
3031561aafbcSJohan Hedberg 
3032a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
3033a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
3034a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
3035a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
3036a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
3037a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
3038a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
303941a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
3040561aafbcSJohan Hedberg 
3041a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
30424ddb1930SJohan Hedberg 			name_known = eir_has_data_type(info->data,
30434ddb1930SJohan Hedberg 						       sizeof(info->data),
30444ddb1930SJohan Hedberg 						       EIR_NAME_COMPLETE);
3045561aafbcSJohan Hedberg 		else
3046561aafbcSJohan Hedberg 			name_known = true;
3047561aafbcSJohan Hedberg 
3048388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, name_known,
3049388fc8faSJohan Hedberg 						      &ssp);
30509d939d94SVishal Agarwal 		eir_len = eir_get_length(info->data, sizeof(info->data));
305148264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
305204124681SGustavo F. Padovan 				  info->dev_class, info->rssi, !name_known,
30539d939d94SVishal Agarwal 				  ssp, info->data, eir_len);
3054a9de9248SMarcel Holtmann 	}
3055a9de9248SMarcel Holtmann 
3056a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3057a9de9248SMarcel Holtmann }
3058a9de9248SMarcel Holtmann 
30591c2e0041SJohan Hedberg static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
30601c2e0041SJohan Hedberg 					 struct sk_buff *skb)
30611c2e0041SJohan Hedberg {
30621c2e0041SJohan Hedberg 	struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
30631c2e0041SJohan Hedberg 	struct hci_conn *conn;
30641c2e0041SJohan Hedberg 
30659f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
30661c2e0041SJohan Hedberg 	       __le16_to_cpu(ev->handle));
30671c2e0041SJohan Hedberg 
30681c2e0041SJohan Hedberg 	hci_dev_lock(hdev);
30691c2e0041SJohan Hedberg 
30701c2e0041SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
30711c2e0041SJohan Hedberg 	if (!conn)
30721c2e0041SJohan Hedberg 		goto unlock;
30731c2e0041SJohan Hedberg 
30741c2e0041SJohan Hedberg 	if (!ev->status)
30751c2e0041SJohan Hedberg 		conn->sec_level = conn->pending_sec_level;
30761c2e0041SJohan Hedberg 
30771c2e0041SJohan Hedberg 	clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
30781c2e0041SJohan Hedberg 
30791c2e0041SJohan Hedberg 	if (ev->status && conn->state == BT_CONNECTED) {
30801c2e0041SJohan Hedberg 		hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
30811c2e0041SJohan Hedberg 		hci_conn_put(conn);
30821c2e0041SJohan Hedberg 		goto unlock;
30831c2e0041SJohan Hedberg 	}
30841c2e0041SJohan Hedberg 
30851c2e0041SJohan Hedberg 	if (conn->state == BT_CONFIG) {
30861c2e0041SJohan Hedberg 		if (!ev->status)
30871c2e0041SJohan Hedberg 			conn->state = BT_CONNECTED;
30881c2e0041SJohan Hedberg 
30891c2e0041SJohan Hedberg 		hci_proto_connect_cfm(conn, ev->status);
30901c2e0041SJohan Hedberg 		hci_conn_put(conn);
30911c2e0041SJohan Hedberg 	} else {
30921c2e0041SJohan Hedberg 		hci_auth_cfm(conn, ev->status);
30931c2e0041SJohan Hedberg 
30941c2e0041SJohan Hedberg 		hci_conn_hold(conn);
30951c2e0041SJohan Hedberg 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
30961c2e0041SJohan Hedberg 		hci_conn_put(conn);
30971c2e0041SJohan Hedberg 	}
30981c2e0041SJohan Hedberg 
30991c2e0041SJohan Hedberg unlock:
31001c2e0041SJohan Hedberg 	hci_dev_unlock(hdev);
31011c2e0041SJohan Hedberg }
31021c2e0041SJohan Hedberg 
31036039aa73SGustavo Padovan static u8 hci_get_auth_req(struct hci_conn *conn)
310417fa4b9dSJohan Hedberg {
310517fa4b9dSJohan Hedberg 	/* If remote requests dedicated bonding follow that lead */
310617fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
310717fa4b9dSJohan Hedberg 		/* If both remote and local IO capabilities allow MITM
310817fa4b9dSJohan Hedberg 		 * protection then require it, otherwise don't */
310917fa4b9dSJohan Hedberg 		if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
311017fa4b9dSJohan Hedberg 			return 0x02;
311117fa4b9dSJohan Hedberg 		else
311217fa4b9dSJohan Hedberg 			return 0x03;
311317fa4b9dSJohan Hedberg 	}
311417fa4b9dSJohan Hedberg 
311517fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
311617fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
311758797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
311817fa4b9dSJohan Hedberg 
311917fa4b9dSJohan Hedberg 	return conn->auth_type;
312017fa4b9dSJohan Hedberg }
312117fa4b9dSJohan Hedberg 
31226039aa73SGustavo Padovan static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
31230493684eSMarcel Holtmann {
31240493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
31250493684eSMarcel Holtmann 	struct hci_conn *conn;
31260493684eSMarcel Holtmann 
31270493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
31280493684eSMarcel Holtmann 
31290493684eSMarcel Holtmann 	hci_dev_lock(hdev);
31300493684eSMarcel Holtmann 
31310493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
313203b555e1SJohan Hedberg 	if (!conn)
313303b555e1SJohan Hedberg 		goto unlock;
313403b555e1SJohan Hedberg 
31350493684eSMarcel Holtmann 	hci_conn_hold(conn);
31360493684eSMarcel Holtmann 
3137a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
313803b555e1SJohan Hedberg 		goto unlock;
313903b555e1SJohan Hedberg 
3140a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
314103b555e1SJohan Hedberg 	    (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
314217fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
314317fa4b9dSJohan Hedberg 
314417fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
31457a7f1e7cSHemant Gupta 		/* Change the IO capability from KeyboardDisplay
31467a7f1e7cSHemant Gupta 		 * to DisplayYesNo as it is not supported by BT spec. */
31477a7f1e7cSHemant Gupta 		cp.capability = (conn->io_capability == 0x04) ?
31487a7f1e7cSHemant Gupta 						0x01 : conn->io_capability;
31497cbc9bd9SJohan Hedberg 		conn->auth_type = hci_get_auth_req(conn);
31507cbc9bd9SJohan Hedberg 		cp.authentication = conn->auth_type;
315117fa4b9dSJohan Hedberg 
31528fc9ced3SGustavo Padovan 		if (hci_find_remote_oob_data(hdev, &conn->dst) &&
31538fc9ced3SGustavo Padovan 		    (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
3154ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
3155ce85ee13SSzymon Janc 		else
3156ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
3157ce85ee13SSzymon Janc 
315817fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
315917fa4b9dSJohan Hedberg 			     sizeof(cp), &cp);
316003b555e1SJohan Hedberg 	} else {
316103b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
316203b555e1SJohan Hedberg 
316303b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
31649f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
316503b555e1SJohan Hedberg 
316603b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
316703b555e1SJohan Hedberg 			     sizeof(cp), &cp);
316803b555e1SJohan Hedberg 	}
316903b555e1SJohan Hedberg 
317003b555e1SJohan Hedberg unlock:
317103b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
317203b555e1SJohan Hedberg }
317303b555e1SJohan Hedberg 
31746039aa73SGustavo Padovan static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
317503b555e1SJohan Hedberg {
317603b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
317703b555e1SJohan Hedberg 	struct hci_conn *conn;
317803b555e1SJohan Hedberg 
317903b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
318003b555e1SJohan Hedberg 
318103b555e1SJohan Hedberg 	hci_dev_lock(hdev);
318203b555e1SJohan Hedberg 
318303b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
318403b555e1SJohan Hedberg 	if (!conn)
318503b555e1SJohan Hedberg 		goto unlock;
318603b555e1SJohan Hedberg 
318703b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
318803b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
318958a681efSJohan Hedberg 	if (ev->oob_data)
319058a681efSJohan Hedberg 		set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
319103b555e1SJohan Hedberg 
319203b555e1SJohan Hedberg unlock:
31930493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
31940493684eSMarcel Holtmann }
31950493684eSMarcel Holtmann 
31966039aa73SGustavo Padovan static void hci_user_confirm_request_evt(struct hci_dev *hdev,
3197a5c29683SJohan Hedberg 					 struct sk_buff *skb)
3198a5c29683SJohan Hedberg {
3199a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
320055bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
32017a828908SJohan Hedberg 	struct hci_conn *conn;
3202a5c29683SJohan Hedberg 
3203a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
3204a5c29683SJohan Hedberg 
3205a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
3206a5c29683SJohan Hedberg 
3207a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
32087a828908SJohan Hedberg 		goto unlock;
32097a828908SJohan Hedberg 
32107a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
32117a828908SJohan Hedberg 	if (!conn)
32127a828908SJohan Hedberg 		goto unlock;
32137a828908SJohan Hedberg 
32147a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
32157a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
32167a828908SJohan Hedberg 
32177a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
32187a828908SJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
32197a828908SJohan Hedberg 	 * request. The only exception is when we're dedicated bonding
32207a828908SJohan Hedberg 	 * initiators (connect_cfm_cb set) since then we always have the MITM
32217a828908SJohan Hedberg 	 * bit set. */
32227a828908SJohan Hedberg 	if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
32237a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
32247a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
32257a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
32267a828908SJohan Hedberg 		goto unlock;
32277a828908SJohan Hedberg 	}
32287a828908SJohan Hedberg 
32297a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
32307a828908SJohan Hedberg 	if ((!loc_mitm || conn->remote_cap == 0x03) &&
32317a828908SJohan Hedberg 	    (!rem_mitm || conn->io_capability == 0x03)) {
323255bc1a37SJohan Hedberg 
323355bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
323455bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
323555bc1a37SJohan Hedberg 		 * confirm_hint set to 1). */
323651a8efd7SJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
323755bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
323855bc1a37SJohan Hedberg 			confirm_hint = 1;
323955bc1a37SJohan Hedberg 			goto confirm;
324055bc1a37SJohan Hedberg 		}
324155bc1a37SJohan Hedberg 
32429f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
32439f61656aSJohan Hedberg 		       hdev->auto_accept_delay);
32449f61656aSJohan Hedberg 
32459f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
32469f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
32479f61656aSJohan Hedberg 			mod_timer(&conn->auto_accept_timer, jiffies + delay);
32489f61656aSJohan Hedberg 			goto unlock;
32499f61656aSJohan Hedberg 		}
32509f61656aSJohan Hedberg 
32517a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
32527a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
32537a828908SJohan Hedberg 		goto unlock;
32547a828908SJohan Hedberg 	}
32557a828908SJohan Hedberg 
325655bc1a37SJohan Hedberg confirm:
3257272d90dfSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
325855bc1a37SJohan Hedberg 				  confirm_hint);
3259a5c29683SJohan Hedberg 
32607a828908SJohan Hedberg unlock:
3261a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
3262a5c29683SJohan Hedberg }
3263a5c29683SJohan Hedberg 
32646039aa73SGustavo Padovan static void hci_user_passkey_request_evt(struct hci_dev *hdev,
32651143d458SBrian Gix 					 struct sk_buff *skb)
32661143d458SBrian Gix {
32671143d458SBrian Gix 	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
32681143d458SBrian Gix 
32691143d458SBrian Gix 	BT_DBG("%s", hdev->name);
32701143d458SBrian Gix 
32711143d458SBrian Gix 	hci_dev_lock(hdev);
32721143d458SBrian Gix 
3273a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3274272d90dfSJohan Hedberg 		mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
32751143d458SBrian Gix 
32761143d458SBrian Gix 	hci_dev_unlock(hdev);
32771143d458SBrian Gix }
32781143d458SBrian Gix 
32796039aa73SGustavo Padovan static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
3280807deac2SGustavo Padovan 					 struct sk_buff *skb)
32810493684eSMarcel Holtmann {
32820493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
32830493684eSMarcel Holtmann 	struct hci_conn *conn;
32840493684eSMarcel Holtmann 
32850493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
32860493684eSMarcel Holtmann 
32870493684eSMarcel Holtmann 	hci_dev_lock(hdev);
32880493684eSMarcel Holtmann 
32890493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
32902a611692SJohan Hedberg 	if (!conn)
32912a611692SJohan Hedberg 		goto unlock;
32922a611692SJohan Hedberg 
32932a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
32942a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
32952a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
32962a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
32972a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
329851a8efd7SJohan Hedberg 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status != 0)
3299bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
3300bab73cb6SJohan Hedberg 				 ev->status);
33012a611692SJohan Hedberg 
33020493684eSMarcel Holtmann 	hci_conn_put(conn);
33030493684eSMarcel Holtmann 
33042a611692SJohan Hedberg unlock:
33050493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
33060493684eSMarcel Holtmann }
33070493684eSMarcel Holtmann 
33086039aa73SGustavo Padovan static void hci_remote_host_features_evt(struct hci_dev *hdev,
3309807deac2SGustavo Padovan 					 struct sk_buff *skb)
331041a96212SMarcel Holtmann {
331141a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
331241a96212SMarcel Holtmann 	struct inquiry_entry *ie;
331341a96212SMarcel Holtmann 
331441a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
331541a96212SMarcel Holtmann 
331641a96212SMarcel Holtmann 	hci_dev_lock(hdev);
331741a96212SMarcel Holtmann 
3318cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3319cc11b9c1SAndrei Emeltchenko 	if (ie)
332002b7cc62SJohan Hedberg 		ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
332141a96212SMarcel Holtmann 
332241a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
332341a96212SMarcel Holtmann }
332441a96212SMarcel Holtmann 
33256039aa73SGustavo Padovan static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
33262763eda6SSzymon Janc 					    struct sk_buff *skb)
33272763eda6SSzymon Janc {
33282763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
33292763eda6SSzymon Janc 	struct oob_data *data;
33302763eda6SSzymon Janc 
33312763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
33322763eda6SSzymon Janc 
33332763eda6SSzymon Janc 	hci_dev_lock(hdev);
33342763eda6SSzymon Janc 
3335a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
3336e1ba1f15SSzymon Janc 		goto unlock;
3337e1ba1f15SSzymon Janc 
33382763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
33392763eda6SSzymon Janc 	if (data) {
33402763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_reply cp;
33412763eda6SSzymon Janc 
33422763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
33432763eda6SSzymon Janc 		memcpy(cp.hash, data->hash, sizeof(cp.hash));
33442763eda6SSzymon Janc 		memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
33452763eda6SSzymon Janc 
33462763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
33472763eda6SSzymon Janc 			     &cp);
33482763eda6SSzymon Janc 	} else {
33492763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
33502763eda6SSzymon Janc 
33512763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
33522763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
33532763eda6SSzymon Janc 			     &cp);
33542763eda6SSzymon Janc 	}
33552763eda6SSzymon Janc 
3356e1ba1f15SSzymon Janc unlock:
33572763eda6SSzymon Janc 	hci_dev_unlock(hdev);
33582763eda6SSzymon Janc }
33592763eda6SSzymon Janc 
33606039aa73SGustavo Padovan static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3361fcd89c09SVille Tervo {
3362fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3363fcd89c09SVille Tervo 	struct hci_conn *conn;
3364fcd89c09SVille Tervo 
33659f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3366fcd89c09SVille Tervo 
3367fcd89c09SVille Tervo 	hci_dev_lock(hdev);
3368fcd89c09SVille Tervo 
33694f72b329SAndrzej Kaczmarek 	if (ev->status) {
33704f72b329SAndrzej Kaczmarek 		conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
33714f72b329SAndrzej Kaczmarek 		if (!conn)
33724f72b329SAndrzej Kaczmarek 			goto unlock;
33734f72b329SAndrzej Kaczmarek 
33744f72b329SAndrzej Kaczmarek 		mgmt_connect_failed(hdev, &conn->dst, conn->type,
33754f72b329SAndrzej Kaczmarek 				    conn->dst_type, ev->status);
33764f72b329SAndrzej Kaczmarek 		hci_proto_connect_cfm(conn, ev->status);
33774f72b329SAndrzej Kaczmarek 		conn->state = BT_CLOSED;
33784f72b329SAndrzej Kaczmarek 		hci_conn_del(conn);
33794f72b329SAndrzej Kaczmarek 		goto unlock;
33804f72b329SAndrzej Kaczmarek 	}
33814f72b329SAndrzej Kaczmarek 
3382fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
3383b62f328bSVille Tervo 	if (!conn) {
3384b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3385b62f328bSVille Tervo 		if (!conn) {
3386b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
3387b62f328bSVille Tervo 			hci_dev_unlock(hdev);
3388b62f328bSVille Tervo 			return;
3389b62f328bSVille Tervo 		}
339029b7988aSAndre Guedes 
339129b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
3392b62f328bSVille Tervo 	}
3393fcd89c09SVille Tervo 
3394b644ba33SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3395b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
339695b23582SSzymon Janc 				      conn->dst_type, 0, NULL, 0, NULL);
339783bc71b4SVinicius Costa Gomes 
33987b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
3399fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
3400fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
3401fcd89c09SVille Tervo 
3402fcd89c09SVille Tervo 	hci_conn_hold_device(conn);
3403fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
3404fcd89c09SVille Tervo 
3405fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
3406fcd89c09SVille Tervo 
3407fcd89c09SVille Tervo unlock:
3408fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
3409fcd89c09SVille Tervo }
3410fcd89c09SVille Tervo 
34116039aa73SGustavo Padovan static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
34129aa04c91SAndre Guedes {
3413e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
3414e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
34153c9e9195SAndre Guedes 	s8 rssi;
34169aa04c91SAndre Guedes 
34179aa04c91SAndre Guedes 	hci_dev_lock(hdev);
34189aa04c91SAndre Guedes 
3419e95beb41SAndre Guedes 	while (num_reports--) {
3420e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
3421e95beb41SAndre Guedes 
34223c9e9195SAndre Guedes 		rssi = ev->data[ev->length];
34233c9e9195SAndre Guedes 		mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
342404124681SGustavo F. Padovan 				  NULL, rssi, 0, 1, ev->data, ev->length);
34253c9e9195SAndre Guedes 
3426e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
34279aa04c91SAndre Guedes 	}
34289aa04c91SAndre Guedes 
34299aa04c91SAndre Guedes 	hci_dev_unlock(hdev);
34309aa04c91SAndre Guedes }
34319aa04c91SAndre Guedes 
34326039aa73SGustavo Padovan static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
3433a7a595f6SVinicius Costa Gomes {
3434a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3435a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
3436bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
3437a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
3438c9839a11SVinicius Costa Gomes 	struct smp_ltk *ltk;
3439a7a595f6SVinicius Costa Gomes 
34409f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
3441a7a595f6SVinicius Costa Gomes 
3442a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
3443a7a595f6SVinicius Costa Gomes 
3444a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3445bea710feSVinicius Costa Gomes 	if (conn == NULL)
3446bea710feSVinicius Costa Gomes 		goto not_found;
3447a7a595f6SVinicius Costa Gomes 
3448bea710feSVinicius Costa Gomes 	ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3449bea710feSVinicius Costa Gomes 	if (ltk == NULL)
3450bea710feSVinicius Costa Gomes 		goto not_found;
3451bea710feSVinicius Costa Gomes 
3452bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
3453a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
3454c9839a11SVinicius Costa Gomes 
3455c9839a11SVinicius Costa Gomes 	if (ltk->authenticated)
3456c9839a11SVinicius Costa Gomes 		conn->sec_level = BT_SECURITY_HIGH;
3457a7a595f6SVinicius Costa Gomes 
3458a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3459a7a595f6SVinicius Costa Gomes 
3460c9839a11SVinicius Costa Gomes 	if (ltk->type & HCI_SMP_STK) {
3461c9839a11SVinicius Costa Gomes 		list_del(&ltk->list);
3462c9839a11SVinicius Costa Gomes 		kfree(ltk);
3463c9839a11SVinicius Costa Gomes 	}
3464c9839a11SVinicius Costa Gomes 
3465a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
3466bea710feSVinicius Costa Gomes 
3467bea710feSVinicius Costa Gomes 	return;
3468bea710feSVinicius Costa Gomes 
3469bea710feSVinicius Costa Gomes not_found:
3470bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
3471bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3472bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
3473a7a595f6SVinicius Costa Gomes }
3474a7a595f6SVinicius Costa Gomes 
34756039aa73SGustavo Padovan static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3476fcd89c09SVille Tervo {
3477fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
3478fcd89c09SVille Tervo 
3479fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
3480fcd89c09SVille Tervo 
3481fcd89c09SVille Tervo 	switch (le_ev->subevent) {
3482fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
3483fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
3484fcd89c09SVille Tervo 		break;
3485fcd89c09SVille Tervo 
34869aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
34879aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
34889aa04c91SAndre Guedes 		break;
34899aa04c91SAndre Guedes 
3490a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
3491a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
3492a7a595f6SVinicius Costa Gomes 		break;
3493a7a595f6SVinicius Costa Gomes 
3494fcd89c09SVille Tervo 	default:
3495fcd89c09SVille Tervo 		break;
3496fcd89c09SVille Tervo 	}
3497fcd89c09SVille Tervo }
3498fcd89c09SVille Tervo 
34991da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
35001da177e4SLinus Torvalds {
3501a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
3502a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
35031da177e4SLinus Torvalds 
35041da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
35051da177e4SLinus Torvalds 
3506a9de9248SMarcel Holtmann 	switch (event) {
35071da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
35081da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
35091da177e4SLinus Torvalds 		break;
35101da177e4SLinus Torvalds 
35111da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
35121da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
35131da177e4SLinus Torvalds 		break;
35141da177e4SLinus Torvalds 
3515a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
3516a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
351721d9e30eSMarcel Holtmann 		break;
351821d9e30eSMarcel Holtmann 
35191da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
35201da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
35211da177e4SLinus Torvalds 		break;
35221da177e4SLinus Torvalds 
35231da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
35241da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
35251da177e4SLinus Torvalds 		break;
35261da177e4SLinus Torvalds 
35271da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
35281da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
35291da177e4SLinus Torvalds 		break;
35301da177e4SLinus Torvalds 
3531a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
3532a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
3533a9de9248SMarcel Holtmann 		break;
3534a9de9248SMarcel Holtmann 
35351da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
35361da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
35371da177e4SLinus Torvalds 		break;
35381da177e4SLinus Torvalds 
3539a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3540a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
3541a9de9248SMarcel Holtmann 		break;
3542a9de9248SMarcel Holtmann 
3543a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
3544a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
3545a9de9248SMarcel Holtmann 		break;
3546a9de9248SMarcel Holtmann 
3547a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_VERSION:
3548a9de9248SMarcel Holtmann 		hci_remote_version_evt(hdev, skb);
3549a9de9248SMarcel Holtmann 		break;
3550a9de9248SMarcel Holtmann 
3551a9de9248SMarcel Holtmann 	case HCI_EV_QOS_SETUP_COMPLETE:
3552a9de9248SMarcel Holtmann 		hci_qos_setup_complete_evt(hdev, skb);
3553a9de9248SMarcel Holtmann 		break;
3554a9de9248SMarcel Holtmann 
3555a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
3556a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
3557a9de9248SMarcel Holtmann 		break;
3558a9de9248SMarcel Holtmann 
3559a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
3560a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
3561a9de9248SMarcel Holtmann 		break;
3562a9de9248SMarcel Holtmann 
3563a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
3564a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
3565a9de9248SMarcel Holtmann 		break;
3566a9de9248SMarcel Holtmann 
3567a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
3568a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
3569a9de9248SMarcel Holtmann 		break;
3570a9de9248SMarcel Holtmann 
3571a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
3572a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
35731da177e4SLinus Torvalds 		break;
35741da177e4SLinus Torvalds 
35751da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
35761da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
35771da177e4SLinus Torvalds 		break;
35781da177e4SLinus Torvalds 
35791da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
35801da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
35811da177e4SLinus Torvalds 		break;
35821da177e4SLinus Torvalds 
35831da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
35841da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
35851da177e4SLinus Torvalds 		break;
35861da177e4SLinus Torvalds 
35871da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
35881da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
35891da177e4SLinus Torvalds 		break;
35901da177e4SLinus Torvalds 
3591a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
3592a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
3593a8746417SMarcel Holtmann 		break;
3594a8746417SMarcel Holtmann 
359585a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
359685a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
359785a1e930SMarcel Holtmann 		break;
359885a1e930SMarcel Holtmann 
3599a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3600a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
3601a9de9248SMarcel Holtmann 		break;
3602a9de9248SMarcel Holtmann 
3603a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
3604a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
3605a9de9248SMarcel Holtmann 		break;
3606a9de9248SMarcel Holtmann 
3607a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
3608a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
3609a9de9248SMarcel Holtmann 		break;
3610a9de9248SMarcel Holtmann 
3611a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_CHANGED:
3612a9de9248SMarcel Holtmann 		hci_sync_conn_changed_evt(hdev, skb);
3613a9de9248SMarcel Holtmann 		break;
3614a9de9248SMarcel Holtmann 
361504837f64SMarcel Holtmann 	case HCI_EV_SNIFF_SUBRATE:
361604837f64SMarcel Holtmann 		hci_sniff_subrate_evt(hdev, skb);
361704837f64SMarcel Holtmann 		break;
361804837f64SMarcel Holtmann 
3619a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
3620a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
36211da177e4SLinus Torvalds 		break;
36221da177e4SLinus Torvalds 
36231c2e0041SJohan Hedberg 	case HCI_EV_KEY_REFRESH_COMPLETE:
36241c2e0041SJohan Hedberg 		hci_key_refresh_complete_evt(hdev, skb);
36251c2e0041SJohan Hedberg 		break;
36261c2e0041SJohan Hedberg 
36270493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
36280493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
36290493684eSMarcel Holtmann 		break;
36300493684eSMarcel Holtmann 
363103b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
363203b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
363303b555e1SJohan Hedberg 		break;
363403b555e1SJohan Hedberg 
3635a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
3636a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
3637a5c29683SJohan Hedberg 		break;
3638a5c29683SJohan Hedberg 
36391143d458SBrian Gix 	case HCI_EV_USER_PASSKEY_REQUEST:
36401143d458SBrian Gix 		hci_user_passkey_request_evt(hdev, skb);
36411143d458SBrian Gix 		break;
36421143d458SBrian Gix 
36430493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
36440493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
36450493684eSMarcel Holtmann 		break;
36460493684eSMarcel Holtmann 
364741a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
364841a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
364941a96212SMarcel Holtmann 		break;
365041a96212SMarcel Holtmann 
3651fcd89c09SVille Tervo 	case HCI_EV_LE_META:
3652fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
3653fcd89c09SVille Tervo 		break;
3654fcd89c09SVille Tervo 
36552763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
36562763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
36572763eda6SSzymon Janc 		break;
36582763eda6SSzymon Janc 
365925e89e99SAndrei Emeltchenko 	case HCI_EV_NUM_COMP_BLOCKS:
366025e89e99SAndrei Emeltchenko 		hci_num_comp_blocks_evt(hdev, skb);
366125e89e99SAndrei Emeltchenko 		break;
366225e89e99SAndrei Emeltchenko 
36631da177e4SLinus Torvalds 	default:
36649f1db00cSAndrei Emeltchenko 		BT_DBG("%s event 0x%2.2x", hdev->name, event);
36651da177e4SLinus Torvalds 		break;
36661da177e4SLinus Torvalds 	}
36671da177e4SLinus Torvalds 
36681da177e4SLinus Torvalds 	kfree_skb(skb);
36691da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
36701da177e4SLinus Torvalds }
3671