xref: /openbmc/linux/net/bluetooth/hci_event.c (revision 034cbea0)
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 
271da177e4SLinus Torvalds #include <asm/unaligned.h>
281da177e4SLinus Torvalds 
291da177e4SLinus Torvalds #include <net/bluetooth/bluetooth.h>
301da177e4SLinus Torvalds #include <net/bluetooth/hci_core.h>
31f0d6a0eaSMikel Astiz #include <net/bluetooth/mgmt.h>
328e2a0d92SAndrei Emeltchenko #include <net/bluetooth/a2mp.h>
33903e4541SAndrei Emeltchenko #include <net/bluetooth/amp.h>
341da177e4SLinus Torvalds 
351da177e4SLinus Torvalds /* Handle HCI Event packets */
361da177e4SLinus Torvalds 
37a9de9248SMarcel Holtmann static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
381da177e4SLinus Torvalds {
39a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
401da177e4SLinus Torvalds 
419f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
421da177e4SLinus Torvalds 
4382f4785cSAndre Guedes 	if (status)
44a9de9248SMarcel Holtmann 		return;
451da177e4SLinus Torvalds 
4689352e7dSAndre Guedes 	clear_bit(HCI_INQUIRY, &hdev->flags);
473e13fa1eSAndre Guedes 	smp_mb__after_clear_bit(); /* wake_up_bit advises about this barrier */
483e13fa1eSAndre Guedes 	wake_up_bit(&hdev->flags, HCI_INQUIRY);
4989352e7dSAndre Guedes 
50a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
511da177e4SLinus Torvalds }
526bd57416SMarcel Holtmann 
534d93483bSAndre Guedes static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
544d93483bSAndre Guedes {
554d93483bSAndre Guedes 	__u8 status = *((__u8 *) skb->data);
564d93483bSAndre Guedes 
579f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
58ae854a70SAndre Guedes 
59ae854a70SAndre Guedes 	if (status)
60ae854a70SAndre Guedes 		return;
61ae854a70SAndre Guedes 
62ae854a70SAndre Guedes 	set_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
634d93483bSAndre Guedes }
644d93483bSAndre Guedes 
65a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
661da177e4SLinus Torvalds {
67a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
68a9de9248SMarcel Holtmann 
699f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
70a9de9248SMarcel Holtmann 
71a9de9248SMarcel Holtmann 	if (status)
72a9de9248SMarcel Holtmann 		return;
73a9de9248SMarcel Holtmann 
74ae854a70SAndre Guedes 	clear_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
75ae854a70SAndre Guedes 
76a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
77a9de9248SMarcel Holtmann }
78a9de9248SMarcel Holtmann 
79807deac2SGustavo Padovan static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev,
80807deac2SGustavo Padovan 					  struct sk_buff *skb)
81a9de9248SMarcel Holtmann {
82a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
83a9de9248SMarcel Holtmann }
84a9de9248SMarcel Holtmann 
85a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
86a9de9248SMarcel Holtmann {
87a9de9248SMarcel Holtmann 	struct hci_rp_role_discovery *rp = (void *) skb->data;
881da177e4SLinus Torvalds 	struct hci_conn *conn;
891da177e4SLinus Torvalds 
909f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
911da177e4SLinus Torvalds 
92a9de9248SMarcel Holtmann 	if (rp->status)
93a9de9248SMarcel Holtmann 		return;
941da177e4SLinus Torvalds 
951da177e4SLinus Torvalds 	hci_dev_lock(hdev);
961da177e4SLinus Torvalds 
97a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
981da177e4SLinus Torvalds 	if (conn) {
99a9de9248SMarcel Holtmann 		if (rp->role)
1001da177e4SLinus Torvalds 			conn->link_mode &= ~HCI_LM_MASTER;
1011da177e4SLinus Torvalds 		else
1021da177e4SLinus Torvalds 			conn->link_mode |= HCI_LM_MASTER;
1031da177e4SLinus Torvalds 	}
1041da177e4SLinus Torvalds 
1051da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
106a9de9248SMarcel Holtmann }
1071da177e4SLinus Torvalds 
108e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
109e4e8e37cSMarcel Holtmann {
110e4e8e37cSMarcel Holtmann 	struct hci_rp_read_link_policy *rp = (void *) skb->data;
111e4e8e37cSMarcel Holtmann 	struct hci_conn *conn;
112e4e8e37cSMarcel Holtmann 
1139f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
114e4e8e37cSMarcel Holtmann 
115e4e8e37cSMarcel Holtmann 	if (rp->status)
116e4e8e37cSMarcel Holtmann 		return;
117e4e8e37cSMarcel Holtmann 
118e4e8e37cSMarcel Holtmann 	hci_dev_lock(hdev);
119e4e8e37cSMarcel Holtmann 
120e4e8e37cSMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
121e4e8e37cSMarcel Holtmann 	if (conn)
122e4e8e37cSMarcel Holtmann 		conn->link_policy = __le16_to_cpu(rp->policy);
123e4e8e37cSMarcel Holtmann 
124e4e8e37cSMarcel Holtmann 	hci_dev_unlock(hdev);
125e4e8e37cSMarcel Holtmann }
126e4e8e37cSMarcel Holtmann 
127a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
128a9de9248SMarcel Holtmann {
129a9de9248SMarcel Holtmann 	struct hci_rp_write_link_policy *rp = (void *) skb->data;
130a9de9248SMarcel Holtmann 	struct hci_conn *conn;
131a9de9248SMarcel Holtmann 	void *sent;
132a9de9248SMarcel Holtmann 
1339f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
134a9de9248SMarcel Holtmann 
135a9de9248SMarcel Holtmann 	if (rp->status)
136a9de9248SMarcel Holtmann 		return;
137a9de9248SMarcel Holtmann 
138a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
13904837f64SMarcel Holtmann 	if (!sent)
140a9de9248SMarcel Holtmann 		return;
14104837f64SMarcel Holtmann 
14204837f64SMarcel Holtmann 	hci_dev_lock(hdev);
14304837f64SMarcel Holtmann 
144a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
145e4e8e37cSMarcel Holtmann 	if (conn)
14683985319SHarvey Harrison 		conn->link_policy = get_unaligned_le16(sent + 2);
14704837f64SMarcel Holtmann 
14804837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
1491da177e4SLinus Torvalds }
1501da177e4SLinus Torvalds 
151807deac2SGustavo Padovan static void hci_cc_read_def_link_policy(struct hci_dev *hdev,
152807deac2SGustavo Padovan 					struct sk_buff *skb)
153e4e8e37cSMarcel Holtmann {
154e4e8e37cSMarcel Holtmann 	struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
155e4e8e37cSMarcel Holtmann 
1569f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
157e4e8e37cSMarcel Holtmann 
158e4e8e37cSMarcel Holtmann 	if (rp->status)
159e4e8e37cSMarcel Holtmann 		return;
160e4e8e37cSMarcel Holtmann 
161e4e8e37cSMarcel Holtmann 	hdev->link_policy = __le16_to_cpu(rp->policy);
162e4e8e37cSMarcel Holtmann }
163e4e8e37cSMarcel Holtmann 
164807deac2SGustavo Padovan static void hci_cc_write_def_link_policy(struct hci_dev *hdev,
165807deac2SGustavo Padovan 					 struct sk_buff *skb)
166e4e8e37cSMarcel Holtmann {
167e4e8e37cSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
168e4e8e37cSMarcel Holtmann 	void *sent;
169e4e8e37cSMarcel Holtmann 
1709f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
171e4e8e37cSMarcel Holtmann 
172e4e8e37cSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
173e4e8e37cSMarcel Holtmann 	if (!sent)
174e4e8e37cSMarcel Holtmann 		return;
175e4e8e37cSMarcel Holtmann 
176e4e8e37cSMarcel Holtmann 	if (!status)
177e4e8e37cSMarcel Holtmann 		hdev->link_policy = get_unaligned_le16(sent);
178e4e8e37cSMarcel Holtmann }
179e4e8e37cSMarcel Holtmann 
180a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
1811da177e4SLinus Torvalds {
182a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
183a9de9248SMarcel Holtmann 
1849f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
185a9de9248SMarcel Holtmann 
18610572132SGustavo F. Padovan 	clear_bit(HCI_RESET, &hdev->flags);
18710572132SGustavo F. Padovan 
188a297e97cSJohan Hedberg 	/* Reset all non-persistent flags */
1892cc6fb00SJohan Hedberg 	hdev->dev_flags &= ~HCI_PERSISTENT_MASK;
19069775ff6SAndre Guedes 
19169775ff6SAndre Guedes 	hdev->discovery.state = DISCOVERY_STOPPED;
192bbaf444aSJohan Hedberg 	hdev->inq_tx_power = HCI_TX_POWER_INVALID;
193bbaf444aSJohan Hedberg 	hdev->adv_tx_power = HCI_TX_POWER_INVALID;
1943f0f524bSJohan Hedberg 
1953f0f524bSJohan Hedberg 	memset(hdev->adv_data, 0, sizeof(hdev->adv_data));
1963f0f524bSJohan Hedberg 	hdev->adv_data_len = 0;
197a9de9248SMarcel Holtmann }
198a9de9248SMarcel Holtmann 
199a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
200a9de9248SMarcel Holtmann {
201a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
2021da177e4SLinus Torvalds 	void *sent;
2031da177e4SLinus Torvalds 
2049f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
2051da177e4SLinus Torvalds 
206a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
2071da177e4SLinus Torvalds 	if (!sent)
208a9de9248SMarcel Holtmann 		return;
2091da177e4SLinus Torvalds 
21056e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
21156e5cb86SJohan Hedberg 
212f51d5b24SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
213f51d5b24SJohan Hedberg 		mgmt_set_local_name_complete(hdev, sent, status);
21428cc7bdeSJohan Hedberg 	else if (!status)
21528cc7bdeSJohan Hedberg 		memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
216f51d5b24SJohan Hedberg 
21756e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
218a9de9248SMarcel Holtmann }
219a9de9248SMarcel Holtmann 
220a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
221a9de9248SMarcel Holtmann {
222a9de9248SMarcel Holtmann 	struct hci_rp_read_local_name *rp = (void *) skb->data;
223a9de9248SMarcel Holtmann 
2249f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
225a9de9248SMarcel Holtmann 
226a9de9248SMarcel Holtmann 	if (rp->status)
227a9de9248SMarcel Holtmann 		return;
228a9de9248SMarcel Holtmann 
229db99b5fcSJohan Hedberg 	if (test_bit(HCI_SETUP, &hdev->dev_flags))
2301f6c6378SJohan Hedberg 		memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
231a9de9248SMarcel Holtmann }
232a9de9248SMarcel Holtmann 
233a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
234a9de9248SMarcel Holtmann {
235a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
236a9de9248SMarcel Holtmann 	void *sent;
237a9de9248SMarcel Holtmann 
2389f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
239a9de9248SMarcel Holtmann 
240a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
241a9de9248SMarcel Holtmann 	if (!sent)
242a9de9248SMarcel Holtmann 		return;
2431da177e4SLinus Torvalds 
2441da177e4SLinus Torvalds 	if (!status) {
245a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
246a9de9248SMarcel Holtmann 
2471da177e4SLinus Torvalds 		if (param == AUTH_ENABLED)
2481da177e4SLinus Torvalds 			set_bit(HCI_AUTH, &hdev->flags);
2491da177e4SLinus Torvalds 		else
2501da177e4SLinus Torvalds 			clear_bit(HCI_AUTH, &hdev->flags);
2511da177e4SLinus Torvalds 	}
252a9de9248SMarcel Holtmann 
25333ef95edSJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
25433ef95edSJohan Hedberg 		mgmt_auth_enable_complete(hdev, status);
255a9de9248SMarcel Holtmann }
2561da177e4SLinus Torvalds 
257a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
258a9de9248SMarcel Holtmann {
259a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
260a9de9248SMarcel Holtmann 	void *sent;
261a9de9248SMarcel Holtmann 
2629f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
263a9de9248SMarcel Holtmann 
264a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
2651da177e4SLinus Torvalds 	if (!sent)
266a9de9248SMarcel Holtmann 		return;
2671da177e4SLinus Torvalds 
2681da177e4SLinus Torvalds 	if (!status) {
269a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
270a9de9248SMarcel Holtmann 
2711da177e4SLinus Torvalds 		if (param)
2721da177e4SLinus Torvalds 			set_bit(HCI_ENCRYPT, &hdev->flags);
2731da177e4SLinus Torvalds 		else
2741da177e4SLinus Torvalds 			clear_bit(HCI_ENCRYPT, &hdev->flags);
2751da177e4SLinus Torvalds 	}
2761da177e4SLinus Torvalds }
2771da177e4SLinus Torvalds 
278a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
279a9de9248SMarcel Holtmann {
28036f7fc7eSJohan Hedberg 	__u8 param, status = *((__u8 *) skb->data);
28136f7fc7eSJohan Hedberg 	int old_pscan, old_iscan;
282a9de9248SMarcel Holtmann 	void *sent;
2831da177e4SLinus Torvalds 
2849f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
285a9de9248SMarcel Holtmann 
286a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
2871da177e4SLinus Torvalds 	if (!sent)
288a9de9248SMarcel Holtmann 		return;
2891da177e4SLinus Torvalds 
29036f7fc7eSJohan Hedberg 	param = *((__u8 *) sent);
291a9de9248SMarcel Holtmann 
29256e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
29356e5cb86SJohan Hedberg 
294fa1bd918SMikel Astiz 	if (status) {
295744cf19eSJohan Hedberg 		mgmt_write_scan_failed(hdev, param, status);
2962d7cee58SJohan Hedberg 		hdev->discov_timeout = 0;
2972d7cee58SJohan Hedberg 		goto done;
2982d7cee58SJohan Hedberg 	}
2992d7cee58SJohan Hedberg 
3009fbcbb45SJohan Hedberg 	old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
3019fbcbb45SJohan Hedberg 	old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
302a9de9248SMarcel Holtmann 
30373f22f62SJohan Hedberg 	if (param & SCAN_INQUIRY) {
3041da177e4SLinus Torvalds 		set_bit(HCI_ISCAN, &hdev->flags);
3059fbcbb45SJohan Hedberg 		if (!old_iscan)
306744cf19eSJohan Hedberg 			mgmt_discoverable(hdev, 1);
30716ab91abSJohan Hedberg 		if (hdev->discov_timeout > 0) {
30816ab91abSJohan Hedberg 			int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
30916ab91abSJohan Hedberg 			queue_delayed_work(hdev->workqueue, &hdev->discov_off,
31016ab91abSJohan Hedberg 					   to);
31116ab91abSJohan Hedberg 		}
3129fbcbb45SJohan Hedberg 	} else if (old_iscan)
313744cf19eSJohan Hedberg 		mgmt_discoverable(hdev, 0);
3141da177e4SLinus Torvalds 
3159fbcbb45SJohan Hedberg 	if (param & SCAN_PAGE) {
3161da177e4SLinus Torvalds 		set_bit(HCI_PSCAN, &hdev->flags);
3179fbcbb45SJohan Hedberg 		if (!old_pscan)
318744cf19eSJohan Hedberg 			mgmt_connectable(hdev, 1);
3199fbcbb45SJohan Hedberg 	} else if (old_pscan)
320744cf19eSJohan Hedberg 		mgmt_connectable(hdev, 0);
321a9de9248SMarcel Holtmann 
32236f7fc7eSJohan Hedberg done:
32356e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
3241da177e4SLinus Torvalds }
3251da177e4SLinus Torvalds 
326a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
327a9de9248SMarcel Holtmann {
328a9de9248SMarcel Holtmann 	struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
329a9de9248SMarcel Holtmann 
3309f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
331a9de9248SMarcel Holtmann 
332a9de9248SMarcel Holtmann 	if (rp->status)
333a9de9248SMarcel Holtmann 		return;
334a9de9248SMarcel Holtmann 
335a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, rp->dev_class, 3);
336a9de9248SMarcel Holtmann 
337a9de9248SMarcel Holtmann 	BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
338a9de9248SMarcel Holtmann 	       hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
339a9de9248SMarcel Holtmann }
340a9de9248SMarcel Holtmann 
341a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
342a9de9248SMarcel Holtmann {
343a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
344a9de9248SMarcel Holtmann 	void *sent;
345a9de9248SMarcel Holtmann 
3469f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
347a9de9248SMarcel Holtmann 
348a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
349a9de9248SMarcel Holtmann 	if (!sent)
350a9de9248SMarcel Holtmann 		return;
351a9de9248SMarcel Holtmann 
3527f9a903cSMarcel Holtmann 	hci_dev_lock(hdev);
3537f9a903cSMarcel Holtmann 
3547f9a903cSMarcel Holtmann 	if (status == 0)
355a9de9248SMarcel Holtmann 		memcpy(hdev->dev_class, sent, 3);
3567f9a903cSMarcel Holtmann 
3577f9a903cSMarcel Holtmann 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3587f9a903cSMarcel Holtmann 		mgmt_set_class_of_dev_complete(hdev, sent, status);
3597f9a903cSMarcel Holtmann 
3607f9a903cSMarcel Holtmann 	hci_dev_unlock(hdev);
361a9de9248SMarcel Holtmann }
362a9de9248SMarcel Holtmann 
363a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
364a9de9248SMarcel Holtmann {
365a9de9248SMarcel Holtmann 	struct hci_rp_read_voice_setting *rp = (void *) skb->data;
366a9de9248SMarcel Holtmann 	__u16 setting;
367a9de9248SMarcel Holtmann 
3689f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
369a9de9248SMarcel Holtmann 
370a9de9248SMarcel Holtmann 	if (rp->status)
371a9de9248SMarcel Holtmann 		return;
372a9de9248SMarcel Holtmann 
373a9de9248SMarcel Holtmann 	setting = __le16_to_cpu(rp->voice_setting);
374a9de9248SMarcel Holtmann 
375a9de9248SMarcel Holtmann 	if (hdev->voice_setting == setting)
376a9de9248SMarcel Holtmann 		return;
377a9de9248SMarcel Holtmann 
378a9de9248SMarcel Holtmann 	hdev->voice_setting = setting;
379a9de9248SMarcel Holtmann 
3809f1db00cSAndrei Emeltchenko 	BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
381a9de9248SMarcel Holtmann 
3823c54711cSGustavo F. Padovan 	if (hdev->notify)
383a9de9248SMarcel Holtmann 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
384a9de9248SMarcel Holtmann }
385a9de9248SMarcel Holtmann 
3868fc9ced3SGustavo Padovan static void hci_cc_write_voice_setting(struct hci_dev *hdev,
3878fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
388a9de9248SMarcel Holtmann {
389a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
390f383f275SMarcel Holtmann 	__u16 setting;
391a9de9248SMarcel Holtmann 	void *sent;
392a9de9248SMarcel Holtmann 
3939f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
394a9de9248SMarcel Holtmann 
395f383f275SMarcel Holtmann 	if (status)
396f383f275SMarcel Holtmann 		return;
397f383f275SMarcel Holtmann 
398a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
399a9de9248SMarcel Holtmann 	if (!sent)
400a9de9248SMarcel Holtmann 		return;
401a9de9248SMarcel Holtmann 
402f383f275SMarcel Holtmann 	setting = get_unaligned_le16(sent);
4031da177e4SLinus Torvalds 
404f383f275SMarcel Holtmann 	if (hdev->voice_setting == setting)
405f383f275SMarcel Holtmann 		return;
406f383f275SMarcel Holtmann 
4071da177e4SLinus Torvalds 	hdev->voice_setting = setting;
4081da177e4SLinus Torvalds 
4099f1db00cSAndrei Emeltchenko 	BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
4101da177e4SLinus Torvalds 
4113c54711cSGustavo F. Padovan 	if (hdev->notify)
4121da177e4SLinus Torvalds 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
4131da177e4SLinus Torvalds }
4141da177e4SLinus Torvalds 
415333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
416333140b5SMarcel Holtmann {
417333140b5SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
4185ed8eb2fSJohan Hedberg 	struct hci_cp_write_ssp_mode *sent;
419333140b5SMarcel Holtmann 
4209f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
421333140b5SMarcel Holtmann 
422333140b5SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
423333140b5SMarcel Holtmann 	if (!sent)
424333140b5SMarcel Holtmann 		return;
425333140b5SMarcel Holtmann 
4265ed8eb2fSJohan Hedberg 	if (!status) {
4275ed8eb2fSJohan Hedberg 		if (sent->mode)
428cad718edSJohan Hedberg 			hdev->features[1][0] |= LMP_HOST_SSP;
4295ed8eb2fSJohan Hedberg 		else
430cad718edSJohan Hedberg 			hdev->features[1][0] &= ~LMP_HOST_SSP;
4315ed8eb2fSJohan Hedberg 	}
4325ed8eb2fSJohan Hedberg 
433c0ecddc2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
4345ed8eb2fSJohan Hedberg 		mgmt_ssp_enable_complete(hdev, sent->mode, status);
435c0ecddc2SJohan Hedberg 	else if (!status) {
4365ed8eb2fSJohan Hedberg 		if (sent->mode)
43784bde9d6SJohan Hedberg 			set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
43884bde9d6SJohan Hedberg 		else
43984bde9d6SJohan Hedberg 			clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
440c0ecddc2SJohan Hedberg 	}
441333140b5SMarcel Holtmann }
442333140b5SMarcel Holtmann 
443a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
444a9de9248SMarcel Holtmann {
445a9de9248SMarcel Holtmann 	struct hci_rp_read_local_version *rp = (void *) skb->data;
4461143e5a6SMarcel Holtmann 
4479f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
4481143e5a6SMarcel Holtmann 
449a9de9248SMarcel Holtmann 	if (rp->status)
45042c6b129SJohan Hedberg 		return;
4511143e5a6SMarcel Holtmann 
452a9de9248SMarcel Holtmann 	hdev->hci_ver = rp->hci_ver;
453e4e8e37cSMarcel Holtmann 	hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
454d5859e22SJohan Hedberg 	hdev->lmp_ver = rp->lmp_ver;
455e4e8e37cSMarcel Holtmann 	hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
456d5859e22SJohan Hedberg 	hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
4571da177e4SLinus Torvalds 
4589f1db00cSAndrei Emeltchenko 	BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name,
459807deac2SGustavo Padovan 	       hdev->manufacturer, hdev->hci_ver, hdev->hci_rev);
460d5859e22SJohan Hedberg }
461d5859e22SJohan Hedberg 
4628fc9ced3SGustavo Padovan static void hci_cc_read_local_commands(struct hci_dev *hdev,
4638fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
464a9de9248SMarcel Holtmann {
465a9de9248SMarcel Holtmann 	struct hci_rp_read_local_commands *rp = (void *) skb->data;
466a9de9248SMarcel Holtmann 
4679f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
468a9de9248SMarcel Holtmann 
4692177bab5SJohan Hedberg 	if (!rp->status)
470a9de9248SMarcel Holtmann 		memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
471a9de9248SMarcel Holtmann }
472a9de9248SMarcel Holtmann 
4738fc9ced3SGustavo Padovan static void hci_cc_read_local_features(struct hci_dev *hdev,
4748fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
475a9de9248SMarcel Holtmann {
476a9de9248SMarcel Holtmann 	struct hci_rp_read_local_features *rp = (void *) skb->data;
477a9de9248SMarcel Holtmann 
4789f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
479a9de9248SMarcel Holtmann 
480a9de9248SMarcel Holtmann 	if (rp->status)
481a9de9248SMarcel Holtmann 		return;
482a9de9248SMarcel Holtmann 
483a9de9248SMarcel Holtmann 	memcpy(hdev->features, rp->features, 8);
4841da177e4SLinus Torvalds 
4851da177e4SLinus Torvalds 	/* Adjust default settings according to features
4861da177e4SLinus Torvalds 	 * supported by device. */
487a9de9248SMarcel Holtmann 
488cad718edSJohan Hedberg 	if (hdev->features[0][0] & LMP_3SLOT)
4891da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
4901da177e4SLinus Torvalds 
491cad718edSJohan Hedberg 	if (hdev->features[0][0] & LMP_5SLOT)
4921da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
4931da177e4SLinus Torvalds 
494cad718edSJohan Hedberg 	if (hdev->features[0][1] & LMP_HV2) {
4951da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV2);
4965b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV2);
4975b7f9909SMarcel Holtmann 	}
4981da177e4SLinus Torvalds 
499cad718edSJohan Hedberg 	if (hdev->features[0][1] & LMP_HV3) {
5001da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV3);
5015b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV3);
5025b7f9909SMarcel Holtmann 	}
5035b7f9909SMarcel Holtmann 
50445db810fSAndre Guedes 	if (lmp_esco_capable(hdev))
5055b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV3);
5065b7f9909SMarcel Holtmann 
507cad718edSJohan Hedberg 	if (hdev->features[0][4] & LMP_EV4)
5085b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV4);
5095b7f9909SMarcel Holtmann 
510cad718edSJohan Hedberg 	if (hdev->features[0][4] & LMP_EV5)
5115b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV5);
5121da177e4SLinus Torvalds 
513cad718edSJohan Hedberg 	if (hdev->features[0][5] & LMP_EDR_ESCO_2M)
514efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV3);
515efc7688bSMarcel Holtmann 
516cad718edSJohan Hedberg 	if (hdev->features[0][5] & LMP_EDR_ESCO_3M)
517efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_3EV3);
518efc7688bSMarcel Holtmann 
519cad718edSJohan Hedberg 	if (hdev->features[0][5] & LMP_EDR_3S_ESCO)
520efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
521efc7688bSMarcel Holtmann 
522a9de9248SMarcel Holtmann 	BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
523cad718edSJohan Hedberg 	       hdev->features[0][0], hdev->features[0][1],
524cad718edSJohan Hedberg 	       hdev->features[0][2], hdev->features[0][3],
525cad718edSJohan Hedberg 	       hdev->features[0][4], hdev->features[0][5],
526cad718edSJohan Hedberg 	       hdev->features[0][6], hdev->features[0][7]);
5271da177e4SLinus Torvalds }
5281da177e4SLinus Torvalds 
529971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
530971e3a4bSAndre Guedes 					   struct sk_buff *skb)
531971e3a4bSAndre Guedes {
532971e3a4bSAndre Guedes 	struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
533971e3a4bSAndre Guedes 
5349f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
535971e3a4bSAndre Guedes 
536971e3a4bSAndre Guedes 	if (rp->status)
53742c6b129SJohan Hedberg 		return;
538971e3a4bSAndre Guedes 
539d2c5d77fSJohan Hedberg 	hdev->max_page = rp->max_page;
540d2c5d77fSJohan Hedberg 
541cad718edSJohan Hedberg 	if (rp->page < HCI_MAX_PAGES)
542cad718edSJohan Hedberg 		memcpy(hdev->features[rp->page], rp->features, 8);
543971e3a4bSAndre Guedes }
544971e3a4bSAndre Guedes 
5451e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
5461e89cffbSAndrei Emeltchenko 					  struct sk_buff *skb)
5471e89cffbSAndrei Emeltchenko {
5481e89cffbSAndrei Emeltchenko 	struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
5491e89cffbSAndrei Emeltchenko 
5509f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
5511e89cffbSAndrei Emeltchenko 
55242c6b129SJohan Hedberg 	if (!rp->status)
5531e89cffbSAndrei Emeltchenko 		hdev->flow_ctl_mode = rp->mode;
5541e89cffbSAndrei Emeltchenko }
5551e89cffbSAndrei Emeltchenko 
556a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
557a9de9248SMarcel Holtmann {
558a9de9248SMarcel Holtmann 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
559a9de9248SMarcel Holtmann 
5609f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
561a9de9248SMarcel Holtmann 
562a9de9248SMarcel Holtmann 	if (rp->status)
563a9de9248SMarcel Holtmann 		return;
564a9de9248SMarcel Holtmann 
565a9de9248SMarcel Holtmann 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
566a9de9248SMarcel Holtmann 	hdev->sco_mtu  = rp->sco_mtu;
567a9de9248SMarcel Holtmann 	hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
568a9de9248SMarcel Holtmann 	hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
569da1f5198SMarcel Holtmann 
570da1f5198SMarcel Holtmann 	if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
571da1f5198SMarcel Holtmann 		hdev->sco_mtu  = 64;
572da1f5198SMarcel Holtmann 		hdev->sco_pkts = 8;
573da1f5198SMarcel Holtmann 	}
574da1f5198SMarcel Holtmann 
575da1f5198SMarcel Holtmann 	hdev->acl_cnt = hdev->acl_pkts;
576da1f5198SMarcel Holtmann 	hdev->sco_cnt = hdev->sco_pkts;
5771da177e4SLinus Torvalds 
578807deac2SGustavo Padovan 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
579807deac2SGustavo Padovan 	       hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
5801da177e4SLinus Torvalds }
5811da177e4SLinus Torvalds 
582a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
583a9de9248SMarcel Holtmann {
584a9de9248SMarcel Holtmann 	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
5851da177e4SLinus Torvalds 
5869f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
587a9de9248SMarcel Holtmann 
588a9de9248SMarcel Holtmann 	if (!rp->status)
589a9de9248SMarcel Holtmann 		bacpy(&hdev->bdaddr, &rp->bdaddr);
59023bb5763SJohan Hedberg }
59123bb5763SJohan Hedberg 
592f332ec66SJohan Hedberg static void hci_cc_read_page_scan_activity(struct hci_dev *hdev,
593f332ec66SJohan Hedberg 					   struct sk_buff *skb)
594f332ec66SJohan Hedberg {
595f332ec66SJohan Hedberg 	struct hci_rp_read_page_scan_activity *rp = (void *) skb->data;
596f332ec66SJohan Hedberg 
597f332ec66SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
598f332ec66SJohan Hedberg 
599f332ec66SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags) && !rp->status) {
600f332ec66SJohan Hedberg 		hdev->page_scan_interval = __le16_to_cpu(rp->interval);
601f332ec66SJohan Hedberg 		hdev->page_scan_window = __le16_to_cpu(rp->window);
602f332ec66SJohan Hedberg 	}
603f332ec66SJohan Hedberg }
604f332ec66SJohan Hedberg 
6054a3ee763SJohan Hedberg static void hci_cc_write_page_scan_activity(struct hci_dev *hdev,
6064a3ee763SJohan Hedberg 					    struct sk_buff *skb)
6074a3ee763SJohan Hedberg {
6084a3ee763SJohan Hedberg 	u8 status = *((u8 *) skb->data);
6094a3ee763SJohan Hedberg 	struct hci_cp_write_page_scan_activity *sent;
6104a3ee763SJohan Hedberg 
6114a3ee763SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
6124a3ee763SJohan Hedberg 
6134a3ee763SJohan Hedberg 	if (status)
6144a3ee763SJohan Hedberg 		return;
6154a3ee763SJohan Hedberg 
6164a3ee763SJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY);
6174a3ee763SJohan Hedberg 	if (!sent)
6184a3ee763SJohan Hedberg 		return;
6194a3ee763SJohan Hedberg 
6204a3ee763SJohan Hedberg 	hdev->page_scan_interval = __le16_to_cpu(sent->interval);
6214a3ee763SJohan Hedberg 	hdev->page_scan_window = __le16_to_cpu(sent->window);
6224a3ee763SJohan Hedberg }
6234a3ee763SJohan Hedberg 
624f332ec66SJohan Hedberg static void hci_cc_read_page_scan_type(struct hci_dev *hdev,
625f332ec66SJohan Hedberg 					   struct sk_buff *skb)
626f332ec66SJohan Hedberg {
627f332ec66SJohan Hedberg 	struct hci_rp_read_page_scan_type *rp = (void *) skb->data;
628f332ec66SJohan Hedberg 
629f332ec66SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
630f332ec66SJohan Hedberg 
631f332ec66SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags) && !rp->status)
632f332ec66SJohan Hedberg 		hdev->page_scan_type = rp->type;
633f332ec66SJohan Hedberg }
634f332ec66SJohan Hedberg 
6354a3ee763SJohan Hedberg static void hci_cc_write_page_scan_type(struct hci_dev *hdev,
6364a3ee763SJohan Hedberg 					struct sk_buff *skb)
6374a3ee763SJohan Hedberg {
6384a3ee763SJohan Hedberg 	u8 status = *((u8 *) skb->data);
6394a3ee763SJohan Hedberg 	u8 *type;
6404a3ee763SJohan Hedberg 
6414a3ee763SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
6424a3ee763SJohan Hedberg 
6434a3ee763SJohan Hedberg 	if (status)
6444a3ee763SJohan Hedberg 		return;
6454a3ee763SJohan Hedberg 
6464a3ee763SJohan Hedberg 	type = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE);
6474a3ee763SJohan Hedberg 	if (type)
6484a3ee763SJohan Hedberg 		hdev->page_scan_type = *type;
6494a3ee763SJohan Hedberg }
6504a3ee763SJohan Hedberg 
651350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev,
652350ee4cfSAndrei Emeltchenko 					struct sk_buff *skb)
653350ee4cfSAndrei Emeltchenko {
654350ee4cfSAndrei Emeltchenko 	struct hci_rp_read_data_block_size *rp = (void *) skb->data;
655350ee4cfSAndrei Emeltchenko 
6569f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
657350ee4cfSAndrei Emeltchenko 
658350ee4cfSAndrei Emeltchenko 	if (rp->status)
659350ee4cfSAndrei Emeltchenko 		return;
660350ee4cfSAndrei Emeltchenko 
661350ee4cfSAndrei Emeltchenko 	hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
662350ee4cfSAndrei Emeltchenko 	hdev->block_len = __le16_to_cpu(rp->block_len);
663350ee4cfSAndrei Emeltchenko 	hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
664350ee4cfSAndrei Emeltchenko 
665350ee4cfSAndrei Emeltchenko 	hdev->block_cnt = hdev->num_blocks;
666350ee4cfSAndrei Emeltchenko 
667350ee4cfSAndrei Emeltchenko 	BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
668350ee4cfSAndrei Emeltchenko 	       hdev->block_cnt, hdev->block_len);
669350ee4cfSAndrei Emeltchenko }
670350ee4cfSAndrei Emeltchenko 
671928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
672928abaa7SAndrei Emeltchenko 				       struct sk_buff *skb)
673928abaa7SAndrei Emeltchenko {
674928abaa7SAndrei Emeltchenko 	struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
675928abaa7SAndrei Emeltchenko 
6769f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
677928abaa7SAndrei Emeltchenko 
678928abaa7SAndrei Emeltchenko 	if (rp->status)
6798e2a0d92SAndrei Emeltchenko 		goto a2mp_rsp;
680928abaa7SAndrei Emeltchenko 
681928abaa7SAndrei Emeltchenko 	hdev->amp_status = rp->amp_status;
682928abaa7SAndrei Emeltchenko 	hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
683928abaa7SAndrei Emeltchenko 	hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
684928abaa7SAndrei Emeltchenko 	hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
685928abaa7SAndrei Emeltchenko 	hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
686928abaa7SAndrei Emeltchenko 	hdev->amp_type = rp->amp_type;
687928abaa7SAndrei Emeltchenko 	hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
688928abaa7SAndrei Emeltchenko 	hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
689928abaa7SAndrei Emeltchenko 	hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
690928abaa7SAndrei Emeltchenko 	hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
691928abaa7SAndrei Emeltchenko 
6928e2a0d92SAndrei Emeltchenko a2mp_rsp:
6938e2a0d92SAndrei Emeltchenko 	a2mp_send_getinfo_rsp(hdev);
694928abaa7SAndrei Emeltchenko }
695928abaa7SAndrei Emeltchenko 
696903e4541SAndrei Emeltchenko static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev,
697903e4541SAndrei Emeltchenko 					struct sk_buff *skb)
698903e4541SAndrei Emeltchenko {
699903e4541SAndrei Emeltchenko 	struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data;
700903e4541SAndrei Emeltchenko 	struct amp_assoc *assoc = &hdev->loc_assoc;
701903e4541SAndrei Emeltchenko 	size_t rem_len, frag_len;
702903e4541SAndrei Emeltchenko 
703903e4541SAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
704903e4541SAndrei Emeltchenko 
705903e4541SAndrei Emeltchenko 	if (rp->status)
706903e4541SAndrei Emeltchenko 		goto a2mp_rsp;
707903e4541SAndrei Emeltchenko 
708903e4541SAndrei Emeltchenko 	frag_len = skb->len - sizeof(*rp);
709903e4541SAndrei Emeltchenko 	rem_len = __le16_to_cpu(rp->rem_len);
710903e4541SAndrei Emeltchenko 
711903e4541SAndrei Emeltchenko 	if (rem_len > frag_len) {
7122e430be3SAndrei Emeltchenko 		BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len);
713903e4541SAndrei Emeltchenko 
714903e4541SAndrei Emeltchenko 		memcpy(assoc->data + assoc->offset, rp->frag, frag_len);
715903e4541SAndrei Emeltchenko 		assoc->offset += frag_len;
716903e4541SAndrei Emeltchenko 
717903e4541SAndrei Emeltchenko 		/* Read other fragments */
718903e4541SAndrei Emeltchenko 		amp_read_loc_assoc_frag(hdev, rp->phy_handle);
719903e4541SAndrei Emeltchenko 
720903e4541SAndrei Emeltchenko 		return;
721903e4541SAndrei Emeltchenko 	}
722903e4541SAndrei Emeltchenko 
723903e4541SAndrei Emeltchenko 	memcpy(assoc->data + assoc->offset, rp->frag, rem_len);
724903e4541SAndrei Emeltchenko 	assoc->len = assoc->offset + rem_len;
725903e4541SAndrei Emeltchenko 	assoc->offset = 0;
726903e4541SAndrei Emeltchenko 
727903e4541SAndrei Emeltchenko a2mp_rsp:
728903e4541SAndrei Emeltchenko 	/* Send A2MP Rsp when all fragments are received */
729903e4541SAndrei Emeltchenko 	a2mp_send_getampassoc_rsp(hdev, rp->status);
7309495b2eeSAndrei Emeltchenko 	a2mp_send_create_phy_link_req(hdev, rp->status);
731903e4541SAndrei Emeltchenko }
732903e4541SAndrei Emeltchenko 
733d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
734d5859e22SJohan Hedberg 					 struct sk_buff *skb)
735d5859e22SJohan Hedberg {
73691c4e9b1SMarcel Holtmann 	struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
737d5859e22SJohan Hedberg 
7389f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
739d5859e22SJohan Hedberg 
74091c4e9b1SMarcel Holtmann 	if (!rp->status)
74191c4e9b1SMarcel Holtmann 		hdev->inq_tx_power = rp->tx_power;
742d5859e22SJohan Hedberg }
743d5859e22SJohan Hedberg 
744980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
745980e1a53SJohan Hedberg {
746980e1a53SJohan Hedberg 	struct hci_rp_pin_code_reply *rp = (void *) skb->data;
747980e1a53SJohan Hedberg 	struct hci_cp_pin_code_reply *cp;
748980e1a53SJohan Hedberg 	struct hci_conn *conn;
749980e1a53SJohan Hedberg 
7509f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
751980e1a53SJohan Hedberg 
75256e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
75356e5cb86SJohan Hedberg 
754a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
755744cf19eSJohan Hedberg 		mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
756980e1a53SJohan Hedberg 
757fa1bd918SMikel Astiz 	if (rp->status)
75856e5cb86SJohan Hedberg 		goto unlock;
759980e1a53SJohan Hedberg 
760980e1a53SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
761980e1a53SJohan Hedberg 	if (!cp)
76256e5cb86SJohan Hedberg 		goto unlock;
763980e1a53SJohan Hedberg 
764980e1a53SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
765980e1a53SJohan Hedberg 	if (conn)
766980e1a53SJohan Hedberg 		conn->pin_length = cp->pin_len;
76756e5cb86SJohan Hedberg 
76856e5cb86SJohan Hedberg unlock:
76956e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
770980e1a53SJohan Hedberg }
771980e1a53SJohan Hedberg 
772980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
773980e1a53SJohan Hedberg {
774980e1a53SJohan Hedberg 	struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
775980e1a53SJohan Hedberg 
7769f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
777980e1a53SJohan Hedberg 
77856e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
77956e5cb86SJohan Hedberg 
780a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
781744cf19eSJohan Hedberg 		mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
782980e1a53SJohan Hedberg 						 rp->status);
78356e5cb86SJohan Hedberg 
78456e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
785980e1a53SJohan Hedberg }
78656e5cb86SJohan Hedberg 
7876ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
7886ed58ec5SVille Tervo 				       struct sk_buff *skb)
7896ed58ec5SVille Tervo {
7906ed58ec5SVille Tervo 	struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
7916ed58ec5SVille Tervo 
7929f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
7936ed58ec5SVille Tervo 
7946ed58ec5SVille Tervo 	if (rp->status)
7956ed58ec5SVille Tervo 		return;
7966ed58ec5SVille Tervo 
7976ed58ec5SVille Tervo 	hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
7986ed58ec5SVille Tervo 	hdev->le_pkts = rp->le_max_pkt;
7996ed58ec5SVille Tervo 
8006ed58ec5SVille Tervo 	hdev->le_cnt = hdev->le_pkts;
8016ed58ec5SVille Tervo 
8026ed58ec5SVille Tervo 	BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
8036ed58ec5SVille Tervo }
804980e1a53SJohan Hedberg 
80560e77321SJohan Hedberg static void hci_cc_le_read_local_features(struct hci_dev *hdev,
80660e77321SJohan Hedberg 					  struct sk_buff *skb)
80760e77321SJohan Hedberg {
80860e77321SJohan Hedberg 	struct hci_rp_le_read_local_features *rp = (void *) skb->data;
80960e77321SJohan Hedberg 
81060e77321SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
81160e77321SJohan Hedberg 
81260e77321SJohan Hedberg 	if (!rp->status)
81360e77321SJohan Hedberg 		memcpy(hdev->le_features, rp->features, 8);
81460e77321SJohan Hedberg }
81560e77321SJohan Hedberg 
8168fa19098SJohan Hedberg static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
8178fa19098SJohan Hedberg 					struct sk_buff *skb)
8188fa19098SJohan Hedberg {
8198fa19098SJohan Hedberg 	struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data;
8208fa19098SJohan Hedberg 
8218fa19098SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
8228fa19098SJohan Hedberg 
82304b4edcbSJohan Hedberg 	if (!rp->status)
8248fa19098SJohan Hedberg 		hdev->adv_tx_power = rp->tx_power;
8258fa19098SJohan Hedberg }
8268fa19098SJohan Hedberg 
827a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
828a5c29683SJohan Hedberg {
829a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
830a5c29683SJohan Hedberg 
8319f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
832a5c29683SJohan Hedberg 
83356e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
83456e5cb86SJohan Hedberg 
835a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
83604124681SGustavo F. Padovan 		mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
83704124681SGustavo F. Padovan 						 rp->status);
83856e5cb86SJohan Hedberg 
83956e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
840a5c29683SJohan Hedberg }
841a5c29683SJohan Hedberg 
842a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
843a5c29683SJohan Hedberg 					  struct sk_buff *skb)
844a5c29683SJohan Hedberg {
845a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
846a5c29683SJohan Hedberg 
8479f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
848a5c29683SJohan Hedberg 
84956e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
85056e5cb86SJohan Hedberg 
851a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
852744cf19eSJohan Hedberg 		mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
85304124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
85456e5cb86SJohan Hedberg 
85556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
856a5c29683SJohan Hedberg }
857a5c29683SJohan Hedberg 
8581143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
8591143d458SBrian Gix {
8601143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
8611143d458SBrian Gix 
8629f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
8631143d458SBrian Gix 
8641143d458SBrian Gix 	hci_dev_lock(hdev);
8651143d458SBrian Gix 
866a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
867272d90dfSJohan Hedberg 		mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
868272d90dfSJohan Hedberg 						 0, rp->status);
8691143d458SBrian Gix 
8701143d458SBrian Gix 	hci_dev_unlock(hdev);
8711143d458SBrian Gix }
8721143d458SBrian Gix 
8731143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
8741143d458SBrian Gix 					  struct sk_buff *skb)
8751143d458SBrian Gix {
8761143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
8771143d458SBrian Gix 
8789f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
8791143d458SBrian Gix 
8801143d458SBrian Gix 	hci_dev_lock(hdev);
8811143d458SBrian Gix 
882a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
8831143d458SBrian Gix 		mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
88404124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
8851143d458SBrian Gix 
8861143d458SBrian Gix 	hci_dev_unlock(hdev);
8871143d458SBrian Gix }
8881143d458SBrian Gix 
889c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
890c35938b2SSzymon Janc 					     struct sk_buff *skb)
891c35938b2SSzymon Janc {
892c35938b2SSzymon Janc 	struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
893c35938b2SSzymon Janc 
8949f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
895c35938b2SSzymon Janc 
89656e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
897744cf19eSJohan Hedberg 	mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
898c35938b2SSzymon Janc 						rp->randomizer, rp->status);
89956e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
900c35938b2SSzymon Janc }
901c35938b2SSzymon Janc 
902c1d5dc4aSJohan Hedberg static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
903c1d5dc4aSJohan Hedberg {
904c1d5dc4aSJohan Hedberg 	__u8 *sent, status = *((__u8 *) skb->data);
905c1d5dc4aSJohan Hedberg 
906c1d5dc4aSJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
907c1d5dc4aSJohan Hedberg 
908c1d5dc4aSJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE);
909c1d5dc4aSJohan Hedberg 	if (!sent)
910c1d5dc4aSJohan Hedberg 		return;
911c1d5dc4aSJohan Hedberg 
912c1d5dc4aSJohan Hedberg 	hci_dev_lock(hdev);
913c1d5dc4aSJohan Hedberg 
914c1d5dc4aSJohan Hedberg 	if (!status) {
915c1d5dc4aSJohan Hedberg 		if (*sent)
916c1d5dc4aSJohan Hedberg 			set_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
917c1d5dc4aSJohan Hedberg 		else
918c1d5dc4aSJohan Hedberg 			clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
919c1d5dc4aSJohan Hedberg 	}
920c1d5dc4aSJohan Hedberg 
92104b4edcbSJohan Hedberg 	if (!test_bit(HCI_INIT, &hdev->flags)) {
92204b4edcbSJohan Hedberg 		struct hci_request req;
923c1d5dc4aSJohan Hedberg 
92404b4edcbSJohan Hedberg 		hci_req_init(&req, hdev);
92504b4edcbSJohan Hedberg 		hci_update_ad(&req);
92604b4edcbSJohan Hedberg 		hci_req_run(&req, NULL);
92704b4edcbSJohan Hedberg 	}
92804b4edcbSJohan Hedberg 
92904b4edcbSJohan Hedberg 	hci_dev_unlock(hdev);
930c1d5dc4aSJohan Hedberg }
931c1d5dc4aSJohan Hedberg 
932eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
933eb9d91f5SAndre Guedes 				      struct sk_buff *skb)
934eb9d91f5SAndre Guedes {
935eb9d91f5SAndre Guedes 	struct hci_cp_le_set_scan_enable *cp;
936eb9d91f5SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
937eb9d91f5SAndre Guedes 
9389f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
939eb9d91f5SAndre Guedes 
940eb9d91f5SAndre Guedes 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
941eb9d91f5SAndre Guedes 	if (!cp)
942eb9d91f5SAndre Guedes 		return;
943eb9d91f5SAndre Guedes 
944fef5234aSAndre Guedes 	if (status)
9457ba8b4beSAndre Guedes 		return;
9467ba8b4beSAndre Guedes 
9473fd319b8SAndre Guedes 	switch (cp->enable) {
9483fd319b8SAndre Guedes 	case LE_SCAN_ENABLE:
949d23264a8SAndre Guedes 		set_bit(HCI_LE_SCAN, &hdev->dev_flags);
95068a8aea4SAndrei Emeltchenko 		break;
95168a8aea4SAndrei Emeltchenko 
95276a388beSAndre Guedes 	case LE_SCAN_DISABLE:
953d23264a8SAndre Guedes 		clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
95468a8aea4SAndrei Emeltchenko 		break;
95568a8aea4SAndrei Emeltchenko 
95668a8aea4SAndrei Emeltchenko 	default:
95768a8aea4SAndrei Emeltchenko 		BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
95868a8aea4SAndrei Emeltchenko 		break;
95935815085SAndre Guedes 	}
960eb9d91f5SAndre Guedes }
961eb9d91f5SAndre Guedes 
962cf1d081fSJohan Hedberg static void hci_cc_le_read_white_list_size(struct hci_dev *hdev,
963cf1d081fSJohan Hedberg 					   struct sk_buff *skb)
964cf1d081fSJohan Hedberg {
965cf1d081fSJohan Hedberg 	struct hci_rp_le_read_white_list_size *rp = (void *) skb->data;
966cf1d081fSJohan Hedberg 
967cf1d081fSJohan Hedberg 	BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size);
968cf1d081fSJohan Hedberg 
969cf1d081fSJohan Hedberg 	if (!rp->status)
970cf1d081fSJohan Hedberg 		hdev->le_white_list_size = rp->size;
971cf1d081fSJohan Hedberg }
972cf1d081fSJohan Hedberg 
9739b008c04SJohan Hedberg static void hci_cc_le_read_supported_states(struct hci_dev *hdev,
9749b008c04SJohan Hedberg 					    struct sk_buff *skb)
9759b008c04SJohan Hedberg {
9769b008c04SJohan Hedberg 	struct hci_rp_le_read_supported_states *rp = (void *) skb->data;
9779b008c04SJohan Hedberg 
9789b008c04SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
9799b008c04SJohan Hedberg 
9809b008c04SJohan Hedberg 	if (!rp->status)
9819b008c04SJohan Hedberg 		memcpy(hdev->le_states, rp->le_states, 8);
9829b008c04SJohan Hedberg }
9839b008c04SJohan Hedberg 
9846039aa73SGustavo Padovan static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
985f9b49306SAndre Guedes 					   struct sk_buff *skb)
986f9b49306SAndre Guedes {
98706199cf8SJohan Hedberg 	struct hci_cp_write_le_host_supported *sent;
988f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
989f9b49306SAndre Guedes 
9909f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
991f9b49306SAndre Guedes 
99206199cf8SJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
9938f984dfaSJohan Hedberg 	if (!sent)
994f9b49306SAndre Guedes 		return;
995f9b49306SAndre Guedes 
9968f984dfaSJohan Hedberg 	if (!status) {
9978f984dfaSJohan Hedberg 		if (sent->le)
998cad718edSJohan Hedberg 			hdev->features[1][0] |= LMP_HOST_LE;
9998f984dfaSJohan Hedberg 		else
1000cad718edSJohan Hedberg 			hdev->features[1][0] &= ~LMP_HOST_LE;
100153b2caabSJohan Hedberg 
100253b2caabSJohan Hedberg 		if (sent->simul)
1003cad718edSJohan Hedberg 			hdev->features[1][0] |= LMP_HOST_LE_BREDR;
100453b2caabSJohan Hedberg 		else
1005cad718edSJohan Hedberg 			hdev->features[1][0] &= ~LMP_HOST_LE_BREDR;
10068f984dfaSJohan Hedberg 	}
10078f984dfaSJohan Hedberg 
10088f984dfaSJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
10098f984dfaSJohan Hedberg 	    !test_bit(HCI_INIT, &hdev->flags))
10108f984dfaSJohan Hedberg 		mgmt_le_enable_complete(hdev, sent->le, status);
1011f9b49306SAndre Guedes }
1012f9b49306SAndre Guedes 
101393c284eeSAndrei Emeltchenko static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
101493c284eeSAndrei Emeltchenko 					  struct sk_buff *skb)
101593c284eeSAndrei Emeltchenko {
101693c284eeSAndrei Emeltchenko 	struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data;
101793c284eeSAndrei Emeltchenko 
101893c284eeSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
101993c284eeSAndrei Emeltchenko 	       hdev->name, rp->status, rp->phy_handle);
102093c284eeSAndrei Emeltchenko 
102193c284eeSAndrei Emeltchenko 	if (rp->status)
102293c284eeSAndrei Emeltchenko 		return;
102393c284eeSAndrei Emeltchenko 
102493c284eeSAndrei Emeltchenko 	amp_write_rem_assoc_continue(hdev, rp->phy_handle);
102593c284eeSAndrei Emeltchenko }
102693c284eeSAndrei Emeltchenko 
10276039aa73SGustavo Padovan static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1028a9de9248SMarcel Holtmann {
10299f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1030a9de9248SMarcel Holtmann 
1031a9de9248SMarcel Holtmann 	if (status) {
1032a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
1033314b2381SJohan Hedberg 		return;
1034314b2381SJohan Hedberg 	}
1035314b2381SJohan Hedberg 
103689352e7dSAndre Guedes 	set_bit(HCI_INQUIRY, &hdev->flags);
1037a9de9248SMarcel Holtmann }
1038a9de9248SMarcel Holtmann 
10396039aa73SGustavo Padovan static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
10401da177e4SLinus Torvalds {
1041a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
10421da177e4SLinus Torvalds 	struct hci_conn *conn;
10431da177e4SLinus Torvalds 
10449f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1045a9de9248SMarcel Holtmann 
1046a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
10471da177e4SLinus Torvalds 	if (!cp)
10481da177e4SLinus Torvalds 		return;
10491da177e4SLinus Torvalds 
10501da177e4SLinus Torvalds 	hci_dev_lock(hdev);
10511da177e4SLinus Torvalds 
10521da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
10531da177e4SLinus Torvalds 
10546ed93dc6SAndrei Emeltchenko 	BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn);
10551da177e4SLinus Torvalds 
10561da177e4SLinus Torvalds 	if (status) {
10571da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
10584c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
10591da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
10601da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
10611da177e4SLinus Torvalds 				hci_conn_del(conn);
10624c67bc74SMarcel Holtmann 			} else
10634c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
10641da177e4SLinus Torvalds 		}
10651da177e4SLinus Torvalds 	} else {
10661da177e4SLinus Torvalds 		if (!conn) {
10671da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
10681da177e4SLinus Torvalds 			if (conn) {
1069a0c808b3SJohan Hedberg 				conn->out = true;
10701da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
10711da177e4SLinus Torvalds 			} else
1072893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
10731da177e4SLinus Torvalds 		}
10741da177e4SLinus Torvalds 	}
10751da177e4SLinus Torvalds 
10761da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
10771da177e4SLinus Torvalds }
10781da177e4SLinus Torvalds 
1079a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
10801da177e4SLinus Torvalds {
1081a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
10821da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
10831da177e4SLinus Torvalds 	__u16 handle;
10841da177e4SLinus Torvalds 
10859f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1086b6a0dc82SMarcel Holtmann 
1087a9de9248SMarcel Holtmann 	if (!status)
1088a9de9248SMarcel Holtmann 		return;
1089a9de9248SMarcel Holtmann 
1090a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
10911da177e4SLinus Torvalds 	if (!cp)
1092a9de9248SMarcel Holtmann 		return;
10931da177e4SLinus Torvalds 
10941da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
10951da177e4SLinus Torvalds 
10969f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
10971da177e4SLinus Torvalds 
10981da177e4SLinus Torvalds 	hci_dev_lock(hdev);
10991da177e4SLinus Torvalds 
11001da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
11015a08ecceSAndrei Emeltchenko 	if (acl) {
11025a08ecceSAndrei Emeltchenko 		sco = acl->link;
11035a08ecceSAndrei Emeltchenko 		if (sco) {
11041da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
11051da177e4SLinus Torvalds 
11061da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
11071da177e4SLinus Torvalds 			hci_conn_del(sco);
11081da177e4SLinus Torvalds 		}
11095a08ecceSAndrei Emeltchenko 	}
11101da177e4SLinus Torvalds 
11111da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
11121da177e4SLinus Torvalds }
11131da177e4SLinus Torvalds 
1114f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1115f8558555SMarcel Holtmann {
1116f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1117f8558555SMarcel Holtmann 	struct hci_conn *conn;
1118f8558555SMarcel Holtmann 
11199f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1120f8558555SMarcel Holtmann 
1121f8558555SMarcel Holtmann 	if (!status)
1122f8558555SMarcel Holtmann 		return;
1123f8558555SMarcel Holtmann 
1124f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1125f8558555SMarcel Holtmann 	if (!cp)
1126f8558555SMarcel Holtmann 		return;
1127f8558555SMarcel Holtmann 
1128f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1129f8558555SMarcel Holtmann 
1130f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1131f8558555SMarcel Holtmann 	if (conn) {
1132f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1133f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
113476a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1135f8558555SMarcel Holtmann 		}
1136f8558555SMarcel Holtmann 	}
1137f8558555SMarcel Holtmann 
1138f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1139f8558555SMarcel Holtmann }
1140f8558555SMarcel Holtmann 
1141f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1142f8558555SMarcel Holtmann {
1143f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1144f8558555SMarcel Holtmann 	struct hci_conn *conn;
1145f8558555SMarcel Holtmann 
11469f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1147f8558555SMarcel Holtmann 
1148f8558555SMarcel Holtmann 	if (!status)
1149f8558555SMarcel Holtmann 		return;
1150f8558555SMarcel Holtmann 
1151f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1152f8558555SMarcel Holtmann 	if (!cp)
1153f8558555SMarcel Holtmann 		return;
1154f8558555SMarcel Holtmann 
1155f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1156f8558555SMarcel Holtmann 
1157f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1158f8558555SMarcel Holtmann 	if (conn) {
1159f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1160f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
116176a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1162f8558555SMarcel Holtmann 		}
1163f8558555SMarcel Holtmann 	}
1164f8558555SMarcel Holtmann 
1165f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1166f8558555SMarcel Holtmann }
1167f8558555SMarcel Holtmann 
1168127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1169392599b9SJohan Hedberg 				    struct hci_conn *conn)
1170392599b9SJohan Hedberg {
1171392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1172392599b9SJohan Hedberg 		return 0;
1173392599b9SJohan Hedberg 
1174765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1175392599b9SJohan Hedberg 		return 0;
1176392599b9SJohan Hedberg 
1177392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1178e9bf2bf0SVinicius Costa Gomes 	 * devices with sec_level HIGH or if MITM protection is requested */
1179807deac2SGustavo Padovan 	if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
1180807deac2SGustavo Padovan 	    conn->pending_sec_level != BT_SECURITY_HIGH)
1181392599b9SJohan Hedberg 		return 0;
1182392599b9SJohan Hedberg 
1183392599b9SJohan Hedberg 	return 1;
1184392599b9SJohan Hedberg }
1185392599b9SJohan Hedberg 
11866039aa73SGustavo Padovan static int hci_resolve_name(struct hci_dev *hdev,
118700abfe44SGustavo F. Padovan 				   struct inquiry_entry *e)
118830dc78e1SJohan Hedberg {
118930dc78e1SJohan Hedberg 	struct hci_cp_remote_name_req cp;
119030dc78e1SJohan Hedberg 
119130dc78e1SJohan Hedberg 	memset(&cp, 0, sizeof(cp));
119230dc78e1SJohan Hedberg 
119330dc78e1SJohan Hedberg 	bacpy(&cp.bdaddr, &e->data.bdaddr);
119430dc78e1SJohan Hedberg 	cp.pscan_rep_mode = e->data.pscan_rep_mode;
119530dc78e1SJohan Hedberg 	cp.pscan_mode = e->data.pscan_mode;
119630dc78e1SJohan Hedberg 	cp.clock_offset = e->data.clock_offset;
119730dc78e1SJohan Hedberg 
119830dc78e1SJohan Hedberg 	return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
119930dc78e1SJohan Hedberg }
120030dc78e1SJohan Hedberg 
1201b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev)
120230dc78e1SJohan Hedberg {
120330dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
120430dc78e1SJohan Hedberg 	struct inquiry_entry *e;
120530dc78e1SJohan Hedberg 
1206b644ba33SJohan Hedberg 	if (list_empty(&discov->resolve))
1207b644ba33SJohan Hedberg 		return false;
1208b644ba33SJohan Hedberg 
1209b644ba33SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1210c810089cSRam Malovany 	if (!e)
1211c810089cSRam Malovany 		return false;
1212c810089cSRam Malovany 
1213b644ba33SJohan Hedberg 	if (hci_resolve_name(hdev, e) == 0) {
1214b644ba33SJohan Hedberg 		e->name_state = NAME_PENDING;
1215b644ba33SJohan Hedberg 		return true;
1216b644ba33SJohan Hedberg 	}
1217b644ba33SJohan Hedberg 
1218b644ba33SJohan Hedberg 	return false;
1219b644ba33SJohan Hedberg }
1220b644ba33SJohan Hedberg 
1221b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
1222b644ba33SJohan Hedberg 				   bdaddr_t *bdaddr, u8 *name, u8 name_len)
1223b644ba33SJohan Hedberg {
1224b644ba33SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
1225b644ba33SJohan Hedberg 	struct inquiry_entry *e;
1226b644ba33SJohan Hedberg 
1227b644ba33SJohan Hedberg 	if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
122804124681SGustavo F. Padovan 		mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
122904124681SGustavo F. Padovan 				      name_len, conn->dev_class);
1230b644ba33SJohan Hedberg 
1231b644ba33SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPED)
1232b644ba33SJohan Hedberg 		return;
1233b644ba33SJohan Hedberg 
123430dc78e1SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPING)
123530dc78e1SJohan Hedberg 		goto discov_complete;
123630dc78e1SJohan Hedberg 
123730dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_RESOLVING)
123830dc78e1SJohan Hedberg 		return;
123930dc78e1SJohan Hedberg 
124030dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
12417cc8380eSRam Malovany 	/* If the device was not found in a list of found devices names of which
12427cc8380eSRam Malovany 	 * are pending. there is no need to continue resolving a next name as it
12437cc8380eSRam Malovany 	 * will be done upon receiving another Remote Name Request Complete
12447cc8380eSRam Malovany 	 * Event */
12457cc8380eSRam Malovany 	if (!e)
12467cc8380eSRam Malovany 		return;
12477cc8380eSRam Malovany 
124830dc78e1SJohan Hedberg 	list_del(&e->list);
12497cc8380eSRam Malovany 	if (name) {
12507cc8380eSRam Malovany 		e->name_state = NAME_KNOWN;
1251b644ba33SJohan Hedberg 		mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1252b644ba33SJohan Hedberg 				 e->data.rssi, name, name_len);
1253c3e7c0d9SRam Malovany 	} else {
1254c3e7c0d9SRam Malovany 		e->name_state = NAME_NOT_KNOWN;
125530dc78e1SJohan Hedberg 	}
125630dc78e1SJohan Hedberg 
1257b644ba33SJohan Hedberg 	if (hci_resolve_next_name(hdev))
125830dc78e1SJohan Hedberg 		return;
125930dc78e1SJohan Hedberg 
126030dc78e1SJohan Hedberg discov_complete:
126130dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
126230dc78e1SJohan Hedberg }
126330dc78e1SJohan Hedberg 
1264a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
12651da177e4SLinus Torvalds {
1266127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1267127178d2SJohan Hedberg 	struct hci_conn *conn;
1268127178d2SJohan Hedberg 
12699f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1270127178d2SJohan Hedberg 
1271127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1272127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1273127178d2SJohan Hedberg 	if (!status)
1274127178d2SJohan Hedberg 		return;
1275127178d2SJohan Hedberg 
1276127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1277127178d2SJohan Hedberg 	if (!cp)
1278127178d2SJohan Hedberg 		return;
1279127178d2SJohan Hedberg 
1280127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1281127178d2SJohan Hedberg 
1282127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1283b644ba33SJohan Hedberg 
1284b644ba33SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1285b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1286b644ba33SJohan Hedberg 
128779c6c70cSJohan Hedberg 	if (!conn)
128879c6c70cSJohan Hedberg 		goto unlock;
128979c6c70cSJohan Hedberg 
129079c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
129179c6c70cSJohan Hedberg 		goto unlock;
129279c6c70cSJohan Hedberg 
129351a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1294127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1295127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1296127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1297127178d2SJohan Hedberg 	}
1298127178d2SJohan Hedberg 
129979c6c70cSJohan Hedberg unlock:
1300127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1301a9de9248SMarcel Holtmann }
13021da177e4SLinus Torvalds 
1303769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1304769be974SMarcel Holtmann {
1305769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1306769be974SMarcel Holtmann 	struct hci_conn *conn;
1307769be974SMarcel Holtmann 
13089f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1309769be974SMarcel Holtmann 
1310769be974SMarcel Holtmann 	if (!status)
1311769be974SMarcel Holtmann 		return;
1312769be974SMarcel Holtmann 
1313769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1314769be974SMarcel Holtmann 	if (!cp)
1315769be974SMarcel Holtmann 		return;
1316769be974SMarcel Holtmann 
1317769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1318769be974SMarcel Holtmann 
1319769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1320769be974SMarcel Holtmann 	if (conn) {
1321769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1322769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
132376a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1324769be974SMarcel Holtmann 		}
1325769be974SMarcel Holtmann 	}
1326769be974SMarcel Holtmann 
1327769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1328769be974SMarcel Holtmann }
1329769be974SMarcel Holtmann 
1330769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1331769be974SMarcel Holtmann {
1332769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1333769be974SMarcel Holtmann 	struct hci_conn *conn;
1334769be974SMarcel Holtmann 
13359f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1336769be974SMarcel Holtmann 
1337769be974SMarcel Holtmann 	if (!status)
1338769be974SMarcel Holtmann 		return;
1339769be974SMarcel Holtmann 
1340769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1341769be974SMarcel Holtmann 	if (!cp)
1342769be974SMarcel Holtmann 		return;
1343769be974SMarcel Holtmann 
1344769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1345769be974SMarcel Holtmann 
1346769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1347769be974SMarcel Holtmann 	if (conn) {
1348769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1349769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
135076a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1351769be974SMarcel Holtmann 		}
1352769be974SMarcel Holtmann 	}
1353769be974SMarcel Holtmann 
1354769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1355769be974SMarcel Holtmann }
1356769be974SMarcel Holtmann 
1357a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1358a9de9248SMarcel Holtmann {
1359b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1360b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1361b6a0dc82SMarcel Holtmann 	__u16 handle;
1362b6a0dc82SMarcel Holtmann 
13639f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1364b6a0dc82SMarcel Holtmann 
1365b6a0dc82SMarcel Holtmann 	if (!status)
1366b6a0dc82SMarcel Holtmann 		return;
1367b6a0dc82SMarcel Holtmann 
1368b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1369b6a0dc82SMarcel Holtmann 	if (!cp)
1370b6a0dc82SMarcel Holtmann 		return;
1371b6a0dc82SMarcel Holtmann 
1372b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1373b6a0dc82SMarcel Holtmann 
13749f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
1375b6a0dc82SMarcel Holtmann 
1376b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1377b6a0dc82SMarcel Holtmann 
1378b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
13795a08ecceSAndrei Emeltchenko 	if (acl) {
13805a08ecceSAndrei Emeltchenko 		sco = acl->link;
13815a08ecceSAndrei Emeltchenko 		if (sco) {
1382b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1383b6a0dc82SMarcel Holtmann 
1384b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1385b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1386b6a0dc82SMarcel Holtmann 		}
13875a08ecceSAndrei Emeltchenko 	}
1388b6a0dc82SMarcel Holtmann 
1389b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1390a9de9248SMarcel Holtmann }
1391a9de9248SMarcel Holtmann 
1392a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1393a9de9248SMarcel Holtmann {
1394a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
139504837f64SMarcel Holtmann 	struct hci_conn *conn;
139604837f64SMarcel Holtmann 
13979f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1398a9de9248SMarcel Holtmann 
1399a9de9248SMarcel Holtmann 	if (!status)
1400a9de9248SMarcel Holtmann 		return;
1401a9de9248SMarcel Holtmann 
1402a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
140304837f64SMarcel Holtmann 	if (!cp)
1404a9de9248SMarcel Holtmann 		return;
140504837f64SMarcel Holtmann 
140604837f64SMarcel Holtmann 	hci_dev_lock(hdev);
140704837f64SMarcel Holtmann 
140804837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1409e73439d8SMarcel Holtmann 	if (conn) {
141051a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
141104837f64SMarcel Holtmann 
141251a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1413e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1414e73439d8SMarcel Holtmann 	}
1415e73439d8SMarcel Holtmann 
141604837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
141704837f64SMarcel Holtmann }
141804837f64SMarcel Holtmann 
1419a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1420a9de9248SMarcel Holtmann {
1421a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
142204837f64SMarcel Holtmann 	struct hci_conn *conn;
142304837f64SMarcel Holtmann 
14249f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1425a9de9248SMarcel Holtmann 
1426a9de9248SMarcel Holtmann 	if (!status)
1427a9de9248SMarcel Holtmann 		return;
1428a9de9248SMarcel Holtmann 
1429a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
143004837f64SMarcel Holtmann 	if (!cp)
1431a9de9248SMarcel Holtmann 		return;
143204837f64SMarcel Holtmann 
143304837f64SMarcel Holtmann 	hci_dev_lock(hdev);
143404837f64SMarcel Holtmann 
143504837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1436e73439d8SMarcel Holtmann 	if (conn) {
143751a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
143804837f64SMarcel Holtmann 
143951a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1440e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1441e73439d8SMarcel Holtmann 	}
1442e73439d8SMarcel Holtmann 
144304837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
144404837f64SMarcel Holtmann }
144504837f64SMarcel Holtmann 
144688c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
144788c3df13SJohan Hedberg {
144888c3df13SJohan Hedberg 	struct hci_cp_disconnect *cp;
144988c3df13SJohan Hedberg 	struct hci_conn *conn;
145088c3df13SJohan Hedberg 
145188c3df13SJohan Hedberg 	if (!status)
145288c3df13SJohan Hedberg 		return;
145388c3df13SJohan Hedberg 
145488c3df13SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
145588c3df13SJohan Hedberg 	if (!cp)
145688c3df13SJohan Hedberg 		return;
145788c3df13SJohan Hedberg 
145888c3df13SJohan Hedberg 	hci_dev_lock(hdev);
145988c3df13SJohan Hedberg 
146088c3df13SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
146188c3df13SJohan Hedberg 	if (conn)
146288c3df13SJohan Hedberg 		mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
146388c3df13SJohan Hedberg 				       conn->dst_type, status);
146488c3df13SJohan Hedberg 
146588c3df13SJohan Hedberg 	hci_dev_unlock(hdev);
146688c3df13SJohan Hedberg }
146788c3df13SJohan Hedberg 
1468fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1469fcd89c09SVille Tervo {
1470fcd89c09SVille Tervo 	struct hci_conn *conn;
1471fcd89c09SVille Tervo 
14729f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1473fcd89c09SVille Tervo 
1474f00a06acSAndre Guedes 	if (status) {
1475fcd89c09SVille Tervo 		hci_dev_lock(hdev);
1476fcd89c09SVille Tervo 
14770c95ab78SAndre Guedes 		conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
1478f00a06acSAndre Guedes 		if (!conn) {
1479f00a06acSAndre Guedes 			hci_dev_unlock(hdev);
1480f00a06acSAndre Guedes 			return;
1481f00a06acSAndre Guedes 		}
1482fcd89c09SVille Tervo 
14836ed93dc6SAndrei Emeltchenko 		BT_DBG("%s bdaddr %pMR conn %p", hdev->name, &conn->dst, conn);
1484fcd89c09SVille Tervo 
1485fcd89c09SVille Tervo 		conn->state = BT_CLOSED;
14860c95ab78SAndre Guedes 		mgmt_connect_failed(hdev, &conn->dst, conn->type,
1487328c9248SHemant Gupta 				    conn->dst_type, status);
1488fcd89c09SVille Tervo 		hci_proto_connect_cfm(conn, status);
1489fcd89c09SVille Tervo 		hci_conn_del(conn);
1490fcd89c09SVille Tervo 
1491fcd89c09SVille Tervo 		hci_dev_unlock(hdev);
1492fcd89c09SVille Tervo 	}
1493f00a06acSAndre Guedes }
1494fcd89c09SVille Tervo 
1495a02226d6SAndrei Emeltchenko static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
1496a02226d6SAndrei Emeltchenko {
149793c284eeSAndrei Emeltchenko 	struct hci_cp_create_phy_link *cp;
149893c284eeSAndrei Emeltchenko 
1499a02226d6SAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
150093c284eeSAndrei Emeltchenko 
150193c284eeSAndrei Emeltchenko 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
150293c284eeSAndrei Emeltchenko 	if (!cp)
150393c284eeSAndrei Emeltchenko 		return;
150493c284eeSAndrei Emeltchenko 
1505e58917b9SAndrei Emeltchenko 	hci_dev_lock(hdev);
1506e58917b9SAndrei Emeltchenko 
1507e58917b9SAndrei Emeltchenko 	if (status) {
1508e58917b9SAndrei Emeltchenko 		struct hci_conn *hcon;
1509e58917b9SAndrei Emeltchenko 
1510e58917b9SAndrei Emeltchenko 		hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle);
1511e58917b9SAndrei Emeltchenko 		if (hcon)
1512e58917b9SAndrei Emeltchenko 			hci_conn_del(hcon);
1513e58917b9SAndrei Emeltchenko 	} else {
151493c284eeSAndrei Emeltchenko 		amp_write_remote_assoc(hdev, cp->phy_handle);
1515a02226d6SAndrei Emeltchenko 	}
1516a02226d6SAndrei Emeltchenko 
1517e58917b9SAndrei Emeltchenko 	hci_dev_unlock(hdev);
1518e58917b9SAndrei Emeltchenko }
1519e58917b9SAndrei Emeltchenko 
15200b26ab9dSAndrei Emeltchenko static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
15210b26ab9dSAndrei Emeltchenko {
15220b26ab9dSAndrei Emeltchenko 	struct hci_cp_accept_phy_link *cp;
15230b26ab9dSAndrei Emeltchenko 
15240b26ab9dSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
15250b26ab9dSAndrei Emeltchenko 
15260b26ab9dSAndrei Emeltchenko 	if (status)
15270b26ab9dSAndrei Emeltchenko 		return;
15280b26ab9dSAndrei Emeltchenko 
15290b26ab9dSAndrei Emeltchenko 	cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
15300b26ab9dSAndrei Emeltchenko 	if (!cp)
15310b26ab9dSAndrei Emeltchenko 		return;
15320b26ab9dSAndrei Emeltchenko 
15330b26ab9dSAndrei Emeltchenko 	amp_write_remote_assoc(hdev, cp->phy_handle);
15340b26ab9dSAndrei Emeltchenko }
15350b26ab9dSAndrei Emeltchenko 
15366039aa73SGustavo Padovan static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
15371da177e4SLinus Torvalds {
15381da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
153930dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
154030dc78e1SJohan Hedberg 	struct inquiry_entry *e;
15411da177e4SLinus Torvalds 
15429f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
15431da177e4SLinus Torvalds 
1544a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
154589352e7dSAndre Guedes 
154689352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
154789352e7dSAndre Guedes 		return;
154889352e7dSAndre Guedes 
15493e13fa1eSAndre Guedes 	smp_mb__after_clear_bit(); /* wake_up_bit advises about this barrier */
15503e13fa1eSAndre Guedes 	wake_up_bit(&hdev->flags, HCI_INQUIRY);
15513e13fa1eSAndre Guedes 
1552a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
155330dc78e1SJohan Hedberg 		return;
155430dc78e1SJohan Hedberg 
155556e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
155630dc78e1SJohan Hedberg 
1557343f935bSAndre Guedes 	if (discov->state != DISCOVERY_FINDING)
155830dc78e1SJohan Hedberg 		goto unlock;
155930dc78e1SJohan Hedberg 
156030dc78e1SJohan Hedberg 	if (list_empty(&discov->resolve)) {
1561ff9ef578SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
156230dc78e1SJohan Hedberg 		goto unlock;
156330dc78e1SJohan Hedberg 	}
156430dc78e1SJohan Hedberg 
156530dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
156630dc78e1SJohan Hedberg 	if (e && hci_resolve_name(hdev, e) == 0) {
156730dc78e1SJohan Hedberg 		e->name_state = NAME_PENDING;
156830dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
156930dc78e1SJohan Hedberg 	} else {
157030dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
157130dc78e1SJohan Hedberg 	}
157230dc78e1SJohan Hedberg 
157330dc78e1SJohan Hedberg unlock:
157456e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
15751da177e4SLinus Torvalds }
15761da177e4SLinus Torvalds 
15776039aa73SGustavo Padovan static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
15781da177e4SLinus Torvalds {
157945bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1580a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
15811da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
15821da177e4SLinus Torvalds 
15831da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
15841da177e4SLinus Torvalds 
158545bb4bf0SMarcel Holtmann 	if (!num_rsp)
158645bb4bf0SMarcel Holtmann 		return;
158745bb4bf0SMarcel Holtmann 
15881519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
15891519cc17SAndre Guedes 		return;
15901519cc17SAndre Guedes 
15911da177e4SLinus Torvalds 	hci_dev_lock(hdev);
159245bb4bf0SMarcel Holtmann 
1593e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
1594388fc8faSJohan Hedberg 		bool name_known, ssp;
15953175405bSJohan Hedberg 
15961da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
15971da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
15981da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
15991da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
16001da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
16011da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
16021da177e4SLinus Torvalds 		data.rssi		= 0x00;
160341a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
16043175405bSJohan Hedberg 
1605388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
160648264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
160704124681SGustavo F. Padovan 				  info->dev_class, 0, !name_known, ssp, NULL,
160804124681SGustavo F. Padovan 				  0);
16091da177e4SLinus Torvalds 	}
161045bb4bf0SMarcel Holtmann 
16111da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
16121da177e4SLinus Torvalds }
16131da177e4SLinus Torvalds 
16146039aa73SGustavo Padovan static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
16151da177e4SLinus Torvalds {
1616a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
1617a9de9248SMarcel Holtmann 	struct hci_conn *conn;
16181da177e4SLinus Torvalds 
1619a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
162045bb4bf0SMarcel Holtmann 
16211da177e4SLinus Torvalds 	hci_dev_lock(hdev);
162245bb4bf0SMarcel Holtmann 
1623a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
16249499237aSMarcel Holtmann 	if (!conn) {
16259499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
16269499237aSMarcel Holtmann 			goto unlock;
16279499237aSMarcel Holtmann 
16289499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1629a9de9248SMarcel Holtmann 		if (!conn)
1630a9de9248SMarcel Holtmann 			goto unlock;
163145bb4bf0SMarcel Holtmann 
16329499237aSMarcel Holtmann 		conn->type = SCO_LINK;
16339499237aSMarcel Holtmann 	}
16349499237aSMarcel Holtmann 
1635a9de9248SMarcel Holtmann 	if (!ev->status) {
1636a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1637769be974SMarcel Holtmann 
1638769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1639769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
1640769be974SMarcel Holtmann 			hci_conn_hold(conn);
1641a9ea3ed9SSzymon Janc 
1642a9ea3ed9SSzymon Janc 			if (!conn->out && !hci_conn_ssp_enabled(conn) &&
1643a9ea3ed9SSzymon Janc 			    !hci_find_link_key(hdev, &ev->bdaddr))
1644a9ea3ed9SSzymon Janc 				conn->disc_timeout = HCI_PAIRING_TIMEOUT;
1645a9ea3ed9SSzymon Janc 			else
1646052b30b0SMarcel Holtmann 				conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1647769be974SMarcel Holtmann 		} else
1648a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
1649a9de9248SMarcel Holtmann 
16507d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
16517d0db0a3SMarcel Holtmann 
1652a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1653a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1654a9de9248SMarcel Holtmann 
1655a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1656a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1657a9de9248SMarcel Holtmann 
1658a9de9248SMarcel Holtmann 		/* Get remote features */
1659a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1660a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1661a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1662769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1663769be974SMarcel Holtmann 				     sizeof(cp), &cp);
166445bb4bf0SMarcel Holtmann 		}
1665a9de9248SMarcel Holtmann 
1666a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1667d095c1ebSAndrei Emeltchenko 		if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
1668a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1669a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1670a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
167104124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
167204124681SGustavo F. Padovan 				     &cp);
1673a9de9248SMarcel Holtmann 		}
167417d5c04cSJohan Hedberg 	} else {
1675a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
167617d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
1677744cf19eSJohan Hedberg 			mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
167848264f06SJohan Hedberg 					    conn->dst_type, ev->status);
167917d5c04cSJohan Hedberg 	}
168045bb4bf0SMarcel Holtmann 
1681e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
1682e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
168345bb4bf0SMarcel Holtmann 
1684769be974SMarcel Holtmann 	if (ev->status) {
1685a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1686a9de9248SMarcel Holtmann 		hci_conn_del(conn);
1687c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
1688c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1689a9de9248SMarcel Holtmann 
1690a9de9248SMarcel Holtmann unlock:
16911da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
1692a9de9248SMarcel Holtmann 
1693a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
16941da177e4SLinus Torvalds }
16951da177e4SLinus Torvalds 
16966039aa73SGustavo Padovan static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
16971da177e4SLinus Torvalds {
1698a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
16991da177e4SLinus Torvalds 	int mask = hdev->link_mode;
170020714bfeSFrédéric Dalleau 	__u8 flags = 0;
17011da177e4SLinus Torvalds 
17026ed93dc6SAndrei Emeltchenko 	BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
1703807deac2SGustavo Padovan 	       ev->link_type);
17041da177e4SLinus Torvalds 
170520714bfeSFrédéric Dalleau 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type,
170620714bfeSFrédéric Dalleau 				      &flags);
17071da177e4SLinus Torvalds 
1708138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
1709138d22efSSzymon Janc 	    !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
17101da177e4SLinus Torvalds 		/* Connection accepted */
1711c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
17121da177e4SLinus Torvalds 		struct hci_conn *conn;
17131da177e4SLinus Torvalds 
17141da177e4SLinus Torvalds 		hci_dev_lock(hdev);
1715b6a0dc82SMarcel Holtmann 
1716cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1717cc11b9c1SAndrei Emeltchenko 		if (ie)
1718c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
1719c7bdd502SMarcel Holtmann 
17208fc9ced3SGustavo Padovan 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
17218fc9ced3SGustavo Padovan 					       &ev->bdaddr);
17221da177e4SLinus Torvalds 		if (!conn) {
1723cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1724cc11b9c1SAndrei Emeltchenko 			if (!conn) {
1725893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
17261da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
17271da177e4SLinus Torvalds 				return;
17281da177e4SLinus Torvalds 			}
17291da177e4SLinus Torvalds 		}
1730b6a0dc82SMarcel Holtmann 
17311da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
1732b6a0dc82SMarcel Holtmann 
17331da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
17341da177e4SLinus Torvalds 
173520714bfeSFrédéric Dalleau 		if (ev->link_type == ACL_LINK ||
173620714bfeSFrédéric Dalleau 		    (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) {
1737b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
173820714bfeSFrédéric Dalleau 			conn->state = BT_CONNECT;
1739b6a0dc82SMarcel Holtmann 
17401da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
17411da177e4SLinus Torvalds 
17421da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
17431da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
17441da177e4SLinus Torvalds 			else
17451da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
17461da177e4SLinus Torvalds 
174704124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
174804124681SGustavo F. Padovan 				     &cp);
174920714bfeSFrédéric Dalleau 		} else if (!(flags & HCI_PROTO_DEFER)) {
1750b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
175120714bfeSFrédéric Dalleau 			conn->state = BT_CONNECT;
1752b6a0dc82SMarcel Holtmann 
1753b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
1754a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1755b6a0dc82SMarcel Holtmann 
175682781e63SAndrei Emeltchenko 			cp.tx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
175782781e63SAndrei Emeltchenko 			cp.rx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
175882781e63SAndrei Emeltchenko 			cp.max_latency    = __constant_cpu_to_le16(0xffff);
1759b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
1760b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
1761b6a0dc82SMarcel Holtmann 
1762b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1763b6a0dc82SMarcel Holtmann 				     sizeof(cp), &cp);
176420714bfeSFrédéric Dalleau 		} else {
176520714bfeSFrédéric Dalleau 			conn->state = BT_CONNECT2;
176620714bfeSFrédéric Dalleau 			hci_proto_connect_cfm(conn, 0);
1767b6a0dc82SMarcel Holtmann 		}
17681da177e4SLinus Torvalds 	} else {
17691da177e4SLinus Torvalds 		/* Connection rejected */
17701da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
17711da177e4SLinus Torvalds 
17721da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
17739f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_REJ_BAD_ADDR;
1774a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
17751da177e4SLinus Torvalds 	}
17761da177e4SLinus Torvalds }
17771da177e4SLinus Torvalds 
1778f0d6a0eaSMikel Astiz static u8 hci_to_mgmt_reason(u8 err)
1779f0d6a0eaSMikel Astiz {
1780f0d6a0eaSMikel Astiz 	switch (err) {
1781f0d6a0eaSMikel Astiz 	case HCI_ERROR_CONNECTION_TIMEOUT:
1782f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_TIMEOUT;
1783f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_USER_TERM:
1784f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_LOW_RESOURCES:
1785f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_POWER_OFF:
1786f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_REMOTE;
1787f0d6a0eaSMikel Astiz 	case HCI_ERROR_LOCAL_HOST_TERM:
1788f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_LOCAL_HOST;
1789f0d6a0eaSMikel Astiz 	default:
1790f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_UNKNOWN;
1791f0d6a0eaSMikel Astiz 	}
1792f0d6a0eaSMikel Astiz }
1793f0d6a0eaSMikel Astiz 
17946039aa73SGustavo Padovan static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
17951da177e4SLinus Torvalds {
1796a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
179704837f64SMarcel Holtmann 	struct hci_conn *conn;
17981da177e4SLinus Torvalds 
17999f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
18001da177e4SLinus Torvalds 
18011da177e4SLinus Torvalds 	hci_dev_lock(hdev);
18021da177e4SLinus Torvalds 
180304837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1804f7520543SJohan Hedberg 	if (!conn)
1805f7520543SJohan Hedberg 		goto unlock;
1806f7520543SJohan Hedberg 
180737d9ef76SJohan Hedberg 	if (ev->status == 0)
18081da177e4SLinus Torvalds 		conn->state = BT_CLOSED;
18097d0db0a3SMarcel Holtmann 
1810b644ba33SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
1811b644ba33SJohan Hedberg 	    (conn->type == ACL_LINK || conn->type == LE_LINK)) {
1812f0d6a0eaSMikel Astiz 		if (ev->status) {
181388c3df13SJohan Hedberg 			mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
181488c3df13SJohan Hedberg 					       conn->dst_type, ev->status);
1815f0d6a0eaSMikel Astiz 		} else {
1816f0d6a0eaSMikel Astiz 			u8 reason = hci_to_mgmt_reason(ev->reason);
1817f0d6a0eaSMikel Astiz 
1818afc747a6SJohan Hedberg 			mgmt_device_disconnected(hdev, &conn->dst, conn->type,
1819f0d6a0eaSMikel Astiz 						 conn->dst_type, reason);
1820f0d6a0eaSMikel Astiz 		}
182137d9ef76SJohan Hedberg 	}
1822f7520543SJohan Hedberg 
182337d9ef76SJohan Hedberg 	if (ev->status == 0) {
18246ec5bcadSVishal Agarwal 		if (conn->type == ACL_LINK && conn->flush_key)
18256ec5bcadSVishal Agarwal 			hci_remove_link_key(hdev, &conn->dst);
18262950f21aSMarcel Holtmann 		hci_proto_disconn_cfm(conn, ev->reason);
18271da177e4SLinus Torvalds 		hci_conn_del(conn);
182837d9ef76SJohan Hedberg 	}
18291da177e4SLinus Torvalds 
1830f7520543SJohan Hedberg unlock:
18311da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
18321da177e4SLinus Torvalds }
18331da177e4SLinus Torvalds 
18346039aa73SGustavo Padovan static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1835a9de9248SMarcel Holtmann {
1836a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
1837a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1838a9de9248SMarcel Holtmann 
18399f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
1840a9de9248SMarcel Holtmann 
1841a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1842a9de9248SMarcel Holtmann 
1843a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1844d7556e20SWaldemar Rymarkiewicz 	if (!conn)
1845d7556e20SWaldemar Rymarkiewicz 		goto unlock;
1846d7556e20SWaldemar Rymarkiewicz 
1847765c2a96SJohan Hedberg 	if (!ev->status) {
1848aa64a8b5SJohan Hedberg 		if (!hci_conn_ssp_enabled(conn) &&
184951a8efd7SJohan Hedberg 		    test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
1850d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
185119f8def0SWaldemar Rymarkiewicz 		} else {
1852a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1853765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
185419f8def0SWaldemar Rymarkiewicz 		}
18552a611692SJohan Hedberg 	} else {
1856bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
1857bab73cb6SJohan Hedberg 				 ev->status);
18582a611692SJohan Hedberg 	}
1859a9de9248SMarcel Holtmann 
186051a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
186151a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
1862a9de9248SMarcel Holtmann 
1863f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
1864aa64a8b5SJohan Hedberg 		if (!ev->status && hci_conn_ssp_enabled(conn)) {
1865f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1866f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1867f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1868d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1869d7556e20SWaldemar Rymarkiewicz 				     &cp);
1870f8558555SMarcel Holtmann 		} else {
1871f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
1872f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
187376a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1874f8558555SMarcel Holtmann 		}
1875052b30b0SMarcel Holtmann 	} else {
1876a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
1877a9de9248SMarcel Holtmann 
1878052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
1879052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
188076a68ba0SDavid Herrmann 		hci_conn_drop(conn);
1881052b30b0SMarcel Holtmann 	}
1882052b30b0SMarcel Holtmann 
188351a8efd7SJohan Hedberg 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
1884a9de9248SMarcel Holtmann 		if (!ev->status) {
1885a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1886f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1887f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1888d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1889d7556e20SWaldemar Rymarkiewicz 				     &cp);
1890a9de9248SMarcel Holtmann 		} else {
189151a8efd7SJohan Hedberg 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
1892a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
1893a9de9248SMarcel Holtmann 		}
1894a9de9248SMarcel Holtmann 	}
1895a9de9248SMarcel Holtmann 
1896d7556e20SWaldemar Rymarkiewicz unlock:
1897a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1898a9de9248SMarcel Holtmann }
1899a9de9248SMarcel Holtmann 
19006039aa73SGustavo Padovan static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1901a9de9248SMarcel Holtmann {
1902127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
1903127178d2SJohan Hedberg 	struct hci_conn *conn;
1904127178d2SJohan Hedberg 
1905a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1906a9de9248SMarcel Holtmann 
1907a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
1908127178d2SJohan Hedberg 
1909127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1910127178d2SJohan Hedberg 
1911127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1912b644ba33SJohan Hedberg 
1913b644ba33SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
1914b644ba33SJohan Hedberg 		goto check_auth;
1915b644ba33SJohan Hedberg 
1916b644ba33SJohan Hedberg 	if (ev->status == 0)
1917b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
1918b644ba33SJohan Hedberg 				       strnlen(ev->name, HCI_MAX_NAME_LENGTH));
1919b644ba33SJohan Hedberg 	else
1920b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
1921b644ba33SJohan Hedberg 
1922b644ba33SJohan Hedberg check_auth:
192379c6c70cSJohan Hedberg 	if (!conn)
192479c6c70cSJohan Hedberg 		goto unlock;
192579c6c70cSJohan Hedberg 
192679c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
192779c6c70cSJohan Hedberg 		goto unlock;
192879c6c70cSJohan Hedberg 
192951a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1930127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1931127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1932127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1933127178d2SJohan Hedberg 	}
1934127178d2SJohan Hedberg 
193579c6c70cSJohan Hedberg unlock:
1936127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1937a9de9248SMarcel Holtmann }
1938a9de9248SMarcel Holtmann 
19396039aa73SGustavo Padovan static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1940a9de9248SMarcel Holtmann {
1941a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
1942a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1943a9de9248SMarcel Holtmann 
19449f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
1945a9de9248SMarcel Holtmann 
1946a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1947a9de9248SMarcel Holtmann 
1948a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1949a9de9248SMarcel Holtmann 	if (conn) {
1950a9de9248SMarcel Holtmann 		if (!ev->status) {
1951ae293196SMarcel Holtmann 			if (ev->encrypt) {
1952ae293196SMarcel Holtmann 				/* Encryption implies authentication */
1953ae293196SMarcel Holtmann 				conn->link_mode |= HCI_LM_AUTH;
1954a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_ENCRYPT;
1955da85e5e5SVinicius Costa Gomes 				conn->sec_level = conn->pending_sec_level;
1956ae293196SMarcel Holtmann 			} else
1957a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_ENCRYPT;
1958a9de9248SMarcel Holtmann 		}
1959a9de9248SMarcel Holtmann 
196051a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
1961a9de9248SMarcel Holtmann 
1962a7d7723aSGustavo Padovan 		if (ev->status && conn->state == BT_CONNECTED) {
1963bed71748SAndre Guedes 			hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
196476a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1965a7d7723aSGustavo Padovan 			goto unlock;
1966a7d7723aSGustavo Padovan 		}
1967a7d7723aSGustavo Padovan 
1968f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1969f8558555SMarcel Holtmann 			if (!ev->status)
1970f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
1971f8558555SMarcel Holtmann 
1972f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
197376a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1974f8558555SMarcel Holtmann 		} else
1975a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, ev->encrypt);
1976a9de9248SMarcel Holtmann 	}
1977a9de9248SMarcel Holtmann 
1978a7d7723aSGustavo Padovan unlock:
1979a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1980a9de9248SMarcel Holtmann }
1981a9de9248SMarcel Holtmann 
19826039aa73SGustavo Padovan static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
1983807deac2SGustavo Padovan 					     struct sk_buff *skb)
1984a9de9248SMarcel Holtmann {
1985a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
1986a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1987a9de9248SMarcel Holtmann 
19889f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
1989a9de9248SMarcel Holtmann 
1990a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1991a9de9248SMarcel Holtmann 
1992a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1993a9de9248SMarcel Holtmann 	if (conn) {
1994a9de9248SMarcel Holtmann 		if (!ev->status)
1995a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
1996a9de9248SMarcel Holtmann 
199751a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
1998a9de9248SMarcel Holtmann 
1999a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
2000a9de9248SMarcel Holtmann 	}
2001a9de9248SMarcel Holtmann 
2002a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2003a9de9248SMarcel Holtmann }
2004a9de9248SMarcel Holtmann 
20056039aa73SGustavo Padovan static void hci_remote_features_evt(struct hci_dev *hdev,
2006807deac2SGustavo Padovan 				    struct sk_buff *skb)
2007a9de9248SMarcel Holtmann {
2008a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
2009a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2010a9de9248SMarcel Holtmann 
20119f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2012a9de9248SMarcel Holtmann 
2013a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2014a9de9248SMarcel Holtmann 
2015a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2016ccd556feSJohan Hedberg 	if (!conn)
2017ccd556feSJohan Hedberg 		goto unlock;
2018ccd556feSJohan Hedberg 
2019769be974SMarcel Holtmann 	if (!ev->status)
2020cad718edSJohan Hedberg 		memcpy(conn->features[0], ev->features, 8);
2021a9de9248SMarcel Holtmann 
2022ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2023ccd556feSJohan Hedberg 		goto unlock;
2024ccd556feSJohan Hedberg 
2025ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2026769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
2027769be974SMarcel Holtmann 		cp.handle = ev->handle;
2028769be974SMarcel Holtmann 		cp.page = 0x01;
2029ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
2030769be974SMarcel Holtmann 			     sizeof(cp), &cp);
2031392599b9SJohan Hedberg 		goto unlock;
2032392599b9SJohan Hedberg 	}
2033392599b9SJohan Hedberg 
2034671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
2035127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2036127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2037127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2038127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2039127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2040b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2041b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
204208c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
2043b644ba33SJohan Hedberg 				      conn->dev_class);
2044392599b9SJohan Hedberg 
2045127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2046769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2047769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
204876a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2049769be974SMarcel Holtmann 	}
2050769be974SMarcel Holtmann 
2051ccd556feSJohan Hedberg unlock:
2052a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2053a9de9248SMarcel Holtmann }
2054a9de9248SMarcel Holtmann 
20556039aa73SGustavo Padovan static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2056a9de9248SMarcel Holtmann {
2057a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
20589238f36aSJohan Hedberg 	u8 status = skb->data[sizeof(*ev)];
2059a9de9248SMarcel Holtmann 	__u16 opcode;
2060a9de9248SMarcel Holtmann 
2061a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2062a9de9248SMarcel Holtmann 
2063a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2064a9de9248SMarcel Holtmann 
2065a9de9248SMarcel Holtmann 	switch (opcode) {
2066a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
2067a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
2068a9de9248SMarcel Holtmann 		break;
2069a9de9248SMarcel Holtmann 
20704d93483bSAndre Guedes 	case HCI_OP_PERIODIC_INQ:
20714d93483bSAndre Guedes 		hci_cc_periodic_inq(hdev, skb);
20724d93483bSAndre Guedes 		break;
20734d93483bSAndre Guedes 
2074a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
2075a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
2076a9de9248SMarcel Holtmann 		break;
2077a9de9248SMarcel Holtmann 
2078a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2079a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
2080a9de9248SMarcel Holtmann 		break;
2081a9de9248SMarcel Holtmann 
2082a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
2083a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
2084a9de9248SMarcel Holtmann 		break;
2085a9de9248SMarcel Holtmann 
2086e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
2087e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
2088e4e8e37cSMarcel Holtmann 		break;
2089e4e8e37cSMarcel Holtmann 
2090a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
2091a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
2092a9de9248SMarcel Holtmann 		break;
2093a9de9248SMarcel Holtmann 
2094e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
2095e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
2096e4e8e37cSMarcel Holtmann 		break;
2097e4e8e37cSMarcel Holtmann 
2098e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
2099e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
2100e4e8e37cSMarcel Holtmann 		break;
2101e4e8e37cSMarcel Holtmann 
2102a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
2103a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
2104a9de9248SMarcel Holtmann 		break;
2105a9de9248SMarcel Holtmann 
2106a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
2107a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
2108a9de9248SMarcel Holtmann 		break;
2109a9de9248SMarcel Holtmann 
2110a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
2111a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
2112a9de9248SMarcel Holtmann 		break;
2113a9de9248SMarcel Holtmann 
2114a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
2115a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
2116a9de9248SMarcel Holtmann 		break;
2117a9de9248SMarcel Holtmann 
2118a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
2119a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
2120a9de9248SMarcel Holtmann 		break;
2121a9de9248SMarcel Holtmann 
2122a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
2123a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
2124a9de9248SMarcel Holtmann 		break;
2125a9de9248SMarcel Holtmann 
2126a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
2127a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
2128a9de9248SMarcel Holtmann 		break;
2129a9de9248SMarcel Holtmann 
2130a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
2131a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
2132a9de9248SMarcel Holtmann 		break;
2133a9de9248SMarcel Holtmann 
2134a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
2135a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
2136a9de9248SMarcel Holtmann 		break;
2137a9de9248SMarcel Holtmann 
2138a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
2139a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
2140a9de9248SMarcel Holtmann 		break;
2141a9de9248SMarcel Holtmann 
2142333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
2143333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
2144333140b5SMarcel Holtmann 		break;
2145333140b5SMarcel Holtmann 
2146a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
2147a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
2148a9de9248SMarcel Holtmann 		break;
2149a9de9248SMarcel Holtmann 
2150a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
2151a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
2152a9de9248SMarcel Holtmann 		break;
2153a9de9248SMarcel Holtmann 
2154a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
2155a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
2156a9de9248SMarcel Holtmann 		break;
2157a9de9248SMarcel Holtmann 
2158971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
2159971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
2160971e3a4bSAndre Guedes 		break;
2161971e3a4bSAndre Guedes 
2162a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
2163a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
2164a9de9248SMarcel Holtmann 		break;
2165a9de9248SMarcel Holtmann 
2166a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
2167a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
2168a9de9248SMarcel Holtmann 		break;
2169a9de9248SMarcel Holtmann 
2170f332ec66SJohan Hedberg 	case HCI_OP_READ_PAGE_SCAN_ACTIVITY:
2171f332ec66SJohan Hedberg 		hci_cc_read_page_scan_activity(hdev, skb);
2172f332ec66SJohan Hedberg 		break;
2173f332ec66SJohan Hedberg 
21744a3ee763SJohan Hedberg 	case HCI_OP_WRITE_PAGE_SCAN_ACTIVITY:
21754a3ee763SJohan Hedberg 		hci_cc_write_page_scan_activity(hdev, skb);
21764a3ee763SJohan Hedberg 		break;
21774a3ee763SJohan Hedberg 
2178f332ec66SJohan Hedberg 	case HCI_OP_READ_PAGE_SCAN_TYPE:
2179f332ec66SJohan Hedberg 		hci_cc_read_page_scan_type(hdev, skb);
2180f332ec66SJohan Hedberg 		break;
2181f332ec66SJohan Hedberg 
21824a3ee763SJohan Hedberg 	case HCI_OP_WRITE_PAGE_SCAN_TYPE:
21834a3ee763SJohan Hedberg 		hci_cc_write_page_scan_type(hdev, skb);
21844a3ee763SJohan Hedberg 		break;
21854a3ee763SJohan Hedberg 
2186350ee4cfSAndrei Emeltchenko 	case HCI_OP_READ_DATA_BLOCK_SIZE:
2187350ee4cfSAndrei Emeltchenko 		hci_cc_read_data_block_size(hdev, skb);
2188350ee4cfSAndrei Emeltchenko 		break;
2189350ee4cfSAndrei Emeltchenko 
21901e89cffbSAndrei Emeltchenko 	case HCI_OP_READ_FLOW_CONTROL_MODE:
21911e89cffbSAndrei Emeltchenko 		hci_cc_read_flow_control_mode(hdev, skb);
21921e89cffbSAndrei Emeltchenko 		break;
21931e89cffbSAndrei Emeltchenko 
2194928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
2195928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
2196928abaa7SAndrei Emeltchenko 		break;
2197928abaa7SAndrei Emeltchenko 
2198903e4541SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_ASSOC:
2199903e4541SAndrei Emeltchenko 		hci_cc_read_local_amp_assoc(hdev, skb);
2200903e4541SAndrei Emeltchenko 		break;
2201903e4541SAndrei Emeltchenko 
2202d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
2203d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
2204d5859e22SJohan Hedberg 		break;
2205d5859e22SJohan Hedberg 
2206980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
2207980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
2208980e1a53SJohan Hedberg 		break;
2209980e1a53SJohan Hedberg 
2210980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
2211980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
2212980e1a53SJohan Hedberg 		break;
2213980e1a53SJohan Hedberg 
2214c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
2215c35938b2SSzymon Janc 		hci_cc_read_local_oob_data_reply(hdev, skb);
2216c35938b2SSzymon Janc 		break;
2217c35938b2SSzymon Janc 
22186ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
22196ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
22206ed58ec5SVille Tervo 		break;
22216ed58ec5SVille Tervo 
222260e77321SJohan Hedberg 	case HCI_OP_LE_READ_LOCAL_FEATURES:
222360e77321SJohan Hedberg 		hci_cc_le_read_local_features(hdev, skb);
222460e77321SJohan Hedberg 		break;
222560e77321SJohan Hedberg 
22268fa19098SJohan Hedberg 	case HCI_OP_LE_READ_ADV_TX_POWER:
22278fa19098SJohan Hedberg 		hci_cc_le_read_adv_tx_power(hdev, skb);
22288fa19098SJohan Hedberg 		break;
22298fa19098SJohan Hedberg 
2230a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
2231a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
2232a5c29683SJohan Hedberg 		break;
2233a5c29683SJohan Hedberg 
2234a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
2235a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
2236a5c29683SJohan Hedberg 		break;
2237a5c29683SJohan Hedberg 
22381143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_REPLY:
22391143d458SBrian Gix 		hci_cc_user_passkey_reply(hdev, skb);
22401143d458SBrian Gix 		break;
22411143d458SBrian Gix 
22421143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_NEG_REPLY:
22431143d458SBrian Gix 		hci_cc_user_passkey_neg_reply(hdev, skb);
224416cde993SSzymon Janc 		break;
224507f7fa5dSAndre Guedes 
2246c1d5dc4aSJohan Hedberg 	case HCI_OP_LE_SET_ADV_ENABLE:
2247c1d5dc4aSJohan Hedberg 		hci_cc_le_set_adv_enable(hdev, skb);
2248c1d5dc4aSJohan Hedberg 		break;
2249c1d5dc4aSJohan Hedberg 
2250eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
2251eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
2252eb9d91f5SAndre Guedes 		break;
2253eb9d91f5SAndre Guedes 
2254cf1d081fSJohan Hedberg 	case HCI_OP_LE_READ_WHITE_LIST_SIZE:
2255cf1d081fSJohan Hedberg 		hci_cc_le_read_white_list_size(hdev, skb);
2256cf1d081fSJohan Hedberg 		break;
2257cf1d081fSJohan Hedberg 
22589b008c04SJohan Hedberg 	case HCI_OP_LE_READ_SUPPORTED_STATES:
22599b008c04SJohan Hedberg 		hci_cc_le_read_supported_states(hdev, skb);
22609b008c04SJohan Hedberg 		break;
22619b008c04SJohan Hedberg 
2262f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2263f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
2264f9b49306SAndre Guedes 		break;
2265f9b49306SAndre Guedes 
226693c284eeSAndrei Emeltchenko 	case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
226793c284eeSAndrei Emeltchenko 		hci_cc_write_remote_amp_assoc(hdev, skb);
226893c284eeSAndrei Emeltchenko 		break;
226993c284eeSAndrei Emeltchenko 
2270a9de9248SMarcel Holtmann 	default:
22719f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2272a9de9248SMarcel Holtmann 		break;
2273a9de9248SMarcel Holtmann 	}
2274a9de9248SMarcel Holtmann 
2275ad82cdd1SJohan Hedberg 	if (opcode != HCI_OP_NOP)
22766bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
22776bd32326SVille Tervo 
2278ad82cdd1SJohan Hedberg 	hci_req_cmd_complete(hdev, opcode, status);
22799238f36aSJohan Hedberg 
2280dbccd791SSzymon Janc 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2281a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2282a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2283c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2284a9de9248SMarcel Holtmann 	}
2285a9de9248SMarcel Holtmann }
2286a9de9248SMarcel Holtmann 
22876039aa73SGustavo Padovan static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2288a9de9248SMarcel Holtmann {
2289a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
2290a9de9248SMarcel Holtmann 	__u16 opcode;
2291a9de9248SMarcel Holtmann 
2292a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2293a9de9248SMarcel Holtmann 
2294a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2295a9de9248SMarcel Holtmann 
2296a9de9248SMarcel Holtmann 	switch (opcode) {
2297a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
2298a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
2299a9de9248SMarcel Holtmann 		break;
2300a9de9248SMarcel Holtmann 
2301a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
2302a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
2303a9de9248SMarcel Holtmann 		break;
2304a9de9248SMarcel Holtmann 
2305a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
2306a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
2307a9de9248SMarcel Holtmann 		break;
2308a9de9248SMarcel Holtmann 
2309f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2310f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2311f8558555SMarcel Holtmann 		break;
2312f8558555SMarcel Holtmann 
2313f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2314f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2315f8558555SMarcel Holtmann 		break;
2316f8558555SMarcel Holtmann 
2317a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2318a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2319a9de9248SMarcel Holtmann 		break;
2320a9de9248SMarcel Holtmann 
2321769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2322769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2323769be974SMarcel Holtmann 		break;
2324769be974SMarcel Holtmann 
2325769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2326769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2327769be974SMarcel Holtmann 		break;
2328769be974SMarcel Holtmann 
2329a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2330a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2331a9de9248SMarcel Holtmann 		break;
2332a9de9248SMarcel Holtmann 
2333a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2334a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2335a9de9248SMarcel Holtmann 		break;
2336a9de9248SMarcel Holtmann 
2337a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2338a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2339a9de9248SMarcel Holtmann 		break;
2340a9de9248SMarcel Holtmann 
23418962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
234288c3df13SJohan Hedberg 		hci_cs_disconnect(hdev, ev->status);
23438962ee74SJohan Hedberg 		break;
23448962ee74SJohan Hedberg 
2345fcd89c09SVille Tervo 	case HCI_OP_LE_CREATE_CONN:
2346fcd89c09SVille Tervo 		hci_cs_le_create_conn(hdev, ev->status);
2347fcd89c09SVille Tervo 		break;
2348fcd89c09SVille Tervo 
2349a02226d6SAndrei Emeltchenko 	case HCI_OP_CREATE_PHY_LINK:
2350a02226d6SAndrei Emeltchenko 		hci_cs_create_phylink(hdev, ev->status);
2351a02226d6SAndrei Emeltchenko 		break;
2352a02226d6SAndrei Emeltchenko 
23530b26ab9dSAndrei Emeltchenko 	case HCI_OP_ACCEPT_PHY_LINK:
23540b26ab9dSAndrei Emeltchenko 		hci_cs_accept_phylink(hdev, ev->status);
23550b26ab9dSAndrei Emeltchenko 		break;
23560b26ab9dSAndrei Emeltchenko 
2357a9de9248SMarcel Holtmann 	default:
23589f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2359a9de9248SMarcel Holtmann 		break;
2360a9de9248SMarcel Holtmann 	}
2361a9de9248SMarcel Holtmann 
2362ad82cdd1SJohan Hedberg 	if (opcode != HCI_OP_NOP)
23636bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
23646bd32326SVille Tervo 
236502350a72SJohan Hedberg 	if (ev->status ||
236602350a72SJohan Hedberg 	    (hdev->sent_cmd && !bt_cb(hdev->sent_cmd)->req.event))
236733720450SAndre Guedes 		hci_req_cmd_complete(hdev, opcode, ev->status);
23689238f36aSJohan Hedberg 
236910572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2370a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2371a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2372c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2373a9de9248SMarcel Holtmann 	}
2374a9de9248SMarcel Holtmann }
2375a9de9248SMarcel Holtmann 
23766039aa73SGustavo Padovan static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2377a9de9248SMarcel Holtmann {
2378a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2379a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2380a9de9248SMarcel Holtmann 
23819f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2382a9de9248SMarcel Holtmann 
2383a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2384a9de9248SMarcel Holtmann 
2385a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2386a9de9248SMarcel Holtmann 	if (conn) {
2387a9de9248SMarcel Holtmann 		if (!ev->status) {
2388a9de9248SMarcel Holtmann 			if (ev->role)
2389a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
2390a9de9248SMarcel Holtmann 			else
2391a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
2392a9de9248SMarcel Holtmann 		}
2393a9de9248SMarcel Holtmann 
239451a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
2395a9de9248SMarcel Holtmann 
2396a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2397a9de9248SMarcel Holtmann 	}
2398a9de9248SMarcel Holtmann 
2399a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2400a9de9248SMarcel Holtmann }
2401a9de9248SMarcel Holtmann 
24026039aa73SGustavo Padovan static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
24031da177e4SLinus Torvalds {
2404a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
24051da177e4SLinus Torvalds 	int i;
24061da177e4SLinus Torvalds 
240732ac5b9bSAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
240832ac5b9bSAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
240932ac5b9bSAndrei Emeltchenko 		return;
241032ac5b9bSAndrei Emeltchenko 	}
241132ac5b9bSAndrei Emeltchenko 
2412c5993de8SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2413c5993de8SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
24141da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
24151da177e4SLinus Torvalds 		return;
24161da177e4SLinus Torvalds 	}
24171da177e4SLinus Torvalds 
2418c5993de8SAndrei Emeltchenko 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2419c5993de8SAndrei Emeltchenko 
2420613a1c0cSAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
2421613a1c0cSAndrei Emeltchenko 		struct hci_comp_pkts_info *info = &ev->handles[i];
24221da177e4SLinus Torvalds 		struct hci_conn *conn;
24231da177e4SLinus Torvalds 		__u16  handle, count;
24241da177e4SLinus Torvalds 
2425613a1c0cSAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
2426613a1c0cSAndrei Emeltchenko 		count  = __le16_to_cpu(info->count);
24271da177e4SLinus Torvalds 
24281da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
2429f4280918SAndrei Emeltchenko 		if (!conn)
2430f4280918SAndrei Emeltchenko 			continue;
2431f4280918SAndrei Emeltchenko 
24321da177e4SLinus Torvalds 		conn->sent -= count;
24331da177e4SLinus Torvalds 
2434f4280918SAndrei Emeltchenko 		switch (conn->type) {
2435f4280918SAndrei Emeltchenko 		case ACL_LINK:
243670f23020SAndrei Emeltchenko 			hdev->acl_cnt += count;
243770f23020SAndrei Emeltchenko 			if (hdev->acl_cnt > hdev->acl_pkts)
24381da177e4SLinus Torvalds 				hdev->acl_cnt = hdev->acl_pkts;
2439f4280918SAndrei Emeltchenko 			break;
2440f4280918SAndrei Emeltchenko 
2441f4280918SAndrei Emeltchenko 		case LE_LINK:
24426ed58ec5SVille Tervo 			if (hdev->le_pkts) {
24436ed58ec5SVille Tervo 				hdev->le_cnt += count;
24446ed58ec5SVille Tervo 				if (hdev->le_cnt > hdev->le_pkts)
24456ed58ec5SVille Tervo 					hdev->le_cnt = hdev->le_pkts;
24466ed58ec5SVille Tervo 			} else {
24476ed58ec5SVille Tervo 				hdev->acl_cnt += count;
24486ed58ec5SVille Tervo 				if (hdev->acl_cnt > hdev->acl_pkts)
24496ed58ec5SVille Tervo 					hdev->acl_cnt = hdev->acl_pkts;
24506ed58ec5SVille Tervo 			}
2451f4280918SAndrei Emeltchenko 			break;
2452f4280918SAndrei Emeltchenko 
2453f4280918SAndrei Emeltchenko 		case SCO_LINK:
245470f23020SAndrei Emeltchenko 			hdev->sco_cnt += count;
245570f23020SAndrei Emeltchenko 			if (hdev->sco_cnt > hdev->sco_pkts)
24565b7f9909SMarcel Holtmann 				hdev->sco_cnt = hdev->sco_pkts;
2457f4280918SAndrei Emeltchenko 			break;
2458f4280918SAndrei Emeltchenko 
2459f4280918SAndrei Emeltchenko 		default:
2460f4280918SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
2461f4280918SAndrei Emeltchenko 			break;
24621da177e4SLinus Torvalds 		}
24631da177e4SLinus Torvalds 	}
2464a9de9248SMarcel Holtmann 
24653eff45eaSGustavo F. Padovan 	queue_work(hdev->workqueue, &hdev->tx_work);
24661da177e4SLinus Torvalds }
24671da177e4SLinus Torvalds 
246876ef7cf7SAndrei Emeltchenko static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
246976ef7cf7SAndrei Emeltchenko 						 __u16 handle)
247076ef7cf7SAndrei Emeltchenko {
247176ef7cf7SAndrei Emeltchenko 	struct hci_chan *chan;
247276ef7cf7SAndrei Emeltchenko 
247376ef7cf7SAndrei Emeltchenko 	switch (hdev->dev_type) {
247476ef7cf7SAndrei Emeltchenko 	case HCI_BREDR:
247576ef7cf7SAndrei Emeltchenko 		return hci_conn_hash_lookup_handle(hdev, handle);
247676ef7cf7SAndrei Emeltchenko 	case HCI_AMP:
247776ef7cf7SAndrei Emeltchenko 		chan = hci_chan_lookup_handle(hdev, handle);
247876ef7cf7SAndrei Emeltchenko 		if (chan)
247976ef7cf7SAndrei Emeltchenko 			return chan->conn;
248076ef7cf7SAndrei Emeltchenko 		break;
248176ef7cf7SAndrei Emeltchenko 	default:
248276ef7cf7SAndrei Emeltchenko 		BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type);
248376ef7cf7SAndrei Emeltchenko 		break;
248476ef7cf7SAndrei Emeltchenko 	}
248576ef7cf7SAndrei Emeltchenko 
248676ef7cf7SAndrei Emeltchenko 	return NULL;
248776ef7cf7SAndrei Emeltchenko }
248876ef7cf7SAndrei Emeltchenko 
24896039aa73SGustavo Padovan static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
249025e89e99SAndrei Emeltchenko {
249125e89e99SAndrei Emeltchenko 	struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
249225e89e99SAndrei Emeltchenko 	int i;
249325e89e99SAndrei Emeltchenko 
249425e89e99SAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
249525e89e99SAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
249625e89e99SAndrei Emeltchenko 		return;
249725e89e99SAndrei Emeltchenko 	}
249825e89e99SAndrei Emeltchenko 
249925e89e99SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
250025e89e99SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
250125e89e99SAndrei Emeltchenko 		BT_DBG("%s bad parameters", hdev->name);
250225e89e99SAndrei Emeltchenko 		return;
250325e89e99SAndrei Emeltchenko 	}
250425e89e99SAndrei Emeltchenko 
250525e89e99SAndrei Emeltchenko 	BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
250625e89e99SAndrei Emeltchenko 	       ev->num_hndl);
250725e89e99SAndrei Emeltchenko 
250825e89e99SAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
250925e89e99SAndrei Emeltchenko 		struct hci_comp_blocks_info *info = &ev->handles[i];
251076ef7cf7SAndrei Emeltchenko 		struct hci_conn *conn = NULL;
251125e89e99SAndrei Emeltchenko 		__u16  handle, block_count;
251225e89e99SAndrei Emeltchenko 
251325e89e99SAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
251425e89e99SAndrei Emeltchenko 		block_count = __le16_to_cpu(info->blocks);
251525e89e99SAndrei Emeltchenko 
251676ef7cf7SAndrei Emeltchenko 		conn = __hci_conn_lookup_handle(hdev, handle);
251725e89e99SAndrei Emeltchenko 		if (!conn)
251825e89e99SAndrei Emeltchenko 			continue;
251925e89e99SAndrei Emeltchenko 
252025e89e99SAndrei Emeltchenko 		conn->sent -= block_count;
252125e89e99SAndrei Emeltchenko 
252225e89e99SAndrei Emeltchenko 		switch (conn->type) {
252325e89e99SAndrei Emeltchenko 		case ACL_LINK:
2524bd1eb66bSAndrei Emeltchenko 		case AMP_LINK:
252525e89e99SAndrei Emeltchenko 			hdev->block_cnt += block_count;
252625e89e99SAndrei Emeltchenko 			if (hdev->block_cnt > hdev->num_blocks)
252725e89e99SAndrei Emeltchenko 				hdev->block_cnt = hdev->num_blocks;
252825e89e99SAndrei Emeltchenko 			break;
252925e89e99SAndrei Emeltchenko 
253025e89e99SAndrei Emeltchenko 		default:
253125e89e99SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
253225e89e99SAndrei Emeltchenko 			break;
253325e89e99SAndrei Emeltchenko 		}
253425e89e99SAndrei Emeltchenko 	}
253525e89e99SAndrei Emeltchenko 
253625e89e99SAndrei Emeltchenko 	queue_work(hdev->workqueue, &hdev->tx_work);
253725e89e99SAndrei Emeltchenko }
253825e89e99SAndrei Emeltchenko 
25396039aa73SGustavo Padovan static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
25401da177e4SLinus Torvalds {
2541a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
254204837f64SMarcel Holtmann 	struct hci_conn *conn;
25431da177e4SLinus Torvalds 
25449f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
25451da177e4SLinus Torvalds 
25461da177e4SLinus Torvalds 	hci_dev_lock(hdev);
25471da177e4SLinus Torvalds 
254804837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
254904837f64SMarcel Holtmann 	if (conn) {
255004837f64SMarcel Holtmann 		conn->mode = ev->mode;
255104837f64SMarcel Holtmann 		conn->interval = __le16_to_cpu(ev->interval);
255204837f64SMarcel Holtmann 
25538fc9ced3SGustavo Padovan 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
25548fc9ced3SGustavo Padovan 					&conn->flags)) {
255504837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
255658a681efSJohan Hedberg 				set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
255704837f64SMarcel Holtmann 			else
255858a681efSJohan Hedberg 				clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
255904837f64SMarcel Holtmann 		}
2560e73439d8SMarcel Holtmann 
256151a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
2562e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
256304837f64SMarcel Holtmann 	}
256404837f64SMarcel Holtmann 
256504837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
256604837f64SMarcel Holtmann }
256704837f64SMarcel Holtmann 
25686039aa73SGustavo Padovan static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
25691da177e4SLinus Torvalds {
2570052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
2571052b30b0SMarcel Holtmann 	struct hci_conn *conn;
2572052b30b0SMarcel Holtmann 
2573a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2574052b30b0SMarcel Holtmann 
2575052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2576052b30b0SMarcel Holtmann 
2577052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2578b6f98044SWaldemar Rymarkiewicz 	if (!conn)
2579b6f98044SWaldemar Rymarkiewicz 		goto unlock;
2580b6f98044SWaldemar Rymarkiewicz 
2581b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
2582052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2583052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
258476a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2585052b30b0SMarcel Holtmann 	}
2586052b30b0SMarcel Holtmann 
2587a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
258803b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
258903b555e1SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
2590a8b2d5c2SJohan Hedberg 	else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
2591a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
2592a770bb5aSWaldemar Rymarkiewicz 
2593a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
2594a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
2595a770bb5aSWaldemar Rymarkiewicz 		else
2596a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
2597a770bb5aSWaldemar Rymarkiewicz 
2598744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
2599a770bb5aSWaldemar Rymarkiewicz 	}
2600980e1a53SJohan Hedberg 
2601b6f98044SWaldemar Rymarkiewicz unlock:
2602052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
26031da177e4SLinus Torvalds }
26041da177e4SLinus Torvalds 
26056039aa73SGustavo Padovan static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
26061da177e4SLinus Torvalds {
260755ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
260855ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
260955ed8ca1SJohan Hedberg 	struct hci_conn *conn;
261055ed8ca1SJohan Hedberg 	struct link_key *key;
261155ed8ca1SJohan Hedberg 
2612a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
261355ed8ca1SJohan Hedberg 
2614034cbea0SAndrei Emeltchenko 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
261555ed8ca1SJohan Hedberg 		return;
261655ed8ca1SJohan Hedberg 
261755ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
261855ed8ca1SJohan Hedberg 
261955ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
262055ed8ca1SJohan Hedberg 	if (!key) {
26216ed93dc6SAndrei Emeltchenko 		BT_DBG("%s link key not found for %pMR", hdev->name,
26226ed93dc6SAndrei Emeltchenko 		       &ev->bdaddr);
262355ed8ca1SJohan Hedberg 		goto not_found;
262455ed8ca1SJohan Hedberg 	}
262555ed8ca1SJohan Hedberg 
26266ed93dc6SAndrei Emeltchenko 	BT_DBG("%s found key type %u for %pMR", hdev->name, key->type,
26276ed93dc6SAndrei Emeltchenko 	       &ev->bdaddr);
262855ed8ca1SJohan Hedberg 
2629a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
2630b6020ba0SWaldemar Rymarkiewicz 	    key->type == HCI_LK_DEBUG_COMBINATION) {
263155ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
263255ed8ca1SJohan Hedberg 		goto not_found;
263355ed8ca1SJohan Hedberg 	}
263455ed8ca1SJohan Hedberg 
263555ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
263660b83f57SWaldemar Rymarkiewicz 	if (conn) {
263760b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_UNAUTH_COMBINATION &&
2638807deac2SGustavo Padovan 		    conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
263955ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
264055ed8ca1SJohan Hedberg 			goto not_found;
264155ed8ca1SJohan Hedberg 		}
264255ed8ca1SJohan Hedberg 
264360b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
264460b83f57SWaldemar Rymarkiewicz 		    conn->pending_sec_level == BT_SECURITY_HIGH) {
26458fc9ced3SGustavo Padovan 			BT_DBG("%s ignoring key unauthenticated for high security",
26468fc9ced3SGustavo Padovan 			       hdev->name);
264760b83f57SWaldemar Rymarkiewicz 			goto not_found;
264860b83f57SWaldemar Rymarkiewicz 		}
264960b83f57SWaldemar Rymarkiewicz 
265060b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
265160b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
265260b83f57SWaldemar Rymarkiewicz 	}
265360b83f57SWaldemar Rymarkiewicz 
265455ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
26559b3b4460SAndrei Emeltchenko 	memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
265655ed8ca1SJohan Hedberg 
265755ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
265855ed8ca1SJohan Hedberg 
265955ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
266055ed8ca1SJohan Hedberg 
266155ed8ca1SJohan Hedberg 	return;
266255ed8ca1SJohan Hedberg 
266355ed8ca1SJohan Hedberg not_found:
266455ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
266555ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
26661da177e4SLinus Torvalds }
26671da177e4SLinus Torvalds 
26686039aa73SGustavo Padovan static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
26691da177e4SLinus Torvalds {
2670052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
2671052b30b0SMarcel Holtmann 	struct hci_conn *conn;
267255ed8ca1SJohan Hedberg 	u8 pin_len = 0;
2673052b30b0SMarcel Holtmann 
2674a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2675052b30b0SMarcel Holtmann 
2676052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2677052b30b0SMarcel Holtmann 
2678052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2679052b30b0SMarcel Holtmann 	if (conn) {
2680052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2681052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2682980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
268313d39315SWaldemar Rymarkiewicz 
268413d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
268513d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
268613d39315SWaldemar Rymarkiewicz 
268776a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2688052b30b0SMarcel Holtmann 	}
2689052b30b0SMarcel Holtmann 
2690034cbea0SAndrei Emeltchenko 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
2691d25e28abSJohan Hedberg 		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
269255ed8ca1SJohan Hedberg 				 ev->key_type, pin_len);
269355ed8ca1SJohan Hedberg 
2694052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
26951da177e4SLinus Torvalds }
26961da177e4SLinus Torvalds 
26976039aa73SGustavo Padovan static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
269804837f64SMarcel Holtmann {
2699a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
270004837f64SMarcel Holtmann 	struct hci_conn *conn;
270104837f64SMarcel Holtmann 
27029f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
270304837f64SMarcel Holtmann 
270404837f64SMarcel Holtmann 	hci_dev_lock(hdev);
270504837f64SMarcel Holtmann 
270604837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
27071da177e4SLinus Torvalds 	if (conn && !ev->status) {
27081da177e4SLinus Torvalds 		struct inquiry_entry *ie;
27091da177e4SLinus Torvalds 
2710cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2711cc11b9c1SAndrei Emeltchenko 		if (ie) {
27121da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
27131da177e4SLinus Torvalds 			ie->timestamp = jiffies;
27141da177e4SLinus Torvalds 		}
27151da177e4SLinus Torvalds 	}
27161da177e4SLinus Torvalds 
27171da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
27181da177e4SLinus Torvalds }
27191da177e4SLinus Torvalds 
27206039aa73SGustavo Padovan static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2721a8746417SMarcel Holtmann {
2722a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2723a8746417SMarcel Holtmann 	struct hci_conn *conn;
2724a8746417SMarcel Holtmann 
27259f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2726a8746417SMarcel Holtmann 
2727a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
2728a8746417SMarcel Holtmann 
2729a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2730a8746417SMarcel Holtmann 	if (conn && !ev->status)
2731a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2732a8746417SMarcel Holtmann 
2733a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
2734a8746417SMarcel Holtmann }
2735a8746417SMarcel Holtmann 
27366039aa73SGustavo Padovan static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
273785a1e930SMarcel Holtmann {
2738a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
273985a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
274085a1e930SMarcel Holtmann 
274185a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
274285a1e930SMarcel Holtmann 
274385a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
274485a1e930SMarcel Holtmann 
2745cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2746cc11b9c1SAndrei Emeltchenko 	if (ie) {
274785a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
274885a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
274985a1e930SMarcel Holtmann 	}
275085a1e930SMarcel Holtmann 
275185a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
275285a1e930SMarcel Holtmann }
275385a1e930SMarcel Holtmann 
27546039aa73SGustavo Padovan static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
2755807deac2SGustavo Padovan 					     struct sk_buff *skb)
2756a9de9248SMarcel Holtmann {
2757a9de9248SMarcel Holtmann 	struct inquiry_data data;
2758a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2759388fc8faSJohan Hedberg 	bool name_known, ssp;
2760a9de9248SMarcel Holtmann 
2761a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2762a9de9248SMarcel Holtmann 
2763a9de9248SMarcel Holtmann 	if (!num_rsp)
2764a9de9248SMarcel Holtmann 		return;
2765a9de9248SMarcel Holtmann 
27661519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
27671519cc17SAndre Guedes 		return;
27681519cc17SAndre Guedes 
2769a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2770a9de9248SMarcel Holtmann 
2771a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
2772138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
2773138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
2774a9de9248SMarcel Holtmann 
2775e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2776a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2777a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2778a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2779a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
2780a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2781a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2782a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
278341a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
27843175405bSJohan Hedberg 
27853175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
2786388fc8faSJohan Hedberg 							      false, &ssp);
278748264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2788e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
2789388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
2790a9de9248SMarcel Holtmann 		}
2791a9de9248SMarcel Holtmann 	} else {
2792a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2793a9de9248SMarcel Holtmann 
2794e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2795a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2796a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2797a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2798a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
2799a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2800a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2801a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
280241a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
28033175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
2804388fc8faSJohan Hedberg 							      false, &ssp);
280548264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2806e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
2807388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
2808a9de9248SMarcel Holtmann 		}
2809a9de9248SMarcel Holtmann 	}
2810a9de9248SMarcel Holtmann 
2811a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2812a9de9248SMarcel Holtmann }
2813a9de9248SMarcel Holtmann 
28146039aa73SGustavo Padovan static void hci_remote_ext_features_evt(struct hci_dev *hdev,
2815807deac2SGustavo Padovan 					struct sk_buff *skb)
2816a9de9248SMarcel Holtmann {
281741a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
281841a96212SMarcel Holtmann 	struct hci_conn *conn;
281941a96212SMarcel Holtmann 
2820a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
282141a96212SMarcel Holtmann 
282241a96212SMarcel Holtmann 	hci_dev_lock(hdev);
282341a96212SMarcel Holtmann 
282441a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2825ccd556feSJohan Hedberg 	if (!conn)
2826ccd556feSJohan Hedberg 		goto unlock;
2827ccd556feSJohan Hedberg 
2828cad718edSJohan Hedberg 	if (ev->page < HCI_MAX_PAGES)
2829cad718edSJohan Hedberg 		memcpy(conn->features[ev->page], ev->features, 8);
2830cad718edSJohan Hedberg 
2831769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
283241a96212SMarcel Holtmann 		struct inquiry_entry *ie;
283341a96212SMarcel Holtmann 
2834cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2835cc11b9c1SAndrei Emeltchenko 		if (ie)
283602b7cc62SJohan Hedberg 			ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
283741a96212SMarcel Holtmann 
2838bbb0eadaSJaganath Kanakkassery 		if (ev->features[0] & LMP_HOST_SSP) {
283958a681efSJohan Hedberg 			set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
2840bbb0eadaSJaganath Kanakkassery 		} else {
2841bbb0eadaSJaganath Kanakkassery 			/* It is mandatory by the Bluetooth specification that
2842bbb0eadaSJaganath Kanakkassery 			 * Extended Inquiry Results are only used when Secure
2843bbb0eadaSJaganath Kanakkassery 			 * Simple Pairing is enabled, but some devices violate
2844bbb0eadaSJaganath Kanakkassery 			 * this.
2845bbb0eadaSJaganath Kanakkassery 			 *
2846bbb0eadaSJaganath Kanakkassery 			 * To make these devices work, the internal SSP
2847bbb0eadaSJaganath Kanakkassery 			 * enabled flag needs to be cleared if the remote host
2848bbb0eadaSJaganath Kanakkassery 			 * features do not indicate SSP support */
2849bbb0eadaSJaganath Kanakkassery 			clear_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
2850bbb0eadaSJaganath Kanakkassery 		}
285141a96212SMarcel Holtmann 	}
285241a96212SMarcel Holtmann 
2853ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2854ccd556feSJohan Hedberg 		goto unlock;
2855ccd556feSJohan Hedberg 
2856671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
2857127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2858127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2859127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2860127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2861127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2862b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2863b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
286408c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
2865b644ba33SJohan Hedberg 				      conn->dev_class);
2866392599b9SJohan Hedberg 
2867127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2868769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2869769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
287076a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2871769be974SMarcel Holtmann 	}
2872769be974SMarcel Holtmann 
2873ccd556feSJohan Hedberg unlock:
287441a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
2875a9de9248SMarcel Holtmann }
2876a9de9248SMarcel Holtmann 
28776039aa73SGustavo Padovan static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
2878807deac2SGustavo Padovan 				       struct sk_buff *skb)
2879a9de9248SMarcel Holtmann {
2880b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2881b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
2882b6a0dc82SMarcel Holtmann 
28839f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2884b6a0dc82SMarcel Holtmann 
2885b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
2886b6a0dc82SMarcel Holtmann 
2887b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
28889dc0a3afSMarcel Holtmann 	if (!conn) {
28899dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
28909dc0a3afSMarcel Holtmann 			goto unlock;
28919dc0a3afSMarcel Holtmann 
28929dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2893b6a0dc82SMarcel Holtmann 		if (!conn)
2894b6a0dc82SMarcel Holtmann 			goto unlock;
2895b6a0dc82SMarcel Holtmann 
28969dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
28979dc0a3afSMarcel Holtmann 	}
28989dc0a3afSMarcel Holtmann 
2899732547f9SMarcel Holtmann 	switch (ev->status) {
2900732547f9SMarcel Holtmann 	case 0x00:
2901732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
2902732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
2903732547f9SMarcel Holtmann 
2904732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
2905732547f9SMarcel Holtmann 		break;
2906732547f9SMarcel Holtmann 
2907705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
2908732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
29091038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
2910732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
2911732547f9SMarcel Holtmann 		if (conn->out && conn->attempt < 2) {
2912efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2913efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
2914efc7688bSMarcel Holtmann 			hci_setup_sync(conn, conn->link->handle);
2915efc7688bSMarcel Holtmann 			goto unlock;
2916efc7688bSMarcel Holtmann 		}
2917732547f9SMarcel Holtmann 		/* fall through */
2918efc7688bSMarcel Holtmann 
2919732547f9SMarcel Holtmann 	default:
2920b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
2921732547f9SMarcel Holtmann 		break;
2922732547f9SMarcel Holtmann 	}
2923b6a0dc82SMarcel Holtmann 
2924b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
2925b6a0dc82SMarcel Holtmann 	if (ev->status)
2926b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
2927b6a0dc82SMarcel Holtmann 
2928b6a0dc82SMarcel Holtmann unlock:
2929b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
2930a9de9248SMarcel Holtmann }
2931a9de9248SMarcel Holtmann 
29326039aa73SGustavo Padovan static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
2933807deac2SGustavo Padovan 					    struct sk_buff *skb)
2934a9de9248SMarcel Holtmann {
2935a9de9248SMarcel Holtmann 	struct inquiry_data data;
2936a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
2937a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
29389d939d94SVishal Agarwal 	size_t eir_len;
2939a9de9248SMarcel Holtmann 
2940a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2941a9de9248SMarcel Holtmann 
2942a9de9248SMarcel Holtmann 	if (!num_rsp)
2943a9de9248SMarcel Holtmann 		return;
2944a9de9248SMarcel Holtmann 
29451519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
29461519cc17SAndre Guedes 		return;
29471519cc17SAndre Guedes 
2948a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2949a9de9248SMarcel Holtmann 
2950e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
2951388fc8faSJohan Hedberg 		bool name_known, ssp;
2952561aafbcSJohan Hedberg 
2953a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
2954a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
2955a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
2956a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
2957a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
2958a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
2959a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
296041a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
2961561aafbcSJohan Hedberg 
2962a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
29634ddb1930SJohan Hedberg 			name_known = eir_has_data_type(info->data,
29644ddb1930SJohan Hedberg 						       sizeof(info->data),
29654ddb1930SJohan Hedberg 						       EIR_NAME_COMPLETE);
2966561aafbcSJohan Hedberg 		else
2967561aafbcSJohan Hedberg 			name_known = true;
2968561aafbcSJohan Hedberg 
2969388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, name_known,
2970388fc8faSJohan Hedberg 						      &ssp);
29719d939d94SVishal Agarwal 		eir_len = eir_get_length(info->data, sizeof(info->data));
297248264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
297304124681SGustavo F. Padovan 				  info->dev_class, info->rssi, !name_known,
29749d939d94SVishal Agarwal 				  ssp, info->data, eir_len);
2975a9de9248SMarcel Holtmann 	}
2976a9de9248SMarcel Holtmann 
2977a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2978a9de9248SMarcel Holtmann }
2979a9de9248SMarcel Holtmann 
29801c2e0041SJohan Hedberg static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
29811c2e0041SJohan Hedberg 					 struct sk_buff *skb)
29821c2e0041SJohan Hedberg {
29831c2e0041SJohan Hedberg 	struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
29841c2e0041SJohan Hedberg 	struct hci_conn *conn;
29851c2e0041SJohan Hedberg 
29869f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
29871c2e0041SJohan Hedberg 	       __le16_to_cpu(ev->handle));
29881c2e0041SJohan Hedberg 
29891c2e0041SJohan Hedberg 	hci_dev_lock(hdev);
29901c2e0041SJohan Hedberg 
29911c2e0041SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
29921c2e0041SJohan Hedberg 	if (!conn)
29931c2e0041SJohan Hedberg 		goto unlock;
29941c2e0041SJohan Hedberg 
29951c2e0041SJohan Hedberg 	if (!ev->status)
29961c2e0041SJohan Hedberg 		conn->sec_level = conn->pending_sec_level;
29971c2e0041SJohan Hedberg 
29981c2e0041SJohan Hedberg 	clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
29991c2e0041SJohan Hedberg 
30001c2e0041SJohan Hedberg 	if (ev->status && conn->state == BT_CONNECTED) {
3001bed71748SAndre Guedes 		hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
300276a68ba0SDavid Herrmann 		hci_conn_drop(conn);
30031c2e0041SJohan Hedberg 		goto unlock;
30041c2e0041SJohan Hedberg 	}
30051c2e0041SJohan Hedberg 
30061c2e0041SJohan Hedberg 	if (conn->state == BT_CONFIG) {
30071c2e0041SJohan Hedberg 		if (!ev->status)
30081c2e0041SJohan Hedberg 			conn->state = BT_CONNECTED;
30091c2e0041SJohan Hedberg 
30101c2e0041SJohan Hedberg 		hci_proto_connect_cfm(conn, ev->status);
301176a68ba0SDavid Herrmann 		hci_conn_drop(conn);
30121c2e0041SJohan Hedberg 	} else {
30131c2e0041SJohan Hedberg 		hci_auth_cfm(conn, ev->status);
30141c2e0041SJohan Hedberg 
30151c2e0041SJohan Hedberg 		hci_conn_hold(conn);
30161c2e0041SJohan Hedberg 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
301776a68ba0SDavid Herrmann 		hci_conn_drop(conn);
30181c2e0041SJohan Hedberg 	}
30191c2e0041SJohan Hedberg 
30201c2e0041SJohan Hedberg unlock:
30211c2e0041SJohan Hedberg 	hci_dev_unlock(hdev);
30221c2e0041SJohan Hedberg }
30231c2e0041SJohan Hedberg 
30246039aa73SGustavo Padovan static u8 hci_get_auth_req(struct hci_conn *conn)
302517fa4b9dSJohan Hedberg {
302617fa4b9dSJohan Hedberg 	/* If remote requests dedicated bonding follow that lead */
302717fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
302817fa4b9dSJohan Hedberg 		/* If both remote and local IO capabilities allow MITM
302917fa4b9dSJohan Hedberg 		 * protection then require it, otherwise don't */
303017fa4b9dSJohan Hedberg 		if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
303117fa4b9dSJohan Hedberg 			return 0x02;
303217fa4b9dSJohan Hedberg 		else
303317fa4b9dSJohan Hedberg 			return 0x03;
303417fa4b9dSJohan Hedberg 	}
303517fa4b9dSJohan Hedberg 
303617fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
303717fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
303858797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
303917fa4b9dSJohan Hedberg 
304017fa4b9dSJohan Hedberg 	return conn->auth_type;
304117fa4b9dSJohan Hedberg }
304217fa4b9dSJohan Hedberg 
30436039aa73SGustavo Padovan static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
30440493684eSMarcel Holtmann {
30450493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
30460493684eSMarcel Holtmann 	struct hci_conn *conn;
30470493684eSMarcel Holtmann 
30480493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
30490493684eSMarcel Holtmann 
30500493684eSMarcel Holtmann 	hci_dev_lock(hdev);
30510493684eSMarcel Holtmann 
30520493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
305303b555e1SJohan Hedberg 	if (!conn)
305403b555e1SJohan Hedberg 		goto unlock;
305503b555e1SJohan Hedberg 
30560493684eSMarcel Holtmann 	hci_conn_hold(conn);
30570493684eSMarcel Holtmann 
3058a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
305903b555e1SJohan Hedberg 		goto unlock;
306003b555e1SJohan Hedberg 
3061a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
306203b555e1SJohan Hedberg 	    (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
306317fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
306417fa4b9dSJohan Hedberg 
306517fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
30667a7f1e7cSHemant Gupta 		/* Change the IO capability from KeyboardDisplay
30677a7f1e7cSHemant Gupta 		 * to DisplayYesNo as it is not supported by BT spec. */
30687a7f1e7cSHemant Gupta 		cp.capability = (conn->io_capability == 0x04) ?
30697a7f1e7cSHemant Gupta 						0x01 : conn->io_capability;
30707cbc9bd9SJohan Hedberg 		conn->auth_type = hci_get_auth_req(conn);
30717cbc9bd9SJohan Hedberg 		cp.authentication = conn->auth_type;
307217fa4b9dSJohan Hedberg 
30738fc9ced3SGustavo Padovan 		if (hci_find_remote_oob_data(hdev, &conn->dst) &&
30748fc9ced3SGustavo Padovan 		    (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
3075ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
3076ce85ee13SSzymon Janc 		else
3077ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
3078ce85ee13SSzymon Janc 
307917fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
308017fa4b9dSJohan Hedberg 			     sizeof(cp), &cp);
308103b555e1SJohan Hedberg 	} else {
308203b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
308303b555e1SJohan Hedberg 
308403b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
30859f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
308603b555e1SJohan Hedberg 
308703b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
308803b555e1SJohan Hedberg 			     sizeof(cp), &cp);
308903b555e1SJohan Hedberg 	}
309003b555e1SJohan Hedberg 
309103b555e1SJohan Hedberg unlock:
309203b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
309303b555e1SJohan Hedberg }
309403b555e1SJohan Hedberg 
30956039aa73SGustavo Padovan static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
309603b555e1SJohan Hedberg {
309703b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
309803b555e1SJohan Hedberg 	struct hci_conn *conn;
309903b555e1SJohan Hedberg 
310003b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
310103b555e1SJohan Hedberg 
310203b555e1SJohan Hedberg 	hci_dev_lock(hdev);
310303b555e1SJohan Hedberg 
310403b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
310503b555e1SJohan Hedberg 	if (!conn)
310603b555e1SJohan Hedberg 		goto unlock;
310703b555e1SJohan Hedberg 
310803b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
310903b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
311058a681efSJohan Hedberg 	if (ev->oob_data)
311158a681efSJohan Hedberg 		set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
311203b555e1SJohan Hedberg 
311303b555e1SJohan Hedberg unlock:
31140493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
31150493684eSMarcel Holtmann }
31160493684eSMarcel Holtmann 
31176039aa73SGustavo Padovan static void hci_user_confirm_request_evt(struct hci_dev *hdev,
3118a5c29683SJohan Hedberg 					 struct sk_buff *skb)
3119a5c29683SJohan Hedberg {
3120a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
312155bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
31227a828908SJohan Hedberg 	struct hci_conn *conn;
3123a5c29683SJohan Hedberg 
3124a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
3125a5c29683SJohan Hedberg 
3126a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
3127a5c29683SJohan Hedberg 
3128a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
31297a828908SJohan Hedberg 		goto unlock;
31307a828908SJohan Hedberg 
31317a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
31327a828908SJohan Hedberg 	if (!conn)
31337a828908SJohan Hedberg 		goto unlock;
31347a828908SJohan Hedberg 
31357a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
31367a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
31377a828908SJohan Hedberg 
31387a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
31397a828908SJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
31407a828908SJohan Hedberg 	 * request. The only exception is when we're dedicated bonding
31417a828908SJohan Hedberg 	 * initiators (connect_cfm_cb set) since then we always have the MITM
31427a828908SJohan Hedberg 	 * bit set. */
31437a828908SJohan Hedberg 	if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
31447a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
31457a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
31467a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
31477a828908SJohan Hedberg 		goto unlock;
31487a828908SJohan Hedberg 	}
31497a828908SJohan Hedberg 
31507a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
31517a828908SJohan Hedberg 	if ((!loc_mitm || conn->remote_cap == 0x03) &&
31527a828908SJohan Hedberg 	    (!rem_mitm || conn->io_capability == 0x03)) {
315355bc1a37SJohan Hedberg 
315455bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
315555bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
315655bc1a37SJohan Hedberg 		 * confirm_hint set to 1). */
315751a8efd7SJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
315855bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
315955bc1a37SJohan Hedberg 			confirm_hint = 1;
316055bc1a37SJohan Hedberg 			goto confirm;
316155bc1a37SJohan Hedberg 		}
316255bc1a37SJohan Hedberg 
31639f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
31649f61656aSJohan Hedberg 		       hdev->auto_accept_delay);
31659f61656aSJohan Hedberg 
31669f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
31679f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
31689f61656aSJohan Hedberg 			mod_timer(&conn->auto_accept_timer, jiffies + delay);
31699f61656aSJohan Hedberg 			goto unlock;
31709f61656aSJohan Hedberg 		}
31719f61656aSJohan Hedberg 
31727a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
31737a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
31747a828908SJohan Hedberg 		goto unlock;
31757a828908SJohan Hedberg 	}
31767a828908SJohan Hedberg 
317755bc1a37SJohan Hedberg confirm:
3178272d90dfSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
317955bc1a37SJohan Hedberg 				  confirm_hint);
3180a5c29683SJohan Hedberg 
31817a828908SJohan Hedberg unlock:
3182a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
3183a5c29683SJohan Hedberg }
3184a5c29683SJohan Hedberg 
31856039aa73SGustavo Padovan static void hci_user_passkey_request_evt(struct hci_dev *hdev,
31861143d458SBrian Gix 					 struct sk_buff *skb)
31871143d458SBrian Gix {
31881143d458SBrian Gix 	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
31891143d458SBrian Gix 
31901143d458SBrian Gix 	BT_DBG("%s", hdev->name);
31911143d458SBrian Gix 
3192a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3193272d90dfSJohan Hedberg 		mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
31941143d458SBrian Gix }
31951143d458SBrian Gix 
319692a25256SJohan Hedberg static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
319792a25256SJohan Hedberg 					struct sk_buff *skb)
319892a25256SJohan Hedberg {
319992a25256SJohan Hedberg 	struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
320092a25256SJohan Hedberg 	struct hci_conn *conn;
320192a25256SJohan Hedberg 
320292a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
320392a25256SJohan Hedberg 
320492a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
320592a25256SJohan Hedberg 	if (!conn)
320692a25256SJohan Hedberg 		return;
320792a25256SJohan Hedberg 
320892a25256SJohan Hedberg 	conn->passkey_notify = __le32_to_cpu(ev->passkey);
320992a25256SJohan Hedberg 	conn->passkey_entered = 0;
321092a25256SJohan Hedberg 
321192a25256SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
321292a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
321392a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
321492a25256SJohan Hedberg 					 conn->passkey_entered);
321592a25256SJohan Hedberg }
321692a25256SJohan Hedberg 
321792a25256SJohan Hedberg static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
321892a25256SJohan Hedberg {
321992a25256SJohan Hedberg 	struct hci_ev_keypress_notify *ev = (void *) skb->data;
322092a25256SJohan Hedberg 	struct hci_conn *conn;
322192a25256SJohan Hedberg 
322292a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
322392a25256SJohan Hedberg 
322492a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
322592a25256SJohan Hedberg 	if (!conn)
322692a25256SJohan Hedberg 		return;
322792a25256SJohan Hedberg 
322892a25256SJohan Hedberg 	switch (ev->type) {
322992a25256SJohan Hedberg 	case HCI_KEYPRESS_STARTED:
323092a25256SJohan Hedberg 		conn->passkey_entered = 0;
323192a25256SJohan Hedberg 		return;
323292a25256SJohan Hedberg 
323392a25256SJohan Hedberg 	case HCI_KEYPRESS_ENTERED:
323492a25256SJohan Hedberg 		conn->passkey_entered++;
323592a25256SJohan Hedberg 		break;
323692a25256SJohan Hedberg 
323792a25256SJohan Hedberg 	case HCI_KEYPRESS_ERASED:
323892a25256SJohan Hedberg 		conn->passkey_entered--;
323992a25256SJohan Hedberg 		break;
324092a25256SJohan Hedberg 
324192a25256SJohan Hedberg 	case HCI_KEYPRESS_CLEARED:
324292a25256SJohan Hedberg 		conn->passkey_entered = 0;
324392a25256SJohan Hedberg 		break;
324492a25256SJohan Hedberg 
324592a25256SJohan Hedberg 	case HCI_KEYPRESS_COMPLETED:
324692a25256SJohan Hedberg 		return;
324792a25256SJohan Hedberg 	}
324892a25256SJohan Hedberg 
324992a25256SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
325092a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
325192a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
325292a25256SJohan Hedberg 					 conn->passkey_entered);
325392a25256SJohan Hedberg }
325492a25256SJohan Hedberg 
32556039aa73SGustavo Padovan static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
3256807deac2SGustavo Padovan 					 struct sk_buff *skb)
32570493684eSMarcel Holtmann {
32580493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
32590493684eSMarcel Holtmann 	struct hci_conn *conn;
32600493684eSMarcel Holtmann 
32610493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
32620493684eSMarcel Holtmann 
32630493684eSMarcel Holtmann 	hci_dev_lock(hdev);
32640493684eSMarcel Holtmann 
32650493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
32662a611692SJohan Hedberg 	if (!conn)
32672a611692SJohan Hedberg 		goto unlock;
32682a611692SJohan Hedberg 
32692a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
32702a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
32712a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
32722a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
32732a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
3274fa1bd918SMikel Astiz 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status)
3275bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
3276bab73cb6SJohan Hedberg 				 ev->status);
32772a611692SJohan Hedberg 
327876a68ba0SDavid Herrmann 	hci_conn_drop(conn);
32790493684eSMarcel Holtmann 
32802a611692SJohan Hedberg unlock:
32810493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
32820493684eSMarcel Holtmann }
32830493684eSMarcel Holtmann 
32846039aa73SGustavo Padovan static void hci_remote_host_features_evt(struct hci_dev *hdev,
3285807deac2SGustavo Padovan 					 struct sk_buff *skb)
328641a96212SMarcel Holtmann {
328741a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
328841a96212SMarcel Holtmann 	struct inquiry_entry *ie;
3289cad718edSJohan Hedberg 	struct hci_conn *conn;
329041a96212SMarcel Holtmann 
329141a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
329241a96212SMarcel Holtmann 
329341a96212SMarcel Holtmann 	hci_dev_lock(hdev);
329441a96212SMarcel Holtmann 
3295cad718edSJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3296cad718edSJohan Hedberg 	if (conn)
3297cad718edSJohan Hedberg 		memcpy(conn->features[1], ev->features, 8);
3298cad718edSJohan Hedberg 
3299cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3300cc11b9c1SAndrei Emeltchenko 	if (ie)
330102b7cc62SJohan Hedberg 		ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
330241a96212SMarcel Holtmann 
330341a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
330441a96212SMarcel Holtmann }
330541a96212SMarcel Holtmann 
33066039aa73SGustavo Padovan static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
33072763eda6SSzymon Janc 					    struct sk_buff *skb)
33082763eda6SSzymon Janc {
33092763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
33102763eda6SSzymon Janc 	struct oob_data *data;
33112763eda6SSzymon Janc 
33122763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
33132763eda6SSzymon Janc 
33142763eda6SSzymon Janc 	hci_dev_lock(hdev);
33152763eda6SSzymon Janc 
3316a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
3317e1ba1f15SSzymon Janc 		goto unlock;
3318e1ba1f15SSzymon Janc 
33192763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
33202763eda6SSzymon Janc 	if (data) {
33212763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_reply cp;
33222763eda6SSzymon Janc 
33232763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
33242763eda6SSzymon Janc 		memcpy(cp.hash, data->hash, sizeof(cp.hash));
33252763eda6SSzymon Janc 		memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
33262763eda6SSzymon Janc 
33272763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
33282763eda6SSzymon Janc 			     &cp);
33292763eda6SSzymon Janc 	} else {
33302763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
33312763eda6SSzymon Janc 
33322763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
33332763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
33342763eda6SSzymon Janc 			     &cp);
33352763eda6SSzymon Janc 	}
33362763eda6SSzymon Janc 
3337e1ba1f15SSzymon Janc unlock:
33382763eda6SSzymon Janc 	hci_dev_unlock(hdev);
33392763eda6SSzymon Janc }
33402763eda6SSzymon Janc 
3341d5e91192SAndrei Emeltchenko static void hci_phy_link_complete_evt(struct hci_dev *hdev,
3342d5e91192SAndrei Emeltchenko 				      struct sk_buff *skb)
3343d5e91192SAndrei Emeltchenko {
3344d5e91192SAndrei Emeltchenko 	struct hci_ev_phy_link_complete *ev = (void *) skb->data;
3345d5e91192SAndrei Emeltchenko 	struct hci_conn *hcon, *bredr_hcon;
3346d5e91192SAndrei Emeltchenko 
3347d5e91192SAndrei Emeltchenko 	BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle,
3348d5e91192SAndrei Emeltchenko 	       ev->status);
3349d5e91192SAndrei Emeltchenko 
3350d5e91192SAndrei Emeltchenko 	hci_dev_lock(hdev);
3351d5e91192SAndrei Emeltchenko 
3352d5e91192SAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3353d5e91192SAndrei Emeltchenko 	if (!hcon) {
3354d5e91192SAndrei Emeltchenko 		hci_dev_unlock(hdev);
3355d5e91192SAndrei Emeltchenko 		return;
3356d5e91192SAndrei Emeltchenko 	}
3357d5e91192SAndrei Emeltchenko 
3358d5e91192SAndrei Emeltchenko 	if (ev->status) {
3359d5e91192SAndrei Emeltchenko 		hci_conn_del(hcon);
3360d5e91192SAndrei Emeltchenko 		hci_dev_unlock(hdev);
3361d5e91192SAndrei Emeltchenko 		return;
3362d5e91192SAndrei Emeltchenko 	}
3363d5e91192SAndrei Emeltchenko 
3364d5e91192SAndrei Emeltchenko 	bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon;
3365d5e91192SAndrei Emeltchenko 
3366d5e91192SAndrei Emeltchenko 	hcon->state = BT_CONNECTED;
3367d5e91192SAndrei Emeltchenko 	bacpy(&hcon->dst, &bredr_hcon->dst);
3368d5e91192SAndrei Emeltchenko 
3369d5e91192SAndrei Emeltchenko 	hci_conn_hold(hcon);
3370d5e91192SAndrei Emeltchenko 	hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
337176a68ba0SDavid Herrmann 	hci_conn_drop(hcon);
3372d5e91192SAndrei Emeltchenko 
3373d5e91192SAndrei Emeltchenko 	hci_conn_add_sysfs(hcon);
3374d5e91192SAndrei Emeltchenko 
3375cf70ff22SAndrei Emeltchenko 	amp_physical_cfm(bredr_hcon, hcon);
3376cf70ff22SAndrei Emeltchenko 
3377d5e91192SAndrei Emeltchenko 	hci_dev_unlock(hdev);
3378d5e91192SAndrei Emeltchenko }
3379d5e91192SAndrei Emeltchenko 
338027695fb4SAndrei Emeltchenko static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
338127695fb4SAndrei Emeltchenko {
338227695fb4SAndrei Emeltchenko 	struct hci_ev_logical_link_complete *ev = (void *) skb->data;
338327695fb4SAndrei Emeltchenko 	struct hci_conn *hcon;
338427695fb4SAndrei Emeltchenko 	struct hci_chan *hchan;
338527695fb4SAndrei Emeltchenko 	struct amp_mgr *mgr;
338627695fb4SAndrei Emeltchenko 
338727695fb4SAndrei Emeltchenko 	BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x",
338827695fb4SAndrei Emeltchenko 	       hdev->name, le16_to_cpu(ev->handle), ev->phy_handle,
338927695fb4SAndrei Emeltchenko 	       ev->status);
339027695fb4SAndrei Emeltchenko 
339127695fb4SAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
339227695fb4SAndrei Emeltchenko 	if (!hcon)
339327695fb4SAndrei Emeltchenko 		return;
339427695fb4SAndrei Emeltchenko 
339527695fb4SAndrei Emeltchenko 	/* Create AMP hchan */
339627695fb4SAndrei Emeltchenko 	hchan = hci_chan_create(hcon);
339727695fb4SAndrei Emeltchenko 	if (!hchan)
339827695fb4SAndrei Emeltchenko 		return;
339927695fb4SAndrei Emeltchenko 
340027695fb4SAndrei Emeltchenko 	hchan->handle = le16_to_cpu(ev->handle);
340127695fb4SAndrei Emeltchenko 
340227695fb4SAndrei Emeltchenko 	BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan);
340327695fb4SAndrei Emeltchenko 
340427695fb4SAndrei Emeltchenko 	mgr = hcon->amp_mgr;
340527695fb4SAndrei Emeltchenko 	if (mgr && mgr->bredr_chan) {
340627695fb4SAndrei Emeltchenko 		struct l2cap_chan *bredr_chan = mgr->bredr_chan;
340727695fb4SAndrei Emeltchenko 
340827695fb4SAndrei Emeltchenko 		l2cap_chan_lock(bredr_chan);
340927695fb4SAndrei Emeltchenko 
341027695fb4SAndrei Emeltchenko 		bredr_chan->conn->mtu = hdev->block_mtu;
341127695fb4SAndrei Emeltchenko 		l2cap_logical_cfm(bredr_chan, hchan, 0);
341227695fb4SAndrei Emeltchenko 		hci_conn_hold(hcon);
341327695fb4SAndrei Emeltchenko 
341427695fb4SAndrei Emeltchenko 		l2cap_chan_unlock(bredr_chan);
341527695fb4SAndrei Emeltchenko 	}
341627695fb4SAndrei Emeltchenko }
341727695fb4SAndrei Emeltchenko 
3418606e2a10SAndrei Emeltchenko static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,
3419606e2a10SAndrei Emeltchenko 					     struct sk_buff *skb)
3420606e2a10SAndrei Emeltchenko {
3421606e2a10SAndrei Emeltchenko 	struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data;
3422606e2a10SAndrei Emeltchenko 	struct hci_chan *hchan;
3423606e2a10SAndrei Emeltchenko 
3424606e2a10SAndrei Emeltchenko 	BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name,
3425606e2a10SAndrei Emeltchenko 	       le16_to_cpu(ev->handle), ev->status);
3426606e2a10SAndrei Emeltchenko 
3427606e2a10SAndrei Emeltchenko 	if (ev->status)
3428606e2a10SAndrei Emeltchenko 		return;
3429606e2a10SAndrei Emeltchenko 
3430606e2a10SAndrei Emeltchenko 	hci_dev_lock(hdev);
3431606e2a10SAndrei Emeltchenko 
3432606e2a10SAndrei Emeltchenko 	hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle));
3433606e2a10SAndrei Emeltchenko 	if (!hchan)
3434606e2a10SAndrei Emeltchenko 		goto unlock;
3435606e2a10SAndrei Emeltchenko 
3436606e2a10SAndrei Emeltchenko 	amp_destroy_logical_link(hchan, ev->reason);
3437606e2a10SAndrei Emeltchenko 
3438606e2a10SAndrei Emeltchenko unlock:
3439606e2a10SAndrei Emeltchenko 	hci_dev_unlock(hdev);
3440606e2a10SAndrei Emeltchenko }
3441606e2a10SAndrei Emeltchenko 
34429eef6b3aSAndrei Emeltchenko static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev,
34439eef6b3aSAndrei Emeltchenko 					     struct sk_buff *skb)
34449eef6b3aSAndrei Emeltchenko {
34459eef6b3aSAndrei Emeltchenko 	struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data;
34469eef6b3aSAndrei Emeltchenko 	struct hci_conn *hcon;
34479eef6b3aSAndrei Emeltchenko 
34489eef6b3aSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
34499eef6b3aSAndrei Emeltchenko 
34509eef6b3aSAndrei Emeltchenko 	if (ev->status)
34519eef6b3aSAndrei Emeltchenko 		return;
34529eef6b3aSAndrei Emeltchenko 
34539eef6b3aSAndrei Emeltchenko 	hci_dev_lock(hdev);
34549eef6b3aSAndrei Emeltchenko 
34559eef6b3aSAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
34569eef6b3aSAndrei Emeltchenko 	if (hcon) {
34579eef6b3aSAndrei Emeltchenko 		hcon->state = BT_CLOSED;
34589eef6b3aSAndrei Emeltchenko 		hci_conn_del(hcon);
34599eef6b3aSAndrei Emeltchenko 	}
34609eef6b3aSAndrei Emeltchenko 
34619eef6b3aSAndrei Emeltchenko 	hci_dev_unlock(hdev);
34629eef6b3aSAndrei Emeltchenko }
34639eef6b3aSAndrei Emeltchenko 
34646039aa73SGustavo Padovan static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3465fcd89c09SVille Tervo {
3466fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3467fcd89c09SVille Tervo 	struct hci_conn *conn;
3468fcd89c09SVille Tervo 
34699f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3470fcd89c09SVille Tervo 
3471fcd89c09SVille Tervo 	hci_dev_lock(hdev);
3472fcd89c09SVille Tervo 
34734f72b329SAndrzej Kaczmarek 	conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
3474b62f328bSVille Tervo 	if (!conn) {
3475b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3476b62f328bSVille Tervo 		if (!conn) {
3477b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
3478230fd16aSAndre Guedes 			goto unlock;
3479b62f328bSVille Tervo 		}
348029b7988aSAndre Guedes 
348129b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
3482b9b343d2SAndre Guedes 
3483b9b343d2SAndre Guedes 		if (ev->role == LE_CONN_ROLE_MASTER) {
3484b9b343d2SAndre Guedes 			conn->out = true;
3485b9b343d2SAndre Guedes 			conn->link_mode |= HCI_LM_MASTER;
3486b9b343d2SAndre Guedes 		}
3487b62f328bSVille Tervo 	}
3488fcd89c09SVille Tervo 
3489cd17decbSAndre Guedes 	if (ev->status) {
3490cd17decbSAndre Guedes 		mgmt_connect_failed(hdev, &conn->dst, conn->type,
3491cd17decbSAndre Guedes 				    conn->dst_type, ev->status);
3492cd17decbSAndre Guedes 		hci_proto_connect_cfm(conn, ev->status);
3493cd17decbSAndre Guedes 		conn->state = BT_CLOSED;
3494cd17decbSAndre Guedes 		hci_conn_del(conn);
3495cd17decbSAndre Guedes 		goto unlock;
3496cd17decbSAndre Guedes 	}
3497cd17decbSAndre Guedes 
3498b644ba33SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3499b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
350095b23582SSzymon Janc 				      conn->dst_type, 0, NULL, 0, NULL);
350183bc71b4SVinicius Costa Gomes 
35027b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
3503fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
3504fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
3505fcd89c09SVille Tervo 
3506fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
3507fcd89c09SVille Tervo 
3508fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
3509fcd89c09SVille Tervo 
3510fcd89c09SVille Tervo unlock:
3511fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
3512fcd89c09SVille Tervo }
3513fcd89c09SVille Tervo 
35146039aa73SGustavo Padovan static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
35159aa04c91SAndre Guedes {
3516e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
3517e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
35183c9e9195SAndre Guedes 	s8 rssi;
35199aa04c91SAndre Guedes 
3520e95beb41SAndre Guedes 	while (num_reports--) {
3521e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
3522e95beb41SAndre Guedes 
35233c9e9195SAndre Guedes 		rssi = ev->data[ev->length];
35243c9e9195SAndre Guedes 		mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
352504124681SGustavo F. Padovan 				  NULL, rssi, 0, 1, ev->data, ev->length);
35263c9e9195SAndre Guedes 
3527e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
35289aa04c91SAndre Guedes 	}
35299aa04c91SAndre Guedes }
35309aa04c91SAndre Guedes 
35316039aa73SGustavo Padovan static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
3532a7a595f6SVinicius Costa Gomes {
3533a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3534a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
3535bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
3536a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
3537c9839a11SVinicius Costa Gomes 	struct smp_ltk *ltk;
3538a7a595f6SVinicius Costa Gomes 
35399f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
3540a7a595f6SVinicius Costa Gomes 
3541a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
3542a7a595f6SVinicius Costa Gomes 
3543a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3544bea710feSVinicius Costa Gomes 	if (conn == NULL)
3545bea710feSVinicius Costa Gomes 		goto not_found;
3546a7a595f6SVinicius Costa Gomes 
3547bea710feSVinicius Costa Gomes 	ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3548bea710feSVinicius Costa Gomes 	if (ltk == NULL)
3549bea710feSVinicius Costa Gomes 		goto not_found;
3550bea710feSVinicius Costa Gomes 
3551bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
3552a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
3553c9839a11SVinicius Costa Gomes 
3554c9839a11SVinicius Costa Gomes 	if (ltk->authenticated)
3555c9839a11SVinicius Costa Gomes 		conn->sec_level = BT_SECURITY_HIGH;
3556a7a595f6SVinicius Costa Gomes 
3557a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3558a7a595f6SVinicius Costa Gomes 
3559c9839a11SVinicius Costa Gomes 	if (ltk->type & HCI_SMP_STK) {
3560c9839a11SVinicius Costa Gomes 		list_del(&ltk->list);
3561c9839a11SVinicius Costa Gomes 		kfree(ltk);
3562c9839a11SVinicius Costa Gomes 	}
3563c9839a11SVinicius Costa Gomes 
3564a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
3565bea710feSVinicius Costa Gomes 
3566bea710feSVinicius Costa Gomes 	return;
3567bea710feSVinicius Costa Gomes 
3568bea710feSVinicius Costa Gomes not_found:
3569bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
3570bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3571bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
3572a7a595f6SVinicius Costa Gomes }
3573a7a595f6SVinicius Costa Gomes 
35746039aa73SGustavo Padovan static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3575fcd89c09SVille Tervo {
3576fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
3577fcd89c09SVille Tervo 
3578fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
3579fcd89c09SVille Tervo 
3580fcd89c09SVille Tervo 	switch (le_ev->subevent) {
3581fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
3582fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
3583fcd89c09SVille Tervo 		break;
3584fcd89c09SVille Tervo 
35859aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
35869aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
35879aa04c91SAndre Guedes 		break;
35889aa04c91SAndre Guedes 
3589a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
3590a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
3591a7a595f6SVinicius Costa Gomes 		break;
3592a7a595f6SVinicius Costa Gomes 
3593fcd89c09SVille Tervo 	default:
3594fcd89c09SVille Tervo 		break;
3595fcd89c09SVille Tervo 	}
3596fcd89c09SVille Tervo }
3597fcd89c09SVille Tervo 
35989495b2eeSAndrei Emeltchenko static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
35999495b2eeSAndrei Emeltchenko {
36009495b2eeSAndrei Emeltchenko 	struct hci_ev_channel_selected *ev = (void *) skb->data;
36019495b2eeSAndrei Emeltchenko 	struct hci_conn *hcon;
36029495b2eeSAndrei Emeltchenko 
36039495b2eeSAndrei Emeltchenko 	BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
36049495b2eeSAndrei Emeltchenko 
36059495b2eeSAndrei Emeltchenko 	skb_pull(skb, sizeof(*ev));
36069495b2eeSAndrei Emeltchenko 
36079495b2eeSAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
36089495b2eeSAndrei Emeltchenko 	if (!hcon)
36099495b2eeSAndrei Emeltchenko 		return;
36109495b2eeSAndrei Emeltchenko 
36119495b2eeSAndrei Emeltchenko 	amp_read_loc_assoc_final_data(hdev, hcon);
36129495b2eeSAndrei Emeltchenko }
36139495b2eeSAndrei Emeltchenko 
36141da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
36151da177e4SLinus Torvalds {
3616a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
3617a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
36181da177e4SLinus Torvalds 
3619b6ddb638SJohan Hedberg 	hci_dev_lock(hdev);
3620b6ddb638SJohan Hedberg 
3621b6ddb638SJohan Hedberg 	/* Received events are (currently) only needed when a request is
3622b6ddb638SJohan Hedberg 	 * ongoing so avoid unnecessary memory allocation.
3623b6ddb638SJohan Hedberg 	 */
3624b6ddb638SJohan Hedberg 	if (hdev->req_status == HCI_REQ_PEND) {
3625b6ddb638SJohan Hedberg 		kfree_skb(hdev->recv_evt);
3626b6ddb638SJohan Hedberg 		hdev->recv_evt = skb_clone(skb, GFP_KERNEL);
3627b6ddb638SJohan Hedberg 	}
3628b6ddb638SJohan Hedberg 
3629b6ddb638SJohan Hedberg 	hci_dev_unlock(hdev);
3630b6ddb638SJohan Hedberg 
36311da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
36321da177e4SLinus Torvalds 
363302350a72SJohan Hedberg 	if (hdev->sent_cmd && bt_cb(hdev->sent_cmd)->req.event == event) {
363402350a72SJohan Hedberg 		struct hci_command_hdr *hdr = (void *) hdev->sent_cmd->data;
363502350a72SJohan Hedberg 		u16 opcode = __le16_to_cpu(hdr->opcode);
363602350a72SJohan Hedberg 
363702350a72SJohan Hedberg 		hci_req_cmd_complete(hdev, opcode, 0);
363802350a72SJohan Hedberg 	}
363902350a72SJohan Hedberg 
3640a9de9248SMarcel Holtmann 	switch (event) {
36411da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
36421da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
36431da177e4SLinus Torvalds 		break;
36441da177e4SLinus Torvalds 
36451da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
36461da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
36471da177e4SLinus Torvalds 		break;
36481da177e4SLinus Torvalds 
3649a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
3650a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
365121d9e30eSMarcel Holtmann 		break;
365221d9e30eSMarcel Holtmann 
36531da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
36541da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
36551da177e4SLinus Torvalds 		break;
36561da177e4SLinus Torvalds 
36571da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
36581da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
36591da177e4SLinus Torvalds 		break;
36601da177e4SLinus Torvalds 
36611da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
36621da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
36631da177e4SLinus Torvalds 		break;
36641da177e4SLinus Torvalds 
3665a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
3666a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
3667a9de9248SMarcel Holtmann 		break;
3668a9de9248SMarcel Holtmann 
36691da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
36701da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
36711da177e4SLinus Torvalds 		break;
36721da177e4SLinus Torvalds 
3673a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3674a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
3675a9de9248SMarcel Holtmann 		break;
3676a9de9248SMarcel Holtmann 
3677a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
3678a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
3679a9de9248SMarcel Holtmann 		break;
3680a9de9248SMarcel Holtmann 
3681a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
3682a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
3683a9de9248SMarcel Holtmann 		break;
3684a9de9248SMarcel Holtmann 
3685a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
3686a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
3687a9de9248SMarcel Holtmann 		break;
3688a9de9248SMarcel Holtmann 
3689a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
3690a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
3691a9de9248SMarcel Holtmann 		break;
3692a9de9248SMarcel Holtmann 
3693a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
3694a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
3695a9de9248SMarcel Holtmann 		break;
3696a9de9248SMarcel Holtmann 
3697a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
3698a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
36991da177e4SLinus Torvalds 		break;
37001da177e4SLinus Torvalds 
37011da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
37021da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
37031da177e4SLinus Torvalds 		break;
37041da177e4SLinus Torvalds 
37051da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
37061da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
37071da177e4SLinus Torvalds 		break;
37081da177e4SLinus Torvalds 
37091da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
37101da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
37111da177e4SLinus Torvalds 		break;
37121da177e4SLinus Torvalds 
37131da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
37141da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
37151da177e4SLinus Torvalds 		break;
37161da177e4SLinus Torvalds 
3717a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
3718a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
3719a8746417SMarcel Holtmann 		break;
3720a8746417SMarcel Holtmann 
372185a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
372285a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
372385a1e930SMarcel Holtmann 		break;
372485a1e930SMarcel Holtmann 
3725a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3726a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
3727a9de9248SMarcel Holtmann 		break;
3728a9de9248SMarcel Holtmann 
3729a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
3730a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
3731a9de9248SMarcel Holtmann 		break;
3732a9de9248SMarcel Holtmann 
3733a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
3734a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
3735a9de9248SMarcel Holtmann 		break;
3736a9de9248SMarcel Holtmann 
3737a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
3738a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
37391da177e4SLinus Torvalds 		break;
37401da177e4SLinus Torvalds 
37411c2e0041SJohan Hedberg 	case HCI_EV_KEY_REFRESH_COMPLETE:
37421c2e0041SJohan Hedberg 		hci_key_refresh_complete_evt(hdev, skb);
37431c2e0041SJohan Hedberg 		break;
37441c2e0041SJohan Hedberg 
37450493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
37460493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
37470493684eSMarcel Holtmann 		break;
37480493684eSMarcel Holtmann 
374903b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
375003b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
375103b555e1SJohan Hedberg 		break;
375203b555e1SJohan Hedberg 
3753a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
3754a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
3755a5c29683SJohan Hedberg 		break;
3756a5c29683SJohan Hedberg 
37571143d458SBrian Gix 	case HCI_EV_USER_PASSKEY_REQUEST:
37581143d458SBrian Gix 		hci_user_passkey_request_evt(hdev, skb);
37591143d458SBrian Gix 		break;
37601143d458SBrian Gix 
376192a25256SJohan Hedberg 	case HCI_EV_USER_PASSKEY_NOTIFY:
376292a25256SJohan Hedberg 		hci_user_passkey_notify_evt(hdev, skb);
376392a25256SJohan Hedberg 		break;
376492a25256SJohan Hedberg 
376592a25256SJohan Hedberg 	case HCI_EV_KEYPRESS_NOTIFY:
376692a25256SJohan Hedberg 		hci_keypress_notify_evt(hdev, skb);
376792a25256SJohan Hedberg 		break;
376892a25256SJohan Hedberg 
37690493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
37700493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
37710493684eSMarcel Holtmann 		break;
37720493684eSMarcel Holtmann 
377341a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
377441a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
377541a96212SMarcel Holtmann 		break;
377641a96212SMarcel Holtmann 
3777fcd89c09SVille Tervo 	case HCI_EV_LE_META:
3778fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
3779fcd89c09SVille Tervo 		break;
3780fcd89c09SVille Tervo 
37819495b2eeSAndrei Emeltchenko 	case HCI_EV_CHANNEL_SELECTED:
37829495b2eeSAndrei Emeltchenko 		hci_chan_selected_evt(hdev, skb);
37839495b2eeSAndrei Emeltchenko 		break;
37849495b2eeSAndrei Emeltchenko 
37852763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
37862763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
37872763eda6SSzymon Janc 		break;
37882763eda6SSzymon Janc 
3789d5e91192SAndrei Emeltchenko 	case HCI_EV_PHY_LINK_COMPLETE:
3790d5e91192SAndrei Emeltchenko 		hci_phy_link_complete_evt(hdev, skb);
3791d5e91192SAndrei Emeltchenko 		break;
3792d5e91192SAndrei Emeltchenko 
379327695fb4SAndrei Emeltchenko 	case HCI_EV_LOGICAL_LINK_COMPLETE:
379427695fb4SAndrei Emeltchenko 		hci_loglink_complete_evt(hdev, skb);
379527695fb4SAndrei Emeltchenko 		break;
379627695fb4SAndrei Emeltchenko 
3797606e2a10SAndrei Emeltchenko 	case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE:
3798606e2a10SAndrei Emeltchenko 		hci_disconn_loglink_complete_evt(hdev, skb);
3799606e2a10SAndrei Emeltchenko 		break;
3800606e2a10SAndrei Emeltchenko 
38019eef6b3aSAndrei Emeltchenko 	case HCI_EV_DISCONN_PHY_LINK_COMPLETE:
38029eef6b3aSAndrei Emeltchenko 		hci_disconn_phylink_complete_evt(hdev, skb);
38039eef6b3aSAndrei Emeltchenko 		break;
38049eef6b3aSAndrei Emeltchenko 
380525e89e99SAndrei Emeltchenko 	case HCI_EV_NUM_COMP_BLOCKS:
380625e89e99SAndrei Emeltchenko 		hci_num_comp_blocks_evt(hdev, skb);
380725e89e99SAndrei Emeltchenko 		break;
380825e89e99SAndrei Emeltchenko 
38091da177e4SLinus Torvalds 	default:
38109f1db00cSAndrei Emeltchenko 		BT_DBG("%s event 0x%2.2x", hdev->name, event);
38111da177e4SLinus Torvalds 		break;
38121da177e4SLinus Torvalds 	}
38131da177e4SLinus Torvalds 
38141da177e4SLinus Torvalds 	kfree_skb(skb);
38151da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
38161da177e4SLinus Torvalds }
3817