xref: /openbmc/linux/net/bluetooth/hci_event.c (revision 2cc6fb00)
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 
43e6d465cbSAndre Guedes 	if (status) {
44e6d465cbSAndre Guedes 		hci_dev_lock(hdev);
45e6d465cbSAndre Guedes 		mgmt_stop_discovery_failed(hdev, status);
46e6d465cbSAndre Guedes 		hci_dev_unlock(hdev);
47a9de9248SMarcel Holtmann 		return;
48e6d465cbSAndre Guedes 	}
491da177e4SLinus Torvalds 
5089352e7dSAndre Guedes 	clear_bit(HCI_INQUIRY, &hdev->flags);
5189352e7dSAndre Guedes 
5256e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
53ff9ef578SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
5456e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
55a9de9248SMarcel Holtmann 
569238f36aSJohan Hedberg 	hci_req_cmd_complete(hdev, HCI_OP_INQUIRY, status);
57a9de9248SMarcel Holtmann 
58a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
591da177e4SLinus Torvalds }
606bd57416SMarcel Holtmann 
614d93483bSAndre Guedes static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
624d93483bSAndre Guedes {
634d93483bSAndre Guedes 	__u8 status = *((__u8 *) skb->data);
644d93483bSAndre Guedes 
659f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
66ae854a70SAndre Guedes 
67ae854a70SAndre Guedes 	if (status)
68ae854a70SAndre Guedes 		return;
69ae854a70SAndre Guedes 
70ae854a70SAndre Guedes 	set_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
714d93483bSAndre Guedes }
724d93483bSAndre Guedes 
73a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
741da177e4SLinus Torvalds {
75a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
76a9de9248SMarcel Holtmann 
779f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
78a9de9248SMarcel Holtmann 
79a9de9248SMarcel Holtmann 	if (status)
80a9de9248SMarcel Holtmann 		return;
81a9de9248SMarcel Holtmann 
82ae854a70SAndre Guedes 	clear_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
83ae854a70SAndre Guedes 
84a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
85a9de9248SMarcel Holtmann }
86a9de9248SMarcel Holtmann 
87807deac2SGustavo Padovan static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev,
88807deac2SGustavo Padovan 					  struct sk_buff *skb)
89a9de9248SMarcel Holtmann {
90a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
91a9de9248SMarcel Holtmann }
92a9de9248SMarcel Holtmann 
93a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
94a9de9248SMarcel Holtmann {
95a9de9248SMarcel Holtmann 	struct hci_rp_role_discovery *rp = (void *) skb->data;
961da177e4SLinus Torvalds 	struct hci_conn *conn;
971da177e4SLinus Torvalds 
989f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
991da177e4SLinus Torvalds 
100a9de9248SMarcel Holtmann 	if (rp->status)
101a9de9248SMarcel Holtmann 		return;
1021da177e4SLinus Torvalds 
1031da177e4SLinus Torvalds 	hci_dev_lock(hdev);
1041da177e4SLinus Torvalds 
105a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
1061da177e4SLinus Torvalds 	if (conn) {
107a9de9248SMarcel Holtmann 		if (rp->role)
1081da177e4SLinus Torvalds 			conn->link_mode &= ~HCI_LM_MASTER;
1091da177e4SLinus Torvalds 		else
1101da177e4SLinus Torvalds 			conn->link_mode |= HCI_LM_MASTER;
1111da177e4SLinus Torvalds 	}
1121da177e4SLinus Torvalds 
1131da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
114a9de9248SMarcel Holtmann }
1151da177e4SLinus Torvalds 
116e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
117e4e8e37cSMarcel Holtmann {
118e4e8e37cSMarcel Holtmann 	struct hci_rp_read_link_policy *rp = (void *) skb->data;
119e4e8e37cSMarcel Holtmann 	struct hci_conn *conn;
120e4e8e37cSMarcel Holtmann 
1219f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
122e4e8e37cSMarcel Holtmann 
123e4e8e37cSMarcel Holtmann 	if (rp->status)
124e4e8e37cSMarcel Holtmann 		return;
125e4e8e37cSMarcel Holtmann 
126e4e8e37cSMarcel Holtmann 	hci_dev_lock(hdev);
127e4e8e37cSMarcel Holtmann 
128e4e8e37cSMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
129e4e8e37cSMarcel Holtmann 	if (conn)
130e4e8e37cSMarcel Holtmann 		conn->link_policy = __le16_to_cpu(rp->policy);
131e4e8e37cSMarcel Holtmann 
132e4e8e37cSMarcel Holtmann 	hci_dev_unlock(hdev);
133e4e8e37cSMarcel Holtmann }
134e4e8e37cSMarcel Holtmann 
135a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
136a9de9248SMarcel Holtmann {
137a9de9248SMarcel Holtmann 	struct hci_rp_write_link_policy *rp = (void *) skb->data;
138a9de9248SMarcel Holtmann 	struct hci_conn *conn;
139a9de9248SMarcel Holtmann 	void *sent;
140a9de9248SMarcel Holtmann 
1419f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
142a9de9248SMarcel Holtmann 
143a9de9248SMarcel Holtmann 	if (rp->status)
144a9de9248SMarcel Holtmann 		return;
145a9de9248SMarcel Holtmann 
146a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
14704837f64SMarcel Holtmann 	if (!sent)
148a9de9248SMarcel Holtmann 		return;
14904837f64SMarcel Holtmann 
15004837f64SMarcel Holtmann 	hci_dev_lock(hdev);
15104837f64SMarcel Holtmann 
152a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
153e4e8e37cSMarcel Holtmann 	if (conn)
15483985319SHarvey Harrison 		conn->link_policy = get_unaligned_le16(sent + 2);
15504837f64SMarcel Holtmann 
15604837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
1571da177e4SLinus Torvalds }
1581da177e4SLinus Torvalds 
159807deac2SGustavo Padovan static void hci_cc_read_def_link_policy(struct hci_dev *hdev,
160807deac2SGustavo Padovan 					struct sk_buff *skb)
161e4e8e37cSMarcel Holtmann {
162e4e8e37cSMarcel Holtmann 	struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
163e4e8e37cSMarcel Holtmann 
1649f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
165e4e8e37cSMarcel Holtmann 
166e4e8e37cSMarcel Holtmann 	if (rp->status)
167e4e8e37cSMarcel Holtmann 		return;
168e4e8e37cSMarcel Holtmann 
169e4e8e37cSMarcel Holtmann 	hdev->link_policy = __le16_to_cpu(rp->policy);
170e4e8e37cSMarcel Holtmann }
171e4e8e37cSMarcel Holtmann 
172807deac2SGustavo Padovan static void hci_cc_write_def_link_policy(struct hci_dev *hdev,
173807deac2SGustavo Padovan 					 struct sk_buff *skb)
174e4e8e37cSMarcel Holtmann {
175e4e8e37cSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
176e4e8e37cSMarcel Holtmann 	void *sent;
177e4e8e37cSMarcel Holtmann 
1789f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
179e4e8e37cSMarcel Holtmann 
180e4e8e37cSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
181e4e8e37cSMarcel Holtmann 	if (!sent)
182e4e8e37cSMarcel Holtmann 		return;
183e4e8e37cSMarcel Holtmann 
184e4e8e37cSMarcel Holtmann 	if (!status)
185e4e8e37cSMarcel Holtmann 		hdev->link_policy = get_unaligned_le16(sent);
186e4e8e37cSMarcel Holtmann }
187e4e8e37cSMarcel Holtmann 
188a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
1891da177e4SLinus Torvalds {
190a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
191a9de9248SMarcel Holtmann 
1929f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
193a9de9248SMarcel Holtmann 
19410572132SGustavo F. Padovan 	clear_bit(HCI_RESET, &hdev->flags);
19510572132SGustavo F. Padovan 
196a297e97cSJohan Hedberg 	/* Reset all non-persistent flags */
1972cc6fb00SJohan Hedberg 	hdev->dev_flags &= ~HCI_PERSISTENT_MASK;
19869775ff6SAndre Guedes 
19969775ff6SAndre Guedes 	hdev->discovery.state = DISCOVERY_STOPPED;
200bbaf444aSJohan Hedberg 	hdev->inq_tx_power = HCI_TX_POWER_INVALID;
201bbaf444aSJohan Hedberg 	hdev->adv_tx_power = HCI_TX_POWER_INVALID;
2023f0f524bSJohan Hedberg 
2033f0f524bSJohan Hedberg 	memset(hdev->adv_data, 0, sizeof(hdev->adv_data));
2043f0f524bSJohan Hedberg 	hdev->adv_data_len = 0;
205a9de9248SMarcel Holtmann }
206a9de9248SMarcel Holtmann 
207a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
208a9de9248SMarcel Holtmann {
209a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
2101da177e4SLinus Torvalds 	void *sent;
2111da177e4SLinus Torvalds 
2129f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
2131da177e4SLinus Torvalds 
214a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
2151da177e4SLinus Torvalds 	if (!sent)
216a9de9248SMarcel Holtmann 		return;
2171da177e4SLinus Torvalds 
21856e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
21956e5cb86SJohan Hedberg 
220f51d5b24SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
221f51d5b24SJohan Hedberg 		mgmt_set_local_name_complete(hdev, sent, status);
22228cc7bdeSJohan Hedberg 	else if (!status)
22328cc7bdeSJohan Hedberg 		memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
224f51d5b24SJohan Hedberg 
22556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
2263159d384SJohan Hedberg 
2273f0f524bSJohan Hedberg 	if (!status && !test_bit(HCI_INIT, &hdev->flags))
2283f0f524bSJohan Hedberg 		hci_update_ad(hdev);
229a9de9248SMarcel Holtmann }
230a9de9248SMarcel Holtmann 
231a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
232a9de9248SMarcel Holtmann {
233a9de9248SMarcel Holtmann 	struct hci_rp_read_local_name *rp = (void *) skb->data;
234a9de9248SMarcel Holtmann 
2359f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
236a9de9248SMarcel Holtmann 
237a9de9248SMarcel Holtmann 	if (rp->status)
238a9de9248SMarcel Holtmann 		return;
239a9de9248SMarcel Holtmann 
240db99b5fcSJohan Hedberg 	if (test_bit(HCI_SETUP, &hdev->dev_flags))
2411f6c6378SJohan Hedberg 		memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
242a9de9248SMarcel Holtmann }
243a9de9248SMarcel Holtmann 
244a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
245a9de9248SMarcel Holtmann {
246a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
247a9de9248SMarcel Holtmann 	void *sent;
248a9de9248SMarcel Holtmann 
2499f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
250a9de9248SMarcel Holtmann 
251a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
252a9de9248SMarcel Holtmann 	if (!sent)
253a9de9248SMarcel Holtmann 		return;
2541da177e4SLinus Torvalds 
2551da177e4SLinus Torvalds 	if (!status) {
256a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
257a9de9248SMarcel Holtmann 
2581da177e4SLinus Torvalds 		if (param == AUTH_ENABLED)
2591da177e4SLinus Torvalds 			set_bit(HCI_AUTH, &hdev->flags);
2601da177e4SLinus Torvalds 		else
2611da177e4SLinus Torvalds 			clear_bit(HCI_AUTH, &hdev->flags);
2621da177e4SLinus Torvalds 	}
263a9de9248SMarcel Holtmann 
26433ef95edSJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
26533ef95edSJohan Hedberg 		mgmt_auth_enable_complete(hdev, status);
266a9de9248SMarcel Holtmann }
2671da177e4SLinus Torvalds 
268a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
269a9de9248SMarcel Holtmann {
270a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
271a9de9248SMarcel Holtmann 	void *sent;
272a9de9248SMarcel Holtmann 
2739f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
274a9de9248SMarcel Holtmann 
275a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
2761da177e4SLinus Torvalds 	if (!sent)
277a9de9248SMarcel Holtmann 		return;
2781da177e4SLinus Torvalds 
2791da177e4SLinus Torvalds 	if (!status) {
280a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
281a9de9248SMarcel Holtmann 
2821da177e4SLinus Torvalds 		if (param)
2831da177e4SLinus Torvalds 			set_bit(HCI_ENCRYPT, &hdev->flags);
2841da177e4SLinus Torvalds 		else
2851da177e4SLinus Torvalds 			clear_bit(HCI_ENCRYPT, &hdev->flags);
2861da177e4SLinus Torvalds 	}
2871da177e4SLinus Torvalds }
2881da177e4SLinus Torvalds 
289a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
290a9de9248SMarcel Holtmann {
29136f7fc7eSJohan Hedberg 	__u8 param, status = *((__u8 *) skb->data);
29236f7fc7eSJohan Hedberg 	int old_pscan, old_iscan;
293a9de9248SMarcel Holtmann 	void *sent;
2941da177e4SLinus Torvalds 
2959f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
296a9de9248SMarcel Holtmann 
297a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
2981da177e4SLinus Torvalds 	if (!sent)
299a9de9248SMarcel Holtmann 		return;
3001da177e4SLinus Torvalds 
30136f7fc7eSJohan Hedberg 	param = *((__u8 *) sent);
302a9de9248SMarcel Holtmann 
30356e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
30456e5cb86SJohan Hedberg 
305fa1bd918SMikel Astiz 	if (status) {
306744cf19eSJohan Hedberg 		mgmt_write_scan_failed(hdev, param, status);
3072d7cee58SJohan Hedberg 		hdev->discov_timeout = 0;
3082d7cee58SJohan Hedberg 		goto done;
3092d7cee58SJohan Hedberg 	}
3102d7cee58SJohan Hedberg 
3119fbcbb45SJohan Hedberg 	old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
3129fbcbb45SJohan Hedberg 	old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
313a9de9248SMarcel Holtmann 
31473f22f62SJohan Hedberg 	if (param & SCAN_INQUIRY) {
3151da177e4SLinus Torvalds 		set_bit(HCI_ISCAN, &hdev->flags);
3169fbcbb45SJohan Hedberg 		if (!old_iscan)
317744cf19eSJohan Hedberg 			mgmt_discoverable(hdev, 1);
31816ab91abSJohan Hedberg 		if (hdev->discov_timeout > 0) {
31916ab91abSJohan Hedberg 			int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
32016ab91abSJohan Hedberg 			queue_delayed_work(hdev->workqueue, &hdev->discov_off,
32116ab91abSJohan Hedberg 					   to);
32216ab91abSJohan Hedberg 		}
3239fbcbb45SJohan Hedberg 	} else if (old_iscan)
324744cf19eSJohan Hedberg 		mgmt_discoverable(hdev, 0);
3251da177e4SLinus Torvalds 
3269fbcbb45SJohan Hedberg 	if (param & SCAN_PAGE) {
3271da177e4SLinus Torvalds 		set_bit(HCI_PSCAN, &hdev->flags);
3289fbcbb45SJohan Hedberg 		if (!old_pscan)
329744cf19eSJohan Hedberg 			mgmt_connectable(hdev, 1);
3309fbcbb45SJohan Hedberg 	} else if (old_pscan)
331744cf19eSJohan Hedberg 		mgmt_connectable(hdev, 0);
332a9de9248SMarcel Holtmann 
33336f7fc7eSJohan Hedberg done:
33456e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
3351da177e4SLinus Torvalds }
3361da177e4SLinus Torvalds 
337a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
338a9de9248SMarcel Holtmann {
339a9de9248SMarcel Holtmann 	struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
340a9de9248SMarcel Holtmann 
3419f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
342a9de9248SMarcel Holtmann 
343a9de9248SMarcel Holtmann 	if (rp->status)
344a9de9248SMarcel Holtmann 		return;
345a9de9248SMarcel Holtmann 
346a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, rp->dev_class, 3);
347a9de9248SMarcel Holtmann 
348a9de9248SMarcel Holtmann 	BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
349a9de9248SMarcel Holtmann 	       hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
350a9de9248SMarcel Holtmann }
351a9de9248SMarcel Holtmann 
352a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
353a9de9248SMarcel Holtmann {
354a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
355a9de9248SMarcel Holtmann 	void *sent;
356a9de9248SMarcel Holtmann 
3579f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
358a9de9248SMarcel Holtmann 
359a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
360a9de9248SMarcel Holtmann 	if (!sent)
361a9de9248SMarcel Holtmann 		return;
362a9de9248SMarcel Holtmann 
3637f9a903cSMarcel Holtmann 	hci_dev_lock(hdev);
3647f9a903cSMarcel Holtmann 
3657f9a903cSMarcel Holtmann 	if (status == 0)
366a9de9248SMarcel Holtmann 		memcpy(hdev->dev_class, sent, 3);
3677f9a903cSMarcel Holtmann 
3687f9a903cSMarcel Holtmann 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3697f9a903cSMarcel Holtmann 		mgmt_set_class_of_dev_complete(hdev, sent, status);
3707f9a903cSMarcel Holtmann 
3717f9a903cSMarcel Holtmann 	hci_dev_unlock(hdev);
372a9de9248SMarcel Holtmann }
373a9de9248SMarcel Holtmann 
374a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
375a9de9248SMarcel Holtmann {
376a9de9248SMarcel Holtmann 	struct hci_rp_read_voice_setting *rp = (void *) skb->data;
377a9de9248SMarcel Holtmann 	__u16 setting;
378a9de9248SMarcel Holtmann 
3799f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
380a9de9248SMarcel Holtmann 
381a9de9248SMarcel Holtmann 	if (rp->status)
382a9de9248SMarcel Holtmann 		return;
383a9de9248SMarcel Holtmann 
384a9de9248SMarcel Holtmann 	setting = __le16_to_cpu(rp->voice_setting);
385a9de9248SMarcel Holtmann 
386a9de9248SMarcel Holtmann 	if (hdev->voice_setting == setting)
387a9de9248SMarcel Holtmann 		return;
388a9de9248SMarcel Holtmann 
389a9de9248SMarcel Holtmann 	hdev->voice_setting = setting;
390a9de9248SMarcel Holtmann 
3919f1db00cSAndrei Emeltchenko 	BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
392a9de9248SMarcel Holtmann 
3933c54711cSGustavo F. Padovan 	if (hdev->notify)
394a9de9248SMarcel Holtmann 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
395a9de9248SMarcel Holtmann }
396a9de9248SMarcel Holtmann 
3978fc9ced3SGustavo Padovan static void hci_cc_write_voice_setting(struct hci_dev *hdev,
3988fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
399a9de9248SMarcel Holtmann {
400a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
401f383f275SMarcel Holtmann 	__u16 setting;
402a9de9248SMarcel Holtmann 	void *sent;
403a9de9248SMarcel Holtmann 
4049f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
405a9de9248SMarcel Holtmann 
406f383f275SMarcel Holtmann 	if (status)
407f383f275SMarcel Holtmann 		return;
408f383f275SMarcel Holtmann 
409a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
410a9de9248SMarcel Holtmann 	if (!sent)
411a9de9248SMarcel Holtmann 		return;
412a9de9248SMarcel Holtmann 
413f383f275SMarcel Holtmann 	setting = get_unaligned_le16(sent);
4141da177e4SLinus Torvalds 
415f383f275SMarcel Holtmann 	if (hdev->voice_setting == setting)
416f383f275SMarcel Holtmann 		return;
417f383f275SMarcel Holtmann 
4181da177e4SLinus Torvalds 	hdev->voice_setting = setting;
4191da177e4SLinus Torvalds 
4209f1db00cSAndrei Emeltchenko 	BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
4211da177e4SLinus Torvalds 
4223c54711cSGustavo F. Padovan 	if (hdev->notify)
4231da177e4SLinus Torvalds 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
4241da177e4SLinus Torvalds }
4251da177e4SLinus Torvalds 
426333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
427333140b5SMarcel Holtmann {
428333140b5SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
4295ed8eb2fSJohan Hedberg 	struct hci_cp_write_ssp_mode *sent;
430333140b5SMarcel Holtmann 
4319f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
432333140b5SMarcel Holtmann 
433333140b5SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
434333140b5SMarcel Holtmann 	if (!sent)
435333140b5SMarcel Holtmann 		return;
436333140b5SMarcel Holtmann 
4375ed8eb2fSJohan Hedberg 	if (!status) {
4385ed8eb2fSJohan Hedberg 		if (sent->mode)
4395ed8eb2fSJohan Hedberg 			hdev->host_features[0] |= LMP_HOST_SSP;
4405ed8eb2fSJohan Hedberg 		else
4415ed8eb2fSJohan Hedberg 			hdev->host_features[0] &= ~LMP_HOST_SSP;
4425ed8eb2fSJohan Hedberg 	}
4435ed8eb2fSJohan Hedberg 
444c0ecddc2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
4455ed8eb2fSJohan Hedberg 		mgmt_ssp_enable_complete(hdev, sent->mode, status);
446c0ecddc2SJohan Hedberg 	else if (!status) {
4475ed8eb2fSJohan Hedberg 		if (sent->mode)
44884bde9d6SJohan Hedberg 			set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
44984bde9d6SJohan Hedberg 		else
45084bde9d6SJohan Hedberg 			clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
451c0ecddc2SJohan Hedberg 	}
452333140b5SMarcel Holtmann }
453333140b5SMarcel Holtmann 
454a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
455a9de9248SMarcel Holtmann {
456a9de9248SMarcel Holtmann 	struct hci_rp_read_local_version *rp = (void *) skb->data;
4571143e5a6SMarcel Holtmann 
4589f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
4591143e5a6SMarcel Holtmann 
460a9de9248SMarcel Holtmann 	if (rp->status)
46142c6b129SJohan Hedberg 		return;
4621143e5a6SMarcel Holtmann 
463a9de9248SMarcel Holtmann 	hdev->hci_ver = rp->hci_ver;
464e4e8e37cSMarcel Holtmann 	hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
465d5859e22SJohan Hedberg 	hdev->lmp_ver = rp->lmp_ver;
466e4e8e37cSMarcel Holtmann 	hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
467d5859e22SJohan Hedberg 	hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
4681da177e4SLinus Torvalds 
4699f1db00cSAndrei Emeltchenko 	BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name,
470807deac2SGustavo Padovan 	       hdev->manufacturer, hdev->hci_ver, hdev->hci_rev);
471d5859e22SJohan Hedberg }
472d5859e22SJohan Hedberg 
4738fc9ced3SGustavo Padovan static void hci_cc_read_local_commands(struct hci_dev *hdev,
4748fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
475a9de9248SMarcel Holtmann {
476a9de9248SMarcel Holtmann 	struct hci_rp_read_local_commands *rp = (void *) skb->data;
477a9de9248SMarcel Holtmann 
4789f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
479a9de9248SMarcel Holtmann 
4802177bab5SJohan Hedberg 	if (!rp->status)
481a9de9248SMarcel Holtmann 		memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
482a9de9248SMarcel Holtmann }
483a9de9248SMarcel Holtmann 
4848fc9ced3SGustavo Padovan static void hci_cc_read_local_features(struct hci_dev *hdev,
4858fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
486a9de9248SMarcel Holtmann {
487a9de9248SMarcel Holtmann 	struct hci_rp_read_local_features *rp = (void *) skb->data;
488a9de9248SMarcel Holtmann 
4899f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
490a9de9248SMarcel Holtmann 
491a9de9248SMarcel Holtmann 	if (rp->status)
492a9de9248SMarcel Holtmann 		return;
493a9de9248SMarcel Holtmann 
494a9de9248SMarcel Holtmann 	memcpy(hdev->features, rp->features, 8);
4951da177e4SLinus Torvalds 
4961da177e4SLinus Torvalds 	/* Adjust default settings according to features
4971da177e4SLinus Torvalds 	 * supported by device. */
498a9de9248SMarcel Holtmann 
4991da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_3SLOT)
5001da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
5011da177e4SLinus Torvalds 
5021da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_5SLOT)
5031da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
5041da177e4SLinus Torvalds 
5055b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV2) {
5061da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV2);
5075b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV2);
5085b7f9909SMarcel Holtmann 	}
5091da177e4SLinus Torvalds 
5105b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV3) {
5111da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV3);
5125b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV3);
5135b7f9909SMarcel Holtmann 	}
5145b7f9909SMarcel Holtmann 
51545db810fSAndre Guedes 	if (lmp_esco_capable(hdev))
5165b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV3);
5175b7f9909SMarcel Holtmann 
5185b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV4)
5195b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV4);
5205b7f9909SMarcel Holtmann 
5215b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV5)
5225b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV5);
5231da177e4SLinus Torvalds 
524efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_2M)
525efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV3);
526efc7688bSMarcel Holtmann 
527efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_3M)
528efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_3EV3);
529efc7688bSMarcel Holtmann 
530efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_3S_ESCO)
531efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
532efc7688bSMarcel Holtmann 
533a9de9248SMarcel Holtmann 	BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
534a9de9248SMarcel Holtmann 	       hdev->features[0], hdev->features[1],
535a9de9248SMarcel Holtmann 	       hdev->features[2], hdev->features[3],
536a9de9248SMarcel Holtmann 	       hdev->features[4], hdev->features[5],
537a9de9248SMarcel Holtmann 	       hdev->features[6], hdev->features[7]);
5381da177e4SLinus Torvalds }
5391da177e4SLinus Torvalds 
540971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
541971e3a4bSAndre Guedes 					   struct sk_buff *skb)
542971e3a4bSAndre Guedes {
543971e3a4bSAndre Guedes 	struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
544971e3a4bSAndre Guedes 
5459f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
546971e3a4bSAndre Guedes 
547971e3a4bSAndre Guedes 	if (rp->status)
54842c6b129SJohan Hedberg 		return;
549971e3a4bSAndre Guedes 
550b5b32b65SAndre Guedes 	switch (rp->page) {
551b5b32b65SAndre Guedes 	case 0:
552b5b32b65SAndre Guedes 		memcpy(hdev->features, rp->features, 8);
553b5b32b65SAndre Guedes 		break;
554b5b32b65SAndre Guedes 	case 1:
55559e29406SAndre Guedes 		memcpy(hdev->host_features, rp->features, 8);
556b5b32b65SAndre Guedes 		break;
557b5b32b65SAndre Guedes 	}
558971e3a4bSAndre Guedes }
559971e3a4bSAndre Guedes 
5601e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
5611e89cffbSAndrei Emeltchenko 					  struct sk_buff *skb)
5621e89cffbSAndrei Emeltchenko {
5631e89cffbSAndrei Emeltchenko 	struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
5641e89cffbSAndrei Emeltchenko 
5659f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
5661e89cffbSAndrei Emeltchenko 
56742c6b129SJohan Hedberg 	if (!rp->status)
5681e89cffbSAndrei Emeltchenko 		hdev->flow_ctl_mode = rp->mode;
5691e89cffbSAndrei Emeltchenko }
5701e89cffbSAndrei Emeltchenko 
571a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
572a9de9248SMarcel Holtmann {
573a9de9248SMarcel Holtmann 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
574a9de9248SMarcel Holtmann 
5759f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
576a9de9248SMarcel Holtmann 
577a9de9248SMarcel Holtmann 	if (rp->status)
578a9de9248SMarcel Holtmann 		return;
579a9de9248SMarcel Holtmann 
580a9de9248SMarcel Holtmann 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
581a9de9248SMarcel Holtmann 	hdev->sco_mtu  = rp->sco_mtu;
582a9de9248SMarcel Holtmann 	hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
583a9de9248SMarcel Holtmann 	hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
584da1f5198SMarcel Holtmann 
585da1f5198SMarcel Holtmann 	if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
586da1f5198SMarcel Holtmann 		hdev->sco_mtu  = 64;
587da1f5198SMarcel Holtmann 		hdev->sco_pkts = 8;
588da1f5198SMarcel Holtmann 	}
589da1f5198SMarcel Holtmann 
590da1f5198SMarcel Holtmann 	hdev->acl_cnt = hdev->acl_pkts;
591da1f5198SMarcel Holtmann 	hdev->sco_cnt = hdev->sco_pkts;
5921da177e4SLinus Torvalds 
593807deac2SGustavo Padovan 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
594807deac2SGustavo Padovan 	       hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
5951da177e4SLinus Torvalds }
5961da177e4SLinus Torvalds 
597a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
598a9de9248SMarcel Holtmann {
599a9de9248SMarcel Holtmann 	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
6001da177e4SLinus Torvalds 
6019f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
602a9de9248SMarcel Holtmann 
603a9de9248SMarcel Holtmann 	if (!rp->status)
604a9de9248SMarcel Holtmann 		bacpy(&hdev->bdaddr, &rp->bdaddr);
60523bb5763SJohan Hedberg }
60623bb5763SJohan Hedberg 
607350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev,
608350ee4cfSAndrei Emeltchenko 					struct sk_buff *skb)
609350ee4cfSAndrei Emeltchenko {
610350ee4cfSAndrei Emeltchenko 	struct hci_rp_read_data_block_size *rp = (void *) skb->data;
611350ee4cfSAndrei Emeltchenko 
6129f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
613350ee4cfSAndrei Emeltchenko 
614350ee4cfSAndrei Emeltchenko 	if (rp->status)
615350ee4cfSAndrei Emeltchenko 		return;
616350ee4cfSAndrei Emeltchenko 
617350ee4cfSAndrei Emeltchenko 	hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
618350ee4cfSAndrei Emeltchenko 	hdev->block_len = __le16_to_cpu(rp->block_len);
619350ee4cfSAndrei Emeltchenko 	hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
620350ee4cfSAndrei Emeltchenko 
621350ee4cfSAndrei Emeltchenko 	hdev->block_cnt = hdev->num_blocks;
622350ee4cfSAndrei Emeltchenko 
623350ee4cfSAndrei Emeltchenko 	BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
624350ee4cfSAndrei Emeltchenko 	       hdev->block_cnt, hdev->block_len);
625350ee4cfSAndrei Emeltchenko }
626350ee4cfSAndrei Emeltchenko 
627928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
628928abaa7SAndrei Emeltchenko 				       struct sk_buff *skb)
629928abaa7SAndrei Emeltchenko {
630928abaa7SAndrei Emeltchenko 	struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
631928abaa7SAndrei Emeltchenko 
6329f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
633928abaa7SAndrei Emeltchenko 
634928abaa7SAndrei Emeltchenko 	if (rp->status)
6358e2a0d92SAndrei Emeltchenko 		goto a2mp_rsp;
636928abaa7SAndrei Emeltchenko 
637928abaa7SAndrei Emeltchenko 	hdev->amp_status = rp->amp_status;
638928abaa7SAndrei Emeltchenko 	hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
639928abaa7SAndrei Emeltchenko 	hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
640928abaa7SAndrei Emeltchenko 	hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
641928abaa7SAndrei Emeltchenko 	hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
642928abaa7SAndrei Emeltchenko 	hdev->amp_type = rp->amp_type;
643928abaa7SAndrei Emeltchenko 	hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
644928abaa7SAndrei Emeltchenko 	hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
645928abaa7SAndrei Emeltchenko 	hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
646928abaa7SAndrei Emeltchenko 	hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
647928abaa7SAndrei Emeltchenko 
6488e2a0d92SAndrei Emeltchenko a2mp_rsp:
6498e2a0d92SAndrei Emeltchenko 	a2mp_send_getinfo_rsp(hdev);
650928abaa7SAndrei Emeltchenko }
651928abaa7SAndrei Emeltchenko 
652903e4541SAndrei Emeltchenko static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev,
653903e4541SAndrei Emeltchenko 					struct sk_buff *skb)
654903e4541SAndrei Emeltchenko {
655903e4541SAndrei Emeltchenko 	struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data;
656903e4541SAndrei Emeltchenko 	struct amp_assoc *assoc = &hdev->loc_assoc;
657903e4541SAndrei Emeltchenko 	size_t rem_len, frag_len;
658903e4541SAndrei Emeltchenko 
659903e4541SAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
660903e4541SAndrei Emeltchenko 
661903e4541SAndrei Emeltchenko 	if (rp->status)
662903e4541SAndrei Emeltchenko 		goto a2mp_rsp;
663903e4541SAndrei Emeltchenko 
664903e4541SAndrei Emeltchenko 	frag_len = skb->len - sizeof(*rp);
665903e4541SAndrei Emeltchenko 	rem_len = __le16_to_cpu(rp->rem_len);
666903e4541SAndrei Emeltchenko 
667903e4541SAndrei Emeltchenko 	if (rem_len > frag_len) {
6682e430be3SAndrei Emeltchenko 		BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len);
669903e4541SAndrei Emeltchenko 
670903e4541SAndrei Emeltchenko 		memcpy(assoc->data + assoc->offset, rp->frag, frag_len);
671903e4541SAndrei Emeltchenko 		assoc->offset += frag_len;
672903e4541SAndrei Emeltchenko 
673903e4541SAndrei Emeltchenko 		/* Read other fragments */
674903e4541SAndrei Emeltchenko 		amp_read_loc_assoc_frag(hdev, rp->phy_handle);
675903e4541SAndrei Emeltchenko 
676903e4541SAndrei Emeltchenko 		return;
677903e4541SAndrei Emeltchenko 	}
678903e4541SAndrei Emeltchenko 
679903e4541SAndrei Emeltchenko 	memcpy(assoc->data + assoc->offset, rp->frag, rem_len);
680903e4541SAndrei Emeltchenko 	assoc->len = assoc->offset + rem_len;
681903e4541SAndrei Emeltchenko 	assoc->offset = 0;
682903e4541SAndrei Emeltchenko 
683903e4541SAndrei Emeltchenko a2mp_rsp:
684903e4541SAndrei Emeltchenko 	/* Send A2MP Rsp when all fragments are received */
685903e4541SAndrei Emeltchenko 	a2mp_send_getampassoc_rsp(hdev, rp->status);
6869495b2eeSAndrei Emeltchenko 	a2mp_send_create_phy_link_req(hdev, rp->status);
687903e4541SAndrei Emeltchenko }
688903e4541SAndrei Emeltchenko 
689d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
690d5859e22SJohan Hedberg 					 struct sk_buff *skb)
691d5859e22SJohan Hedberg {
69291c4e9b1SMarcel Holtmann 	struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
693d5859e22SJohan Hedberg 
6949f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
695d5859e22SJohan Hedberg 
69691c4e9b1SMarcel Holtmann 	if (!rp->status)
69791c4e9b1SMarcel Holtmann 		hdev->inq_tx_power = rp->tx_power;
698d5859e22SJohan Hedberg }
699d5859e22SJohan Hedberg 
700980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
701980e1a53SJohan Hedberg {
702980e1a53SJohan Hedberg 	struct hci_rp_pin_code_reply *rp = (void *) skb->data;
703980e1a53SJohan Hedberg 	struct hci_cp_pin_code_reply *cp;
704980e1a53SJohan Hedberg 	struct hci_conn *conn;
705980e1a53SJohan Hedberg 
7069f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
707980e1a53SJohan Hedberg 
70856e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
70956e5cb86SJohan Hedberg 
710a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
711744cf19eSJohan Hedberg 		mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
712980e1a53SJohan Hedberg 
713fa1bd918SMikel Astiz 	if (rp->status)
71456e5cb86SJohan Hedberg 		goto unlock;
715980e1a53SJohan Hedberg 
716980e1a53SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
717980e1a53SJohan Hedberg 	if (!cp)
71856e5cb86SJohan Hedberg 		goto unlock;
719980e1a53SJohan Hedberg 
720980e1a53SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
721980e1a53SJohan Hedberg 	if (conn)
722980e1a53SJohan Hedberg 		conn->pin_length = cp->pin_len;
72356e5cb86SJohan Hedberg 
72456e5cb86SJohan Hedberg unlock:
72556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
726980e1a53SJohan Hedberg }
727980e1a53SJohan Hedberg 
728980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
729980e1a53SJohan Hedberg {
730980e1a53SJohan Hedberg 	struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
731980e1a53SJohan Hedberg 
7329f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
733980e1a53SJohan Hedberg 
73456e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
73556e5cb86SJohan Hedberg 
736a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
737744cf19eSJohan Hedberg 		mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
738980e1a53SJohan Hedberg 						 rp->status);
73956e5cb86SJohan Hedberg 
74056e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
741980e1a53SJohan Hedberg }
74256e5cb86SJohan Hedberg 
7436ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
7446ed58ec5SVille Tervo 				       struct sk_buff *skb)
7456ed58ec5SVille Tervo {
7466ed58ec5SVille Tervo 	struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
7476ed58ec5SVille Tervo 
7489f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
7496ed58ec5SVille Tervo 
7506ed58ec5SVille Tervo 	if (rp->status)
7516ed58ec5SVille Tervo 		return;
7526ed58ec5SVille Tervo 
7536ed58ec5SVille Tervo 	hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
7546ed58ec5SVille Tervo 	hdev->le_pkts = rp->le_max_pkt;
7556ed58ec5SVille Tervo 
7566ed58ec5SVille Tervo 	hdev->le_cnt = hdev->le_pkts;
7576ed58ec5SVille Tervo 
7586ed58ec5SVille Tervo 	BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
7596ed58ec5SVille Tervo }
760980e1a53SJohan Hedberg 
76160e77321SJohan Hedberg static void hci_cc_le_read_local_features(struct hci_dev *hdev,
76260e77321SJohan Hedberg 					  struct sk_buff *skb)
76360e77321SJohan Hedberg {
76460e77321SJohan Hedberg 	struct hci_rp_le_read_local_features *rp = (void *) skb->data;
76560e77321SJohan Hedberg 
76660e77321SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
76760e77321SJohan Hedberg 
76860e77321SJohan Hedberg 	if (!rp->status)
76960e77321SJohan Hedberg 		memcpy(hdev->le_features, rp->features, 8);
77060e77321SJohan Hedberg }
77160e77321SJohan Hedberg 
7728fa19098SJohan Hedberg static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
7738fa19098SJohan Hedberg 					struct sk_buff *skb)
7748fa19098SJohan Hedberg {
7758fa19098SJohan Hedberg 	struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data;
7768fa19098SJohan Hedberg 
7778fa19098SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
7788fa19098SJohan Hedberg 
7793f0f524bSJohan Hedberg 	if (!rp->status) {
7808fa19098SJohan Hedberg 		hdev->adv_tx_power = rp->tx_power;
7813f0f524bSJohan Hedberg 		if (!test_bit(HCI_INIT, &hdev->flags))
7823f0f524bSJohan Hedberg 			hci_update_ad(hdev);
7833f0f524bSJohan Hedberg 	}
7848fa19098SJohan Hedberg }
7858fa19098SJohan Hedberg 
786a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
787a5c29683SJohan Hedberg {
788a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
789a5c29683SJohan Hedberg 
7909f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
791a5c29683SJohan Hedberg 
79256e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
79356e5cb86SJohan Hedberg 
794a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
79504124681SGustavo F. Padovan 		mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
79604124681SGustavo F. Padovan 						 rp->status);
79756e5cb86SJohan Hedberg 
79856e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
799a5c29683SJohan Hedberg }
800a5c29683SJohan Hedberg 
801a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
802a5c29683SJohan Hedberg 					  struct sk_buff *skb)
803a5c29683SJohan Hedberg {
804a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
805a5c29683SJohan Hedberg 
8069f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
807a5c29683SJohan Hedberg 
80856e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
80956e5cb86SJohan Hedberg 
810a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
811744cf19eSJohan Hedberg 		mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
81204124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
81356e5cb86SJohan Hedberg 
81456e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
815a5c29683SJohan Hedberg }
816a5c29683SJohan Hedberg 
8171143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
8181143d458SBrian Gix {
8191143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
8201143d458SBrian Gix 
8219f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
8221143d458SBrian Gix 
8231143d458SBrian Gix 	hci_dev_lock(hdev);
8241143d458SBrian Gix 
825a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
826272d90dfSJohan Hedberg 		mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
827272d90dfSJohan Hedberg 						 0, rp->status);
8281143d458SBrian Gix 
8291143d458SBrian Gix 	hci_dev_unlock(hdev);
8301143d458SBrian Gix }
8311143d458SBrian Gix 
8321143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
8331143d458SBrian Gix 					  struct sk_buff *skb)
8341143d458SBrian Gix {
8351143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
8361143d458SBrian Gix 
8379f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
8381143d458SBrian Gix 
8391143d458SBrian Gix 	hci_dev_lock(hdev);
8401143d458SBrian Gix 
841a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
8421143d458SBrian Gix 		mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
84304124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
8441143d458SBrian Gix 
8451143d458SBrian Gix 	hci_dev_unlock(hdev);
8461143d458SBrian Gix }
8471143d458SBrian Gix 
848c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
849c35938b2SSzymon Janc 					     struct sk_buff *skb)
850c35938b2SSzymon Janc {
851c35938b2SSzymon Janc 	struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
852c35938b2SSzymon Janc 
8539f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
854c35938b2SSzymon Janc 
85556e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
856744cf19eSJohan Hedberg 	mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
857c35938b2SSzymon Janc 						rp->randomizer, rp->status);
85856e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
859c35938b2SSzymon Janc }
860c35938b2SSzymon Janc 
861c1d5dc4aSJohan Hedberg static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
862c1d5dc4aSJohan Hedberg {
863c1d5dc4aSJohan Hedberg 	__u8 *sent, status = *((__u8 *) skb->data);
864c1d5dc4aSJohan Hedberg 
865c1d5dc4aSJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
866c1d5dc4aSJohan Hedberg 
867c1d5dc4aSJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE);
868c1d5dc4aSJohan Hedberg 	if (!sent)
869c1d5dc4aSJohan Hedberg 		return;
870c1d5dc4aSJohan Hedberg 
871c1d5dc4aSJohan Hedberg 	hci_dev_lock(hdev);
872c1d5dc4aSJohan Hedberg 
873c1d5dc4aSJohan Hedberg 	if (!status) {
874c1d5dc4aSJohan Hedberg 		if (*sent)
875c1d5dc4aSJohan Hedberg 			set_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
876c1d5dc4aSJohan Hedberg 		else
877c1d5dc4aSJohan Hedberg 			clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
878c1d5dc4aSJohan Hedberg 	}
879c1d5dc4aSJohan Hedberg 
880c1d5dc4aSJohan Hedberg 	hci_dev_unlock(hdev);
881c1d5dc4aSJohan Hedberg 
882c1d5dc4aSJohan Hedberg 	if (!test_bit(HCI_INIT, &hdev->flags))
883c1d5dc4aSJohan Hedberg 		hci_update_ad(hdev);
884c1d5dc4aSJohan Hedberg }
885c1d5dc4aSJohan Hedberg 
88607f7fa5dSAndre Guedes static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
88707f7fa5dSAndre Guedes {
88807f7fa5dSAndre Guedes 	__u8 status = *((__u8 *) skb->data);
88907f7fa5dSAndre Guedes 
8909f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
8917ba8b4beSAndre Guedes 
8923fd24153SAndre Guedes 	if (status) {
8933fd24153SAndre Guedes 		hci_dev_lock(hdev);
8943fd24153SAndre Guedes 		mgmt_start_discovery_failed(hdev, status);
8953fd24153SAndre Guedes 		hci_dev_unlock(hdev);
8963fd24153SAndre Guedes 		return;
8973fd24153SAndre Guedes 	}
89807f7fa5dSAndre Guedes }
89907f7fa5dSAndre Guedes 
900eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
901eb9d91f5SAndre Guedes 				      struct sk_buff *skb)
902eb9d91f5SAndre Guedes {
903eb9d91f5SAndre Guedes 	struct hci_cp_le_set_scan_enable *cp;
904eb9d91f5SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
905eb9d91f5SAndre Guedes 
9069f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
907eb9d91f5SAndre Guedes 
908eb9d91f5SAndre Guedes 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
909eb9d91f5SAndre Guedes 	if (!cp)
910eb9d91f5SAndre Guedes 		return;
911eb9d91f5SAndre Guedes 
91268a8aea4SAndrei Emeltchenko 	switch (cp->enable) {
91368a8aea4SAndrei Emeltchenko 	case LE_SCANNING_ENABLED:
9143fd24153SAndre Guedes 		if (status) {
9153fd24153SAndre Guedes 			hci_dev_lock(hdev);
9163fd24153SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
9173fd24153SAndre Guedes 			hci_dev_unlock(hdev);
9187ba8b4beSAndre Guedes 			return;
9193fd24153SAndre Guedes 		}
9207ba8b4beSAndre Guedes 
921d23264a8SAndre Guedes 		set_bit(HCI_LE_SCAN, &hdev->dev_flags);
922d23264a8SAndre Guedes 
923a8f13c8cSAndre Guedes 		hci_dev_lock(hdev);
924343f935bSAndre Guedes 		hci_discovery_set_state(hdev, DISCOVERY_FINDING);
925a8f13c8cSAndre Guedes 		hci_dev_unlock(hdev);
92668a8aea4SAndrei Emeltchenko 		break;
92768a8aea4SAndrei Emeltchenko 
92868a8aea4SAndrei Emeltchenko 	case LE_SCANNING_DISABLED:
929c9ecc48eSAndre Guedes 		if (status) {
930c9ecc48eSAndre Guedes 			hci_dev_lock(hdev);
931c9ecc48eSAndre Guedes 			mgmt_stop_discovery_failed(hdev, status);
932c9ecc48eSAndre Guedes 			hci_dev_unlock(hdev);
9337ba8b4beSAndre Guedes 			return;
934c9ecc48eSAndre Guedes 		}
9357ba8b4beSAndre Guedes 
936d23264a8SAndre Guedes 		clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
937d23264a8SAndre Guedes 
938bc3dd33cSAndre Guedes 		if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
939bc3dd33cSAndre Guedes 		    hdev->discovery.state == DISCOVERY_FINDING) {
9405e0452c0SAndre Guedes 			mgmt_interleaved_discovery(hdev);
9415e0452c0SAndre Guedes 		} else {
942c599008fSAndre Guedes 			hci_dev_lock(hdev);
943c599008fSAndre Guedes 			hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
944c599008fSAndre Guedes 			hci_dev_unlock(hdev);
9455e0452c0SAndre Guedes 		}
946c599008fSAndre Guedes 
94768a8aea4SAndrei Emeltchenko 		break;
94868a8aea4SAndrei Emeltchenko 
94968a8aea4SAndrei Emeltchenko 	default:
95068a8aea4SAndrei Emeltchenko 		BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
95168a8aea4SAndrei Emeltchenko 		break;
95235815085SAndre Guedes 	}
953eb9d91f5SAndre Guedes }
954eb9d91f5SAndre Guedes 
955cf1d081fSJohan Hedberg static void hci_cc_le_read_white_list_size(struct hci_dev *hdev,
956cf1d081fSJohan Hedberg 					   struct sk_buff *skb)
957cf1d081fSJohan Hedberg {
958cf1d081fSJohan Hedberg 	struct hci_rp_le_read_white_list_size *rp = (void *) skb->data;
959cf1d081fSJohan Hedberg 
960cf1d081fSJohan Hedberg 	BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size);
961cf1d081fSJohan Hedberg 
962cf1d081fSJohan Hedberg 	if (!rp->status)
963cf1d081fSJohan Hedberg 		hdev->le_white_list_size = rp->size;
964cf1d081fSJohan Hedberg }
965cf1d081fSJohan Hedberg 
9669b008c04SJohan Hedberg static void hci_cc_le_read_supported_states(struct hci_dev *hdev,
9679b008c04SJohan Hedberg 					    struct sk_buff *skb)
9689b008c04SJohan Hedberg {
9699b008c04SJohan Hedberg 	struct hci_rp_le_read_supported_states *rp = (void *) skb->data;
9709b008c04SJohan Hedberg 
9719b008c04SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
9729b008c04SJohan Hedberg 
9739b008c04SJohan Hedberg 	if (!rp->status)
9749b008c04SJohan Hedberg 		memcpy(hdev->le_states, rp->le_states, 8);
9759b008c04SJohan Hedberg }
9769b008c04SJohan Hedberg 
9776039aa73SGustavo Padovan static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
978f9b49306SAndre Guedes 					   struct sk_buff *skb)
979f9b49306SAndre Guedes {
98006199cf8SJohan Hedberg 	struct hci_cp_write_le_host_supported *sent;
981f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
982f9b49306SAndre Guedes 
9839f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
984f9b49306SAndre Guedes 
98506199cf8SJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
9868f984dfaSJohan Hedberg 	if (!sent)
987f9b49306SAndre Guedes 		return;
988f9b49306SAndre Guedes 
9898f984dfaSJohan Hedberg 	if (!status) {
9908f984dfaSJohan Hedberg 		if (sent->le)
9918f984dfaSJohan Hedberg 			hdev->host_features[0] |= LMP_HOST_LE;
9928f984dfaSJohan Hedberg 		else
9938f984dfaSJohan Hedberg 			hdev->host_features[0] &= ~LMP_HOST_LE;
99453b2caabSJohan Hedberg 
99553b2caabSJohan Hedberg 		if (sent->simul)
99653b2caabSJohan Hedberg 			hdev->host_features[0] |= LMP_HOST_LE_BREDR;
99753b2caabSJohan Hedberg 		else
99853b2caabSJohan Hedberg 			hdev->host_features[0] &= ~LMP_HOST_LE_BREDR;
9998f984dfaSJohan Hedberg 	}
10008f984dfaSJohan Hedberg 
10018f984dfaSJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
10028f984dfaSJohan Hedberg 	    !test_bit(HCI_INIT, &hdev->flags))
10038f984dfaSJohan Hedberg 		mgmt_le_enable_complete(hdev, sent->le, status);
1004f9b49306SAndre Guedes }
1005f9b49306SAndre Guedes 
100693c284eeSAndrei Emeltchenko static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
100793c284eeSAndrei Emeltchenko 					  struct sk_buff *skb)
100893c284eeSAndrei Emeltchenko {
100993c284eeSAndrei Emeltchenko 	struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data;
101093c284eeSAndrei Emeltchenko 
101193c284eeSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
101293c284eeSAndrei Emeltchenko 	       hdev->name, rp->status, rp->phy_handle);
101393c284eeSAndrei Emeltchenko 
101493c284eeSAndrei Emeltchenko 	if (rp->status)
101593c284eeSAndrei Emeltchenko 		return;
101693c284eeSAndrei Emeltchenko 
101793c284eeSAndrei Emeltchenko 	amp_write_rem_assoc_continue(hdev, rp->phy_handle);
101893c284eeSAndrei Emeltchenko }
101993c284eeSAndrei Emeltchenko 
10206039aa73SGustavo Padovan static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1021a9de9248SMarcel Holtmann {
10229f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1023a9de9248SMarcel Holtmann 
1024a9de9248SMarcel Holtmann 	if (status) {
1025a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
102656e5cb86SJohan Hedberg 		hci_dev_lock(hdev);
1027a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
10287a135109SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
102956e5cb86SJohan Hedberg 		hci_dev_unlock(hdev);
1030314b2381SJohan Hedberg 		return;
1031314b2381SJohan Hedberg 	}
1032314b2381SJohan Hedberg 
103389352e7dSAndre Guedes 	set_bit(HCI_INQUIRY, &hdev->flags);
103489352e7dSAndre Guedes 
103556e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1036343f935bSAndre Guedes 	hci_discovery_set_state(hdev, DISCOVERY_FINDING);
103756e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1038a9de9248SMarcel Holtmann }
1039a9de9248SMarcel Holtmann 
10406039aa73SGustavo Padovan static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
10411da177e4SLinus Torvalds {
1042a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
10431da177e4SLinus Torvalds 	struct hci_conn *conn;
10441da177e4SLinus Torvalds 
10459f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1046a9de9248SMarcel Holtmann 
1047a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
10481da177e4SLinus Torvalds 	if (!cp)
10491da177e4SLinus Torvalds 		return;
10501da177e4SLinus Torvalds 
10511da177e4SLinus Torvalds 	hci_dev_lock(hdev);
10521da177e4SLinus Torvalds 
10531da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
10541da177e4SLinus Torvalds 
10556ed93dc6SAndrei Emeltchenko 	BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn);
10561da177e4SLinus Torvalds 
10571da177e4SLinus Torvalds 	if (status) {
10581da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
10594c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
10601da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
10611da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
10621da177e4SLinus Torvalds 				hci_conn_del(conn);
10634c67bc74SMarcel Holtmann 			} else
10644c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
10651da177e4SLinus Torvalds 		}
10661da177e4SLinus Torvalds 	} else {
10671da177e4SLinus Torvalds 		if (!conn) {
10681da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
10691da177e4SLinus Torvalds 			if (conn) {
1070a0c808b3SJohan Hedberg 				conn->out = true;
10711da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
10721da177e4SLinus Torvalds 			} else
1073893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
10741da177e4SLinus Torvalds 		}
10751da177e4SLinus Torvalds 	}
10761da177e4SLinus Torvalds 
10771da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
10781da177e4SLinus Torvalds }
10791da177e4SLinus Torvalds 
1080a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
10811da177e4SLinus Torvalds {
1082a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
10831da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
10841da177e4SLinus Torvalds 	__u16 handle;
10851da177e4SLinus Torvalds 
10869f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1087b6a0dc82SMarcel Holtmann 
1088a9de9248SMarcel Holtmann 	if (!status)
1089a9de9248SMarcel Holtmann 		return;
1090a9de9248SMarcel Holtmann 
1091a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
10921da177e4SLinus Torvalds 	if (!cp)
1093a9de9248SMarcel Holtmann 		return;
10941da177e4SLinus Torvalds 
10951da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
10961da177e4SLinus Torvalds 
10979f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
10981da177e4SLinus Torvalds 
10991da177e4SLinus Torvalds 	hci_dev_lock(hdev);
11001da177e4SLinus Torvalds 
11011da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
11025a08ecceSAndrei Emeltchenko 	if (acl) {
11035a08ecceSAndrei Emeltchenko 		sco = acl->link;
11045a08ecceSAndrei Emeltchenko 		if (sco) {
11051da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
11061da177e4SLinus Torvalds 
11071da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
11081da177e4SLinus Torvalds 			hci_conn_del(sco);
11091da177e4SLinus Torvalds 		}
11105a08ecceSAndrei Emeltchenko 	}
11111da177e4SLinus Torvalds 
11121da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
11131da177e4SLinus Torvalds }
11141da177e4SLinus Torvalds 
1115f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1116f8558555SMarcel Holtmann {
1117f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1118f8558555SMarcel Holtmann 	struct hci_conn *conn;
1119f8558555SMarcel Holtmann 
11209f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1121f8558555SMarcel Holtmann 
1122f8558555SMarcel Holtmann 	if (!status)
1123f8558555SMarcel Holtmann 		return;
1124f8558555SMarcel Holtmann 
1125f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1126f8558555SMarcel Holtmann 	if (!cp)
1127f8558555SMarcel Holtmann 		return;
1128f8558555SMarcel Holtmann 
1129f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1130f8558555SMarcel Holtmann 
1131f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1132f8558555SMarcel Holtmann 	if (conn) {
1133f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1134f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1135f8558555SMarcel Holtmann 			hci_conn_put(conn);
1136f8558555SMarcel Holtmann 		}
1137f8558555SMarcel Holtmann 	}
1138f8558555SMarcel Holtmann 
1139f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1140f8558555SMarcel Holtmann }
1141f8558555SMarcel Holtmann 
1142f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1143f8558555SMarcel Holtmann {
1144f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1145f8558555SMarcel Holtmann 	struct hci_conn *conn;
1146f8558555SMarcel Holtmann 
11479f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1148f8558555SMarcel Holtmann 
1149f8558555SMarcel Holtmann 	if (!status)
1150f8558555SMarcel Holtmann 		return;
1151f8558555SMarcel Holtmann 
1152f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1153f8558555SMarcel Holtmann 	if (!cp)
1154f8558555SMarcel Holtmann 		return;
1155f8558555SMarcel Holtmann 
1156f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1157f8558555SMarcel Holtmann 
1158f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1159f8558555SMarcel Holtmann 	if (conn) {
1160f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1161f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1162f8558555SMarcel Holtmann 			hci_conn_put(conn);
1163f8558555SMarcel Holtmann 		}
1164f8558555SMarcel Holtmann 	}
1165f8558555SMarcel Holtmann 
1166f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1167f8558555SMarcel Holtmann }
1168f8558555SMarcel Holtmann 
1169127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1170392599b9SJohan Hedberg 				    struct hci_conn *conn)
1171392599b9SJohan Hedberg {
1172392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1173392599b9SJohan Hedberg 		return 0;
1174392599b9SJohan Hedberg 
1175765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1176392599b9SJohan Hedberg 		return 0;
1177392599b9SJohan Hedberg 
1178392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1179e9bf2bf0SVinicius Costa Gomes 	 * devices with sec_level HIGH or if MITM protection is requested */
1180807deac2SGustavo Padovan 	if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
1181807deac2SGustavo Padovan 	    conn->pending_sec_level != BT_SECURITY_HIGH)
1182392599b9SJohan Hedberg 		return 0;
1183392599b9SJohan Hedberg 
1184392599b9SJohan Hedberg 	return 1;
1185392599b9SJohan Hedberg }
1186392599b9SJohan Hedberg 
11876039aa73SGustavo Padovan static int hci_resolve_name(struct hci_dev *hdev,
118800abfe44SGustavo F. Padovan 				   struct inquiry_entry *e)
118930dc78e1SJohan Hedberg {
119030dc78e1SJohan Hedberg 	struct hci_cp_remote_name_req cp;
119130dc78e1SJohan Hedberg 
119230dc78e1SJohan Hedberg 	memset(&cp, 0, sizeof(cp));
119330dc78e1SJohan Hedberg 
119430dc78e1SJohan Hedberg 	bacpy(&cp.bdaddr, &e->data.bdaddr);
119530dc78e1SJohan Hedberg 	cp.pscan_rep_mode = e->data.pscan_rep_mode;
119630dc78e1SJohan Hedberg 	cp.pscan_mode = e->data.pscan_mode;
119730dc78e1SJohan Hedberg 	cp.clock_offset = e->data.clock_offset;
119830dc78e1SJohan Hedberg 
119930dc78e1SJohan Hedberg 	return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
120030dc78e1SJohan Hedberg }
120130dc78e1SJohan Hedberg 
1202b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev)
120330dc78e1SJohan Hedberg {
120430dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
120530dc78e1SJohan Hedberg 	struct inquiry_entry *e;
120630dc78e1SJohan Hedberg 
1207b644ba33SJohan Hedberg 	if (list_empty(&discov->resolve))
1208b644ba33SJohan Hedberg 		return false;
1209b644ba33SJohan Hedberg 
1210b644ba33SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1211c810089cSRam Malovany 	if (!e)
1212c810089cSRam Malovany 		return false;
1213c810089cSRam Malovany 
1214b644ba33SJohan Hedberg 	if (hci_resolve_name(hdev, e) == 0) {
1215b644ba33SJohan Hedberg 		e->name_state = NAME_PENDING;
1216b644ba33SJohan Hedberg 		return true;
1217b644ba33SJohan Hedberg 	}
1218b644ba33SJohan Hedberg 
1219b644ba33SJohan Hedberg 	return false;
1220b644ba33SJohan Hedberg }
1221b644ba33SJohan Hedberg 
1222b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
1223b644ba33SJohan Hedberg 				   bdaddr_t *bdaddr, u8 *name, u8 name_len)
1224b644ba33SJohan Hedberg {
1225b644ba33SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
1226b644ba33SJohan Hedberg 	struct inquiry_entry *e;
1227b644ba33SJohan Hedberg 
1228b644ba33SJohan Hedberg 	if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
122904124681SGustavo F. Padovan 		mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
123004124681SGustavo F. Padovan 				      name_len, conn->dev_class);
1231b644ba33SJohan Hedberg 
1232b644ba33SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPED)
1233b644ba33SJohan Hedberg 		return;
1234b644ba33SJohan Hedberg 
123530dc78e1SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPING)
123630dc78e1SJohan Hedberg 		goto discov_complete;
123730dc78e1SJohan Hedberg 
123830dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_RESOLVING)
123930dc78e1SJohan Hedberg 		return;
124030dc78e1SJohan Hedberg 
124130dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
12427cc8380eSRam Malovany 	/* If the device was not found in a list of found devices names of which
12437cc8380eSRam Malovany 	 * are pending. there is no need to continue resolving a next name as it
12447cc8380eSRam Malovany 	 * will be done upon receiving another Remote Name Request Complete
12457cc8380eSRam Malovany 	 * Event */
12467cc8380eSRam Malovany 	if (!e)
12477cc8380eSRam Malovany 		return;
12487cc8380eSRam Malovany 
124930dc78e1SJohan Hedberg 	list_del(&e->list);
12507cc8380eSRam Malovany 	if (name) {
12517cc8380eSRam Malovany 		e->name_state = NAME_KNOWN;
1252b644ba33SJohan Hedberg 		mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1253b644ba33SJohan Hedberg 				 e->data.rssi, name, name_len);
1254c3e7c0d9SRam Malovany 	} else {
1255c3e7c0d9SRam Malovany 		e->name_state = NAME_NOT_KNOWN;
125630dc78e1SJohan Hedberg 	}
125730dc78e1SJohan Hedberg 
1258b644ba33SJohan Hedberg 	if (hci_resolve_next_name(hdev))
125930dc78e1SJohan Hedberg 		return;
126030dc78e1SJohan Hedberg 
126130dc78e1SJohan Hedberg discov_complete:
126230dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
126330dc78e1SJohan Hedberg }
126430dc78e1SJohan Hedberg 
1265a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
12661da177e4SLinus Torvalds {
1267127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1268127178d2SJohan Hedberg 	struct hci_conn *conn;
1269127178d2SJohan Hedberg 
12709f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1271127178d2SJohan Hedberg 
1272127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1273127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1274127178d2SJohan Hedberg 	if (!status)
1275127178d2SJohan Hedberg 		return;
1276127178d2SJohan Hedberg 
1277127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1278127178d2SJohan Hedberg 	if (!cp)
1279127178d2SJohan Hedberg 		return;
1280127178d2SJohan Hedberg 
1281127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1282127178d2SJohan Hedberg 
1283127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1284b644ba33SJohan Hedberg 
1285b644ba33SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1286b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1287b644ba33SJohan Hedberg 
128879c6c70cSJohan Hedberg 	if (!conn)
128979c6c70cSJohan Hedberg 		goto unlock;
129079c6c70cSJohan Hedberg 
129179c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
129279c6c70cSJohan Hedberg 		goto unlock;
129379c6c70cSJohan Hedberg 
129451a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1295127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1296127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1297127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1298127178d2SJohan Hedberg 	}
1299127178d2SJohan Hedberg 
130079c6c70cSJohan Hedberg unlock:
1301127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1302a9de9248SMarcel Holtmann }
13031da177e4SLinus Torvalds 
1304769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1305769be974SMarcel Holtmann {
1306769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1307769be974SMarcel Holtmann 	struct hci_conn *conn;
1308769be974SMarcel Holtmann 
13099f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1310769be974SMarcel Holtmann 
1311769be974SMarcel Holtmann 	if (!status)
1312769be974SMarcel Holtmann 		return;
1313769be974SMarcel Holtmann 
1314769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1315769be974SMarcel Holtmann 	if (!cp)
1316769be974SMarcel Holtmann 		return;
1317769be974SMarcel Holtmann 
1318769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1319769be974SMarcel Holtmann 
1320769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1321769be974SMarcel Holtmann 	if (conn) {
1322769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1323769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1324769be974SMarcel Holtmann 			hci_conn_put(conn);
1325769be974SMarcel Holtmann 		}
1326769be974SMarcel Holtmann 	}
1327769be974SMarcel Holtmann 
1328769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1329769be974SMarcel Holtmann }
1330769be974SMarcel Holtmann 
1331769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1332769be974SMarcel Holtmann {
1333769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1334769be974SMarcel Holtmann 	struct hci_conn *conn;
1335769be974SMarcel Holtmann 
13369f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1337769be974SMarcel Holtmann 
1338769be974SMarcel Holtmann 	if (!status)
1339769be974SMarcel Holtmann 		return;
1340769be974SMarcel Holtmann 
1341769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1342769be974SMarcel Holtmann 	if (!cp)
1343769be974SMarcel Holtmann 		return;
1344769be974SMarcel Holtmann 
1345769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1346769be974SMarcel Holtmann 
1347769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1348769be974SMarcel Holtmann 	if (conn) {
1349769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1350769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1351769be974SMarcel Holtmann 			hci_conn_put(conn);
1352769be974SMarcel Holtmann 		}
1353769be974SMarcel Holtmann 	}
1354769be974SMarcel Holtmann 
1355769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1356769be974SMarcel Holtmann }
1357769be974SMarcel Holtmann 
1358a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1359a9de9248SMarcel Holtmann {
1360b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1361b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1362b6a0dc82SMarcel Holtmann 	__u16 handle;
1363b6a0dc82SMarcel Holtmann 
13649f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1365b6a0dc82SMarcel Holtmann 
1366b6a0dc82SMarcel Holtmann 	if (!status)
1367b6a0dc82SMarcel Holtmann 		return;
1368b6a0dc82SMarcel Holtmann 
1369b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1370b6a0dc82SMarcel Holtmann 	if (!cp)
1371b6a0dc82SMarcel Holtmann 		return;
1372b6a0dc82SMarcel Holtmann 
1373b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1374b6a0dc82SMarcel Holtmann 
13759f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
1376b6a0dc82SMarcel Holtmann 
1377b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1378b6a0dc82SMarcel Holtmann 
1379b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
13805a08ecceSAndrei Emeltchenko 	if (acl) {
13815a08ecceSAndrei Emeltchenko 		sco = acl->link;
13825a08ecceSAndrei Emeltchenko 		if (sco) {
1383b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1384b6a0dc82SMarcel Holtmann 
1385b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1386b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1387b6a0dc82SMarcel Holtmann 		}
13885a08ecceSAndrei Emeltchenko 	}
1389b6a0dc82SMarcel Holtmann 
1390b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1391a9de9248SMarcel Holtmann }
1392a9de9248SMarcel Holtmann 
1393a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1394a9de9248SMarcel Holtmann {
1395a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
139604837f64SMarcel Holtmann 	struct hci_conn *conn;
139704837f64SMarcel Holtmann 
13989f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1399a9de9248SMarcel Holtmann 
1400a9de9248SMarcel Holtmann 	if (!status)
1401a9de9248SMarcel Holtmann 		return;
1402a9de9248SMarcel Holtmann 
1403a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
140404837f64SMarcel Holtmann 	if (!cp)
1405a9de9248SMarcel Holtmann 		return;
140604837f64SMarcel Holtmann 
140704837f64SMarcel Holtmann 	hci_dev_lock(hdev);
140804837f64SMarcel Holtmann 
140904837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1410e73439d8SMarcel Holtmann 	if (conn) {
141151a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
141204837f64SMarcel Holtmann 
141351a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1414e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1415e73439d8SMarcel Holtmann 	}
1416e73439d8SMarcel Holtmann 
141704837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
141804837f64SMarcel Holtmann }
141904837f64SMarcel Holtmann 
1420a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1421a9de9248SMarcel Holtmann {
1422a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
142304837f64SMarcel Holtmann 	struct hci_conn *conn;
142404837f64SMarcel Holtmann 
14259f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1426a9de9248SMarcel Holtmann 
1427a9de9248SMarcel Holtmann 	if (!status)
1428a9de9248SMarcel Holtmann 		return;
1429a9de9248SMarcel Holtmann 
1430a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
143104837f64SMarcel Holtmann 	if (!cp)
1432a9de9248SMarcel Holtmann 		return;
143304837f64SMarcel Holtmann 
143404837f64SMarcel Holtmann 	hci_dev_lock(hdev);
143504837f64SMarcel Holtmann 
143604837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1437e73439d8SMarcel Holtmann 	if (conn) {
143851a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
143904837f64SMarcel Holtmann 
144051a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1441e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1442e73439d8SMarcel Holtmann 	}
1443e73439d8SMarcel Holtmann 
144404837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
144504837f64SMarcel Holtmann }
144604837f64SMarcel Holtmann 
144788c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
144888c3df13SJohan Hedberg {
144988c3df13SJohan Hedberg 	struct hci_cp_disconnect *cp;
145088c3df13SJohan Hedberg 	struct hci_conn *conn;
145188c3df13SJohan Hedberg 
145288c3df13SJohan Hedberg 	if (!status)
145388c3df13SJohan Hedberg 		return;
145488c3df13SJohan Hedberg 
145588c3df13SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
145688c3df13SJohan Hedberg 	if (!cp)
145788c3df13SJohan Hedberg 		return;
145888c3df13SJohan Hedberg 
145988c3df13SJohan Hedberg 	hci_dev_lock(hdev);
146088c3df13SJohan Hedberg 
146188c3df13SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
146288c3df13SJohan Hedberg 	if (conn)
146388c3df13SJohan Hedberg 		mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
146488c3df13SJohan Hedberg 				       conn->dst_type, status);
146588c3df13SJohan Hedberg 
146688c3df13SJohan Hedberg 	hci_dev_unlock(hdev);
146788c3df13SJohan Hedberg }
146888c3df13SJohan Hedberg 
1469fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1470fcd89c09SVille Tervo {
1471fcd89c09SVille Tervo 	struct hci_conn *conn;
1472fcd89c09SVille Tervo 
14739f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1474fcd89c09SVille Tervo 
1475f00a06acSAndre Guedes 	if (status) {
1476fcd89c09SVille Tervo 		hci_dev_lock(hdev);
1477fcd89c09SVille Tervo 
14780c95ab78SAndre Guedes 		conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
1479f00a06acSAndre Guedes 		if (!conn) {
1480f00a06acSAndre Guedes 			hci_dev_unlock(hdev);
1481f00a06acSAndre Guedes 			return;
1482f00a06acSAndre Guedes 		}
1483fcd89c09SVille Tervo 
14846ed93dc6SAndrei Emeltchenko 		BT_DBG("%s bdaddr %pMR conn %p", hdev->name, &conn->dst, conn);
1485fcd89c09SVille Tervo 
1486fcd89c09SVille Tervo 		conn->state = BT_CLOSED;
14870c95ab78SAndre Guedes 		mgmt_connect_failed(hdev, &conn->dst, conn->type,
1488328c9248SHemant Gupta 				    conn->dst_type, status);
1489fcd89c09SVille Tervo 		hci_proto_connect_cfm(conn, status);
1490fcd89c09SVille Tervo 		hci_conn_del(conn);
1491fcd89c09SVille Tervo 
1492fcd89c09SVille Tervo 		hci_dev_unlock(hdev);
1493fcd89c09SVille Tervo 	}
1494f00a06acSAndre Guedes }
1495fcd89c09SVille Tervo 
1496a02226d6SAndrei Emeltchenko static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
1497a02226d6SAndrei Emeltchenko {
149893c284eeSAndrei Emeltchenko 	struct hci_cp_create_phy_link *cp;
149993c284eeSAndrei Emeltchenko 
1500a02226d6SAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
150193c284eeSAndrei Emeltchenko 
150293c284eeSAndrei Emeltchenko 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
150393c284eeSAndrei Emeltchenko 	if (!cp)
150493c284eeSAndrei Emeltchenko 		return;
150593c284eeSAndrei Emeltchenko 
1506e58917b9SAndrei Emeltchenko 	hci_dev_lock(hdev);
1507e58917b9SAndrei Emeltchenko 
1508e58917b9SAndrei Emeltchenko 	if (status) {
1509e58917b9SAndrei Emeltchenko 		struct hci_conn *hcon;
1510e58917b9SAndrei Emeltchenko 
1511e58917b9SAndrei Emeltchenko 		hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle);
1512e58917b9SAndrei Emeltchenko 		if (hcon)
1513e58917b9SAndrei Emeltchenko 			hci_conn_del(hcon);
1514e58917b9SAndrei Emeltchenko 	} else {
151593c284eeSAndrei Emeltchenko 		amp_write_remote_assoc(hdev, cp->phy_handle);
1516a02226d6SAndrei Emeltchenko 	}
1517a02226d6SAndrei Emeltchenko 
1518e58917b9SAndrei Emeltchenko 	hci_dev_unlock(hdev);
1519e58917b9SAndrei Emeltchenko }
1520e58917b9SAndrei Emeltchenko 
15210b26ab9dSAndrei Emeltchenko static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
15220b26ab9dSAndrei Emeltchenko {
15230b26ab9dSAndrei Emeltchenko 	struct hci_cp_accept_phy_link *cp;
15240b26ab9dSAndrei Emeltchenko 
15250b26ab9dSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
15260b26ab9dSAndrei Emeltchenko 
15270b26ab9dSAndrei Emeltchenko 	if (status)
15280b26ab9dSAndrei Emeltchenko 		return;
15290b26ab9dSAndrei Emeltchenko 
15300b26ab9dSAndrei Emeltchenko 	cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
15310b26ab9dSAndrei Emeltchenko 	if (!cp)
15320b26ab9dSAndrei Emeltchenko 		return;
15330b26ab9dSAndrei Emeltchenko 
15340b26ab9dSAndrei Emeltchenko 	amp_write_remote_assoc(hdev, cp->phy_handle);
15350b26ab9dSAndrei Emeltchenko }
15360b26ab9dSAndrei Emeltchenko 
15376039aa73SGustavo Padovan static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
15381da177e4SLinus Torvalds {
15391da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
154030dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
154130dc78e1SJohan Hedberg 	struct inquiry_entry *e;
15421da177e4SLinus Torvalds 
15439f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
15441da177e4SLinus Torvalds 
15459238f36aSJohan Hedberg 	hci_req_cmd_complete(hdev, HCI_OP_INQUIRY, status);
15466bd57416SMarcel Holtmann 
1547a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
154889352e7dSAndre Guedes 
154989352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
155089352e7dSAndre Guedes 		return;
155189352e7dSAndre 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 
16509eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
16517d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
16527d0db0a3SMarcel Holtmann 
1653a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1654a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1655a9de9248SMarcel Holtmann 
1656a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1657a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1658a9de9248SMarcel Holtmann 
1659a9de9248SMarcel Holtmann 		/* Get remote features */
1660a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1661a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1662a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1663769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1664769be974SMarcel Holtmann 				     sizeof(cp), &cp);
166545bb4bf0SMarcel Holtmann 		}
1666a9de9248SMarcel Holtmann 
1667a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1668d095c1ebSAndrei Emeltchenko 		if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
1669a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1670a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1671a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
167204124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
167304124681SGustavo F. Padovan 				     &cp);
1674a9de9248SMarcel Holtmann 		}
167517d5c04cSJohan Hedberg 	} else {
1676a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
167717d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
1678744cf19eSJohan Hedberg 			mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
167948264f06SJohan Hedberg 					    conn->dst_type, ev->status);
168017d5c04cSJohan Hedberg 	}
168145bb4bf0SMarcel Holtmann 
1682e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
1683e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
168445bb4bf0SMarcel Holtmann 
1685769be974SMarcel Holtmann 	if (ev->status) {
1686a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1687a9de9248SMarcel Holtmann 		hci_conn_del(conn);
1688c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
1689c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1690a9de9248SMarcel Holtmann 
1691a9de9248SMarcel Holtmann unlock:
16921da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
1693a9de9248SMarcel Holtmann 
1694a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
16951da177e4SLinus Torvalds }
16961da177e4SLinus Torvalds 
169720714bfeSFrédéric Dalleau void hci_conn_accept(struct hci_conn *conn, int mask)
169820714bfeSFrédéric Dalleau {
169920714bfeSFrédéric Dalleau 	struct hci_dev *hdev = conn->hdev;
170020714bfeSFrédéric Dalleau 
170120714bfeSFrédéric Dalleau 	BT_DBG("conn %p", conn);
170220714bfeSFrédéric Dalleau 
170320714bfeSFrédéric Dalleau 	conn->state = BT_CONFIG;
170420714bfeSFrédéric Dalleau 
170520714bfeSFrédéric Dalleau 	if (!lmp_esco_capable(hdev)) {
170620714bfeSFrédéric Dalleau 		struct hci_cp_accept_conn_req cp;
170720714bfeSFrédéric Dalleau 
170820714bfeSFrédéric Dalleau 		bacpy(&cp.bdaddr, &conn->dst);
170920714bfeSFrédéric Dalleau 
171020714bfeSFrédéric Dalleau 		if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
171120714bfeSFrédéric Dalleau 			cp.role = 0x00; /* Become master */
171220714bfeSFrédéric Dalleau 		else
171320714bfeSFrédéric Dalleau 			cp.role = 0x01; /* Remain slave */
171420714bfeSFrédéric Dalleau 
171520714bfeSFrédéric Dalleau 		hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), &cp);
171620714bfeSFrédéric Dalleau 	} else /* lmp_esco_capable(hdev)) */ {
171720714bfeSFrédéric Dalleau 		struct hci_cp_accept_sync_conn_req cp;
171820714bfeSFrédéric Dalleau 
171920714bfeSFrédéric Dalleau 		bacpy(&cp.bdaddr, &conn->dst);
172020714bfeSFrédéric Dalleau 		cp.pkt_type = cpu_to_le16(conn->pkt_type);
172120714bfeSFrédéric Dalleau 
172220714bfeSFrédéric Dalleau 		cp.tx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
172320714bfeSFrédéric Dalleau 		cp.rx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
172420714bfeSFrédéric Dalleau 		cp.max_latency    = __constant_cpu_to_le16(0xffff);
172520714bfeSFrédéric Dalleau 		cp.content_format = cpu_to_le16(hdev->voice_setting);
172620714bfeSFrédéric Dalleau 		cp.retrans_effort = 0xff;
172720714bfeSFrédéric Dalleau 
172820714bfeSFrédéric Dalleau 		hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
172920714bfeSFrédéric Dalleau 			     sizeof(cp), &cp);
173020714bfeSFrédéric Dalleau 	}
173120714bfeSFrédéric Dalleau }
173220714bfeSFrédéric Dalleau 
17336039aa73SGustavo Padovan static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
17341da177e4SLinus Torvalds {
1735a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
17361da177e4SLinus Torvalds 	int mask = hdev->link_mode;
173720714bfeSFrédéric Dalleau 	__u8 flags = 0;
17381da177e4SLinus Torvalds 
17396ed93dc6SAndrei Emeltchenko 	BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
1740807deac2SGustavo Padovan 	       ev->link_type);
17411da177e4SLinus Torvalds 
174220714bfeSFrédéric Dalleau 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type,
174320714bfeSFrédéric Dalleau 				      &flags);
17441da177e4SLinus Torvalds 
1745138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
1746138d22efSSzymon Janc 	    !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
17471da177e4SLinus Torvalds 		/* Connection accepted */
1748c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
17491da177e4SLinus Torvalds 		struct hci_conn *conn;
17501da177e4SLinus Torvalds 
17511da177e4SLinus Torvalds 		hci_dev_lock(hdev);
1752b6a0dc82SMarcel Holtmann 
1753cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1754cc11b9c1SAndrei Emeltchenko 		if (ie)
1755c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
1756c7bdd502SMarcel Holtmann 
17578fc9ced3SGustavo Padovan 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
17588fc9ced3SGustavo Padovan 					       &ev->bdaddr);
17591da177e4SLinus Torvalds 		if (!conn) {
1760cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1761cc11b9c1SAndrei Emeltchenko 			if (!conn) {
1762893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
17631da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
17641da177e4SLinus Torvalds 				return;
17651da177e4SLinus Torvalds 			}
17661da177e4SLinus Torvalds 		}
1767b6a0dc82SMarcel Holtmann 
17681da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
1769b6a0dc82SMarcel Holtmann 
17701da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
17711da177e4SLinus Torvalds 
177220714bfeSFrédéric Dalleau 		if (ev->link_type == ACL_LINK ||
177320714bfeSFrédéric Dalleau 		    (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) {
1774b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
177520714bfeSFrédéric Dalleau 			conn->state = BT_CONNECT;
1776b6a0dc82SMarcel Holtmann 
17771da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
17781da177e4SLinus Torvalds 
17791da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
17801da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
17811da177e4SLinus Torvalds 			else
17821da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
17831da177e4SLinus Torvalds 
178404124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
178504124681SGustavo F. Padovan 				     &cp);
178620714bfeSFrédéric Dalleau 		} else if (!(flags & HCI_PROTO_DEFER)) {
1787b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
178820714bfeSFrédéric Dalleau 			conn->state = BT_CONNECT;
1789b6a0dc82SMarcel Holtmann 
1790b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
1791a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1792b6a0dc82SMarcel Holtmann 
179382781e63SAndrei Emeltchenko 			cp.tx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
179482781e63SAndrei Emeltchenko 			cp.rx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
179582781e63SAndrei Emeltchenko 			cp.max_latency    = __constant_cpu_to_le16(0xffff);
1796b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
1797b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
1798b6a0dc82SMarcel Holtmann 
1799b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1800b6a0dc82SMarcel Holtmann 				     sizeof(cp), &cp);
180120714bfeSFrédéric Dalleau 		} else {
180220714bfeSFrédéric Dalleau 			conn->state = BT_CONNECT2;
180320714bfeSFrédéric Dalleau 			hci_proto_connect_cfm(conn, 0);
180420714bfeSFrédéric Dalleau 			hci_conn_put(conn);
1805b6a0dc82SMarcel Holtmann 		}
18061da177e4SLinus Torvalds 	} else {
18071da177e4SLinus Torvalds 		/* Connection rejected */
18081da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
18091da177e4SLinus Torvalds 
18101da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
18119f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_REJ_BAD_ADDR;
1812a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
18131da177e4SLinus Torvalds 	}
18141da177e4SLinus Torvalds }
18151da177e4SLinus Torvalds 
1816f0d6a0eaSMikel Astiz static u8 hci_to_mgmt_reason(u8 err)
1817f0d6a0eaSMikel Astiz {
1818f0d6a0eaSMikel Astiz 	switch (err) {
1819f0d6a0eaSMikel Astiz 	case HCI_ERROR_CONNECTION_TIMEOUT:
1820f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_TIMEOUT;
1821f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_USER_TERM:
1822f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_LOW_RESOURCES:
1823f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_POWER_OFF:
1824f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_REMOTE;
1825f0d6a0eaSMikel Astiz 	case HCI_ERROR_LOCAL_HOST_TERM:
1826f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_LOCAL_HOST;
1827f0d6a0eaSMikel Astiz 	default:
1828f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_UNKNOWN;
1829f0d6a0eaSMikel Astiz 	}
1830f0d6a0eaSMikel Astiz }
1831f0d6a0eaSMikel Astiz 
18326039aa73SGustavo Padovan static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
18331da177e4SLinus Torvalds {
1834a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
183504837f64SMarcel Holtmann 	struct hci_conn *conn;
18361da177e4SLinus Torvalds 
18379f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
18381da177e4SLinus Torvalds 
18391da177e4SLinus Torvalds 	hci_dev_lock(hdev);
18401da177e4SLinus Torvalds 
184104837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1842f7520543SJohan Hedberg 	if (!conn)
1843f7520543SJohan Hedberg 		goto unlock;
1844f7520543SJohan Hedberg 
184537d9ef76SJohan Hedberg 	if (ev->status == 0)
18461da177e4SLinus Torvalds 		conn->state = BT_CLOSED;
18477d0db0a3SMarcel Holtmann 
1848b644ba33SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
1849b644ba33SJohan Hedberg 	    (conn->type == ACL_LINK || conn->type == LE_LINK)) {
1850f0d6a0eaSMikel Astiz 		if (ev->status) {
185188c3df13SJohan Hedberg 			mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
185288c3df13SJohan Hedberg 					       conn->dst_type, ev->status);
1853f0d6a0eaSMikel Astiz 		} else {
1854f0d6a0eaSMikel Astiz 			u8 reason = hci_to_mgmt_reason(ev->reason);
1855f0d6a0eaSMikel Astiz 
1856afc747a6SJohan Hedberg 			mgmt_device_disconnected(hdev, &conn->dst, conn->type,
1857f0d6a0eaSMikel Astiz 						 conn->dst_type, reason);
1858f0d6a0eaSMikel Astiz 		}
185937d9ef76SJohan Hedberg 	}
1860f7520543SJohan Hedberg 
186137d9ef76SJohan Hedberg 	if (ev->status == 0) {
18626ec5bcadSVishal Agarwal 		if (conn->type == ACL_LINK && conn->flush_key)
18636ec5bcadSVishal Agarwal 			hci_remove_link_key(hdev, &conn->dst);
18642950f21aSMarcel Holtmann 		hci_proto_disconn_cfm(conn, ev->reason);
18651da177e4SLinus Torvalds 		hci_conn_del(conn);
186637d9ef76SJohan Hedberg 	}
18671da177e4SLinus Torvalds 
1868f7520543SJohan Hedberg unlock:
18691da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
18701da177e4SLinus Torvalds }
18711da177e4SLinus Torvalds 
18726039aa73SGustavo Padovan static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1873a9de9248SMarcel Holtmann {
1874a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
1875a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1876a9de9248SMarcel Holtmann 
18779f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
1878a9de9248SMarcel Holtmann 
1879a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1880a9de9248SMarcel Holtmann 
1881a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1882d7556e20SWaldemar Rymarkiewicz 	if (!conn)
1883d7556e20SWaldemar Rymarkiewicz 		goto unlock;
1884d7556e20SWaldemar Rymarkiewicz 
1885765c2a96SJohan Hedberg 	if (!ev->status) {
1886aa64a8b5SJohan Hedberg 		if (!hci_conn_ssp_enabled(conn) &&
188751a8efd7SJohan Hedberg 		    test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
1888d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
188919f8def0SWaldemar Rymarkiewicz 		} else {
1890a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1891765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
189219f8def0SWaldemar Rymarkiewicz 		}
18932a611692SJohan Hedberg 	} else {
1894bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
1895bab73cb6SJohan Hedberg 				 ev->status);
18962a611692SJohan Hedberg 	}
1897a9de9248SMarcel Holtmann 
189851a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
189951a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
1900a9de9248SMarcel Holtmann 
1901f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
1902aa64a8b5SJohan Hedberg 		if (!ev->status && hci_conn_ssp_enabled(conn)) {
1903f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1904f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1905f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1906d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1907d7556e20SWaldemar Rymarkiewicz 				     &cp);
1908f8558555SMarcel Holtmann 		} else {
1909f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
1910f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1911f8558555SMarcel Holtmann 			hci_conn_put(conn);
1912f8558555SMarcel Holtmann 		}
1913052b30b0SMarcel Holtmann 	} else {
1914a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
1915a9de9248SMarcel Holtmann 
1916052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
1917052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1918052b30b0SMarcel Holtmann 		hci_conn_put(conn);
1919052b30b0SMarcel Holtmann 	}
1920052b30b0SMarcel Holtmann 
192151a8efd7SJohan Hedberg 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
1922a9de9248SMarcel Holtmann 		if (!ev->status) {
1923a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1924f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1925f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1926d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1927d7556e20SWaldemar Rymarkiewicz 				     &cp);
1928a9de9248SMarcel Holtmann 		} else {
192951a8efd7SJohan Hedberg 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
1930a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
1931a9de9248SMarcel Holtmann 		}
1932a9de9248SMarcel Holtmann 	}
1933a9de9248SMarcel Holtmann 
1934d7556e20SWaldemar Rymarkiewicz unlock:
1935a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1936a9de9248SMarcel Holtmann }
1937a9de9248SMarcel Holtmann 
19386039aa73SGustavo Padovan static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1939a9de9248SMarcel Holtmann {
1940127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
1941127178d2SJohan Hedberg 	struct hci_conn *conn;
1942127178d2SJohan Hedberg 
1943a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1944a9de9248SMarcel Holtmann 
1945a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
1946127178d2SJohan Hedberg 
1947127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1948127178d2SJohan Hedberg 
1949127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1950b644ba33SJohan Hedberg 
1951b644ba33SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
1952b644ba33SJohan Hedberg 		goto check_auth;
1953b644ba33SJohan Hedberg 
1954b644ba33SJohan Hedberg 	if (ev->status == 0)
1955b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
1956b644ba33SJohan Hedberg 				       strnlen(ev->name, HCI_MAX_NAME_LENGTH));
1957b644ba33SJohan Hedberg 	else
1958b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
1959b644ba33SJohan Hedberg 
1960b644ba33SJohan Hedberg check_auth:
196179c6c70cSJohan Hedberg 	if (!conn)
196279c6c70cSJohan Hedberg 		goto unlock;
196379c6c70cSJohan Hedberg 
196479c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
196579c6c70cSJohan Hedberg 		goto unlock;
196679c6c70cSJohan Hedberg 
196751a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1968127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1969127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1970127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1971127178d2SJohan Hedberg 	}
1972127178d2SJohan Hedberg 
197379c6c70cSJohan Hedberg unlock:
1974127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1975a9de9248SMarcel Holtmann }
1976a9de9248SMarcel Holtmann 
19776039aa73SGustavo Padovan static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1978a9de9248SMarcel Holtmann {
1979a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
1980a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1981a9de9248SMarcel Holtmann 
19829f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
1983a9de9248SMarcel Holtmann 
1984a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1985a9de9248SMarcel Holtmann 
1986a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1987a9de9248SMarcel Holtmann 	if (conn) {
1988a9de9248SMarcel Holtmann 		if (!ev->status) {
1989ae293196SMarcel Holtmann 			if (ev->encrypt) {
1990ae293196SMarcel Holtmann 				/* Encryption implies authentication */
1991ae293196SMarcel Holtmann 				conn->link_mode |= HCI_LM_AUTH;
1992a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_ENCRYPT;
1993da85e5e5SVinicius Costa Gomes 				conn->sec_level = conn->pending_sec_level;
1994ae293196SMarcel Holtmann 			} else
1995a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_ENCRYPT;
1996a9de9248SMarcel Holtmann 		}
1997a9de9248SMarcel Holtmann 
199851a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
1999a9de9248SMarcel Holtmann 
2000a7d7723aSGustavo Padovan 		if (ev->status && conn->state == BT_CONNECTED) {
2001bed71748SAndre Guedes 			hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
2002a7d7723aSGustavo Padovan 			hci_conn_put(conn);
2003a7d7723aSGustavo Padovan 			goto unlock;
2004a7d7723aSGustavo Padovan 		}
2005a7d7723aSGustavo Padovan 
2006f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
2007f8558555SMarcel Holtmann 			if (!ev->status)
2008f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
2009f8558555SMarcel Holtmann 
2010f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
2011f8558555SMarcel Holtmann 			hci_conn_put(conn);
2012f8558555SMarcel Holtmann 		} else
2013a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, ev->encrypt);
2014a9de9248SMarcel Holtmann 	}
2015a9de9248SMarcel Holtmann 
2016a7d7723aSGustavo Padovan unlock:
2017a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2018a9de9248SMarcel Holtmann }
2019a9de9248SMarcel Holtmann 
20206039aa73SGustavo Padovan static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
2021807deac2SGustavo Padovan 					     struct sk_buff *skb)
2022a9de9248SMarcel Holtmann {
2023a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2024a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2025a9de9248SMarcel Holtmann 
20269f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2027a9de9248SMarcel Holtmann 
2028a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2029a9de9248SMarcel Holtmann 
2030a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2031a9de9248SMarcel Holtmann 	if (conn) {
2032a9de9248SMarcel Holtmann 		if (!ev->status)
2033a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
2034a9de9248SMarcel Holtmann 
203551a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
2036a9de9248SMarcel Holtmann 
2037a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
2038a9de9248SMarcel Holtmann 	}
2039a9de9248SMarcel Holtmann 
2040a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2041a9de9248SMarcel Holtmann }
2042a9de9248SMarcel Holtmann 
20436039aa73SGustavo Padovan static void hci_remote_features_evt(struct hci_dev *hdev,
2044807deac2SGustavo Padovan 				    struct sk_buff *skb)
2045a9de9248SMarcel Holtmann {
2046a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
2047a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2048a9de9248SMarcel Holtmann 
20499f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2050a9de9248SMarcel Holtmann 
2051a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2052a9de9248SMarcel Holtmann 
2053a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2054ccd556feSJohan Hedberg 	if (!conn)
2055ccd556feSJohan Hedberg 		goto unlock;
2056ccd556feSJohan Hedberg 
2057769be974SMarcel Holtmann 	if (!ev->status)
2058a9de9248SMarcel Holtmann 		memcpy(conn->features, ev->features, 8);
2059a9de9248SMarcel Holtmann 
2060ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2061ccd556feSJohan Hedberg 		goto unlock;
2062ccd556feSJohan Hedberg 
2063ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2064769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
2065769be974SMarcel Holtmann 		cp.handle = ev->handle;
2066769be974SMarcel Holtmann 		cp.page = 0x01;
2067ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
2068769be974SMarcel Holtmann 			     sizeof(cp), &cp);
2069392599b9SJohan Hedberg 		goto unlock;
2070392599b9SJohan Hedberg 	}
2071392599b9SJohan Hedberg 
2072671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
2073127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2074127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2075127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2076127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2077127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2078b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2079b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
208008c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
2081b644ba33SJohan Hedberg 				      conn->dev_class);
2082392599b9SJohan Hedberg 
2083127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2084769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2085769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2086769be974SMarcel Holtmann 		hci_conn_put(conn);
2087769be974SMarcel Holtmann 	}
2088769be974SMarcel Holtmann 
2089ccd556feSJohan Hedberg unlock:
2090a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2091a9de9248SMarcel Holtmann }
2092a9de9248SMarcel Holtmann 
20936039aa73SGustavo Padovan static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2094a9de9248SMarcel Holtmann {
2095a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
20969238f36aSJohan Hedberg 	u8 status = skb->data[sizeof(*ev)];
2097a9de9248SMarcel Holtmann 	__u16 opcode;
2098a9de9248SMarcel Holtmann 
2099a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2100a9de9248SMarcel Holtmann 
2101a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2102a9de9248SMarcel Holtmann 
2103a9de9248SMarcel Holtmann 	switch (opcode) {
2104a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
2105a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
2106a9de9248SMarcel Holtmann 		break;
2107a9de9248SMarcel Holtmann 
21084d93483bSAndre Guedes 	case HCI_OP_PERIODIC_INQ:
21094d93483bSAndre Guedes 		hci_cc_periodic_inq(hdev, skb);
21104d93483bSAndre Guedes 		break;
21114d93483bSAndre Guedes 
2112a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
2113a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
2114a9de9248SMarcel Holtmann 		break;
2115a9de9248SMarcel Holtmann 
2116a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2117a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
2118a9de9248SMarcel Holtmann 		break;
2119a9de9248SMarcel Holtmann 
2120a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
2121a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
2122a9de9248SMarcel Holtmann 		break;
2123a9de9248SMarcel Holtmann 
2124e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
2125e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
2126e4e8e37cSMarcel Holtmann 		break;
2127e4e8e37cSMarcel Holtmann 
2128a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
2129a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
2130a9de9248SMarcel Holtmann 		break;
2131a9de9248SMarcel Holtmann 
2132e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
2133e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
2134e4e8e37cSMarcel Holtmann 		break;
2135e4e8e37cSMarcel Holtmann 
2136e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
2137e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
2138e4e8e37cSMarcel Holtmann 		break;
2139e4e8e37cSMarcel Holtmann 
2140a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
2141a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
2142a9de9248SMarcel Holtmann 		break;
2143a9de9248SMarcel Holtmann 
2144a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
2145a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
2146a9de9248SMarcel Holtmann 		break;
2147a9de9248SMarcel Holtmann 
2148a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
2149a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
2150a9de9248SMarcel Holtmann 		break;
2151a9de9248SMarcel Holtmann 
2152a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
2153a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
2154a9de9248SMarcel Holtmann 		break;
2155a9de9248SMarcel Holtmann 
2156a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
2157a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
2158a9de9248SMarcel Holtmann 		break;
2159a9de9248SMarcel Holtmann 
2160a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
2161a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
2162a9de9248SMarcel Holtmann 		break;
2163a9de9248SMarcel Holtmann 
2164a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
2165a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
2166a9de9248SMarcel Holtmann 		break;
2167a9de9248SMarcel Holtmann 
2168a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
2169a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
2170a9de9248SMarcel Holtmann 		break;
2171a9de9248SMarcel Holtmann 
2172a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
2173a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
2174a9de9248SMarcel Holtmann 		break;
2175a9de9248SMarcel Holtmann 
2176a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
2177a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
2178a9de9248SMarcel Holtmann 		break;
2179a9de9248SMarcel Holtmann 
2180333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
2181333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
2182333140b5SMarcel Holtmann 		break;
2183333140b5SMarcel Holtmann 
2184a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
2185a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
2186a9de9248SMarcel Holtmann 		break;
2187a9de9248SMarcel Holtmann 
2188a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
2189a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
2190a9de9248SMarcel Holtmann 		break;
2191a9de9248SMarcel Holtmann 
2192a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
2193a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
2194a9de9248SMarcel Holtmann 		break;
2195a9de9248SMarcel Holtmann 
2196971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
2197971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
2198971e3a4bSAndre Guedes 		break;
2199971e3a4bSAndre Guedes 
2200a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
2201a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
2202a9de9248SMarcel Holtmann 		break;
2203a9de9248SMarcel Holtmann 
2204a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
2205a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
2206a9de9248SMarcel Holtmann 		break;
2207a9de9248SMarcel Holtmann 
2208350ee4cfSAndrei Emeltchenko 	case HCI_OP_READ_DATA_BLOCK_SIZE:
2209350ee4cfSAndrei Emeltchenko 		hci_cc_read_data_block_size(hdev, skb);
2210350ee4cfSAndrei Emeltchenko 		break;
2211350ee4cfSAndrei Emeltchenko 
22121e89cffbSAndrei Emeltchenko 	case HCI_OP_READ_FLOW_CONTROL_MODE:
22131e89cffbSAndrei Emeltchenko 		hci_cc_read_flow_control_mode(hdev, skb);
22141e89cffbSAndrei Emeltchenko 		break;
22151e89cffbSAndrei Emeltchenko 
2216928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
2217928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
2218928abaa7SAndrei Emeltchenko 		break;
2219928abaa7SAndrei Emeltchenko 
2220903e4541SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_ASSOC:
2221903e4541SAndrei Emeltchenko 		hci_cc_read_local_amp_assoc(hdev, skb);
2222903e4541SAndrei Emeltchenko 		break;
2223903e4541SAndrei Emeltchenko 
2224d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
2225d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
2226d5859e22SJohan Hedberg 		break;
2227d5859e22SJohan Hedberg 
2228980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
2229980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
2230980e1a53SJohan Hedberg 		break;
2231980e1a53SJohan Hedberg 
2232980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
2233980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
2234980e1a53SJohan Hedberg 		break;
2235980e1a53SJohan Hedberg 
2236c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
2237c35938b2SSzymon Janc 		hci_cc_read_local_oob_data_reply(hdev, skb);
2238c35938b2SSzymon Janc 		break;
2239c35938b2SSzymon Janc 
22406ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
22416ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
22426ed58ec5SVille Tervo 		break;
22436ed58ec5SVille Tervo 
224460e77321SJohan Hedberg 	case HCI_OP_LE_READ_LOCAL_FEATURES:
224560e77321SJohan Hedberg 		hci_cc_le_read_local_features(hdev, skb);
224660e77321SJohan Hedberg 		break;
224760e77321SJohan Hedberg 
22488fa19098SJohan Hedberg 	case HCI_OP_LE_READ_ADV_TX_POWER:
22498fa19098SJohan Hedberg 		hci_cc_le_read_adv_tx_power(hdev, skb);
22508fa19098SJohan Hedberg 		break;
22518fa19098SJohan Hedberg 
2252a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
2253a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
2254a5c29683SJohan Hedberg 		break;
2255a5c29683SJohan Hedberg 
2256a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
2257a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
2258a5c29683SJohan Hedberg 		break;
2259a5c29683SJohan Hedberg 
22601143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_REPLY:
22611143d458SBrian Gix 		hci_cc_user_passkey_reply(hdev, skb);
22621143d458SBrian Gix 		break;
22631143d458SBrian Gix 
22641143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_NEG_REPLY:
22651143d458SBrian Gix 		hci_cc_user_passkey_neg_reply(hdev, skb);
226616cde993SSzymon Janc 		break;
226707f7fa5dSAndre Guedes 
226807f7fa5dSAndre Guedes 	case HCI_OP_LE_SET_SCAN_PARAM:
226907f7fa5dSAndre Guedes 		hci_cc_le_set_scan_param(hdev, skb);
22701143d458SBrian Gix 		break;
22711143d458SBrian Gix 
2272c1d5dc4aSJohan Hedberg 	case HCI_OP_LE_SET_ADV_ENABLE:
2273c1d5dc4aSJohan Hedberg 		hci_cc_le_set_adv_enable(hdev, skb);
2274c1d5dc4aSJohan Hedberg 		break;
2275c1d5dc4aSJohan Hedberg 
2276eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
2277eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
2278eb9d91f5SAndre Guedes 		break;
2279eb9d91f5SAndre Guedes 
2280cf1d081fSJohan Hedberg 	case HCI_OP_LE_READ_WHITE_LIST_SIZE:
2281cf1d081fSJohan Hedberg 		hci_cc_le_read_white_list_size(hdev, skb);
2282cf1d081fSJohan Hedberg 		break;
2283cf1d081fSJohan Hedberg 
22849b008c04SJohan Hedberg 	case HCI_OP_LE_READ_SUPPORTED_STATES:
22859b008c04SJohan Hedberg 		hci_cc_le_read_supported_states(hdev, skb);
22869b008c04SJohan Hedberg 		break;
22879b008c04SJohan Hedberg 
2288f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2289f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
2290f9b49306SAndre Guedes 		break;
2291f9b49306SAndre Guedes 
229293c284eeSAndrei Emeltchenko 	case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
229393c284eeSAndrei Emeltchenko 		hci_cc_write_remote_amp_assoc(hdev, skb);
229493c284eeSAndrei Emeltchenko 		break;
229593c284eeSAndrei Emeltchenko 
2296a9de9248SMarcel Holtmann 	default:
22979f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2298a9de9248SMarcel Holtmann 		break;
2299a9de9248SMarcel Holtmann 	}
2300a9de9248SMarcel Holtmann 
2301ad82cdd1SJohan Hedberg 	if (opcode != HCI_OP_NOP)
23026bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
23036bd32326SVille Tervo 
2304ad82cdd1SJohan Hedberg 	hci_req_cmd_complete(hdev, opcode, status);
23059238f36aSJohan Hedberg 
2306dbccd791SSzymon Janc 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2307a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2308a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2309c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2310a9de9248SMarcel Holtmann 	}
2311a9de9248SMarcel Holtmann }
2312a9de9248SMarcel Holtmann 
23136039aa73SGustavo Padovan static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2314a9de9248SMarcel Holtmann {
2315a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
2316a9de9248SMarcel Holtmann 	__u16 opcode;
2317a9de9248SMarcel Holtmann 
2318a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2319a9de9248SMarcel Holtmann 
2320a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2321a9de9248SMarcel Holtmann 
2322a9de9248SMarcel Holtmann 	switch (opcode) {
2323a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
2324a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
2325a9de9248SMarcel Holtmann 		break;
2326a9de9248SMarcel Holtmann 
2327a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
2328a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
2329a9de9248SMarcel Holtmann 		break;
2330a9de9248SMarcel Holtmann 
2331a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
2332a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
2333a9de9248SMarcel Holtmann 		break;
2334a9de9248SMarcel Holtmann 
2335f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2336f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2337f8558555SMarcel Holtmann 		break;
2338f8558555SMarcel Holtmann 
2339f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2340f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2341f8558555SMarcel Holtmann 		break;
2342f8558555SMarcel Holtmann 
2343a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2344a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2345a9de9248SMarcel Holtmann 		break;
2346a9de9248SMarcel Holtmann 
2347769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2348769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2349769be974SMarcel Holtmann 		break;
2350769be974SMarcel Holtmann 
2351769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2352769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2353769be974SMarcel Holtmann 		break;
2354769be974SMarcel Holtmann 
2355a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2356a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2357a9de9248SMarcel Holtmann 		break;
2358a9de9248SMarcel Holtmann 
2359a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2360a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2361a9de9248SMarcel Holtmann 		break;
2362a9de9248SMarcel Holtmann 
2363a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2364a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2365a9de9248SMarcel Holtmann 		break;
2366a9de9248SMarcel Holtmann 
23678962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
236888c3df13SJohan Hedberg 		hci_cs_disconnect(hdev, ev->status);
23698962ee74SJohan Hedberg 		break;
23708962ee74SJohan Hedberg 
2371fcd89c09SVille Tervo 	case HCI_OP_LE_CREATE_CONN:
2372fcd89c09SVille Tervo 		hci_cs_le_create_conn(hdev, ev->status);
2373fcd89c09SVille Tervo 		break;
2374fcd89c09SVille Tervo 
2375a02226d6SAndrei Emeltchenko 	case HCI_OP_CREATE_PHY_LINK:
2376a02226d6SAndrei Emeltchenko 		hci_cs_create_phylink(hdev, ev->status);
2377a02226d6SAndrei Emeltchenko 		break;
2378a02226d6SAndrei Emeltchenko 
23790b26ab9dSAndrei Emeltchenko 	case HCI_OP_ACCEPT_PHY_LINK:
23800b26ab9dSAndrei Emeltchenko 		hci_cs_accept_phylink(hdev, ev->status);
23810b26ab9dSAndrei Emeltchenko 		break;
23820b26ab9dSAndrei Emeltchenko 
2383a9de9248SMarcel Holtmann 	default:
23849f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2385a9de9248SMarcel Holtmann 		break;
2386a9de9248SMarcel Holtmann 	}
2387a9de9248SMarcel Holtmann 
2388ad82cdd1SJohan Hedberg 	if (opcode != HCI_OP_NOP)
23896bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
23906bd32326SVille Tervo 
2391ad82cdd1SJohan Hedberg 	hci_req_cmd_status(hdev, opcode, ev->status);
23929238f36aSJohan Hedberg 
239310572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2394a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2395a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2396c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2397a9de9248SMarcel Holtmann 	}
2398a9de9248SMarcel Holtmann }
2399a9de9248SMarcel Holtmann 
24006039aa73SGustavo Padovan static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2401a9de9248SMarcel Holtmann {
2402a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2403a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2404a9de9248SMarcel Holtmann 
24059f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2406a9de9248SMarcel Holtmann 
2407a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2408a9de9248SMarcel Holtmann 
2409a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2410a9de9248SMarcel Holtmann 	if (conn) {
2411a9de9248SMarcel Holtmann 		if (!ev->status) {
2412a9de9248SMarcel Holtmann 			if (ev->role)
2413a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
2414a9de9248SMarcel Holtmann 			else
2415a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
2416a9de9248SMarcel Holtmann 		}
2417a9de9248SMarcel Holtmann 
241851a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
2419a9de9248SMarcel Holtmann 
2420a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2421a9de9248SMarcel Holtmann 	}
2422a9de9248SMarcel Holtmann 
2423a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2424a9de9248SMarcel Holtmann }
2425a9de9248SMarcel Holtmann 
24266039aa73SGustavo Padovan static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
24271da177e4SLinus Torvalds {
2428a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
24291da177e4SLinus Torvalds 	int i;
24301da177e4SLinus Torvalds 
243132ac5b9bSAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
243232ac5b9bSAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
243332ac5b9bSAndrei Emeltchenko 		return;
243432ac5b9bSAndrei Emeltchenko 	}
243532ac5b9bSAndrei Emeltchenko 
2436c5993de8SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2437c5993de8SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
24381da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
24391da177e4SLinus Torvalds 		return;
24401da177e4SLinus Torvalds 	}
24411da177e4SLinus Torvalds 
2442c5993de8SAndrei Emeltchenko 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2443c5993de8SAndrei Emeltchenko 
2444613a1c0cSAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
2445613a1c0cSAndrei Emeltchenko 		struct hci_comp_pkts_info *info = &ev->handles[i];
24461da177e4SLinus Torvalds 		struct hci_conn *conn;
24471da177e4SLinus Torvalds 		__u16  handle, count;
24481da177e4SLinus Torvalds 
2449613a1c0cSAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
2450613a1c0cSAndrei Emeltchenko 		count  = __le16_to_cpu(info->count);
24511da177e4SLinus Torvalds 
24521da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
2453f4280918SAndrei Emeltchenko 		if (!conn)
2454f4280918SAndrei Emeltchenko 			continue;
2455f4280918SAndrei Emeltchenko 
24561da177e4SLinus Torvalds 		conn->sent -= count;
24571da177e4SLinus Torvalds 
2458f4280918SAndrei Emeltchenko 		switch (conn->type) {
2459f4280918SAndrei Emeltchenko 		case ACL_LINK:
246070f23020SAndrei Emeltchenko 			hdev->acl_cnt += count;
246170f23020SAndrei Emeltchenko 			if (hdev->acl_cnt > hdev->acl_pkts)
24621da177e4SLinus Torvalds 				hdev->acl_cnt = hdev->acl_pkts;
2463f4280918SAndrei Emeltchenko 			break;
2464f4280918SAndrei Emeltchenko 
2465f4280918SAndrei Emeltchenko 		case LE_LINK:
24666ed58ec5SVille Tervo 			if (hdev->le_pkts) {
24676ed58ec5SVille Tervo 				hdev->le_cnt += count;
24686ed58ec5SVille Tervo 				if (hdev->le_cnt > hdev->le_pkts)
24696ed58ec5SVille Tervo 					hdev->le_cnt = hdev->le_pkts;
24706ed58ec5SVille Tervo 			} else {
24716ed58ec5SVille Tervo 				hdev->acl_cnt += count;
24726ed58ec5SVille Tervo 				if (hdev->acl_cnt > hdev->acl_pkts)
24736ed58ec5SVille Tervo 					hdev->acl_cnt = hdev->acl_pkts;
24746ed58ec5SVille Tervo 			}
2475f4280918SAndrei Emeltchenko 			break;
2476f4280918SAndrei Emeltchenko 
2477f4280918SAndrei Emeltchenko 		case SCO_LINK:
247870f23020SAndrei Emeltchenko 			hdev->sco_cnt += count;
247970f23020SAndrei Emeltchenko 			if (hdev->sco_cnt > hdev->sco_pkts)
24805b7f9909SMarcel Holtmann 				hdev->sco_cnt = hdev->sco_pkts;
2481f4280918SAndrei Emeltchenko 			break;
2482f4280918SAndrei Emeltchenko 
2483f4280918SAndrei Emeltchenko 		default:
2484f4280918SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
2485f4280918SAndrei Emeltchenko 			break;
24861da177e4SLinus Torvalds 		}
24871da177e4SLinus Torvalds 	}
2488a9de9248SMarcel Holtmann 
24893eff45eaSGustavo F. Padovan 	queue_work(hdev->workqueue, &hdev->tx_work);
24901da177e4SLinus Torvalds }
24911da177e4SLinus Torvalds 
249276ef7cf7SAndrei Emeltchenko static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
249376ef7cf7SAndrei Emeltchenko 						 __u16 handle)
249476ef7cf7SAndrei Emeltchenko {
249576ef7cf7SAndrei Emeltchenko 	struct hci_chan *chan;
249676ef7cf7SAndrei Emeltchenko 
249776ef7cf7SAndrei Emeltchenko 	switch (hdev->dev_type) {
249876ef7cf7SAndrei Emeltchenko 	case HCI_BREDR:
249976ef7cf7SAndrei Emeltchenko 		return hci_conn_hash_lookup_handle(hdev, handle);
250076ef7cf7SAndrei Emeltchenko 	case HCI_AMP:
250176ef7cf7SAndrei Emeltchenko 		chan = hci_chan_lookup_handle(hdev, handle);
250276ef7cf7SAndrei Emeltchenko 		if (chan)
250376ef7cf7SAndrei Emeltchenko 			return chan->conn;
250476ef7cf7SAndrei Emeltchenko 		break;
250576ef7cf7SAndrei Emeltchenko 	default:
250676ef7cf7SAndrei Emeltchenko 		BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type);
250776ef7cf7SAndrei Emeltchenko 		break;
250876ef7cf7SAndrei Emeltchenko 	}
250976ef7cf7SAndrei Emeltchenko 
251076ef7cf7SAndrei Emeltchenko 	return NULL;
251176ef7cf7SAndrei Emeltchenko }
251276ef7cf7SAndrei Emeltchenko 
25136039aa73SGustavo Padovan static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
251425e89e99SAndrei Emeltchenko {
251525e89e99SAndrei Emeltchenko 	struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
251625e89e99SAndrei Emeltchenko 	int i;
251725e89e99SAndrei Emeltchenko 
251825e89e99SAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
251925e89e99SAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
252025e89e99SAndrei Emeltchenko 		return;
252125e89e99SAndrei Emeltchenko 	}
252225e89e99SAndrei Emeltchenko 
252325e89e99SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
252425e89e99SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
252525e89e99SAndrei Emeltchenko 		BT_DBG("%s bad parameters", hdev->name);
252625e89e99SAndrei Emeltchenko 		return;
252725e89e99SAndrei Emeltchenko 	}
252825e89e99SAndrei Emeltchenko 
252925e89e99SAndrei Emeltchenko 	BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
253025e89e99SAndrei Emeltchenko 	       ev->num_hndl);
253125e89e99SAndrei Emeltchenko 
253225e89e99SAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
253325e89e99SAndrei Emeltchenko 		struct hci_comp_blocks_info *info = &ev->handles[i];
253476ef7cf7SAndrei Emeltchenko 		struct hci_conn *conn = NULL;
253525e89e99SAndrei Emeltchenko 		__u16  handle, block_count;
253625e89e99SAndrei Emeltchenko 
253725e89e99SAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
253825e89e99SAndrei Emeltchenko 		block_count = __le16_to_cpu(info->blocks);
253925e89e99SAndrei Emeltchenko 
254076ef7cf7SAndrei Emeltchenko 		conn = __hci_conn_lookup_handle(hdev, handle);
254125e89e99SAndrei Emeltchenko 		if (!conn)
254225e89e99SAndrei Emeltchenko 			continue;
254325e89e99SAndrei Emeltchenko 
254425e89e99SAndrei Emeltchenko 		conn->sent -= block_count;
254525e89e99SAndrei Emeltchenko 
254625e89e99SAndrei Emeltchenko 		switch (conn->type) {
254725e89e99SAndrei Emeltchenko 		case ACL_LINK:
2548bd1eb66bSAndrei Emeltchenko 		case AMP_LINK:
254925e89e99SAndrei Emeltchenko 			hdev->block_cnt += block_count;
255025e89e99SAndrei Emeltchenko 			if (hdev->block_cnt > hdev->num_blocks)
255125e89e99SAndrei Emeltchenko 				hdev->block_cnt = hdev->num_blocks;
255225e89e99SAndrei Emeltchenko 			break;
255325e89e99SAndrei Emeltchenko 
255425e89e99SAndrei Emeltchenko 		default:
255525e89e99SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
255625e89e99SAndrei Emeltchenko 			break;
255725e89e99SAndrei Emeltchenko 		}
255825e89e99SAndrei Emeltchenko 	}
255925e89e99SAndrei Emeltchenko 
256025e89e99SAndrei Emeltchenko 	queue_work(hdev->workqueue, &hdev->tx_work);
256125e89e99SAndrei Emeltchenko }
256225e89e99SAndrei Emeltchenko 
25636039aa73SGustavo Padovan static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
25641da177e4SLinus Torvalds {
2565a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
256604837f64SMarcel Holtmann 	struct hci_conn *conn;
25671da177e4SLinus Torvalds 
25689f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
25691da177e4SLinus Torvalds 
25701da177e4SLinus Torvalds 	hci_dev_lock(hdev);
25711da177e4SLinus Torvalds 
257204837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
257304837f64SMarcel Holtmann 	if (conn) {
257404837f64SMarcel Holtmann 		conn->mode = ev->mode;
257504837f64SMarcel Holtmann 		conn->interval = __le16_to_cpu(ev->interval);
257604837f64SMarcel Holtmann 
25778fc9ced3SGustavo Padovan 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
25788fc9ced3SGustavo Padovan 					&conn->flags)) {
257904837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
258058a681efSJohan Hedberg 				set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
258104837f64SMarcel Holtmann 			else
258258a681efSJohan Hedberg 				clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
258304837f64SMarcel Holtmann 		}
2584e73439d8SMarcel Holtmann 
258551a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
2586e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
258704837f64SMarcel Holtmann 	}
258804837f64SMarcel Holtmann 
258904837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
259004837f64SMarcel Holtmann }
259104837f64SMarcel Holtmann 
25926039aa73SGustavo Padovan static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
25931da177e4SLinus Torvalds {
2594052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
2595052b30b0SMarcel Holtmann 	struct hci_conn *conn;
2596052b30b0SMarcel Holtmann 
2597a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2598052b30b0SMarcel Holtmann 
2599052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2600052b30b0SMarcel Holtmann 
2601052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2602b6f98044SWaldemar Rymarkiewicz 	if (!conn)
2603b6f98044SWaldemar Rymarkiewicz 		goto unlock;
2604b6f98044SWaldemar Rymarkiewicz 
2605b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
2606052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2607052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2608052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2609052b30b0SMarcel Holtmann 	}
2610052b30b0SMarcel Holtmann 
2611a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
261203b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
261303b555e1SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
2614a8b2d5c2SJohan Hedberg 	else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
2615a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
2616a770bb5aSWaldemar Rymarkiewicz 
2617a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
2618a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
2619a770bb5aSWaldemar Rymarkiewicz 		else
2620a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
2621a770bb5aSWaldemar Rymarkiewicz 
2622744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
2623a770bb5aSWaldemar Rymarkiewicz 	}
2624980e1a53SJohan Hedberg 
2625b6f98044SWaldemar Rymarkiewicz unlock:
2626052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
26271da177e4SLinus Torvalds }
26281da177e4SLinus Torvalds 
26296039aa73SGustavo Padovan static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
26301da177e4SLinus Torvalds {
263155ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
263255ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
263355ed8ca1SJohan Hedberg 	struct hci_conn *conn;
263455ed8ca1SJohan Hedberg 	struct link_key *key;
263555ed8ca1SJohan Hedberg 
2636a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
263755ed8ca1SJohan Hedberg 
2638a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
263955ed8ca1SJohan Hedberg 		return;
264055ed8ca1SJohan Hedberg 
264155ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
264255ed8ca1SJohan Hedberg 
264355ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
264455ed8ca1SJohan Hedberg 	if (!key) {
26456ed93dc6SAndrei Emeltchenko 		BT_DBG("%s link key not found for %pMR", hdev->name,
26466ed93dc6SAndrei Emeltchenko 		       &ev->bdaddr);
264755ed8ca1SJohan Hedberg 		goto not_found;
264855ed8ca1SJohan Hedberg 	}
264955ed8ca1SJohan Hedberg 
26506ed93dc6SAndrei Emeltchenko 	BT_DBG("%s found key type %u for %pMR", hdev->name, key->type,
26516ed93dc6SAndrei Emeltchenko 	       &ev->bdaddr);
265255ed8ca1SJohan Hedberg 
2653a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
2654b6020ba0SWaldemar Rymarkiewicz 	    key->type == HCI_LK_DEBUG_COMBINATION) {
265555ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
265655ed8ca1SJohan Hedberg 		goto not_found;
265755ed8ca1SJohan Hedberg 	}
265855ed8ca1SJohan Hedberg 
265955ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
266060b83f57SWaldemar Rymarkiewicz 	if (conn) {
266160b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_UNAUTH_COMBINATION &&
2662807deac2SGustavo Padovan 		    conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
266355ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
266455ed8ca1SJohan Hedberg 			goto not_found;
266555ed8ca1SJohan Hedberg 		}
266655ed8ca1SJohan Hedberg 
266760b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
266860b83f57SWaldemar Rymarkiewicz 		    conn->pending_sec_level == BT_SECURITY_HIGH) {
26698fc9ced3SGustavo Padovan 			BT_DBG("%s ignoring key unauthenticated for high security",
26708fc9ced3SGustavo Padovan 			       hdev->name);
267160b83f57SWaldemar Rymarkiewicz 			goto not_found;
267260b83f57SWaldemar Rymarkiewicz 		}
267360b83f57SWaldemar Rymarkiewicz 
267460b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
267560b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
267660b83f57SWaldemar Rymarkiewicz 	}
267760b83f57SWaldemar Rymarkiewicz 
267855ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
26799b3b4460SAndrei Emeltchenko 	memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
268055ed8ca1SJohan Hedberg 
268155ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
268255ed8ca1SJohan Hedberg 
268355ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
268455ed8ca1SJohan Hedberg 
268555ed8ca1SJohan Hedberg 	return;
268655ed8ca1SJohan Hedberg 
268755ed8ca1SJohan Hedberg not_found:
268855ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
268955ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
26901da177e4SLinus Torvalds }
26911da177e4SLinus Torvalds 
26926039aa73SGustavo Padovan static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
26931da177e4SLinus Torvalds {
2694052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
2695052b30b0SMarcel Holtmann 	struct hci_conn *conn;
269655ed8ca1SJohan Hedberg 	u8 pin_len = 0;
2697052b30b0SMarcel Holtmann 
2698a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2699052b30b0SMarcel Holtmann 
2700052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2701052b30b0SMarcel Holtmann 
2702052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2703052b30b0SMarcel Holtmann 	if (conn) {
2704052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2705052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2706980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
270713d39315SWaldemar Rymarkiewicz 
270813d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
270913d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
271013d39315SWaldemar Rymarkiewicz 
2711052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2712052b30b0SMarcel Holtmann 	}
2713052b30b0SMarcel Holtmann 
2714a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
2715d25e28abSJohan Hedberg 		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
271655ed8ca1SJohan Hedberg 				 ev->key_type, pin_len);
271755ed8ca1SJohan Hedberg 
2718052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
27191da177e4SLinus Torvalds }
27201da177e4SLinus Torvalds 
27216039aa73SGustavo Padovan static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
272204837f64SMarcel Holtmann {
2723a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
272404837f64SMarcel Holtmann 	struct hci_conn *conn;
272504837f64SMarcel Holtmann 
27269f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
272704837f64SMarcel Holtmann 
272804837f64SMarcel Holtmann 	hci_dev_lock(hdev);
272904837f64SMarcel Holtmann 
273004837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
27311da177e4SLinus Torvalds 	if (conn && !ev->status) {
27321da177e4SLinus Torvalds 		struct inquiry_entry *ie;
27331da177e4SLinus Torvalds 
2734cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2735cc11b9c1SAndrei Emeltchenko 		if (ie) {
27361da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
27371da177e4SLinus Torvalds 			ie->timestamp = jiffies;
27381da177e4SLinus Torvalds 		}
27391da177e4SLinus Torvalds 	}
27401da177e4SLinus Torvalds 
27411da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
27421da177e4SLinus Torvalds }
27431da177e4SLinus Torvalds 
27446039aa73SGustavo Padovan static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2745a8746417SMarcel Holtmann {
2746a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2747a8746417SMarcel Holtmann 	struct hci_conn *conn;
2748a8746417SMarcel Holtmann 
27499f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2750a8746417SMarcel Holtmann 
2751a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
2752a8746417SMarcel Holtmann 
2753a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2754a8746417SMarcel Holtmann 	if (conn && !ev->status)
2755a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2756a8746417SMarcel Holtmann 
2757a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
2758a8746417SMarcel Holtmann }
2759a8746417SMarcel Holtmann 
27606039aa73SGustavo Padovan static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
276185a1e930SMarcel Holtmann {
2762a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
276385a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
276485a1e930SMarcel Holtmann 
276585a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
276685a1e930SMarcel Holtmann 
276785a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
276885a1e930SMarcel Holtmann 
2769cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2770cc11b9c1SAndrei Emeltchenko 	if (ie) {
277185a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
277285a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
277385a1e930SMarcel Holtmann 	}
277485a1e930SMarcel Holtmann 
277585a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
277685a1e930SMarcel Holtmann }
277785a1e930SMarcel Holtmann 
27786039aa73SGustavo Padovan static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
2779807deac2SGustavo Padovan 					     struct sk_buff *skb)
2780a9de9248SMarcel Holtmann {
2781a9de9248SMarcel Holtmann 	struct inquiry_data data;
2782a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2783388fc8faSJohan Hedberg 	bool name_known, ssp;
2784a9de9248SMarcel Holtmann 
2785a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2786a9de9248SMarcel Holtmann 
2787a9de9248SMarcel Holtmann 	if (!num_rsp)
2788a9de9248SMarcel Holtmann 		return;
2789a9de9248SMarcel Holtmann 
27901519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
27911519cc17SAndre Guedes 		return;
27921519cc17SAndre Guedes 
2793a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2794a9de9248SMarcel Holtmann 
2795a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
2796138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
2797138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
2798a9de9248SMarcel Holtmann 
2799e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2800a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2801a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2802a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2803a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
2804a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2805a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2806a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
280741a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
28083175405bSJohan Hedberg 
28093175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
2810388fc8faSJohan Hedberg 							      false, &ssp);
281148264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2812e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
2813388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
2814a9de9248SMarcel Holtmann 		}
2815a9de9248SMarcel Holtmann 	} else {
2816a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2817a9de9248SMarcel Holtmann 
2818e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2819a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2820a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2821a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2822a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
2823a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2824a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2825a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
282641a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
28273175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
2828388fc8faSJohan Hedberg 							      false, &ssp);
282948264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2830e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
2831388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
2832a9de9248SMarcel Holtmann 		}
2833a9de9248SMarcel Holtmann 	}
2834a9de9248SMarcel Holtmann 
2835a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2836a9de9248SMarcel Holtmann }
2837a9de9248SMarcel Holtmann 
28386039aa73SGustavo Padovan static void hci_remote_ext_features_evt(struct hci_dev *hdev,
2839807deac2SGustavo Padovan 					struct sk_buff *skb)
2840a9de9248SMarcel Holtmann {
284141a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
284241a96212SMarcel Holtmann 	struct hci_conn *conn;
284341a96212SMarcel Holtmann 
2844a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
284541a96212SMarcel Holtmann 
284641a96212SMarcel Holtmann 	hci_dev_lock(hdev);
284741a96212SMarcel Holtmann 
284841a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2849ccd556feSJohan Hedberg 	if (!conn)
2850ccd556feSJohan Hedberg 		goto unlock;
2851ccd556feSJohan Hedberg 
2852769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
285341a96212SMarcel Holtmann 		struct inquiry_entry *ie;
285441a96212SMarcel Holtmann 
2855cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2856cc11b9c1SAndrei Emeltchenko 		if (ie)
285702b7cc62SJohan Hedberg 			ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
285841a96212SMarcel Holtmann 
285902b7cc62SJohan Hedberg 		if (ev->features[0] & LMP_HOST_SSP)
286058a681efSJohan Hedberg 			set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
286141a96212SMarcel Holtmann 	}
286241a96212SMarcel Holtmann 
2863ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2864ccd556feSJohan Hedberg 		goto unlock;
2865ccd556feSJohan Hedberg 
2866671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
2867127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2868127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2869127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2870127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2871127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2872b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2873b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
287408c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
2875b644ba33SJohan Hedberg 				      conn->dev_class);
2876392599b9SJohan Hedberg 
2877127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2878769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2879769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2880769be974SMarcel Holtmann 		hci_conn_put(conn);
2881769be974SMarcel Holtmann 	}
2882769be974SMarcel Holtmann 
2883ccd556feSJohan Hedberg unlock:
288441a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
2885a9de9248SMarcel Holtmann }
2886a9de9248SMarcel Holtmann 
28876039aa73SGustavo Padovan static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
2888807deac2SGustavo Padovan 				       struct sk_buff *skb)
2889a9de9248SMarcel Holtmann {
2890b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2891b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
2892b6a0dc82SMarcel Holtmann 
28939f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2894b6a0dc82SMarcel Holtmann 
2895b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
2896b6a0dc82SMarcel Holtmann 
2897b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
28989dc0a3afSMarcel Holtmann 	if (!conn) {
28999dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
29009dc0a3afSMarcel Holtmann 			goto unlock;
29019dc0a3afSMarcel Holtmann 
29029dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2903b6a0dc82SMarcel Holtmann 		if (!conn)
2904b6a0dc82SMarcel Holtmann 			goto unlock;
2905b6a0dc82SMarcel Holtmann 
29069dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
29079dc0a3afSMarcel Holtmann 	}
29089dc0a3afSMarcel Holtmann 
2909732547f9SMarcel Holtmann 	switch (ev->status) {
2910732547f9SMarcel Holtmann 	case 0x00:
2911732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
2912732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
2913732547f9SMarcel Holtmann 
29149eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
2915732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
2916732547f9SMarcel Holtmann 		break;
2917732547f9SMarcel Holtmann 
2918705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
2919732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
29201038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
2921732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
2922732547f9SMarcel Holtmann 		if (conn->out && conn->attempt < 2) {
2923efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2924efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
2925efc7688bSMarcel Holtmann 			hci_setup_sync(conn, conn->link->handle);
2926efc7688bSMarcel Holtmann 			goto unlock;
2927efc7688bSMarcel Holtmann 		}
2928732547f9SMarcel Holtmann 		/* fall through */
2929efc7688bSMarcel Holtmann 
2930732547f9SMarcel Holtmann 	default:
2931b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
2932732547f9SMarcel Holtmann 		break;
2933732547f9SMarcel Holtmann 	}
2934b6a0dc82SMarcel Holtmann 
2935b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
2936b6a0dc82SMarcel Holtmann 	if (ev->status)
2937b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
2938b6a0dc82SMarcel Holtmann 
2939b6a0dc82SMarcel Holtmann unlock:
2940b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
2941a9de9248SMarcel Holtmann }
2942a9de9248SMarcel Holtmann 
29436039aa73SGustavo Padovan static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
2944807deac2SGustavo Padovan 					    struct sk_buff *skb)
2945a9de9248SMarcel Holtmann {
2946a9de9248SMarcel Holtmann 	struct inquiry_data data;
2947a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
2948a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
29499d939d94SVishal Agarwal 	size_t eir_len;
2950a9de9248SMarcel Holtmann 
2951a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2952a9de9248SMarcel Holtmann 
2953a9de9248SMarcel Holtmann 	if (!num_rsp)
2954a9de9248SMarcel Holtmann 		return;
2955a9de9248SMarcel Holtmann 
29561519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
29571519cc17SAndre Guedes 		return;
29581519cc17SAndre Guedes 
2959a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2960a9de9248SMarcel Holtmann 
2961e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
2962388fc8faSJohan Hedberg 		bool name_known, ssp;
2963561aafbcSJohan Hedberg 
2964a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
2965a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
2966a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
2967a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
2968a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
2969a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
2970a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
297141a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
2972561aafbcSJohan Hedberg 
2973a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
29744ddb1930SJohan Hedberg 			name_known = eir_has_data_type(info->data,
29754ddb1930SJohan Hedberg 						       sizeof(info->data),
29764ddb1930SJohan Hedberg 						       EIR_NAME_COMPLETE);
2977561aafbcSJohan Hedberg 		else
2978561aafbcSJohan Hedberg 			name_known = true;
2979561aafbcSJohan Hedberg 
2980388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, name_known,
2981388fc8faSJohan Hedberg 						      &ssp);
29829d939d94SVishal Agarwal 		eir_len = eir_get_length(info->data, sizeof(info->data));
298348264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
298404124681SGustavo F. Padovan 				  info->dev_class, info->rssi, !name_known,
29859d939d94SVishal Agarwal 				  ssp, info->data, eir_len);
2986a9de9248SMarcel Holtmann 	}
2987a9de9248SMarcel Holtmann 
2988a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2989a9de9248SMarcel Holtmann }
2990a9de9248SMarcel Holtmann 
29911c2e0041SJohan Hedberg static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
29921c2e0041SJohan Hedberg 					 struct sk_buff *skb)
29931c2e0041SJohan Hedberg {
29941c2e0041SJohan Hedberg 	struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
29951c2e0041SJohan Hedberg 	struct hci_conn *conn;
29961c2e0041SJohan Hedberg 
29979f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
29981c2e0041SJohan Hedberg 	       __le16_to_cpu(ev->handle));
29991c2e0041SJohan Hedberg 
30001c2e0041SJohan Hedberg 	hci_dev_lock(hdev);
30011c2e0041SJohan Hedberg 
30021c2e0041SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
30031c2e0041SJohan Hedberg 	if (!conn)
30041c2e0041SJohan Hedberg 		goto unlock;
30051c2e0041SJohan Hedberg 
30061c2e0041SJohan Hedberg 	if (!ev->status)
30071c2e0041SJohan Hedberg 		conn->sec_level = conn->pending_sec_level;
30081c2e0041SJohan Hedberg 
30091c2e0041SJohan Hedberg 	clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
30101c2e0041SJohan Hedberg 
30111c2e0041SJohan Hedberg 	if (ev->status && conn->state == BT_CONNECTED) {
3012bed71748SAndre Guedes 		hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
30131c2e0041SJohan Hedberg 		hci_conn_put(conn);
30141c2e0041SJohan Hedberg 		goto unlock;
30151c2e0041SJohan Hedberg 	}
30161c2e0041SJohan Hedberg 
30171c2e0041SJohan Hedberg 	if (conn->state == BT_CONFIG) {
30181c2e0041SJohan Hedberg 		if (!ev->status)
30191c2e0041SJohan Hedberg 			conn->state = BT_CONNECTED;
30201c2e0041SJohan Hedberg 
30211c2e0041SJohan Hedberg 		hci_proto_connect_cfm(conn, ev->status);
30221c2e0041SJohan Hedberg 		hci_conn_put(conn);
30231c2e0041SJohan Hedberg 	} else {
30241c2e0041SJohan Hedberg 		hci_auth_cfm(conn, ev->status);
30251c2e0041SJohan Hedberg 
30261c2e0041SJohan Hedberg 		hci_conn_hold(conn);
30271c2e0041SJohan Hedberg 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
30281c2e0041SJohan Hedberg 		hci_conn_put(conn);
30291c2e0041SJohan Hedberg 	}
30301c2e0041SJohan Hedberg 
30311c2e0041SJohan Hedberg unlock:
30321c2e0041SJohan Hedberg 	hci_dev_unlock(hdev);
30331c2e0041SJohan Hedberg }
30341c2e0041SJohan Hedberg 
30356039aa73SGustavo Padovan static u8 hci_get_auth_req(struct hci_conn *conn)
303617fa4b9dSJohan Hedberg {
303717fa4b9dSJohan Hedberg 	/* If remote requests dedicated bonding follow that lead */
303817fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
303917fa4b9dSJohan Hedberg 		/* If both remote and local IO capabilities allow MITM
304017fa4b9dSJohan Hedberg 		 * protection then require it, otherwise don't */
304117fa4b9dSJohan Hedberg 		if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
304217fa4b9dSJohan Hedberg 			return 0x02;
304317fa4b9dSJohan Hedberg 		else
304417fa4b9dSJohan Hedberg 			return 0x03;
304517fa4b9dSJohan Hedberg 	}
304617fa4b9dSJohan Hedberg 
304717fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
304817fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
304958797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
305017fa4b9dSJohan Hedberg 
305117fa4b9dSJohan Hedberg 	return conn->auth_type;
305217fa4b9dSJohan Hedberg }
305317fa4b9dSJohan Hedberg 
30546039aa73SGustavo Padovan static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
30550493684eSMarcel Holtmann {
30560493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
30570493684eSMarcel Holtmann 	struct hci_conn *conn;
30580493684eSMarcel Holtmann 
30590493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
30600493684eSMarcel Holtmann 
30610493684eSMarcel Holtmann 	hci_dev_lock(hdev);
30620493684eSMarcel Holtmann 
30630493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
306403b555e1SJohan Hedberg 	if (!conn)
306503b555e1SJohan Hedberg 		goto unlock;
306603b555e1SJohan Hedberg 
30670493684eSMarcel Holtmann 	hci_conn_hold(conn);
30680493684eSMarcel Holtmann 
3069a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
307003b555e1SJohan Hedberg 		goto unlock;
307103b555e1SJohan Hedberg 
3072a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
307303b555e1SJohan Hedberg 	    (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
307417fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
307517fa4b9dSJohan Hedberg 
307617fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
30777a7f1e7cSHemant Gupta 		/* Change the IO capability from KeyboardDisplay
30787a7f1e7cSHemant Gupta 		 * to DisplayYesNo as it is not supported by BT spec. */
30797a7f1e7cSHemant Gupta 		cp.capability = (conn->io_capability == 0x04) ?
30807a7f1e7cSHemant Gupta 						0x01 : conn->io_capability;
30817cbc9bd9SJohan Hedberg 		conn->auth_type = hci_get_auth_req(conn);
30827cbc9bd9SJohan Hedberg 		cp.authentication = conn->auth_type;
308317fa4b9dSJohan Hedberg 
30848fc9ced3SGustavo Padovan 		if (hci_find_remote_oob_data(hdev, &conn->dst) &&
30858fc9ced3SGustavo Padovan 		    (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
3086ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
3087ce85ee13SSzymon Janc 		else
3088ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
3089ce85ee13SSzymon Janc 
309017fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
309117fa4b9dSJohan Hedberg 			     sizeof(cp), &cp);
309203b555e1SJohan Hedberg 	} else {
309303b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
309403b555e1SJohan Hedberg 
309503b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
30969f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
309703b555e1SJohan Hedberg 
309803b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
309903b555e1SJohan Hedberg 			     sizeof(cp), &cp);
310003b555e1SJohan Hedberg 	}
310103b555e1SJohan Hedberg 
310203b555e1SJohan Hedberg unlock:
310303b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
310403b555e1SJohan Hedberg }
310503b555e1SJohan Hedberg 
31066039aa73SGustavo Padovan static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
310703b555e1SJohan Hedberg {
310803b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
310903b555e1SJohan Hedberg 	struct hci_conn *conn;
311003b555e1SJohan Hedberg 
311103b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
311203b555e1SJohan Hedberg 
311303b555e1SJohan Hedberg 	hci_dev_lock(hdev);
311403b555e1SJohan Hedberg 
311503b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
311603b555e1SJohan Hedberg 	if (!conn)
311703b555e1SJohan Hedberg 		goto unlock;
311803b555e1SJohan Hedberg 
311903b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
312003b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
312158a681efSJohan Hedberg 	if (ev->oob_data)
312258a681efSJohan Hedberg 		set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
312303b555e1SJohan Hedberg 
312403b555e1SJohan Hedberg unlock:
31250493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
31260493684eSMarcel Holtmann }
31270493684eSMarcel Holtmann 
31286039aa73SGustavo Padovan static void hci_user_confirm_request_evt(struct hci_dev *hdev,
3129a5c29683SJohan Hedberg 					 struct sk_buff *skb)
3130a5c29683SJohan Hedberg {
3131a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
313255bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
31337a828908SJohan Hedberg 	struct hci_conn *conn;
3134a5c29683SJohan Hedberg 
3135a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
3136a5c29683SJohan Hedberg 
3137a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
3138a5c29683SJohan Hedberg 
3139a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
31407a828908SJohan Hedberg 		goto unlock;
31417a828908SJohan Hedberg 
31427a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
31437a828908SJohan Hedberg 	if (!conn)
31447a828908SJohan Hedberg 		goto unlock;
31457a828908SJohan Hedberg 
31467a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
31477a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
31487a828908SJohan Hedberg 
31497a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
31507a828908SJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
31517a828908SJohan Hedberg 	 * request. The only exception is when we're dedicated bonding
31527a828908SJohan Hedberg 	 * initiators (connect_cfm_cb set) since then we always have the MITM
31537a828908SJohan Hedberg 	 * bit set. */
31547a828908SJohan Hedberg 	if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
31557a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
31567a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
31577a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
31587a828908SJohan Hedberg 		goto unlock;
31597a828908SJohan Hedberg 	}
31607a828908SJohan Hedberg 
31617a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
31627a828908SJohan Hedberg 	if ((!loc_mitm || conn->remote_cap == 0x03) &&
31637a828908SJohan Hedberg 	    (!rem_mitm || conn->io_capability == 0x03)) {
316455bc1a37SJohan Hedberg 
316555bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
316655bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
316755bc1a37SJohan Hedberg 		 * confirm_hint set to 1). */
316851a8efd7SJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
316955bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
317055bc1a37SJohan Hedberg 			confirm_hint = 1;
317155bc1a37SJohan Hedberg 			goto confirm;
317255bc1a37SJohan Hedberg 		}
317355bc1a37SJohan Hedberg 
31749f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
31759f61656aSJohan Hedberg 		       hdev->auto_accept_delay);
31769f61656aSJohan Hedberg 
31779f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
31789f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
31799f61656aSJohan Hedberg 			mod_timer(&conn->auto_accept_timer, jiffies + delay);
31809f61656aSJohan Hedberg 			goto unlock;
31819f61656aSJohan Hedberg 		}
31829f61656aSJohan Hedberg 
31837a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
31847a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
31857a828908SJohan Hedberg 		goto unlock;
31867a828908SJohan Hedberg 	}
31877a828908SJohan Hedberg 
318855bc1a37SJohan Hedberg confirm:
3189272d90dfSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
319055bc1a37SJohan Hedberg 				  confirm_hint);
3191a5c29683SJohan Hedberg 
31927a828908SJohan Hedberg unlock:
3193a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
3194a5c29683SJohan Hedberg }
3195a5c29683SJohan Hedberg 
31966039aa73SGustavo Padovan static void hci_user_passkey_request_evt(struct hci_dev *hdev,
31971143d458SBrian Gix 					 struct sk_buff *skb)
31981143d458SBrian Gix {
31991143d458SBrian Gix 	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
32001143d458SBrian Gix 
32011143d458SBrian Gix 	BT_DBG("%s", hdev->name);
32021143d458SBrian Gix 
3203a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3204272d90dfSJohan Hedberg 		mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
32051143d458SBrian Gix }
32061143d458SBrian Gix 
320792a25256SJohan Hedberg static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
320892a25256SJohan Hedberg 					struct sk_buff *skb)
320992a25256SJohan Hedberg {
321092a25256SJohan Hedberg 	struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
321192a25256SJohan Hedberg 	struct hci_conn *conn;
321292a25256SJohan Hedberg 
321392a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
321492a25256SJohan Hedberg 
321592a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
321692a25256SJohan Hedberg 	if (!conn)
321792a25256SJohan Hedberg 		return;
321892a25256SJohan Hedberg 
321992a25256SJohan Hedberg 	conn->passkey_notify = __le32_to_cpu(ev->passkey);
322092a25256SJohan Hedberg 	conn->passkey_entered = 0;
322192a25256SJohan Hedberg 
322292a25256SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
322392a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
322492a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
322592a25256SJohan Hedberg 					 conn->passkey_entered);
322692a25256SJohan Hedberg }
322792a25256SJohan Hedberg 
322892a25256SJohan Hedberg static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
322992a25256SJohan Hedberg {
323092a25256SJohan Hedberg 	struct hci_ev_keypress_notify *ev = (void *) skb->data;
323192a25256SJohan Hedberg 	struct hci_conn *conn;
323292a25256SJohan Hedberg 
323392a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
323492a25256SJohan Hedberg 
323592a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
323692a25256SJohan Hedberg 	if (!conn)
323792a25256SJohan Hedberg 		return;
323892a25256SJohan Hedberg 
323992a25256SJohan Hedberg 	switch (ev->type) {
324092a25256SJohan Hedberg 	case HCI_KEYPRESS_STARTED:
324192a25256SJohan Hedberg 		conn->passkey_entered = 0;
324292a25256SJohan Hedberg 		return;
324392a25256SJohan Hedberg 
324492a25256SJohan Hedberg 	case HCI_KEYPRESS_ENTERED:
324592a25256SJohan Hedberg 		conn->passkey_entered++;
324692a25256SJohan Hedberg 		break;
324792a25256SJohan Hedberg 
324892a25256SJohan Hedberg 	case HCI_KEYPRESS_ERASED:
324992a25256SJohan Hedberg 		conn->passkey_entered--;
325092a25256SJohan Hedberg 		break;
325192a25256SJohan Hedberg 
325292a25256SJohan Hedberg 	case HCI_KEYPRESS_CLEARED:
325392a25256SJohan Hedberg 		conn->passkey_entered = 0;
325492a25256SJohan Hedberg 		break;
325592a25256SJohan Hedberg 
325692a25256SJohan Hedberg 	case HCI_KEYPRESS_COMPLETED:
325792a25256SJohan Hedberg 		return;
325892a25256SJohan Hedberg 	}
325992a25256SJohan Hedberg 
326092a25256SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
326192a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
326292a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
326392a25256SJohan Hedberg 					 conn->passkey_entered);
326492a25256SJohan Hedberg }
326592a25256SJohan Hedberg 
32666039aa73SGustavo Padovan static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
3267807deac2SGustavo Padovan 					 struct sk_buff *skb)
32680493684eSMarcel Holtmann {
32690493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
32700493684eSMarcel Holtmann 	struct hci_conn *conn;
32710493684eSMarcel Holtmann 
32720493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
32730493684eSMarcel Holtmann 
32740493684eSMarcel Holtmann 	hci_dev_lock(hdev);
32750493684eSMarcel Holtmann 
32760493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
32772a611692SJohan Hedberg 	if (!conn)
32782a611692SJohan Hedberg 		goto unlock;
32792a611692SJohan Hedberg 
32802a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
32812a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
32822a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
32832a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
32842a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
3285fa1bd918SMikel Astiz 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status)
3286bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
3287bab73cb6SJohan Hedberg 				 ev->status);
32882a611692SJohan Hedberg 
32890493684eSMarcel Holtmann 	hci_conn_put(conn);
32900493684eSMarcel Holtmann 
32912a611692SJohan Hedberg unlock:
32920493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
32930493684eSMarcel Holtmann }
32940493684eSMarcel Holtmann 
32956039aa73SGustavo Padovan static void hci_remote_host_features_evt(struct hci_dev *hdev,
3296807deac2SGustavo Padovan 					 struct sk_buff *skb)
329741a96212SMarcel Holtmann {
329841a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
329941a96212SMarcel Holtmann 	struct inquiry_entry *ie;
330041a96212SMarcel Holtmann 
330141a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
330241a96212SMarcel Holtmann 
330341a96212SMarcel Holtmann 	hci_dev_lock(hdev);
330441a96212SMarcel Holtmann 
3305cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3306cc11b9c1SAndrei Emeltchenko 	if (ie)
330702b7cc62SJohan Hedberg 		ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
330841a96212SMarcel Holtmann 
330941a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
331041a96212SMarcel Holtmann }
331141a96212SMarcel Holtmann 
33126039aa73SGustavo Padovan static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
33132763eda6SSzymon Janc 					    struct sk_buff *skb)
33142763eda6SSzymon Janc {
33152763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
33162763eda6SSzymon Janc 	struct oob_data *data;
33172763eda6SSzymon Janc 
33182763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
33192763eda6SSzymon Janc 
33202763eda6SSzymon Janc 	hci_dev_lock(hdev);
33212763eda6SSzymon Janc 
3322a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
3323e1ba1f15SSzymon Janc 		goto unlock;
3324e1ba1f15SSzymon Janc 
33252763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
33262763eda6SSzymon Janc 	if (data) {
33272763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_reply cp;
33282763eda6SSzymon Janc 
33292763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
33302763eda6SSzymon Janc 		memcpy(cp.hash, data->hash, sizeof(cp.hash));
33312763eda6SSzymon Janc 		memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
33322763eda6SSzymon Janc 
33332763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
33342763eda6SSzymon Janc 			     &cp);
33352763eda6SSzymon Janc 	} else {
33362763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
33372763eda6SSzymon Janc 
33382763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
33392763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
33402763eda6SSzymon Janc 			     &cp);
33412763eda6SSzymon Janc 	}
33422763eda6SSzymon Janc 
3343e1ba1f15SSzymon Janc unlock:
33442763eda6SSzymon Janc 	hci_dev_unlock(hdev);
33452763eda6SSzymon Janc }
33462763eda6SSzymon Janc 
3347d5e91192SAndrei Emeltchenko static void hci_phy_link_complete_evt(struct hci_dev *hdev,
3348d5e91192SAndrei Emeltchenko 				      struct sk_buff *skb)
3349d5e91192SAndrei Emeltchenko {
3350d5e91192SAndrei Emeltchenko 	struct hci_ev_phy_link_complete *ev = (void *) skb->data;
3351d5e91192SAndrei Emeltchenko 	struct hci_conn *hcon, *bredr_hcon;
3352d5e91192SAndrei Emeltchenko 
3353d5e91192SAndrei Emeltchenko 	BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle,
3354d5e91192SAndrei Emeltchenko 	       ev->status);
3355d5e91192SAndrei Emeltchenko 
3356d5e91192SAndrei Emeltchenko 	hci_dev_lock(hdev);
3357d5e91192SAndrei Emeltchenko 
3358d5e91192SAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3359d5e91192SAndrei Emeltchenko 	if (!hcon) {
3360d5e91192SAndrei Emeltchenko 		hci_dev_unlock(hdev);
3361d5e91192SAndrei Emeltchenko 		return;
3362d5e91192SAndrei Emeltchenko 	}
3363d5e91192SAndrei Emeltchenko 
3364d5e91192SAndrei Emeltchenko 	if (ev->status) {
3365d5e91192SAndrei Emeltchenko 		hci_conn_del(hcon);
3366d5e91192SAndrei Emeltchenko 		hci_dev_unlock(hdev);
3367d5e91192SAndrei Emeltchenko 		return;
3368d5e91192SAndrei Emeltchenko 	}
3369d5e91192SAndrei Emeltchenko 
3370d5e91192SAndrei Emeltchenko 	bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon;
3371d5e91192SAndrei Emeltchenko 
3372d5e91192SAndrei Emeltchenko 	hcon->state = BT_CONNECTED;
3373d5e91192SAndrei Emeltchenko 	bacpy(&hcon->dst, &bredr_hcon->dst);
3374d5e91192SAndrei Emeltchenko 
3375d5e91192SAndrei Emeltchenko 	hci_conn_hold(hcon);
3376d5e91192SAndrei Emeltchenko 	hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
3377d5e91192SAndrei Emeltchenko 	hci_conn_put(hcon);
3378d5e91192SAndrei Emeltchenko 
3379d5e91192SAndrei Emeltchenko 	hci_conn_hold_device(hcon);
3380d5e91192SAndrei Emeltchenko 	hci_conn_add_sysfs(hcon);
3381d5e91192SAndrei Emeltchenko 
3382cf70ff22SAndrei Emeltchenko 	amp_physical_cfm(bredr_hcon, hcon);
3383cf70ff22SAndrei Emeltchenko 
3384d5e91192SAndrei Emeltchenko 	hci_dev_unlock(hdev);
3385d5e91192SAndrei Emeltchenko }
3386d5e91192SAndrei Emeltchenko 
338727695fb4SAndrei Emeltchenko static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
338827695fb4SAndrei Emeltchenko {
338927695fb4SAndrei Emeltchenko 	struct hci_ev_logical_link_complete *ev = (void *) skb->data;
339027695fb4SAndrei Emeltchenko 	struct hci_conn *hcon;
339127695fb4SAndrei Emeltchenko 	struct hci_chan *hchan;
339227695fb4SAndrei Emeltchenko 	struct amp_mgr *mgr;
339327695fb4SAndrei Emeltchenko 
339427695fb4SAndrei Emeltchenko 	BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x",
339527695fb4SAndrei Emeltchenko 	       hdev->name, le16_to_cpu(ev->handle), ev->phy_handle,
339627695fb4SAndrei Emeltchenko 	       ev->status);
339727695fb4SAndrei Emeltchenko 
339827695fb4SAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
339927695fb4SAndrei Emeltchenko 	if (!hcon)
340027695fb4SAndrei Emeltchenko 		return;
340127695fb4SAndrei Emeltchenko 
340227695fb4SAndrei Emeltchenko 	/* Create AMP hchan */
340327695fb4SAndrei Emeltchenko 	hchan = hci_chan_create(hcon);
340427695fb4SAndrei Emeltchenko 	if (!hchan)
340527695fb4SAndrei Emeltchenko 		return;
340627695fb4SAndrei Emeltchenko 
340727695fb4SAndrei Emeltchenko 	hchan->handle = le16_to_cpu(ev->handle);
340827695fb4SAndrei Emeltchenko 
340927695fb4SAndrei Emeltchenko 	BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan);
341027695fb4SAndrei Emeltchenko 
341127695fb4SAndrei Emeltchenko 	mgr = hcon->amp_mgr;
341227695fb4SAndrei Emeltchenko 	if (mgr && mgr->bredr_chan) {
341327695fb4SAndrei Emeltchenko 		struct l2cap_chan *bredr_chan = mgr->bredr_chan;
341427695fb4SAndrei Emeltchenko 
341527695fb4SAndrei Emeltchenko 		l2cap_chan_lock(bredr_chan);
341627695fb4SAndrei Emeltchenko 
341727695fb4SAndrei Emeltchenko 		bredr_chan->conn->mtu = hdev->block_mtu;
341827695fb4SAndrei Emeltchenko 		l2cap_logical_cfm(bredr_chan, hchan, 0);
341927695fb4SAndrei Emeltchenko 		hci_conn_hold(hcon);
342027695fb4SAndrei Emeltchenko 
342127695fb4SAndrei Emeltchenko 		l2cap_chan_unlock(bredr_chan);
342227695fb4SAndrei Emeltchenko 	}
342327695fb4SAndrei Emeltchenko }
342427695fb4SAndrei Emeltchenko 
3425606e2a10SAndrei Emeltchenko static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,
3426606e2a10SAndrei Emeltchenko 					     struct sk_buff *skb)
3427606e2a10SAndrei Emeltchenko {
3428606e2a10SAndrei Emeltchenko 	struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data;
3429606e2a10SAndrei Emeltchenko 	struct hci_chan *hchan;
3430606e2a10SAndrei Emeltchenko 
3431606e2a10SAndrei Emeltchenko 	BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name,
3432606e2a10SAndrei Emeltchenko 	       le16_to_cpu(ev->handle), ev->status);
3433606e2a10SAndrei Emeltchenko 
3434606e2a10SAndrei Emeltchenko 	if (ev->status)
3435606e2a10SAndrei Emeltchenko 		return;
3436606e2a10SAndrei Emeltchenko 
3437606e2a10SAndrei Emeltchenko 	hci_dev_lock(hdev);
3438606e2a10SAndrei Emeltchenko 
3439606e2a10SAndrei Emeltchenko 	hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle));
3440606e2a10SAndrei Emeltchenko 	if (!hchan)
3441606e2a10SAndrei Emeltchenko 		goto unlock;
3442606e2a10SAndrei Emeltchenko 
3443606e2a10SAndrei Emeltchenko 	amp_destroy_logical_link(hchan, ev->reason);
3444606e2a10SAndrei Emeltchenko 
3445606e2a10SAndrei Emeltchenko unlock:
3446606e2a10SAndrei Emeltchenko 	hci_dev_unlock(hdev);
3447606e2a10SAndrei Emeltchenko }
3448606e2a10SAndrei Emeltchenko 
34499eef6b3aSAndrei Emeltchenko static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev,
34509eef6b3aSAndrei Emeltchenko 					     struct sk_buff *skb)
34519eef6b3aSAndrei Emeltchenko {
34529eef6b3aSAndrei Emeltchenko 	struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data;
34539eef6b3aSAndrei Emeltchenko 	struct hci_conn *hcon;
34549eef6b3aSAndrei Emeltchenko 
34559eef6b3aSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
34569eef6b3aSAndrei Emeltchenko 
34579eef6b3aSAndrei Emeltchenko 	if (ev->status)
34589eef6b3aSAndrei Emeltchenko 		return;
34599eef6b3aSAndrei Emeltchenko 
34609eef6b3aSAndrei Emeltchenko 	hci_dev_lock(hdev);
34619eef6b3aSAndrei Emeltchenko 
34629eef6b3aSAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
34639eef6b3aSAndrei Emeltchenko 	if (hcon) {
34649eef6b3aSAndrei Emeltchenko 		hcon->state = BT_CLOSED;
34659eef6b3aSAndrei Emeltchenko 		hci_conn_del(hcon);
34669eef6b3aSAndrei Emeltchenko 	}
34679eef6b3aSAndrei Emeltchenko 
34689eef6b3aSAndrei Emeltchenko 	hci_dev_unlock(hdev);
34699eef6b3aSAndrei Emeltchenko }
34709eef6b3aSAndrei Emeltchenko 
34716039aa73SGustavo Padovan static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3472fcd89c09SVille Tervo {
3473fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3474fcd89c09SVille Tervo 	struct hci_conn *conn;
3475fcd89c09SVille Tervo 
34769f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3477fcd89c09SVille Tervo 
3478fcd89c09SVille Tervo 	hci_dev_lock(hdev);
3479fcd89c09SVille Tervo 
34804f72b329SAndrzej Kaczmarek 	conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
3481b62f328bSVille Tervo 	if (!conn) {
3482b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3483b62f328bSVille Tervo 		if (!conn) {
3484b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
3485230fd16aSAndre Guedes 			goto unlock;
3486b62f328bSVille Tervo 		}
348729b7988aSAndre Guedes 
348829b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
3489b9b343d2SAndre Guedes 
3490b9b343d2SAndre Guedes 		if (ev->role == LE_CONN_ROLE_MASTER) {
3491b9b343d2SAndre Guedes 			conn->out = true;
3492b9b343d2SAndre Guedes 			conn->link_mode |= HCI_LM_MASTER;
3493b9b343d2SAndre Guedes 		}
3494b62f328bSVille Tervo 	}
3495fcd89c09SVille Tervo 
3496cd17decbSAndre Guedes 	if (ev->status) {
3497cd17decbSAndre Guedes 		mgmt_connect_failed(hdev, &conn->dst, conn->type,
3498cd17decbSAndre Guedes 				    conn->dst_type, ev->status);
3499cd17decbSAndre Guedes 		hci_proto_connect_cfm(conn, ev->status);
3500cd17decbSAndre Guedes 		conn->state = BT_CLOSED;
3501cd17decbSAndre Guedes 		hci_conn_del(conn);
3502cd17decbSAndre Guedes 		goto unlock;
3503cd17decbSAndre Guedes 	}
3504cd17decbSAndre Guedes 
3505b644ba33SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3506b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
350795b23582SSzymon Janc 				      conn->dst_type, 0, NULL, 0, NULL);
350883bc71b4SVinicius Costa Gomes 
35097b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
3510fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
3511fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
3512fcd89c09SVille Tervo 
3513fcd89c09SVille Tervo 	hci_conn_hold_device(conn);
3514fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
3515fcd89c09SVille Tervo 
3516fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
3517fcd89c09SVille Tervo 
3518fcd89c09SVille Tervo unlock:
3519fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
3520fcd89c09SVille Tervo }
3521fcd89c09SVille Tervo 
35226039aa73SGustavo Padovan static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
35239aa04c91SAndre Guedes {
3524e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
3525e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
35263c9e9195SAndre Guedes 	s8 rssi;
35279aa04c91SAndre Guedes 
3528e95beb41SAndre Guedes 	while (num_reports--) {
3529e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
3530e95beb41SAndre Guedes 
35313c9e9195SAndre Guedes 		rssi = ev->data[ev->length];
35323c9e9195SAndre Guedes 		mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
353304124681SGustavo F. Padovan 				  NULL, rssi, 0, 1, ev->data, ev->length);
35343c9e9195SAndre Guedes 
3535e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
35369aa04c91SAndre Guedes 	}
35379aa04c91SAndre Guedes }
35389aa04c91SAndre Guedes 
35396039aa73SGustavo Padovan static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
3540a7a595f6SVinicius Costa Gomes {
3541a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3542a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
3543bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
3544a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
3545c9839a11SVinicius Costa Gomes 	struct smp_ltk *ltk;
3546a7a595f6SVinicius Costa Gomes 
35479f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
3548a7a595f6SVinicius Costa Gomes 
3549a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
3550a7a595f6SVinicius Costa Gomes 
3551a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3552bea710feSVinicius Costa Gomes 	if (conn == NULL)
3553bea710feSVinicius Costa Gomes 		goto not_found;
3554a7a595f6SVinicius Costa Gomes 
3555bea710feSVinicius Costa Gomes 	ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3556bea710feSVinicius Costa Gomes 	if (ltk == NULL)
3557bea710feSVinicius Costa Gomes 		goto not_found;
3558bea710feSVinicius Costa Gomes 
3559bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
3560a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
3561c9839a11SVinicius Costa Gomes 
3562c9839a11SVinicius Costa Gomes 	if (ltk->authenticated)
3563c9839a11SVinicius Costa Gomes 		conn->sec_level = BT_SECURITY_HIGH;
3564a7a595f6SVinicius Costa Gomes 
3565a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3566a7a595f6SVinicius Costa Gomes 
3567c9839a11SVinicius Costa Gomes 	if (ltk->type & HCI_SMP_STK) {
3568c9839a11SVinicius Costa Gomes 		list_del(&ltk->list);
3569c9839a11SVinicius Costa Gomes 		kfree(ltk);
3570c9839a11SVinicius Costa Gomes 	}
3571c9839a11SVinicius Costa Gomes 
3572a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
3573bea710feSVinicius Costa Gomes 
3574bea710feSVinicius Costa Gomes 	return;
3575bea710feSVinicius Costa Gomes 
3576bea710feSVinicius Costa Gomes not_found:
3577bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
3578bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3579bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
3580a7a595f6SVinicius Costa Gomes }
3581a7a595f6SVinicius Costa Gomes 
35826039aa73SGustavo Padovan static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3583fcd89c09SVille Tervo {
3584fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
3585fcd89c09SVille Tervo 
3586fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
3587fcd89c09SVille Tervo 
3588fcd89c09SVille Tervo 	switch (le_ev->subevent) {
3589fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
3590fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
3591fcd89c09SVille Tervo 		break;
3592fcd89c09SVille Tervo 
35939aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
35949aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
35959aa04c91SAndre Guedes 		break;
35969aa04c91SAndre Guedes 
3597a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
3598a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
3599a7a595f6SVinicius Costa Gomes 		break;
3600a7a595f6SVinicius Costa Gomes 
3601fcd89c09SVille Tervo 	default:
3602fcd89c09SVille Tervo 		break;
3603fcd89c09SVille Tervo 	}
3604fcd89c09SVille Tervo }
3605fcd89c09SVille Tervo 
36069495b2eeSAndrei Emeltchenko static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
36079495b2eeSAndrei Emeltchenko {
36089495b2eeSAndrei Emeltchenko 	struct hci_ev_channel_selected *ev = (void *) skb->data;
36099495b2eeSAndrei Emeltchenko 	struct hci_conn *hcon;
36109495b2eeSAndrei Emeltchenko 
36119495b2eeSAndrei Emeltchenko 	BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
36129495b2eeSAndrei Emeltchenko 
36139495b2eeSAndrei Emeltchenko 	skb_pull(skb, sizeof(*ev));
36149495b2eeSAndrei Emeltchenko 
36159495b2eeSAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
36169495b2eeSAndrei Emeltchenko 	if (!hcon)
36179495b2eeSAndrei Emeltchenko 		return;
36189495b2eeSAndrei Emeltchenko 
36199495b2eeSAndrei Emeltchenko 	amp_read_loc_assoc_final_data(hdev, hcon);
36209495b2eeSAndrei Emeltchenko }
36219495b2eeSAndrei Emeltchenko 
36221da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
36231da177e4SLinus Torvalds {
3624a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
3625a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
36261da177e4SLinus Torvalds 
36271da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
36281da177e4SLinus Torvalds 
3629a9de9248SMarcel Holtmann 	switch (event) {
36301da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
36311da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
36321da177e4SLinus Torvalds 		break;
36331da177e4SLinus Torvalds 
36341da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
36351da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
36361da177e4SLinus Torvalds 		break;
36371da177e4SLinus Torvalds 
3638a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
3639a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
364021d9e30eSMarcel Holtmann 		break;
364121d9e30eSMarcel Holtmann 
36421da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
36431da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
36441da177e4SLinus Torvalds 		break;
36451da177e4SLinus Torvalds 
36461da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
36471da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
36481da177e4SLinus Torvalds 		break;
36491da177e4SLinus Torvalds 
36501da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
36511da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
36521da177e4SLinus Torvalds 		break;
36531da177e4SLinus Torvalds 
3654a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
3655a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
3656a9de9248SMarcel Holtmann 		break;
3657a9de9248SMarcel Holtmann 
36581da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
36591da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
36601da177e4SLinus Torvalds 		break;
36611da177e4SLinus Torvalds 
3662a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3663a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
3664a9de9248SMarcel Holtmann 		break;
3665a9de9248SMarcel Holtmann 
3666a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
3667a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
3668a9de9248SMarcel Holtmann 		break;
3669a9de9248SMarcel Holtmann 
3670a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
3671a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
3672a9de9248SMarcel Holtmann 		break;
3673a9de9248SMarcel Holtmann 
3674a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
3675a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
3676a9de9248SMarcel Holtmann 		break;
3677a9de9248SMarcel Holtmann 
3678a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
3679a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
3680a9de9248SMarcel Holtmann 		break;
3681a9de9248SMarcel Holtmann 
3682a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
3683a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
3684a9de9248SMarcel Holtmann 		break;
3685a9de9248SMarcel Holtmann 
3686a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
3687a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
36881da177e4SLinus Torvalds 		break;
36891da177e4SLinus Torvalds 
36901da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
36911da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
36921da177e4SLinus Torvalds 		break;
36931da177e4SLinus Torvalds 
36941da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
36951da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
36961da177e4SLinus Torvalds 		break;
36971da177e4SLinus Torvalds 
36981da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
36991da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
37001da177e4SLinus Torvalds 		break;
37011da177e4SLinus Torvalds 
37021da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
37031da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
37041da177e4SLinus Torvalds 		break;
37051da177e4SLinus Torvalds 
3706a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
3707a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
3708a8746417SMarcel Holtmann 		break;
3709a8746417SMarcel Holtmann 
371085a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
371185a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
371285a1e930SMarcel Holtmann 		break;
371385a1e930SMarcel Holtmann 
3714a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3715a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
3716a9de9248SMarcel Holtmann 		break;
3717a9de9248SMarcel Holtmann 
3718a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
3719a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
3720a9de9248SMarcel Holtmann 		break;
3721a9de9248SMarcel Holtmann 
3722a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
3723a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
3724a9de9248SMarcel Holtmann 		break;
3725a9de9248SMarcel Holtmann 
3726a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
3727a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
37281da177e4SLinus Torvalds 		break;
37291da177e4SLinus Torvalds 
37301c2e0041SJohan Hedberg 	case HCI_EV_KEY_REFRESH_COMPLETE:
37311c2e0041SJohan Hedberg 		hci_key_refresh_complete_evt(hdev, skb);
37321c2e0041SJohan Hedberg 		break;
37331c2e0041SJohan Hedberg 
37340493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
37350493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
37360493684eSMarcel Holtmann 		break;
37370493684eSMarcel Holtmann 
373803b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
373903b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
374003b555e1SJohan Hedberg 		break;
374103b555e1SJohan Hedberg 
3742a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
3743a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
3744a5c29683SJohan Hedberg 		break;
3745a5c29683SJohan Hedberg 
37461143d458SBrian Gix 	case HCI_EV_USER_PASSKEY_REQUEST:
37471143d458SBrian Gix 		hci_user_passkey_request_evt(hdev, skb);
37481143d458SBrian Gix 		break;
37491143d458SBrian Gix 
375092a25256SJohan Hedberg 	case HCI_EV_USER_PASSKEY_NOTIFY:
375192a25256SJohan Hedberg 		hci_user_passkey_notify_evt(hdev, skb);
375292a25256SJohan Hedberg 		break;
375392a25256SJohan Hedberg 
375492a25256SJohan Hedberg 	case HCI_EV_KEYPRESS_NOTIFY:
375592a25256SJohan Hedberg 		hci_keypress_notify_evt(hdev, skb);
375692a25256SJohan Hedberg 		break;
375792a25256SJohan Hedberg 
37580493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
37590493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
37600493684eSMarcel Holtmann 		break;
37610493684eSMarcel Holtmann 
376241a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
376341a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
376441a96212SMarcel Holtmann 		break;
376541a96212SMarcel Holtmann 
3766fcd89c09SVille Tervo 	case HCI_EV_LE_META:
3767fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
3768fcd89c09SVille Tervo 		break;
3769fcd89c09SVille Tervo 
37709495b2eeSAndrei Emeltchenko 	case HCI_EV_CHANNEL_SELECTED:
37719495b2eeSAndrei Emeltchenko 		hci_chan_selected_evt(hdev, skb);
37729495b2eeSAndrei Emeltchenko 		break;
37739495b2eeSAndrei Emeltchenko 
37742763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
37752763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
37762763eda6SSzymon Janc 		break;
37772763eda6SSzymon Janc 
3778d5e91192SAndrei Emeltchenko 	case HCI_EV_PHY_LINK_COMPLETE:
3779d5e91192SAndrei Emeltchenko 		hci_phy_link_complete_evt(hdev, skb);
3780d5e91192SAndrei Emeltchenko 		break;
3781d5e91192SAndrei Emeltchenko 
378227695fb4SAndrei Emeltchenko 	case HCI_EV_LOGICAL_LINK_COMPLETE:
378327695fb4SAndrei Emeltchenko 		hci_loglink_complete_evt(hdev, skb);
378427695fb4SAndrei Emeltchenko 		break;
378527695fb4SAndrei Emeltchenko 
3786606e2a10SAndrei Emeltchenko 	case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE:
3787606e2a10SAndrei Emeltchenko 		hci_disconn_loglink_complete_evt(hdev, skb);
3788606e2a10SAndrei Emeltchenko 		break;
3789606e2a10SAndrei Emeltchenko 
37909eef6b3aSAndrei Emeltchenko 	case HCI_EV_DISCONN_PHY_LINK_COMPLETE:
37919eef6b3aSAndrei Emeltchenko 		hci_disconn_phylink_complete_evt(hdev, skb);
37929eef6b3aSAndrei Emeltchenko 		break;
37939eef6b3aSAndrei Emeltchenko 
379425e89e99SAndrei Emeltchenko 	case HCI_EV_NUM_COMP_BLOCKS:
379525e89e99SAndrei Emeltchenko 		hci_num_comp_blocks_evt(hdev, skb);
379625e89e99SAndrei Emeltchenko 		break;
379725e89e99SAndrei Emeltchenko 
37981da177e4SLinus Torvalds 	default:
37999f1db00cSAndrei Emeltchenko 		BT_DBG("%s event 0x%2.2x", hdev->name, event);
38001da177e4SLinus Torvalds 		break;
38011da177e4SLinus Torvalds 	}
38021da177e4SLinus Torvalds 
38031da177e4SLinus Torvalds 	kfree_skb(skb);
38041da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
38051da177e4SLinus Torvalds }
3806