xref: /openbmc/linux/net/bluetooth/hci_event.c (revision 0c95ab78)
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 
516999dcd10SAndre Guedes 	if (lmp_sniffsubr_capable(hdev))
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 
525c58e810eSAndre Guedes 	if (lmp_no_flush_capable(hdev))
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 
5319a1a1996SAndre Guedes 	if (lmp_ssp_capable(hdev)) {
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 
544c383ddc4SAndre Guedes 	if (lmp_le_capable(hdev))
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 
6269f92ebf6SAndre Guedes 	if (lmp_rswitch_capable(hdev))
627d5859e22SJohan Hedberg 		link_policy |= HCI_LP_RSWITCH;
628d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_HOLD)
629d5859e22SJohan Hedberg 		link_policy |= HCI_LP_HOLD;
6306eded100SAndre Guedes 	if (lmp_sniff_capable(hdev))
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 
68945db810fSAndre Guedes 	if (lmp_esco_capable(hdev))
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 
749c383ddc4SAndre Guedes 	if (test_bit(HCI_INIT, &hdev->flags) && lmp_le_capable(hdev))
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);
1368b644ba33SJohan Hedberg 	if (hci_resolve_name(hdev, e) == 0) {
1369b644ba33SJohan Hedberg 		e->name_state = NAME_PENDING;
1370b644ba33SJohan Hedberg 		return true;
1371b644ba33SJohan Hedberg 	}
1372b644ba33SJohan Hedberg 
1373b644ba33SJohan Hedberg 	return false;
1374b644ba33SJohan Hedberg }
1375b644ba33SJohan Hedberg 
1376b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
1377b644ba33SJohan Hedberg 				   bdaddr_t *bdaddr, u8 *name, u8 name_len)
1378b644ba33SJohan Hedberg {
1379b644ba33SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
1380b644ba33SJohan Hedberg 	struct inquiry_entry *e;
1381b644ba33SJohan Hedberg 
1382b644ba33SJohan Hedberg 	if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
138304124681SGustavo F. Padovan 		mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
138404124681SGustavo F. Padovan 				      name_len, conn->dev_class);
1385b644ba33SJohan Hedberg 
1386b644ba33SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPED)
1387b644ba33SJohan Hedberg 		return;
1388b644ba33SJohan Hedberg 
138930dc78e1SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPING)
139030dc78e1SJohan Hedberg 		goto discov_complete;
139130dc78e1SJohan Hedberg 
139230dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_RESOLVING)
139330dc78e1SJohan Hedberg 		return;
139430dc78e1SJohan Hedberg 
139530dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
139630dc78e1SJohan Hedberg 	if (e) {
139730dc78e1SJohan Hedberg 		e->name_state = NAME_KNOWN;
139830dc78e1SJohan Hedberg 		list_del(&e->list);
1399b644ba33SJohan Hedberg 		if (name)
1400b644ba33SJohan Hedberg 			mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1401b644ba33SJohan Hedberg 					 e->data.rssi, name, name_len);
140230dc78e1SJohan Hedberg 	}
140330dc78e1SJohan Hedberg 
1404b644ba33SJohan Hedberg 	if (hci_resolve_next_name(hdev))
140530dc78e1SJohan Hedberg 		return;
140630dc78e1SJohan Hedberg 
140730dc78e1SJohan Hedberg discov_complete:
140830dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
140930dc78e1SJohan Hedberg }
141030dc78e1SJohan Hedberg 
1411a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
14121da177e4SLinus Torvalds {
1413127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1414127178d2SJohan Hedberg 	struct hci_conn *conn;
1415127178d2SJohan Hedberg 
14169f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1417127178d2SJohan Hedberg 
1418127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1419127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1420127178d2SJohan Hedberg 	if (!status)
1421127178d2SJohan Hedberg 		return;
1422127178d2SJohan Hedberg 
1423127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1424127178d2SJohan Hedberg 	if (!cp)
1425127178d2SJohan Hedberg 		return;
1426127178d2SJohan Hedberg 
1427127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1428127178d2SJohan Hedberg 
1429127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1430b644ba33SJohan Hedberg 
1431b644ba33SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1432b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1433b644ba33SJohan Hedberg 
143479c6c70cSJohan Hedberg 	if (!conn)
143579c6c70cSJohan Hedberg 		goto unlock;
143679c6c70cSJohan Hedberg 
143779c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
143879c6c70cSJohan Hedberg 		goto unlock;
143979c6c70cSJohan Hedberg 
144051a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1441127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1442127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1443127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1444127178d2SJohan Hedberg 	}
1445127178d2SJohan Hedberg 
144679c6c70cSJohan Hedberg unlock:
1447127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1448a9de9248SMarcel Holtmann }
14491da177e4SLinus Torvalds 
1450769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1451769be974SMarcel Holtmann {
1452769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1453769be974SMarcel Holtmann 	struct hci_conn *conn;
1454769be974SMarcel Holtmann 
14559f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1456769be974SMarcel Holtmann 
1457769be974SMarcel Holtmann 	if (!status)
1458769be974SMarcel Holtmann 		return;
1459769be974SMarcel Holtmann 
1460769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1461769be974SMarcel Holtmann 	if (!cp)
1462769be974SMarcel Holtmann 		return;
1463769be974SMarcel Holtmann 
1464769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1465769be974SMarcel Holtmann 
1466769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1467769be974SMarcel Holtmann 	if (conn) {
1468769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1469769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1470769be974SMarcel Holtmann 			hci_conn_put(conn);
1471769be974SMarcel Holtmann 		}
1472769be974SMarcel Holtmann 	}
1473769be974SMarcel Holtmann 
1474769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1475769be974SMarcel Holtmann }
1476769be974SMarcel Holtmann 
1477769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1478769be974SMarcel Holtmann {
1479769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1480769be974SMarcel Holtmann 	struct hci_conn *conn;
1481769be974SMarcel Holtmann 
14829f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1483769be974SMarcel Holtmann 
1484769be974SMarcel Holtmann 	if (!status)
1485769be974SMarcel Holtmann 		return;
1486769be974SMarcel Holtmann 
1487769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1488769be974SMarcel Holtmann 	if (!cp)
1489769be974SMarcel Holtmann 		return;
1490769be974SMarcel Holtmann 
1491769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1492769be974SMarcel Holtmann 
1493769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1494769be974SMarcel Holtmann 	if (conn) {
1495769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1496769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1497769be974SMarcel Holtmann 			hci_conn_put(conn);
1498769be974SMarcel Holtmann 		}
1499769be974SMarcel Holtmann 	}
1500769be974SMarcel Holtmann 
1501769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1502769be974SMarcel Holtmann }
1503769be974SMarcel Holtmann 
1504a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1505a9de9248SMarcel Holtmann {
1506b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1507b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1508b6a0dc82SMarcel Holtmann 	__u16 handle;
1509b6a0dc82SMarcel Holtmann 
15109f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1511b6a0dc82SMarcel Holtmann 
1512b6a0dc82SMarcel Holtmann 	if (!status)
1513b6a0dc82SMarcel Holtmann 		return;
1514b6a0dc82SMarcel Holtmann 
1515b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1516b6a0dc82SMarcel Holtmann 	if (!cp)
1517b6a0dc82SMarcel Holtmann 		return;
1518b6a0dc82SMarcel Holtmann 
1519b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1520b6a0dc82SMarcel Holtmann 
15219f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
1522b6a0dc82SMarcel Holtmann 
1523b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1524b6a0dc82SMarcel Holtmann 
1525b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
15265a08ecceSAndrei Emeltchenko 	if (acl) {
15275a08ecceSAndrei Emeltchenko 		sco = acl->link;
15285a08ecceSAndrei Emeltchenko 		if (sco) {
1529b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1530b6a0dc82SMarcel Holtmann 
1531b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1532b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1533b6a0dc82SMarcel Holtmann 		}
15345a08ecceSAndrei Emeltchenko 	}
1535b6a0dc82SMarcel Holtmann 
1536b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1537a9de9248SMarcel Holtmann }
1538a9de9248SMarcel Holtmann 
1539a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1540a9de9248SMarcel Holtmann {
1541a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
154204837f64SMarcel Holtmann 	struct hci_conn *conn;
154304837f64SMarcel Holtmann 
15449f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1545a9de9248SMarcel Holtmann 
1546a9de9248SMarcel Holtmann 	if (!status)
1547a9de9248SMarcel Holtmann 		return;
1548a9de9248SMarcel Holtmann 
1549a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
155004837f64SMarcel Holtmann 	if (!cp)
1551a9de9248SMarcel Holtmann 		return;
155204837f64SMarcel Holtmann 
155304837f64SMarcel Holtmann 	hci_dev_lock(hdev);
155404837f64SMarcel Holtmann 
155504837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1556e73439d8SMarcel Holtmann 	if (conn) {
155751a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
155804837f64SMarcel Holtmann 
155951a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1560e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1561e73439d8SMarcel Holtmann 	}
1562e73439d8SMarcel Holtmann 
156304837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
156404837f64SMarcel Holtmann }
156504837f64SMarcel Holtmann 
1566a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1567a9de9248SMarcel Holtmann {
1568a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
156904837f64SMarcel Holtmann 	struct hci_conn *conn;
157004837f64SMarcel Holtmann 
15719f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1572a9de9248SMarcel Holtmann 
1573a9de9248SMarcel Holtmann 	if (!status)
1574a9de9248SMarcel Holtmann 		return;
1575a9de9248SMarcel Holtmann 
1576a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
157704837f64SMarcel Holtmann 	if (!cp)
1578a9de9248SMarcel Holtmann 		return;
157904837f64SMarcel Holtmann 
158004837f64SMarcel Holtmann 	hci_dev_lock(hdev);
158104837f64SMarcel Holtmann 
158204837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1583e73439d8SMarcel Holtmann 	if (conn) {
158451a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
158504837f64SMarcel Holtmann 
158651a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1587e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1588e73439d8SMarcel Holtmann 	}
1589e73439d8SMarcel Holtmann 
159004837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
159104837f64SMarcel Holtmann }
159204837f64SMarcel Holtmann 
159388c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
159488c3df13SJohan Hedberg {
159588c3df13SJohan Hedberg 	struct hci_cp_disconnect *cp;
159688c3df13SJohan Hedberg 	struct hci_conn *conn;
159788c3df13SJohan Hedberg 
159888c3df13SJohan Hedberg 	if (!status)
159988c3df13SJohan Hedberg 		return;
160088c3df13SJohan Hedberg 
160188c3df13SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
160288c3df13SJohan Hedberg 	if (!cp)
160388c3df13SJohan Hedberg 		return;
160488c3df13SJohan Hedberg 
160588c3df13SJohan Hedberg 	hci_dev_lock(hdev);
160688c3df13SJohan Hedberg 
160788c3df13SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
160888c3df13SJohan Hedberg 	if (conn)
160988c3df13SJohan Hedberg 		mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
161088c3df13SJohan Hedberg 				       conn->dst_type, status);
161188c3df13SJohan Hedberg 
161288c3df13SJohan Hedberg 	hci_dev_unlock(hdev);
161388c3df13SJohan Hedberg }
161488c3df13SJohan Hedberg 
1615fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1616fcd89c09SVille Tervo {
1617fcd89c09SVille Tervo 	struct hci_conn *conn;
1618fcd89c09SVille Tervo 
16199f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1620fcd89c09SVille Tervo 
1621f00a06acSAndre Guedes 	if (status) {
1622fcd89c09SVille Tervo 		hci_dev_lock(hdev);
1623fcd89c09SVille Tervo 
16240c95ab78SAndre Guedes 		conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
1625f00a06acSAndre Guedes 		if (!conn) {
1626f00a06acSAndre Guedes 			hci_dev_unlock(hdev);
1627f00a06acSAndre Guedes 			return;
1628f00a06acSAndre Guedes 		}
1629fcd89c09SVille Tervo 
16300c95ab78SAndre Guedes 		BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&conn->dst),
1631fcd89c09SVille Tervo 		       conn);
1632fcd89c09SVille Tervo 
1633fcd89c09SVille Tervo 		conn->state = BT_CLOSED;
16340c95ab78SAndre Guedes 		mgmt_connect_failed(hdev, &conn->dst, conn->type,
1635328c9248SHemant Gupta 				    conn->dst_type, status);
1636fcd89c09SVille Tervo 		hci_proto_connect_cfm(conn, status);
1637fcd89c09SVille Tervo 		hci_conn_del(conn);
1638fcd89c09SVille Tervo 
1639fcd89c09SVille Tervo 		hci_dev_unlock(hdev);
1640fcd89c09SVille Tervo 	}
1641f00a06acSAndre Guedes }
1642fcd89c09SVille Tervo 
1643a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1644a7a595f6SVinicius Costa Gomes {
16459f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1646a7a595f6SVinicius Costa Gomes }
1647a7a595f6SVinicius Costa Gomes 
16486039aa73SGustavo Padovan static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
16491da177e4SLinus Torvalds {
16501da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
165130dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
165230dc78e1SJohan Hedberg 	struct inquiry_entry *e;
16531da177e4SLinus Torvalds 
16549f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
16551da177e4SLinus Torvalds 
165623bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY, status);
16576bd57416SMarcel Holtmann 
1658a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
165989352e7dSAndre Guedes 
166089352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
166189352e7dSAndre Guedes 		return;
166289352e7dSAndre Guedes 
1663a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
166430dc78e1SJohan Hedberg 		return;
166530dc78e1SJohan Hedberg 
166656e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
166730dc78e1SJohan Hedberg 
1668343f935bSAndre Guedes 	if (discov->state != DISCOVERY_FINDING)
166930dc78e1SJohan Hedberg 		goto unlock;
167030dc78e1SJohan Hedberg 
167130dc78e1SJohan Hedberg 	if (list_empty(&discov->resolve)) {
1672ff9ef578SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
167330dc78e1SJohan Hedberg 		goto unlock;
167430dc78e1SJohan Hedberg 	}
167530dc78e1SJohan Hedberg 
167630dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
167730dc78e1SJohan Hedberg 	if (e && hci_resolve_name(hdev, e) == 0) {
167830dc78e1SJohan Hedberg 		e->name_state = NAME_PENDING;
167930dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
168030dc78e1SJohan Hedberg 	} else {
168130dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
168230dc78e1SJohan Hedberg 	}
168330dc78e1SJohan Hedberg 
168430dc78e1SJohan Hedberg unlock:
168556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
16861da177e4SLinus Torvalds }
16871da177e4SLinus Torvalds 
16886039aa73SGustavo Padovan static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
16891da177e4SLinus Torvalds {
169045bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1691a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
16921da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
16931da177e4SLinus Torvalds 
16941da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
16951da177e4SLinus Torvalds 
169645bb4bf0SMarcel Holtmann 	if (!num_rsp)
169745bb4bf0SMarcel Holtmann 		return;
169845bb4bf0SMarcel Holtmann 
16991519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
17001519cc17SAndre Guedes 		return;
17011519cc17SAndre Guedes 
17021da177e4SLinus Torvalds 	hci_dev_lock(hdev);
170345bb4bf0SMarcel Holtmann 
1704e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
1705388fc8faSJohan Hedberg 		bool name_known, ssp;
17063175405bSJohan Hedberg 
17071da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
17081da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
17091da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
17101da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
17111da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
17121da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
17131da177e4SLinus Torvalds 		data.rssi		= 0x00;
171441a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
17153175405bSJohan Hedberg 
1716388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
171748264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
171804124681SGustavo F. Padovan 				  info->dev_class, 0, !name_known, ssp, NULL,
171904124681SGustavo F. Padovan 				  0);
17201da177e4SLinus Torvalds 	}
172145bb4bf0SMarcel Holtmann 
17221da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
17231da177e4SLinus Torvalds }
17241da177e4SLinus Torvalds 
17256039aa73SGustavo Padovan static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
17261da177e4SLinus Torvalds {
1727a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
1728a9de9248SMarcel Holtmann 	struct hci_conn *conn;
17291da177e4SLinus Torvalds 
1730a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
173145bb4bf0SMarcel Holtmann 
17321da177e4SLinus Torvalds 	hci_dev_lock(hdev);
173345bb4bf0SMarcel Holtmann 
1734a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
17359499237aSMarcel Holtmann 	if (!conn) {
17369499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
17379499237aSMarcel Holtmann 			goto unlock;
17389499237aSMarcel Holtmann 
17399499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1740a9de9248SMarcel Holtmann 		if (!conn)
1741a9de9248SMarcel Holtmann 			goto unlock;
174245bb4bf0SMarcel Holtmann 
17439499237aSMarcel Holtmann 		conn->type = SCO_LINK;
17449499237aSMarcel Holtmann 	}
17459499237aSMarcel Holtmann 
1746a9de9248SMarcel Holtmann 	if (!ev->status) {
1747a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1748769be974SMarcel Holtmann 
1749769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1750769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
1751769be974SMarcel Holtmann 			hci_conn_hold(conn);
1752052b30b0SMarcel Holtmann 			conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1753769be974SMarcel Holtmann 		} else
1754a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
1755a9de9248SMarcel Holtmann 
17569eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
17577d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
17587d0db0a3SMarcel Holtmann 
1759a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1760a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1761a9de9248SMarcel Holtmann 
1762a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1763a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1764a9de9248SMarcel Holtmann 
1765a9de9248SMarcel Holtmann 		/* Get remote features */
1766a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1767a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1768a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1769769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1770769be974SMarcel Holtmann 				     sizeof(cp), &cp);
177145bb4bf0SMarcel Holtmann 		}
1772a9de9248SMarcel Holtmann 
1773a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1774d095c1ebSAndrei Emeltchenko 		if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
1775a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1776a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1777a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
177804124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
177904124681SGustavo F. Padovan 				     &cp);
1780a9de9248SMarcel Holtmann 		}
178117d5c04cSJohan Hedberg 	} else {
1782a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
178317d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
1784744cf19eSJohan Hedberg 			mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
178548264f06SJohan Hedberg 					    conn->dst_type, ev->status);
178617d5c04cSJohan Hedberg 	}
178745bb4bf0SMarcel Holtmann 
1788e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
1789e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
179045bb4bf0SMarcel Holtmann 
1791769be974SMarcel Holtmann 	if (ev->status) {
1792a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1793a9de9248SMarcel Holtmann 		hci_conn_del(conn);
1794c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
1795c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1796a9de9248SMarcel Holtmann 
1797a9de9248SMarcel Holtmann unlock:
17981da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
1799a9de9248SMarcel Holtmann 
1800a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
18011da177e4SLinus Torvalds }
18021da177e4SLinus Torvalds 
18036039aa73SGustavo Padovan static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
18041da177e4SLinus Torvalds {
1805a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
18061da177e4SLinus Torvalds 	int mask = hdev->link_mode;
18071da177e4SLinus Torvalds 
1808807deac2SGustavo Padovan 	BT_DBG("%s bdaddr %s type 0x%x", hdev->name, batostr(&ev->bdaddr),
1809807deac2SGustavo Padovan 	       ev->link_type);
18101da177e4SLinus Torvalds 
18111da177e4SLinus Torvalds 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
18121da177e4SLinus Torvalds 
1813138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
1814138d22efSSzymon Janc 	    !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
18151da177e4SLinus Torvalds 		/* Connection accepted */
1816c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
18171da177e4SLinus Torvalds 		struct hci_conn *conn;
18181da177e4SLinus Torvalds 
18191da177e4SLinus Torvalds 		hci_dev_lock(hdev);
1820b6a0dc82SMarcel Holtmann 
1821cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1822cc11b9c1SAndrei Emeltchenko 		if (ie)
1823c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
1824c7bdd502SMarcel Holtmann 
18258fc9ced3SGustavo Padovan 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
18268fc9ced3SGustavo Padovan 					       &ev->bdaddr);
18271da177e4SLinus Torvalds 		if (!conn) {
1828cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1829cc11b9c1SAndrei Emeltchenko 			if (!conn) {
1830893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
18311da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
18321da177e4SLinus Torvalds 				return;
18331da177e4SLinus Torvalds 			}
18341da177e4SLinus Torvalds 		}
1835b6a0dc82SMarcel Holtmann 
18361da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
18371da177e4SLinus Torvalds 		conn->state = BT_CONNECT;
1838b6a0dc82SMarcel Holtmann 
18391da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
18401da177e4SLinus Torvalds 
1841b6a0dc82SMarcel Holtmann 		if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1842b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
1843b6a0dc82SMarcel Holtmann 
18441da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
18451da177e4SLinus Torvalds 
18461da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
18471da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
18481da177e4SLinus Torvalds 			else
18491da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
18501da177e4SLinus Torvalds 
185104124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
185204124681SGustavo F. Padovan 				     &cp);
1853b6a0dc82SMarcel Holtmann 		} else {
1854b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
1855b6a0dc82SMarcel Holtmann 
1856b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
1857a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1858b6a0dc82SMarcel Holtmann 
185982781e63SAndrei Emeltchenko 			cp.tx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
186082781e63SAndrei Emeltchenko 			cp.rx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
186182781e63SAndrei Emeltchenko 			cp.max_latency    = __constant_cpu_to_le16(0xffff);
1862b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
1863b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
1864b6a0dc82SMarcel Holtmann 
1865b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1866b6a0dc82SMarcel Holtmann 				     sizeof(cp), &cp);
1867b6a0dc82SMarcel Holtmann 		}
18681da177e4SLinus Torvalds 	} else {
18691da177e4SLinus Torvalds 		/* Connection rejected */
18701da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
18711da177e4SLinus Torvalds 
18721da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
18739f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_REJ_BAD_ADDR;
1874a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
18751da177e4SLinus Torvalds 	}
18761da177e4SLinus Torvalds }
18771da177e4SLinus Torvalds 
18786039aa73SGustavo Padovan static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
18791da177e4SLinus Torvalds {
1880a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
188104837f64SMarcel Holtmann 	struct hci_conn *conn;
18821da177e4SLinus Torvalds 
18839f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
18841da177e4SLinus Torvalds 
18851da177e4SLinus Torvalds 	hci_dev_lock(hdev);
18861da177e4SLinus Torvalds 
188704837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1888f7520543SJohan Hedberg 	if (!conn)
1889f7520543SJohan Hedberg 		goto unlock;
1890f7520543SJohan Hedberg 
189137d9ef76SJohan Hedberg 	if (ev->status == 0)
18921da177e4SLinus Torvalds 		conn->state = BT_CLOSED;
18937d0db0a3SMarcel Holtmann 
1894b644ba33SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
1895b644ba33SJohan Hedberg 	    (conn->type == ACL_LINK || conn->type == LE_LINK)) {
189637d9ef76SJohan Hedberg 		if (ev->status != 0)
189788c3df13SJohan Hedberg 			mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
189888c3df13SJohan Hedberg 					       conn->dst_type, ev->status);
189937d9ef76SJohan Hedberg 		else
1900afc747a6SJohan Hedberg 			mgmt_device_disconnected(hdev, &conn->dst, conn->type,
190148264f06SJohan Hedberg 						 conn->dst_type);
190237d9ef76SJohan Hedberg 	}
1903f7520543SJohan Hedberg 
190437d9ef76SJohan Hedberg 	if (ev->status == 0) {
19056ec5bcadSVishal Agarwal 		if (conn->type == ACL_LINK && conn->flush_key)
19066ec5bcadSVishal Agarwal 			hci_remove_link_key(hdev, &conn->dst);
19072950f21aSMarcel Holtmann 		hci_proto_disconn_cfm(conn, ev->reason);
19081da177e4SLinus Torvalds 		hci_conn_del(conn);
190937d9ef76SJohan Hedberg 	}
19101da177e4SLinus Torvalds 
1911f7520543SJohan Hedberg unlock:
19121da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
19131da177e4SLinus Torvalds }
19141da177e4SLinus Torvalds 
19156039aa73SGustavo Padovan static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1916a9de9248SMarcel Holtmann {
1917a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
1918a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1919a9de9248SMarcel Holtmann 
19209f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
1921a9de9248SMarcel Holtmann 
1922a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1923a9de9248SMarcel Holtmann 
1924a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1925d7556e20SWaldemar Rymarkiewicz 	if (!conn)
1926d7556e20SWaldemar Rymarkiewicz 		goto unlock;
1927d7556e20SWaldemar Rymarkiewicz 
1928765c2a96SJohan Hedberg 	if (!ev->status) {
1929aa64a8b5SJohan Hedberg 		if (!hci_conn_ssp_enabled(conn) &&
193051a8efd7SJohan Hedberg 		    test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
1931d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
193219f8def0SWaldemar Rymarkiewicz 		} else {
1933a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1934765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
193519f8def0SWaldemar Rymarkiewicz 		}
19362a611692SJohan Hedberg 	} else {
1937bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
1938bab73cb6SJohan Hedberg 				 ev->status);
19392a611692SJohan Hedberg 	}
1940a9de9248SMarcel Holtmann 
194151a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
194251a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
1943a9de9248SMarcel Holtmann 
1944f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
1945aa64a8b5SJohan Hedberg 		if (!ev->status && hci_conn_ssp_enabled(conn)) {
1946f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1947f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1948f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1949d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1950d7556e20SWaldemar Rymarkiewicz 				     &cp);
1951f8558555SMarcel Holtmann 		} else {
1952f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
1953f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1954f8558555SMarcel Holtmann 			hci_conn_put(conn);
1955f8558555SMarcel Holtmann 		}
1956052b30b0SMarcel Holtmann 	} else {
1957a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
1958a9de9248SMarcel Holtmann 
1959052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
1960052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1961052b30b0SMarcel Holtmann 		hci_conn_put(conn);
1962052b30b0SMarcel Holtmann 	}
1963052b30b0SMarcel Holtmann 
196451a8efd7SJohan Hedberg 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
1965a9de9248SMarcel Holtmann 		if (!ev->status) {
1966a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1967f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1968f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1969d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1970d7556e20SWaldemar Rymarkiewicz 				     &cp);
1971a9de9248SMarcel Holtmann 		} else {
197251a8efd7SJohan Hedberg 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
1973a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
1974a9de9248SMarcel Holtmann 		}
1975a9de9248SMarcel Holtmann 	}
1976a9de9248SMarcel Holtmann 
1977d7556e20SWaldemar Rymarkiewicz unlock:
1978a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1979a9de9248SMarcel Holtmann }
1980a9de9248SMarcel Holtmann 
19816039aa73SGustavo Padovan static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1982a9de9248SMarcel Holtmann {
1983127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
1984127178d2SJohan Hedberg 	struct hci_conn *conn;
1985127178d2SJohan Hedberg 
1986a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1987a9de9248SMarcel Holtmann 
1988a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
1989127178d2SJohan Hedberg 
1990127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1991127178d2SJohan Hedberg 
1992127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1993b644ba33SJohan Hedberg 
1994b644ba33SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
1995b644ba33SJohan Hedberg 		goto check_auth;
1996b644ba33SJohan Hedberg 
1997b644ba33SJohan Hedberg 	if (ev->status == 0)
1998b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
1999b644ba33SJohan Hedberg 				       strnlen(ev->name, HCI_MAX_NAME_LENGTH));
2000b644ba33SJohan Hedberg 	else
2001b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
2002b644ba33SJohan Hedberg 
2003b644ba33SJohan Hedberg check_auth:
200479c6c70cSJohan Hedberg 	if (!conn)
200579c6c70cSJohan Hedberg 		goto unlock;
200679c6c70cSJohan Hedberg 
200779c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
200879c6c70cSJohan Hedberg 		goto unlock;
200979c6c70cSJohan Hedberg 
201051a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
2011127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
2012127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
2013127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
2014127178d2SJohan Hedberg 	}
2015127178d2SJohan Hedberg 
201679c6c70cSJohan Hedberg unlock:
2017127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
2018a9de9248SMarcel Holtmann }
2019a9de9248SMarcel Holtmann 
20206039aa73SGustavo Padovan static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2021a9de9248SMarcel Holtmann {
2022a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
2023a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2024a9de9248SMarcel Holtmann 
20259f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2026a9de9248SMarcel Holtmann 
2027a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2028a9de9248SMarcel Holtmann 
2029a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2030a9de9248SMarcel Holtmann 	if (conn) {
2031a9de9248SMarcel Holtmann 		if (!ev->status) {
2032ae293196SMarcel Holtmann 			if (ev->encrypt) {
2033ae293196SMarcel Holtmann 				/* Encryption implies authentication */
2034ae293196SMarcel Holtmann 				conn->link_mode |= HCI_LM_AUTH;
2035a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_ENCRYPT;
2036da85e5e5SVinicius Costa Gomes 				conn->sec_level = conn->pending_sec_level;
2037ae293196SMarcel Holtmann 			} else
2038a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_ENCRYPT;
2039a9de9248SMarcel Holtmann 		}
2040a9de9248SMarcel Holtmann 
204151a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2042a9de9248SMarcel Holtmann 
2043a7d7723aSGustavo Padovan 		if (ev->status && conn->state == BT_CONNECTED) {
2044d839c813SGustavo Padovan 			hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
2045a7d7723aSGustavo Padovan 			hci_conn_put(conn);
2046a7d7723aSGustavo Padovan 			goto unlock;
2047a7d7723aSGustavo Padovan 		}
2048a7d7723aSGustavo Padovan 
2049f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
2050f8558555SMarcel Holtmann 			if (!ev->status)
2051f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
2052f8558555SMarcel Holtmann 
2053f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
2054f8558555SMarcel Holtmann 			hci_conn_put(conn);
2055f8558555SMarcel Holtmann 		} else
2056a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, ev->encrypt);
2057a9de9248SMarcel Holtmann 	}
2058a9de9248SMarcel Holtmann 
2059a7d7723aSGustavo Padovan unlock:
2060a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2061a9de9248SMarcel Holtmann }
2062a9de9248SMarcel Holtmann 
20636039aa73SGustavo Padovan static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
2064807deac2SGustavo Padovan 					     struct sk_buff *skb)
2065a9de9248SMarcel Holtmann {
2066a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2067a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2068a9de9248SMarcel Holtmann 
20699f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2070a9de9248SMarcel Holtmann 
2071a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2072a9de9248SMarcel Holtmann 
2073a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2074a9de9248SMarcel Holtmann 	if (conn) {
2075a9de9248SMarcel Holtmann 		if (!ev->status)
2076a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
2077a9de9248SMarcel Holtmann 
207851a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
2079a9de9248SMarcel Holtmann 
2080a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
2081a9de9248SMarcel Holtmann 	}
2082a9de9248SMarcel Holtmann 
2083a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2084a9de9248SMarcel Holtmann }
2085a9de9248SMarcel Holtmann 
20866039aa73SGustavo Padovan static void hci_remote_features_evt(struct hci_dev *hdev,
2087807deac2SGustavo Padovan 				    struct sk_buff *skb)
2088a9de9248SMarcel Holtmann {
2089a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
2090a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2091a9de9248SMarcel Holtmann 
20929f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2093a9de9248SMarcel Holtmann 
2094a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2095a9de9248SMarcel Holtmann 
2096a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2097ccd556feSJohan Hedberg 	if (!conn)
2098ccd556feSJohan Hedberg 		goto unlock;
2099ccd556feSJohan Hedberg 
2100769be974SMarcel Holtmann 	if (!ev->status)
2101a9de9248SMarcel Holtmann 		memcpy(conn->features, ev->features, 8);
2102a9de9248SMarcel Holtmann 
2103ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2104ccd556feSJohan Hedberg 		goto unlock;
2105ccd556feSJohan Hedberg 
2106ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2107769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
2108769be974SMarcel Holtmann 		cp.handle = ev->handle;
2109769be974SMarcel Holtmann 		cp.page = 0x01;
2110ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
2111769be974SMarcel Holtmann 			     sizeof(cp), &cp);
2112392599b9SJohan Hedberg 		goto unlock;
2113392599b9SJohan Hedberg 	}
2114392599b9SJohan Hedberg 
2115671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
2116127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2117127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2118127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2119127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2120127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2121b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2122b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
212308c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
2124b644ba33SJohan Hedberg 				      conn->dev_class);
2125392599b9SJohan Hedberg 
2126127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2127769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2128769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2129769be974SMarcel Holtmann 		hci_conn_put(conn);
2130769be974SMarcel Holtmann 	}
2131769be974SMarcel Holtmann 
2132ccd556feSJohan Hedberg unlock:
2133a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2134a9de9248SMarcel Holtmann }
2135a9de9248SMarcel Holtmann 
21366039aa73SGustavo Padovan static void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
21376039aa73SGustavo Padovan {
21386039aa73SGustavo Padovan 	BT_DBG("%s", hdev->name);
21396039aa73SGustavo Padovan }
21406039aa73SGustavo Padovan 
21416039aa73SGustavo Padovan static void hci_qos_setup_complete_evt(struct hci_dev *hdev,
2142807deac2SGustavo Padovan 				       struct sk_buff *skb)
2143a9de9248SMarcel Holtmann {
2144a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2145a9de9248SMarcel Holtmann }
2146a9de9248SMarcel Holtmann 
21476039aa73SGustavo Padovan static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2148a9de9248SMarcel Holtmann {
2149a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
2150a9de9248SMarcel Holtmann 	__u16 opcode;
2151a9de9248SMarcel Holtmann 
2152a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2153a9de9248SMarcel Holtmann 
2154a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2155a9de9248SMarcel Holtmann 
2156a9de9248SMarcel Holtmann 	switch (opcode) {
2157a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
2158a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
2159a9de9248SMarcel Holtmann 		break;
2160a9de9248SMarcel Holtmann 
21614d93483bSAndre Guedes 	case HCI_OP_PERIODIC_INQ:
21624d93483bSAndre Guedes 		hci_cc_periodic_inq(hdev, skb);
21634d93483bSAndre Guedes 		break;
21644d93483bSAndre Guedes 
2165a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
2166a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
2167a9de9248SMarcel Holtmann 		break;
2168a9de9248SMarcel Holtmann 
2169a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2170a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
2171a9de9248SMarcel Holtmann 		break;
2172a9de9248SMarcel Holtmann 
2173a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
2174a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
2175a9de9248SMarcel Holtmann 		break;
2176a9de9248SMarcel Holtmann 
2177e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
2178e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
2179e4e8e37cSMarcel Holtmann 		break;
2180e4e8e37cSMarcel Holtmann 
2181a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
2182a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
2183a9de9248SMarcel Holtmann 		break;
2184a9de9248SMarcel Holtmann 
2185e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
2186e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
2187e4e8e37cSMarcel Holtmann 		break;
2188e4e8e37cSMarcel Holtmann 
2189e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
2190e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
2191e4e8e37cSMarcel Holtmann 		break;
2192e4e8e37cSMarcel Holtmann 
2193a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
2194a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
2195a9de9248SMarcel Holtmann 		break;
2196a9de9248SMarcel Holtmann 
2197a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
2198a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
2199a9de9248SMarcel Holtmann 		break;
2200a9de9248SMarcel Holtmann 
2201a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
2202a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
2203a9de9248SMarcel Holtmann 		break;
2204a9de9248SMarcel Holtmann 
2205a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
2206a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
2207a9de9248SMarcel Holtmann 		break;
2208a9de9248SMarcel Holtmann 
2209a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
2210a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
2211a9de9248SMarcel Holtmann 		break;
2212a9de9248SMarcel Holtmann 
2213a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
2214a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
2215a9de9248SMarcel Holtmann 		break;
2216a9de9248SMarcel Holtmann 
2217a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
2218a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
2219a9de9248SMarcel Holtmann 		break;
2220a9de9248SMarcel Holtmann 
2221a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
2222a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
2223a9de9248SMarcel Holtmann 		break;
2224a9de9248SMarcel Holtmann 
2225a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
2226a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
2227a9de9248SMarcel Holtmann 		break;
2228a9de9248SMarcel Holtmann 
2229a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
2230a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
2231a9de9248SMarcel Holtmann 		break;
2232a9de9248SMarcel Holtmann 
2233a9de9248SMarcel Holtmann 	case HCI_OP_HOST_BUFFER_SIZE:
2234a9de9248SMarcel Holtmann 		hci_cc_host_buffer_size(hdev, skb);
2235a9de9248SMarcel Holtmann 		break;
2236a9de9248SMarcel Holtmann 
2237333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
2238333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
2239333140b5SMarcel Holtmann 		break;
2240333140b5SMarcel Holtmann 
2241a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
2242a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
2243a9de9248SMarcel Holtmann 		break;
2244a9de9248SMarcel Holtmann 
2245a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
2246a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
2247a9de9248SMarcel Holtmann 		break;
2248a9de9248SMarcel Holtmann 
2249a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
2250a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
2251a9de9248SMarcel Holtmann 		break;
2252a9de9248SMarcel Holtmann 
2253971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
2254971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
2255971e3a4bSAndre Guedes 		break;
2256971e3a4bSAndre Guedes 
2257a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
2258a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
2259a9de9248SMarcel Holtmann 		break;
2260a9de9248SMarcel Holtmann 
2261a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
2262a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
2263a9de9248SMarcel Holtmann 		break;
2264a9de9248SMarcel Holtmann 
2265350ee4cfSAndrei Emeltchenko 	case HCI_OP_READ_DATA_BLOCK_SIZE:
2266350ee4cfSAndrei Emeltchenko 		hci_cc_read_data_block_size(hdev, skb);
2267350ee4cfSAndrei Emeltchenko 		break;
2268350ee4cfSAndrei Emeltchenko 
226923bb5763SJohan Hedberg 	case HCI_OP_WRITE_CA_TIMEOUT:
227023bb5763SJohan Hedberg 		hci_cc_write_ca_timeout(hdev, skb);
227123bb5763SJohan Hedberg 		break;
227223bb5763SJohan Hedberg 
22731e89cffbSAndrei Emeltchenko 	case HCI_OP_READ_FLOW_CONTROL_MODE:
22741e89cffbSAndrei Emeltchenko 		hci_cc_read_flow_control_mode(hdev, skb);
22751e89cffbSAndrei Emeltchenko 		break;
22761e89cffbSAndrei Emeltchenko 
2277928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
2278928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
2279928abaa7SAndrei Emeltchenko 		break;
2280928abaa7SAndrei Emeltchenko 
2281b0916ea0SJohan Hedberg 	case HCI_OP_DELETE_STORED_LINK_KEY:
2282b0916ea0SJohan Hedberg 		hci_cc_delete_stored_link_key(hdev, skb);
2283b0916ea0SJohan Hedberg 		break;
2284b0916ea0SJohan Hedberg 
2285d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_MASK:
2286d5859e22SJohan Hedberg 		hci_cc_set_event_mask(hdev, skb);
2287d5859e22SJohan Hedberg 		break;
2288d5859e22SJohan Hedberg 
2289d5859e22SJohan Hedberg 	case HCI_OP_WRITE_INQUIRY_MODE:
2290d5859e22SJohan Hedberg 		hci_cc_write_inquiry_mode(hdev, skb);
2291d5859e22SJohan Hedberg 		break;
2292d5859e22SJohan Hedberg 
2293d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
2294d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
2295d5859e22SJohan Hedberg 		break;
2296d5859e22SJohan Hedberg 
2297d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_FLT:
2298d5859e22SJohan Hedberg 		hci_cc_set_event_flt(hdev, skb);
2299d5859e22SJohan Hedberg 		break;
2300d5859e22SJohan Hedberg 
2301980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
2302980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
2303980e1a53SJohan Hedberg 		break;
2304980e1a53SJohan Hedberg 
2305980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
2306980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
2307980e1a53SJohan Hedberg 		break;
2308980e1a53SJohan Hedberg 
2309c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
2310c35938b2SSzymon Janc 		hci_cc_read_local_oob_data_reply(hdev, skb);
2311c35938b2SSzymon Janc 		break;
2312c35938b2SSzymon Janc 
23136ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
23146ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
23156ed58ec5SVille Tervo 		break;
23166ed58ec5SVille Tervo 
2317a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
2318a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
2319a5c29683SJohan Hedberg 		break;
2320a5c29683SJohan Hedberg 
2321a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
2322a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
2323a5c29683SJohan Hedberg 		break;
2324a5c29683SJohan Hedberg 
23251143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_REPLY:
23261143d458SBrian Gix 		hci_cc_user_passkey_reply(hdev, skb);
23271143d458SBrian Gix 		break;
23281143d458SBrian Gix 
23291143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_NEG_REPLY:
23301143d458SBrian Gix 		hci_cc_user_passkey_neg_reply(hdev, skb);
233116cde993SSzymon Janc 		break;
233207f7fa5dSAndre Guedes 
233307f7fa5dSAndre Guedes 	case HCI_OP_LE_SET_SCAN_PARAM:
233407f7fa5dSAndre Guedes 		hci_cc_le_set_scan_param(hdev, skb);
23351143d458SBrian Gix 		break;
23361143d458SBrian Gix 
2337eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
2338eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
2339eb9d91f5SAndre Guedes 		break;
2340eb9d91f5SAndre Guedes 
2341a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_REPLY:
2342a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_reply(hdev, skb);
2343a7a595f6SVinicius Costa Gomes 		break;
2344a7a595f6SVinicius Costa Gomes 
2345a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_NEG_REPLY:
2346a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_neg_reply(hdev, skb);
2347a7a595f6SVinicius Costa Gomes 		break;
2348a7a595f6SVinicius Costa Gomes 
2349f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2350f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
2351f9b49306SAndre Guedes 		break;
2352f9b49306SAndre Guedes 
2353a9de9248SMarcel Holtmann 	default:
23549f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2355a9de9248SMarcel Holtmann 		break;
2356a9de9248SMarcel Holtmann 	}
2357a9de9248SMarcel Holtmann 
23586bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
23596bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
23606bd32326SVille Tervo 
2361a9de9248SMarcel Holtmann 	if (ev->ncmd) {
2362a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2363a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2364c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2365a9de9248SMarcel Holtmann 	}
2366a9de9248SMarcel Holtmann }
2367a9de9248SMarcel Holtmann 
23686039aa73SGustavo Padovan static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2369a9de9248SMarcel Holtmann {
2370a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
2371a9de9248SMarcel Holtmann 	__u16 opcode;
2372a9de9248SMarcel Holtmann 
2373a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2374a9de9248SMarcel Holtmann 
2375a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2376a9de9248SMarcel Holtmann 
2377a9de9248SMarcel Holtmann 	switch (opcode) {
2378a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
2379a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
2380a9de9248SMarcel Holtmann 		break;
2381a9de9248SMarcel Holtmann 
2382a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
2383a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
2384a9de9248SMarcel Holtmann 		break;
2385a9de9248SMarcel Holtmann 
2386a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
2387a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
2388a9de9248SMarcel Holtmann 		break;
2389a9de9248SMarcel Holtmann 
2390f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2391f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2392f8558555SMarcel Holtmann 		break;
2393f8558555SMarcel Holtmann 
2394f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2395f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2396f8558555SMarcel Holtmann 		break;
2397f8558555SMarcel Holtmann 
2398a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2399a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2400a9de9248SMarcel Holtmann 		break;
2401a9de9248SMarcel Holtmann 
2402769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2403769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2404769be974SMarcel Holtmann 		break;
2405769be974SMarcel Holtmann 
2406769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2407769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2408769be974SMarcel Holtmann 		break;
2409769be974SMarcel Holtmann 
2410a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2411a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2412a9de9248SMarcel Holtmann 		break;
2413a9de9248SMarcel Holtmann 
2414a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2415a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2416a9de9248SMarcel Holtmann 		break;
2417a9de9248SMarcel Holtmann 
2418a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2419a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2420a9de9248SMarcel Holtmann 		break;
2421a9de9248SMarcel Holtmann 
24228962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
242388c3df13SJohan Hedberg 		hci_cs_disconnect(hdev, ev->status);
24248962ee74SJohan Hedberg 		break;
24258962ee74SJohan Hedberg 
2426fcd89c09SVille Tervo 	case HCI_OP_LE_CREATE_CONN:
2427fcd89c09SVille Tervo 		hci_cs_le_create_conn(hdev, ev->status);
2428fcd89c09SVille Tervo 		break;
2429fcd89c09SVille Tervo 
2430a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_START_ENC:
2431a7a595f6SVinicius Costa Gomes 		hci_cs_le_start_enc(hdev, ev->status);
2432a7a595f6SVinicius Costa Gomes 		break;
2433a7a595f6SVinicius Costa Gomes 
2434a9de9248SMarcel Holtmann 	default:
24359f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2436a9de9248SMarcel Holtmann 		break;
2437a9de9248SMarcel Holtmann 	}
2438a9de9248SMarcel Holtmann 
24396bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
24406bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
24416bd32326SVille Tervo 
244210572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2443a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2444a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2445c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2446a9de9248SMarcel Holtmann 	}
2447a9de9248SMarcel Holtmann }
2448a9de9248SMarcel Holtmann 
24496039aa73SGustavo Padovan static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2450a9de9248SMarcel Holtmann {
2451a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2452a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2453a9de9248SMarcel Holtmann 
24549f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2455a9de9248SMarcel Holtmann 
2456a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2457a9de9248SMarcel Holtmann 
2458a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2459a9de9248SMarcel Holtmann 	if (conn) {
2460a9de9248SMarcel Holtmann 		if (!ev->status) {
2461a9de9248SMarcel Holtmann 			if (ev->role)
2462a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
2463a9de9248SMarcel Holtmann 			else
2464a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
2465a9de9248SMarcel Holtmann 		}
2466a9de9248SMarcel Holtmann 
246751a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
2468a9de9248SMarcel Holtmann 
2469a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2470a9de9248SMarcel Holtmann 	}
2471a9de9248SMarcel Holtmann 
2472a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2473a9de9248SMarcel Holtmann }
2474a9de9248SMarcel Holtmann 
24756039aa73SGustavo Padovan static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
24761da177e4SLinus Torvalds {
2477a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
24781da177e4SLinus Torvalds 	int i;
24791da177e4SLinus Torvalds 
248032ac5b9bSAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
248132ac5b9bSAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
248232ac5b9bSAndrei Emeltchenko 		return;
248332ac5b9bSAndrei Emeltchenko 	}
248432ac5b9bSAndrei Emeltchenko 
2485c5993de8SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2486c5993de8SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
24871da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
24881da177e4SLinus Torvalds 		return;
24891da177e4SLinus Torvalds 	}
24901da177e4SLinus Torvalds 
2491c5993de8SAndrei Emeltchenko 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2492c5993de8SAndrei Emeltchenko 
2493613a1c0cSAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
2494613a1c0cSAndrei Emeltchenko 		struct hci_comp_pkts_info *info = &ev->handles[i];
24951da177e4SLinus Torvalds 		struct hci_conn *conn;
24961da177e4SLinus Torvalds 		__u16  handle, count;
24971da177e4SLinus Torvalds 
2498613a1c0cSAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
2499613a1c0cSAndrei Emeltchenko 		count  = __le16_to_cpu(info->count);
25001da177e4SLinus Torvalds 
25011da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
2502f4280918SAndrei Emeltchenko 		if (!conn)
2503f4280918SAndrei Emeltchenko 			continue;
2504f4280918SAndrei Emeltchenko 
25051da177e4SLinus Torvalds 		conn->sent -= count;
25061da177e4SLinus Torvalds 
2507f4280918SAndrei Emeltchenko 		switch (conn->type) {
2508f4280918SAndrei Emeltchenko 		case ACL_LINK:
250970f23020SAndrei Emeltchenko 			hdev->acl_cnt += count;
251070f23020SAndrei Emeltchenko 			if (hdev->acl_cnt > hdev->acl_pkts)
25111da177e4SLinus Torvalds 				hdev->acl_cnt = hdev->acl_pkts;
2512f4280918SAndrei Emeltchenko 			break;
2513f4280918SAndrei Emeltchenko 
2514f4280918SAndrei Emeltchenko 		case LE_LINK:
25156ed58ec5SVille Tervo 			if (hdev->le_pkts) {
25166ed58ec5SVille Tervo 				hdev->le_cnt += count;
25176ed58ec5SVille Tervo 				if (hdev->le_cnt > hdev->le_pkts)
25186ed58ec5SVille Tervo 					hdev->le_cnt = hdev->le_pkts;
25196ed58ec5SVille Tervo 			} else {
25206ed58ec5SVille Tervo 				hdev->acl_cnt += count;
25216ed58ec5SVille Tervo 				if (hdev->acl_cnt > hdev->acl_pkts)
25226ed58ec5SVille Tervo 					hdev->acl_cnt = hdev->acl_pkts;
25236ed58ec5SVille Tervo 			}
2524f4280918SAndrei Emeltchenko 			break;
2525f4280918SAndrei Emeltchenko 
2526f4280918SAndrei Emeltchenko 		case SCO_LINK:
252770f23020SAndrei Emeltchenko 			hdev->sco_cnt += count;
252870f23020SAndrei Emeltchenko 			if (hdev->sco_cnt > hdev->sco_pkts)
25295b7f9909SMarcel Holtmann 				hdev->sco_cnt = hdev->sco_pkts;
2530f4280918SAndrei Emeltchenko 			break;
2531f4280918SAndrei Emeltchenko 
2532f4280918SAndrei Emeltchenko 		default:
2533f4280918SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
2534f4280918SAndrei Emeltchenko 			break;
25351da177e4SLinus Torvalds 		}
25361da177e4SLinus Torvalds 	}
2537a9de9248SMarcel Holtmann 
25383eff45eaSGustavo F. Padovan 	queue_work(hdev->workqueue, &hdev->tx_work);
25391da177e4SLinus Torvalds }
25401da177e4SLinus Torvalds 
25416039aa73SGustavo Padovan static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
254225e89e99SAndrei Emeltchenko {
254325e89e99SAndrei Emeltchenko 	struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
254425e89e99SAndrei Emeltchenko 	int i;
254525e89e99SAndrei Emeltchenko 
254625e89e99SAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
254725e89e99SAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
254825e89e99SAndrei Emeltchenko 		return;
254925e89e99SAndrei Emeltchenko 	}
255025e89e99SAndrei Emeltchenko 
255125e89e99SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
255225e89e99SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
255325e89e99SAndrei Emeltchenko 		BT_DBG("%s bad parameters", hdev->name);
255425e89e99SAndrei Emeltchenko 		return;
255525e89e99SAndrei Emeltchenko 	}
255625e89e99SAndrei Emeltchenko 
255725e89e99SAndrei Emeltchenko 	BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
255825e89e99SAndrei Emeltchenko 	       ev->num_hndl);
255925e89e99SAndrei Emeltchenko 
256025e89e99SAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
256125e89e99SAndrei Emeltchenko 		struct hci_comp_blocks_info *info = &ev->handles[i];
256225e89e99SAndrei Emeltchenko 		struct hci_conn *conn;
256325e89e99SAndrei Emeltchenko 		__u16  handle, block_count;
256425e89e99SAndrei Emeltchenko 
256525e89e99SAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
256625e89e99SAndrei Emeltchenko 		block_count = __le16_to_cpu(info->blocks);
256725e89e99SAndrei Emeltchenko 
256825e89e99SAndrei Emeltchenko 		conn = hci_conn_hash_lookup_handle(hdev, handle);
256925e89e99SAndrei Emeltchenko 		if (!conn)
257025e89e99SAndrei Emeltchenko 			continue;
257125e89e99SAndrei Emeltchenko 
257225e89e99SAndrei Emeltchenko 		conn->sent -= block_count;
257325e89e99SAndrei Emeltchenko 
257425e89e99SAndrei Emeltchenko 		switch (conn->type) {
257525e89e99SAndrei Emeltchenko 		case ACL_LINK:
257625e89e99SAndrei Emeltchenko 			hdev->block_cnt += block_count;
257725e89e99SAndrei Emeltchenko 			if (hdev->block_cnt > hdev->num_blocks)
257825e89e99SAndrei Emeltchenko 				hdev->block_cnt = hdev->num_blocks;
257925e89e99SAndrei Emeltchenko 			break;
258025e89e99SAndrei Emeltchenko 
258125e89e99SAndrei Emeltchenko 		default:
258225e89e99SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
258325e89e99SAndrei Emeltchenko 			break;
258425e89e99SAndrei Emeltchenko 		}
258525e89e99SAndrei Emeltchenko 	}
258625e89e99SAndrei Emeltchenko 
258725e89e99SAndrei Emeltchenko 	queue_work(hdev->workqueue, &hdev->tx_work);
258825e89e99SAndrei Emeltchenko }
258925e89e99SAndrei Emeltchenko 
25906039aa73SGustavo Padovan static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
25911da177e4SLinus Torvalds {
2592a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
259304837f64SMarcel Holtmann 	struct hci_conn *conn;
25941da177e4SLinus Torvalds 
25959f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
25961da177e4SLinus Torvalds 
25971da177e4SLinus Torvalds 	hci_dev_lock(hdev);
25981da177e4SLinus Torvalds 
259904837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
260004837f64SMarcel Holtmann 	if (conn) {
260104837f64SMarcel Holtmann 		conn->mode = ev->mode;
260204837f64SMarcel Holtmann 		conn->interval = __le16_to_cpu(ev->interval);
260304837f64SMarcel Holtmann 
26048fc9ced3SGustavo Padovan 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
26058fc9ced3SGustavo Padovan 					&conn->flags)) {
260604837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
260758a681efSJohan Hedberg 				set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
260804837f64SMarcel Holtmann 			else
260958a681efSJohan Hedberg 				clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
261004837f64SMarcel Holtmann 		}
2611e73439d8SMarcel Holtmann 
261251a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
2613e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
261404837f64SMarcel Holtmann 	}
261504837f64SMarcel Holtmann 
261604837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
261704837f64SMarcel Holtmann }
261804837f64SMarcel Holtmann 
26196039aa73SGustavo Padovan static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
26201da177e4SLinus Torvalds {
2621052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
2622052b30b0SMarcel Holtmann 	struct hci_conn *conn;
2623052b30b0SMarcel Holtmann 
2624a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2625052b30b0SMarcel Holtmann 
2626052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2627052b30b0SMarcel Holtmann 
2628052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2629b6f98044SWaldemar Rymarkiewicz 	if (!conn)
2630b6f98044SWaldemar Rymarkiewicz 		goto unlock;
2631b6f98044SWaldemar Rymarkiewicz 
2632b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
2633052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2634052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2635052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2636052b30b0SMarcel Holtmann 	}
2637052b30b0SMarcel Holtmann 
2638a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
263903b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
264003b555e1SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
2641a8b2d5c2SJohan Hedberg 	else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
2642a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
2643a770bb5aSWaldemar Rymarkiewicz 
2644a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
2645a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
2646a770bb5aSWaldemar Rymarkiewicz 		else
2647a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
2648a770bb5aSWaldemar Rymarkiewicz 
2649744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
2650a770bb5aSWaldemar Rymarkiewicz 	}
2651980e1a53SJohan Hedberg 
2652b6f98044SWaldemar Rymarkiewicz unlock:
2653052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
26541da177e4SLinus Torvalds }
26551da177e4SLinus Torvalds 
26566039aa73SGustavo Padovan static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
26571da177e4SLinus Torvalds {
265855ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
265955ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
266055ed8ca1SJohan Hedberg 	struct hci_conn *conn;
266155ed8ca1SJohan Hedberg 	struct link_key *key;
266255ed8ca1SJohan Hedberg 
2663a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
266455ed8ca1SJohan Hedberg 
2665a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
266655ed8ca1SJohan Hedberg 		return;
266755ed8ca1SJohan Hedberg 
266855ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
266955ed8ca1SJohan Hedberg 
267055ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
267155ed8ca1SJohan Hedberg 	if (!key) {
267255ed8ca1SJohan Hedberg 		BT_DBG("%s link key not found for %s", hdev->name,
267355ed8ca1SJohan Hedberg 		       batostr(&ev->bdaddr));
267455ed8ca1SJohan Hedberg 		goto not_found;
267555ed8ca1SJohan Hedberg 	}
267655ed8ca1SJohan Hedberg 
267755ed8ca1SJohan Hedberg 	BT_DBG("%s found key type %u for %s", hdev->name, key->type,
267855ed8ca1SJohan Hedberg 	       batostr(&ev->bdaddr));
267955ed8ca1SJohan Hedberg 
2680a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
2681b6020ba0SWaldemar Rymarkiewicz 	    key->type == HCI_LK_DEBUG_COMBINATION) {
268255ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
268355ed8ca1SJohan Hedberg 		goto not_found;
268455ed8ca1SJohan Hedberg 	}
268555ed8ca1SJohan Hedberg 
268655ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
268760b83f57SWaldemar Rymarkiewicz 	if (conn) {
268860b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_UNAUTH_COMBINATION &&
2689807deac2SGustavo Padovan 		    conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
269055ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
269155ed8ca1SJohan Hedberg 			goto not_found;
269255ed8ca1SJohan Hedberg 		}
269355ed8ca1SJohan Hedberg 
269460b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
269560b83f57SWaldemar Rymarkiewicz 		    conn->pending_sec_level == BT_SECURITY_HIGH) {
26968fc9ced3SGustavo Padovan 			BT_DBG("%s ignoring key unauthenticated for high security",
26978fc9ced3SGustavo Padovan 			       hdev->name);
269860b83f57SWaldemar Rymarkiewicz 			goto not_found;
269960b83f57SWaldemar Rymarkiewicz 		}
270060b83f57SWaldemar Rymarkiewicz 
270160b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
270260b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
270360b83f57SWaldemar Rymarkiewicz 	}
270460b83f57SWaldemar Rymarkiewicz 
270555ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
27069b3b4460SAndrei Emeltchenko 	memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
270755ed8ca1SJohan Hedberg 
270855ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
270955ed8ca1SJohan Hedberg 
271055ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
271155ed8ca1SJohan Hedberg 
271255ed8ca1SJohan Hedberg 	return;
271355ed8ca1SJohan Hedberg 
271455ed8ca1SJohan Hedberg not_found:
271555ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
271655ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
27171da177e4SLinus Torvalds }
27181da177e4SLinus Torvalds 
27196039aa73SGustavo Padovan static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
27201da177e4SLinus Torvalds {
2721052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
2722052b30b0SMarcel Holtmann 	struct hci_conn *conn;
272355ed8ca1SJohan Hedberg 	u8 pin_len = 0;
2724052b30b0SMarcel Holtmann 
2725a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2726052b30b0SMarcel Holtmann 
2727052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2728052b30b0SMarcel Holtmann 
2729052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2730052b30b0SMarcel Holtmann 	if (conn) {
2731052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2732052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2733980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
273413d39315SWaldemar Rymarkiewicz 
273513d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
273613d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
273713d39315SWaldemar Rymarkiewicz 
2738052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2739052b30b0SMarcel Holtmann 	}
2740052b30b0SMarcel Holtmann 
2741a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
2742d25e28abSJohan Hedberg 		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
274355ed8ca1SJohan Hedberg 				 ev->key_type, pin_len);
274455ed8ca1SJohan Hedberg 
2745052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
27461da177e4SLinus Torvalds }
27471da177e4SLinus Torvalds 
27486039aa73SGustavo Padovan static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
274904837f64SMarcel Holtmann {
2750a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
275104837f64SMarcel Holtmann 	struct hci_conn *conn;
275204837f64SMarcel Holtmann 
27539f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
275404837f64SMarcel Holtmann 
275504837f64SMarcel Holtmann 	hci_dev_lock(hdev);
275604837f64SMarcel Holtmann 
275704837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
27581da177e4SLinus Torvalds 	if (conn && !ev->status) {
27591da177e4SLinus Torvalds 		struct inquiry_entry *ie;
27601da177e4SLinus Torvalds 
2761cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2762cc11b9c1SAndrei Emeltchenko 		if (ie) {
27631da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
27641da177e4SLinus Torvalds 			ie->timestamp = jiffies;
27651da177e4SLinus Torvalds 		}
27661da177e4SLinus Torvalds 	}
27671da177e4SLinus Torvalds 
27681da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
27691da177e4SLinus Torvalds }
27701da177e4SLinus Torvalds 
27716039aa73SGustavo Padovan static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2772a8746417SMarcel Holtmann {
2773a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2774a8746417SMarcel Holtmann 	struct hci_conn *conn;
2775a8746417SMarcel Holtmann 
27769f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2777a8746417SMarcel Holtmann 
2778a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
2779a8746417SMarcel Holtmann 
2780a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2781a8746417SMarcel Holtmann 	if (conn && !ev->status)
2782a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2783a8746417SMarcel Holtmann 
2784a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
2785a8746417SMarcel Holtmann }
2786a8746417SMarcel Holtmann 
27876039aa73SGustavo Padovan static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
278885a1e930SMarcel Holtmann {
2789a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
279085a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
279185a1e930SMarcel Holtmann 
279285a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
279385a1e930SMarcel Holtmann 
279485a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
279585a1e930SMarcel Holtmann 
2796cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2797cc11b9c1SAndrei Emeltchenko 	if (ie) {
279885a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
279985a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
280085a1e930SMarcel Holtmann 	}
280185a1e930SMarcel Holtmann 
280285a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
280385a1e930SMarcel Holtmann }
280485a1e930SMarcel Holtmann 
28056039aa73SGustavo Padovan static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
2806807deac2SGustavo Padovan 					     struct sk_buff *skb)
2807a9de9248SMarcel Holtmann {
2808a9de9248SMarcel Holtmann 	struct inquiry_data data;
2809a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2810388fc8faSJohan Hedberg 	bool name_known, ssp;
2811a9de9248SMarcel Holtmann 
2812a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2813a9de9248SMarcel Holtmann 
2814a9de9248SMarcel Holtmann 	if (!num_rsp)
2815a9de9248SMarcel Holtmann 		return;
2816a9de9248SMarcel Holtmann 
28171519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
28181519cc17SAndre Guedes 		return;
28191519cc17SAndre Guedes 
2820a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2821a9de9248SMarcel Holtmann 
2822a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
2823138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
2824138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
2825a9de9248SMarcel Holtmann 
2826e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2827a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2828a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2829a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2830a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
2831a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2832a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2833a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
283441a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
28353175405bSJohan Hedberg 
28363175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
2837388fc8faSJohan Hedberg 							      false, &ssp);
283848264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2839e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
2840388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
2841a9de9248SMarcel Holtmann 		}
2842a9de9248SMarcel Holtmann 	} else {
2843a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2844a9de9248SMarcel Holtmann 
2845e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2846a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2847a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2848a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2849a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
2850a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2851a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2852a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
285341a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
28543175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
2855388fc8faSJohan Hedberg 							      false, &ssp);
285648264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2857e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
2858388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
2859a9de9248SMarcel Holtmann 		}
2860a9de9248SMarcel Holtmann 	}
2861a9de9248SMarcel Holtmann 
2862a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2863a9de9248SMarcel Holtmann }
2864a9de9248SMarcel Holtmann 
28656039aa73SGustavo Padovan static void hci_remote_ext_features_evt(struct hci_dev *hdev,
2866807deac2SGustavo Padovan 					struct sk_buff *skb)
2867a9de9248SMarcel Holtmann {
286841a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
286941a96212SMarcel Holtmann 	struct hci_conn *conn;
287041a96212SMarcel Holtmann 
2871a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
287241a96212SMarcel Holtmann 
287341a96212SMarcel Holtmann 	hci_dev_lock(hdev);
287441a96212SMarcel Holtmann 
287541a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2876ccd556feSJohan Hedberg 	if (!conn)
2877ccd556feSJohan Hedberg 		goto unlock;
2878ccd556feSJohan Hedberg 
2879769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
288041a96212SMarcel Holtmann 		struct inquiry_entry *ie;
288141a96212SMarcel Holtmann 
2882cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2883cc11b9c1SAndrei Emeltchenko 		if (ie)
288402b7cc62SJohan Hedberg 			ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
288541a96212SMarcel Holtmann 
288602b7cc62SJohan Hedberg 		if (ev->features[0] & LMP_HOST_SSP)
288758a681efSJohan Hedberg 			set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
288841a96212SMarcel Holtmann 	}
288941a96212SMarcel Holtmann 
2890ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2891ccd556feSJohan Hedberg 		goto unlock;
2892ccd556feSJohan Hedberg 
2893671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
2894127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2895127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2896127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2897127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2898127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2899b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2900b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
290108c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
2902b644ba33SJohan Hedberg 				      conn->dev_class);
2903392599b9SJohan Hedberg 
2904127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2905769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2906769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2907769be974SMarcel Holtmann 		hci_conn_put(conn);
2908769be974SMarcel Holtmann 	}
2909769be974SMarcel Holtmann 
2910ccd556feSJohan Hedberg unlock:
291141a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
2912a9de9248SMarcel Holtmann }
2913a9de9248SMarcel Holtmann 
29146039aa73SGustavo Padovan static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
2915807deac2SGustavo Padovan 				       struct sk_buff *skb)
2916a9de9248SMarcel Holtmann {
2917b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2918b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
2919b6a0dc82SMarcel Holtmann 
29209f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2921b6a0dc82SMarcel Holtmann 
2922b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
2923b6a0dc82SMarcel Holtmann 
2924b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
29259dc0a3afSMarcel Holtmann 	if (!conn) {
29269dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
29279dc0a3afSMarcel Holtmann 			goto unlock;
29289dc0a3afSMarcel Holtmann 
29299dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2930b6a0dc82SMarcel Holtmann 		if (!conn)
2931b6a0dc82SMarcel Holtmann 			goto unlock;
2932b6a0dc82SMarcel Holtmann 
29339dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
29349dc0a3afSMarcel Holtmann 	}
29359dc0a3afSMarcel Holtmann 
2936732547f9SMarcel Holtmann 	switch (ev->status) {
2937732547f9SMarcel Holtmann 	case 0x00:
2938732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
2939732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
2940732547f9SMarcel Holtmann 
29419eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
2942732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
2943732547f9SMarcel Holtmann 		break;
2944732547f9SMarcel Holtmann 
2945705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
2946732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
29471038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
2948732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
2949732547f9SMarcel Holtmann 		if (conn->out && conn->attempt < 2) {
2950efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2951efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
2952efc7688bSMarcel Holtmann 			hci_setup_sync(conn, conn->link->handle);
2953efc7688bSMarcel Holtmann 			goto unlock;
2954efc7688bSMarcel Holtmann 		}
2955732547f9SMarcel Holtmann 		/* fall through */
2956efc7688bSMarcel Holtmann 
2957732547f9SMarcel Holtmann 	default:
2958b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
2959732547f9SMarcel Holtmann 		break;
2960732547f9SMarcel Holtmann 	}
2961b6a0dc82SMarcel Holtmann 
2962b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
2963b6a0dc82SMarcel Holtmann 	if (ev->status)
2964b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
2965b6a0dc82SMarcel Holtmann 
2966b6a0dc82SMarcel Holtmann unlock:
2967b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
2968a9de9248SMarcel Holtmann }
2969a9de9248SMarcel Holtmann 
29706039aa73SGustavo Padovan static void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
2971a9de9248SMarcel Holtmann {
2972a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2973a9de9248SMarcel Holtmann }
2974a9de9248SMarcel Holtmann 
29756039aa73SGustavo Padovan static void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
297604837f64SMarcel Holtmann {
2977a9de9248SMarcel Holtmann 	struct hci_ev_sniff_subrate *ev = (void *) skb->data;
297804837f64SMarcel Holtmann 
29799f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
298004837f64SMarcel Holtmann }
298104837f64SMarcel Holtmann 
29826039aa73SGustavo Padovan static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
2983807deac2SGustavo Padovan 					    struct sk_buff *skb)
2984a9de9248SMarcel Holtmann {
2985a9de9248SMarcel Holtmann 	struct inquiry_data data;
2986a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
2987a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
29889d939d94SVishal Agarwal 	size_t eir_len;
2989a9de9248SMarcel Holtmann 
2990a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2991a9de9248SMarcel Holtmann 
2992a9de9248SMarcel Holtmann 	if (!num_rsp)
2993a9de9248SMarcel Holtmann 		return;
2994a9de9248SMarcel Holtmann 
29951519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
29961519cc17SAndre Guedes 		return;
29971519cc17SAndre Guedes 
2998a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2999a9de9248SMarcel Holtmann 
3000e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
3001388fc8faSJohan Hedberg 		bool name_known, ssp;
3002561aafbcSJohan Hedberg 
3003a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
3004a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
3005a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
3006a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
3007a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
3008a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
3009a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
301041a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
3011561aafbcSJohan Hedberg 
3012a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
30134ddb1930SJohan Hedberg 			name_known = eir_has_data_type(info->data,
30144ddb1930SJohan Hedberg 						       sizeof(info->data),
30154ddb1930SJohan Hedberg 						       EIR_NAME_COMPLETE);
3016561aafbcSJohan Hedberg 		else
3017561aafbcSJohan Hedberg 			name_known = true;
3018561aafbcSJohan Hedberg 
3019388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, name_known,
3020388fc8faSJohan Hedberg 						      &ssp);
30219d939d94SVishal Agarwal 		eir_len = eir_get_length(info->data, sizeof(info->data));
302248264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
302304124681SGustavo F. Padovan 				  info->dev_class, info->rssi, !name_known,
30249d939d94SVishal Agarwal 				  ssp, info->data, eir_len);
3025a9de9248SMarcel Holtmann 	}
3026a9de9248SMarcel Holtmann 
3027a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3028a9de9248SMarcel Holtmann }
3029a9de9248SMarcel Holtmann 
30301c2e0041SJohan Hedberg static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
30311c2e0041SJohan Hedberg 					 struct sk_buff *skb)
30321c2e0041SJohan Hedberg {
30331c2e0041SJohan Hedberg 	struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
30341c2e0041SJohan Hedberg 	struct hci_conn *conn;
30351c2e0041SJohan Hedberg 
30369f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
30371c2e0041SJohan Hedberg 	       __le16_to_cpu(ev->handle));
30381c2e0041SJohan Hedberg 
30391c2e0041SJohan Hedberg 	hci_dev_lock(hdev);
30401c2e0041SJohan Hedberg 
30411c2e0041SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
30421c2e0041SJohan Hedberg 	if (!conn)
30431c2e0041SJohan Hedberg 		goto unlock;
30441c2e0041SJohan Hedberg 
30451c2e0041SJohan Hedberg 	if (!ev->status)
30461c2e0041SJohan Hedberg 		conn->sec_level = conn->pending_sec_level;
30471c2e0041SJohan Hedberg 
30481c2e0041SJohan Hedberg 	clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
30491c2e0041SJohan Hedberg 
30501c2e0041SJohan Hedberg 	if (ev->status && conn->state == BT_CONNECTED) {
30511c2e0041SJohan Hedberg 		hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
30521c2e0041SJohan Hedberg 		hci_conn_put(conn);
30531c2e0041SJohan Hedberg 		goto unlock;
30541c2e0041SJohan Hedberg 	}
30551c2e0041SJohan Hedberg 
30561c2e0041SJohan Hedberg 	if (conn->state == BT_CONFIG) {
30571c2e0041SJohan Hedberg 		if (!ev->status)
30581c2e0041SJohan Hedberg 			conn->state = BT_CONNECTED;
30591c2e0041SJohan Hedberg 
30601c2e0041SJohan Hedberg 		hci_proto_connect_cfm(conn, ev->status);
30611c2e0041SJohan Hedberg 		hci_conn_put(conn);
30621c2e0041SJohan Hedberg 	} else {
30631c2e0041SJohan Hedberg 		hci_auth_cfm(conn, ev->status);
30641c2e0041SJohan Hedberg 
30651c2e0041SJohan Hedberg 		hci_conn_hold(conn);
30661c2e0041SJohan Hedberg 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
30671c2e0041SJohan Hedberg 		hci_conn_put(conn);
30681c2e0041SJohan Hedberg 	}
30691c2e0041SJohan Hedberg 
30701c2e0041SJohan Hedberg unlock:
30711c2e0041SJohan Hedberg 	hci_dev_unlock(hdev);
30721c2e0041SJohan Hedberg }
30731c2e0041SJohan Hedberg 
30746039aa73SGustavo Padovan static u8 hci_get_auth_req(struct hci_conn *conn)
307517fa4b9dSJohan Hedberg {
307617fa4b9dSJohan Hedberg 	/* If remote requests dedicated bonding follow that lead */
307717fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
307817fa4b9dSJohan Hedberg 		/* If both remote and local IO capabilities allow MITM
307917fa4b9dSJohan Hedberg 		 * protection then require it, otherwise don't */
308017fa4b9dSJohan Hedberg 		if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
308117fa4b9dSJohan Hedberg 			return 0x02;
308217fa4b9dSJohan Hedberg 		else
308317fa4b9dSJohan Hedberg 			return 0x03;
308417fa4b9dSJohan Hedberg 	}
308517fa4b9dSJohan Hedberg 
308617fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
308717fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
308858797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
308917fa4b9dSJohan Hedberg 
309017fa4b9dSJohan Hedberg 	return conn->auth_type;
309117fa4b9dSJohan Hedberg }
309217fa4b9dSJohan Hedberg 
30936039aa73SGustavo Padovan static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
30940493684eSMarcel Holtmann {
30950493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
30960493684eSMarcel Holtmann 	struct hci_conn *conn;
30970493684eSMarcel Holtmann 
30980493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
30990493684eSMarcel Holtmann 
31000493684eSMarcel Holtmann 	hci_dev_lock(hdev);
31010493684eSMarcel Holtmann 
31020493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
310303b555e1SJohan Hedberg 	if (!conn)
310403b555e1SJohan Hedberg 		goto unlock;
310503b555e1SJohan Hedberg 
31060493684eSMarcel Holtmann 	hci_conn_hold(conn);
31070493684eSMarcel Holtmann 
3108a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
310903b555e1SJohan Hedberg 		goto unlock;
311003b555e1SJohan Hedberg 
3111a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
311203b555e1SJohan Hedberg 	    (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
311317fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
311417fa4b9dSJohan Hedberg 
311517fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
31167a7f1e7cSHemant Gupta 		/* Change the IO capability from KeyboardDisplay
31177a7f1e7cSHemant Gupta 		 * to DisplayYesNo as it is not supported by BT spec. */
31187a7f1e7cSHemant Gupta 		cp.capability = (conn->io_capability == 0x04) ?
31197a7f1e7cSHemant Gupta 						0x01 : conn->io_capability;
31207cbc9bd9SJohan Hedberg 		conn->auth_type = hci_get_auth_req(conn);
31217cbc9bd9SJohan Hedberg 		cp.authentication = conn->auth_type;
312217fa4b9dSJohan Hedberg 
31238fc9ced3SGustavo Padovan 		if (hci_find_remote_oob_data(hdev, &conn->dst) &&
31248fc9ced3SGustavo Padovan 		    (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
3125ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
3126ce85ee13SSzymon Janc 		else
3127ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
3128ce85ee13SSzymon Janc 
312917fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
313017fa4b9dSJohan Hedberg 			     sizeof(cp), &cp);
313103b555e1SJohan Hedberg 	} else {
313203b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
313303b555e1SJohan Hedberg 
313403b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
31359f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
313603b555e1SJohan Hedberg 
313703b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
313803b555e1SJohan Hedberg 			     sizeof(cp), &cp);
313903b555e1SJohan Hedberg 	}
314003b555e1SJohan Hedberg 
314103b555e1SJohan Hedberg unlock:
314203b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
314303b555e1SJohan Hedberg }
314403b555e1SJohan Hedberg 
31456039aa73SGustavo Padovan static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
314603b555e1SJohan Hedberg {
314703b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
314803b555e1SJohan Hedberg 	struct hci_conn *conn;
314903b555e1SJohan Hedberg 
315003b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
315103b555e1SJohan Hedberg 
315203b555e1SJohan Hedberg 	hci_dev_lock(hdev);
315303b555e1SJohan Hedberg 
315403b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
315503b555e1SJohan Hedberg 	if (!conn)
315603b555e1SJohan Hedberg 		goto unlock;
315703b555e1SJohan Hedberg 
315803b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
315903b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
316058a681efSJohan Hedberg 	if (ev->oob_data)
316158a681efSJohan Hedberg 		set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
316203b555e1SJohan Hedberg 
316303b555e1SJohan Hedberg unlock:
31640493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
31650493684eSMarcel Holtmann }
31660493684eSMarcel Holtmann 
31676039aa73SGustavo Padovan static void hci_user_confirm_request_evt(struct hci_dev *hdev,
3168a5c29683SJohan Hedberg 					 struct sk_buff *skb)
3169a5c29683SJohan Hedberg {
3170a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
317155bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
31727a828908SJohan Hedberg 	struct hci_conn *conn;
3173a5c29683SJohan Hedberg 
3174a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
3175a5c29683SJohan Hedberg 
3176a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
3177a5c29683SJohan Hedberg 
3178a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
31797a828908SJohan Hedberg 		goto unlock;
31807a828908SJohan Hedberg 
31817a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
31827a828908SJohan Hedberg 	if (!conn)
31837a828908SJohan Hedberg 		goto unlock;
31847a828908SJohan Hedberg 
31857a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
31867a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
31877a828908SJohan Hedberg 
31887a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
31897a828908SJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
31907a828908SJohan Hedberg 	 * request. The only exception is when we're dedicated bonding
31917a828908SJohan Hedberg 	 * initiators (connect_cfm_cb set) since then we always have the MITM
31927a828908SJohan Hedberg 	 * bit set. */
31937a828908SJohan Hedberg 	if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
31947a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
31957a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
31967a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
31977a828908SJohan Hedberg 		goto unlock;
31987a828908SJohan Hedberg 	}
31997a828908SJohan Hedberg 
32007a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
32017a828908SJohan Hedberg 	if ((!loc_mitm || conn->remote_cap == 0x03) &&
32027a828908SJohan Hedberg 	    (!rem_mitm || conn->io_capability == 0x03)) {
320355bc1a37SJohan Hedberg 
320455bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
320555bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
320655bc1a37SJohan Hedberg 		 * confirm_hint set to 1). */
320751a8efd7SJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
320855bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
320955bc1a37SJohan Hedberg 			confirm_hint = 1;
321055bc1a37SJohan Hedberg 			goto confirm;
321155bc1a37SJohan Hedberg 		}
321255bc1a37SJohan Hedberg 
32139f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
32149f61656aSJohan Hedberg 		       hdev->auto_accept_delay);
32159f61656aSJohan Hedberg 
32169f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
32179f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
32189f61656aSJohan Hedberg 			mod_timer(&conn->auto_accept_timer, jiffies + delay);
32199f61656aSJohan Hedberg 			goto unlock;
32209f61656aSJohan Hedberg 		}
32219f61656aSJohan Hedberg 
32227a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
32237a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
32247a828908SJohan Hedberg 		goto unlock;
32257a828908SJohan Hedberg 	}
32267a828908SJohan Hedberg 
322755bc1a37SJohan Hedberg confirm:
3228272d90dfSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
322955bc1a37SJohan Hedberg 				  confirm_hint);
3230a5c29683SJohan Hedberg 
32317a828908SJohan Hedberg unlock:
3232a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
3233a5c29683SJohan Hedberg }
3234a5c29683SJohan Hedberg 
32356039aa73SGustavo Padovan static void hci_user_passkey_request_evt(struct hci_dev *hdev,
32361143d458SBrian Gix 					 struct sk_buff *skb)
32371143d458SBrian Gix {
32381143d458SBrian Gix 	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
32391143d458SBrian Gix 
32401143d458SBrian Gix 	BT_DBG("%s", hdev->name);
32411143d458SBrian Gix 
3242a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3243272d90dfSJohan Hedberg 		mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
32441143d458SBrian Gix }
32451143d458SBrian Gix 
32466039aa73SGustavo Padovan static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
3247807deac2SGustavo Padovan 					 struct sk_buff *skb)
32480493684eSMarcel Holtmann {
32490493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
32500493684eSMarcel Holtmann 	struct hci_conn *conn;
32510493684eSMarcel Holtmann 
32520493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
32530493684eSMarcel Holtmann 
32540493684eSMarcel Holtmann 	hci_dev_lock(hdev);
32550493684eSMarcel Holtmann 
32560493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
32572a611692SJohan Hedberg 	if (!conn)
32582a611692SJohan Hedberg 		goto unlock;
32592a611692SJohan Hedberg 
32602a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
32612a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
32622a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
32632a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
32642a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
326551a8efd7SJohan Hedberg 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status != 0)
3266bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
3267bab73cb6SJohan Hedberg 				 ev->status);
32682a611692SJohan Hedberg 
32690493684eSMarcel Holtmann 	hci_conn_put(conn);
32700493684eSMarcel Holtmann 
32712a611692SJohan Hedberg unlock:
32720493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
32730493684eSMarcel Holtmann }
32740493684eSMarcel Holtmann 
32756039aa73SGustavo Padovan static void hci_remote_host_features_evt(struct hci_dev *hdev,
3276807deac2SGustavo Padovan 					 struct sk_buff *skb)
327741a96212SMarcel Holtmann {
327841a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
327941a96212SMarcel Holtmann 	struct inquiry_entry *ie;
328041a96212SMarcel Holtmann 
328141a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
328241a96212SMarcel Holtmann 
328341a96212SMarcel Holtmann 	hci_dev_lock(hdev);
328441a96212SMarcel Holtmann 
3285cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3286cc11b9c1SAndrei Emeltchenko 	if (ie)
328702b7cc62SJohan Hedberg 		ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
328841a96212SMarcel Holtmann 
328941a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
329041a96212SMarcel Holtmann }
329141a96212SMarcel Holtmann 
32926039aa73SGustavo Padovan static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
32932763eda6SSzymon Janc 					    struct sk_buff *skb)
32942763eda6SSzymon Janc {
32952763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
32962763eda6SSzymon Janc 	struct oob_data *data;
32972763eda6SSzymon Janc 
32982763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
32992763eda6SSzymon Janc 
33002763eda6SSzymon Janc 	hci_dev_lock(hdev);
33012763eda6SSzymon Janc 
3302a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
3303e1ba1f15SSzymon Janc 		goto unlock;
3304e1ba1f15SSzymon Janc 
33052763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
33062763eda6SSzymon Janc 	if (data) {
33072763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_reply cp;
33082763eda6SSzymon Janc 
33092763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
33102763eda6SSzymon Janc 		memcpy(cp.hash, data->hash, sizeof(cp.hash));
33112763eda6SSzymon Janc 		memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
33122763eda6SSzymon Janc 
33132763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
33142763eda6SSzymon Janc 			     &cp);
33152763eda6SSzymon Janc 	} else {
33162763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
33172763eda6SSzymon Janc 
33182763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
33192763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
33202763eda6SSzymon Janc 			     &cp);
33212763eda6SSzymon Janc 	}
33222763eda6SSzymon Janc 
3323e1ba1f15SSzymon Janc unlock:
33242763eda6SSzymon Janc 	hci_dev_unlock(hdev);
33252763eda6SSzymon Janc }
33262763eda6SSzymon Janc 
33276039aa73SGustavo Padovan static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3328fcd89c09SVille Tervo {
3329fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3330fcd89c09SVille Tervo 	struct hci_conn *conn;
3331fcd89c09SVille Tervo 
33329f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3333fcd89c09SVille Tervo 
3334fcd89c09SVille Tervo 	hci_dev_lock(hdev);
3335fcd89c09SVille Tervo 
33364f72b329SAndrzej Kaczmarek 	if (ev->status) {
33374f72b329SAndrzej Kaczmarek 		conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
33384f72b329SAndrzej Kaczmarek 		if (!conn)
33394f72b329SAndrzej Kaczmarek 			goto unlock;
33404f72b329SAndrzej Kaczmarek 
33414f72b329SAndrzej Kaczmarek 		mgmt_connect_failed(hdev, &conn->dst, conn->type,
33424f72b329SAndrzej Kaczmarek 				    conn->dst_type, ev->status);
33434f72b329SAndrzej Kaczmarek 		hci_proto_connect_cfm(conn, ev->status);
33444f72b329SAndrzej Kaczmarek 		conn->state = BT_CLOSED;
33454f72b329SAndrzej Kaczmarek 		hci_conn_del(conn);
33464f72b329SAndrzej Kaczmarek 		goto unlock;
33474f72b329SAndrzej Kaczmarek 	}
33484f72b329SAndrzej Kaczmarek 
3349fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
3350b62f328bSVille Tervo 	if (!conn) {
3351b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3352b62f328bSVille Tervo 		if (!conn) {
3353b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
3354230fd16aSAndre Guedes 			goto unlock;
3355b62f328bSVille Tervo 		}
335629b7988aSAndre Guedes 
335729b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
3358b9b343d2SAndre Guedes 
3359b9b343d2SAndre Guedes 		if (ev->role == LE_CONN_ROLE_MASTER) {
3360b9b343d2SAndre Guedes 			conn->out = true;
3361b9b343d2SAndre Guedes 			conn->link_mode |= HCI_LM_MASTER;
3362b9b343d2SAndre Guedes 		}
3363b62f328bSVille Tervo 	}
3364fcd89c09SVille Tervo 
3365b644ba33SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3366b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
336795b23582SSzymon Janc 				      conn->dst_type, 0, NULL, 0, NULL);
336883bc71b4SVinicius Costa Gomes 
33697b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
3370fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
3371fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
3372fcd89c09SVille Tervo 
3373fcd89c09SVille Tervo 	hci_conn_hold_device(conn);
3374fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
3375fcd89c09SVille Tervo 
3376fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
3377fcd89c09SVille Tervo 
3378fcd89c09SVille Tervo unlock:
3379fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
3380fcd89c09SVille Tervo }
3381fcd89c09SVille Tervo 
33826039aa73SGustavo Padovan static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
33839aa04c91SAndre Guedes {
3384e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
3385e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
33863c9e9195SAndre Guedes 	s8 rssi;
33879aa04c91SAndre Guedes 
33889aa04c91SAndre Guedes 	hci_dev_lock(hdev);
33899aa04c91SAndre Guedes 
3390e95beb41SAndre Guedes 	while (num_reports--) {
3391e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
3392e95beb41SAndre Guedes 
33933c9e9195SAndre Guedes 		rssi = ev->data[ev->length];
33943c9e9195SAndre Guedes 		mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
339504124681SGustavo F. Padovan 				  NULL, rssi, 0, 1, ev->data, ev->length);
33963c9e9195SAndre Guedes 
3397e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
33989aa04c91SAndre Guedes 	}
33999aa04c91SAndre Guedes 
34009aa04c91SAndre Guedes 	hci_dev_unlock(hdev);
34019aa04c91SAndre Guedes }
34029aa04c91SAndre Guedes 
34036039aa73SGustavo Padovan static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
3404a7a595f6SVinicius Costa Gomes {
3405a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3406a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
3407bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
3408a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
3409c9839a11SVinicius Costa Gomes 	struct smp_ltk *ltk;
3410a7a595f6SVinicius Costa Gomes 
34119f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
3412a7a595f6SVinicius Costa Gomes 
3413a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
3414a7a595f6SVinicius Costa Gomes 
3415a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3416bea710feSVinicius Costa Gomes 	if (conn == NULL)
3417bea710feSVinicius Costa Gomes 		goto not_found;
3418a7a595f6SVinicius Costa Gomes 
3419bea710feSVinicius Costa Gomes 	ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3420bea710feSVinicius Costa Gomes 	if (ltk == NULL)
3421bea710feSVinicius Costa Gomes 		goto not_found;
3422bea710feSVinicius Costa Gomes 
3423bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
3424a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
3425c9839a11SVinicius Costa Gomes 
3426c9839a11SVinicius Costa Gomes 	if (ltk->authenticated)
3427c9839a11SVinicius Costa Gomes 		conn->sec_level = BT_SECURITY_HIGH;
3428a7a595f6SVinicius Costa Gomes 
3429a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3430a7a595f6SVinicius Costa Gomes 
3431c9839a11SVinicius Costa Gomes 	if (ltk->type & HCI_SMP_STK) {
3432c9839a11SVinicius Costa Gomes 		list_del(&ltk->list);
3433c9839a11SVinicius Costa Gomes 		kfree(ltk);
3434c9839a11SVinicius Costa Gomes 	}
3435c9839a11SVinicius Costa Gomes 
3436a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
3437bea710feSVinicius Costa Gomes 
3438bea710feSVinicius Costa Gomes 	return;
3439bea710feSVinicius Costa Gomes 
3440bea710feSVinicius Costa Gomes not_found:
3441bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
3442bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3443bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
3444a7a595f6SVinicius Costa Gomes }
3445a7a595f6SVinicius Costa Gomes 
34466039aa73SGustavo Padovan static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3447fcd89c09SVille Tervo {
3448fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
3449fcd89c09SVille Tervo 
3450fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
3451fcd89c09SVille Tervo 
3452fcd89c09SVille Tervo 	switch (le_ev->subevent) {
3453fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
3454fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
3455fcd89c09SVille Tervo 		break;
3456fcd89c09SVille Tervo 
34579aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
34589aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
34599aa04c91SAndre Guedes 		break;
34609aa04c91SAndre Guedes 
3461a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
3462a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
3463a7a595f6SVinicius Costa Gomes 		break;
3464a7a595f6SVinicius Costa Gomes 
3465fcd89c09SVille Tervo 	default:
3466fcd89c09SVille Tervo 		break;
3467fcd89c09SVille Tervo 	}
3468fcd89c09SVille Tervo }
3469fcd89c09SVille Tervo 
34701da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
34711da177e4SLinus Torvalds {
3472a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
3473a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
34741da177e4SLinus Torvalds 
34751da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
34761da177e4SLinus Torvalds 
3477a9de9248SMarcel Holtmann 	switch (event) {
34781da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
34791da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
34801da177e4SLinus Torvalds 		break;
34811da177e4SLinus Torvalds 
34821da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
34831da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
34841da177e4SLinus Torvalds 		break;
34851da177e4SLinus Torvalds 
3486a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
3487a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
348821d9e30eSMarcel Holtmann 		break;
348921d9e30eSMarcel Holtmann 
34901da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
34911da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
34921da177e4SLinus Torvalds 		break;
34931da177e4SLinus Torvalds 
34941da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
34951da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
34961da177e4SLinus Torvalds 		break;
34971da177e4SLinus Torvalds 
34981da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
34991da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
35001da177e4SLinus Torvalds 		break;
35011da177e4SLinus Torvalds 
3502a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
3503a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
3504a9de9248SMarcel Holtmann 		break;
3505a9de9248SMarcel Holtmann 
35061da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
35071da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
35081da177e4SLinus Torvalds 		break;
35091da177e4SLinus Torvalds 
3510a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3511a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
3512a9de9248SMarcel Holtmann 		break;
3513a9de9248SMarcel Holtmann 
3514a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
3515a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
3516a9de9248SMarcel Holtmann 		break;
3517a9de9248SMarcel Holtmann 
3518a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_VERSION:
3519a9de9248SMarcel Holtmann 		hci_remote_version_evt(hdev, skb);
3520a9de9248SMarcel Holtmann 		break;
3521a9de9248SMarcel Holtmann 
3522a9de9248SMarcel Holtmann 	case HCI_EV_QOS_SETUP_COMPLETE:
3523a9de9248SMarcel Holtmann 		hci_qos_setup_complete_evt(hdev, skb);
3524a9de9248SMarcel Holtmann 		break;
3525a9de9248SMarcel Holtmann 
3526a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
3527a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
3528a9de9248SMarcel Holtmann 		break;
3529a9de9248SMarcel Holtmann 
3530a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
3531a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
3532a9de9248SMarcel Holtmann 		break;
3533a9de9248SMarcel Holtmann 
3534a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
3535a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
3536a9de9248SMarcel Holtmann 		break;
3537a9de9248SMarcel Holtmann 
3538a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
3539a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
3540a9de9248SMarcel Holtmann 		break;
3541a9de9248SMarcel Holtmann 
3542a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
3543a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
35441da177e4SLinus Torvalds 		break;
35451da177e4SLinus Torvalds 
35461da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
35471da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
35481da177e4SLinus Torvalds 		break;
35491da177e4SLinus Torvalds 
35501da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
35511da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
35521da177e4SLinus Torvalds 		break;
35531da177e4SLinus Torvalds 
35541da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
35551da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
35561da177e4SLinus Torvalds 		break;
35571da177e4SLinus Torvalds 
35581da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
35591da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
35601da177e4SLinus Torvalds 		break;
35611da177e4SLinus Torvalds 
3562a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
3563a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
3564a8746417SMarcel Holtmann 		break;
3565a8746417SMarcel Holtmann 
356685a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
356785a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
356885a1e930SMarcel Holtmann 		break;
356985a1e930SMarcel Holtmann 
3570a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3571a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
3572a9de9248SMarcel Holtmann 		break;
3573a9de9248SMarcel Holtmann 
3574a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
3575a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
3576a9de9248SMarcel Holtmann 		break;
3577a9de9248SMarcel Holtmann 
3578a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
3579a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
3580a9de9248SMarcel Holtmann 		break;
3581a9de9248SMarcel Holtmann 
3582a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_CHANGED:
3583a9de9248SMarcel Holtmann 		hci_sync_conn_changed_evt(hdev, skb);
3584a9de9248SMarcel Holtmann 		break;
3585a9de9248SMarcel Holtmann 
358604837f64SMarcel Holtmann 	case HCI_EV_SNIFF_SUBRATE:
358704837f64SMarcel Holtmann 		hci_sniff_subrate_evt(hdev, skb);
358804837f64SMarcel Holtmann 		break;
358904837f64SMarcel Holtmann 
3590a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
3591a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
35921da177e4SLinus Torvalds 		break;
35931da177e4SLinus Torvalds 
35941c2e0041SJohan Hedberg 	case HCI_EV_KEY_REFRESH_COMPLETE:
35951c2e0041SJohan Hedberg 		hci_key_refresh_complete_evt(hdev, skb);
35961c2e0041SJohan Hedberg 		break;
35971c2e0041SJohan Hedberg 
35980493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
35990493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
36000493684eSMarcel Holtmann 		break;
36010493684eSMarcel Holtmann 
360203b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
360303b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
360403b555e1SJohan Hedberg 		break;
360503b555e1SJohan Hedberg 
3606a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
3607a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
3608a5c29683SJohan Hedberg 		break;
3609a5c29683SJohan Hedberg 
36101143d458SBrian Gix 	case HCI_EV_USER_PASSKEY_REQUEST:
36111143d458SBrian Gix 		hci_user_passkey_request_evt(hdev, skb);
36121143d458SBrian Gix 		break;
36131143d458SBrian Gix 
36140493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
36150493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
36160493684eSMarcel Holtmann 		break;
36170493684eSMarcel Holtmann 
361841a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
361941a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
362041a96212SMarcel Holtmann 		break;
362141a96212SMarcel Holtmann 
3622fcd89c09SVille Tervo 	case HCI_EV_LE_META:
3623fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
3624fcd89c09SVille Tervo 		break;
3625fcd89c09SVille Tervo 
36262763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
36272763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
36282763eda6SSzymon Janc 		break;
36292763eda6SSzymon Janc 
363025e89e99SAndrei Emeltchenko 	case HCI_EV_NUM_COMP_BLOCKS:
363125e89e99SAndrei Emeltchenko 		hci_num_comp_blocks_evt(hdev, skb);
363225e89e99SAndrei Emeltchenko 		break;
363325e89e99SAndrei Emeltchenko 
36341da177e4SLinus Torvalds 	default:
36359f1db00cSAndrei Emeltchenko 		BT_DBG("%s event 0x%2.2x", hdev->name, event);
36361da177e4SLinus Torvalds 		break;
36371da177e4SLinus Torvalds 	}
36381da177e4SLinus Torvalds 
36391da177e4SLinus Torvalds 	kfree_skb(skb);
36401da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
36411da177e4SLinus Torvalds }
3642