xref: /openbmc/linux/net/bluetooth/hci_event.c (revision 7d0db0a3)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds    BlueZ - Bluetooth protocol stack for Linux
31da177e4SLinus Torvalds    Copyright (C) 2000-2001 Qualcomm Incorporated
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 <linux/module.h>
281da177e4SLinus Torvalds 
291da177e4SLinus Torvalds #include <linux/types.h>
301da177e4SLinus Torvalds #include <linux/errno.h>
311da177e4SLinus Torvalds #include <linux/kernel.h>
321da177e4SLinus Torvalds #include <linux/slab.h>
331da177e4SLinus Torvalds #include <linux/poll.h>
341da177e4SLinus Torvalds #include <linux/fcntl.h>
351da177e4SLinus Torvalds #include <linux/init.h>
361da177e4SLinus Torvalds #include <linux/skbuff.h>
371da177e4SLinus Torvalds #include <linux/interrupt.h>
381da177e4SLinus Torvalds #include <linux/notifier.h>
391da177e4SLinus Torvalds #include <net/sock.h>
401da177e4SLinus Torvalds 
411da177e4SLinus Torvalds #include <asm/system.h>
421da177e4SLinus Torvalds #include <asm/uaccess.h>
431da177e4SLinus Torvalds #include <asm/unaligned.h>
441da177e4SLinus Torvalds 
451da177e4SLinus Torvalds #include <net/bluetooth/bluetooth.h>
461da177e4SLinus Torvalds #include <net/bluetooth/hci_core.h>
471da177e4SLinus Torvalds 
481da177e4SLinus Torvalds #ifndef CONFIG_BT_HCI_CORE_DEBUG
491da177e4SLinus Torvalds #undef  BT_DBG
501da177e4SLinus Torvalds #define BT_DBG(D...)
511da177e4SLinus Torvalds #endif
521da177e4SLinus Torvalds 
531da177e4SLinus Torvalds /* Handle HCI Event packets */
541da177e4SLinus Torvalds 
55a9de9248SMarcel Holtmann static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
561da177e4SLinus Torvalds {
57a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
581da177e4SLinus Torvalds 
59a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
601da177e4SLinus Torvalds 
61a9de9248SMarcel Holtmann 	if (status)
62a9de9248SMarcel Holtmann 		return;
631da177e4SLinus Torvalds 
641da177e4SLinus Torvalds 	clear_bit(HCI_INQUIRY, &hdev->flags);
65a9de9248SMarcel Holtmann 
661da177e4SLinus Torvalds 	hci_req_complete(hdev, status);
67a9de9248SMarcel Holtmann 
68a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
691da177e4SLinus Torvalds }
706bd57416SMarcel Holtmann 
71a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
721da177e4SLinus Torvalds {
73a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
74a9de9248SMarcel Holtmann 
75a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
76a9de9248SMarcel Holtmann 
77a9de9248SMarcel Holtmann 	if (status)
78a9de9248SMarcel Holtmann 		return;
79a9de9248SMarcel Holtmann 
80a9de9248SMarcel Holtmann 	clear_bit(HCI_INQUIRY, &hdev->flags);
81a9de9248SMarcel Holtmann 
82a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
83a9de9248SMarcel Holtmann }
84a9de9248SMarcel Holtmann 
85a9de9248SMarcel Holtmann static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, struct sk_buff *skb)
86a9de9248SMarcel Holtmann {
87a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
88a9de9248SMarcel Holtmann }
89a9de9248SMarcel Holtmann 
90a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
91a9de9248SMarcel Holtmann {
92a9de9248SMarcel Holtmann 	struct hci_rp_role_discovery *rp = (void *) skb->data;
931da177e4SLinus Torvalds 	struct hci_conn *conn;
941da177e4SLinus Torvalds 
95a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
961da177e4SLinus Torvalds 
97a9de9248SMarcel Holtmann 	if (rp->status)
98a9de9248SMarcel Holtmann 		return;
991da177e4SLinus Torvalds 
1001da177e4SLinus Torvalds 	hci_dev_lock(hdev);
1011da177e4SLinus Torvalds 
102a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
1031da177e4SLinus Torvalds 	if (conn) {
104a9de9248SMarcel Holtmann 		if (rp->role)
1051da177e4SLinus Torvalds 			conn->link_mode &= ~HCI_LM_MASTER;
1061da177e4SLinus Torvalds 		else
1071da177e4SLinus Torvalds 			conn->link_mode |= HCI_LM_MASTER;
1081da177e4SLinus Torvalds 	}
1091da177e4SLinus Torvalds 
1101da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
111a9de9248SMarcel Holtmann }
1121da177e4SLinus Torvalds 
113e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
114e4e8e37cSMarcel Holtmann {
115e4e8e37cSMarcel Holtmann 	struct hci_rp_read_link_policy *rp = (void *) skb->data;
116e4e8e37cSMarcel Holtmann 	struct hci_conn *conn;
117e4e8e37cSMarcel Holtmann 
118e4e8e37cSMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
119e4e8e37cSMarcel Holtmann 
120e4e8e37cSMarcel Holtmann 	if (rp->status)
121e4e8e37cSMarcel Holtmann 		return;
122e4e8e37cSMarcel Holtmann 
123e4e8e37cSMarcel Holtmann 	hci_dev_lock(hdev);
124e4e8e37cSMarcel Holtmann 
125e4e8e37cSMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
126e4e8e37cSMarcel Holtmann 	if (conn)
127e4e8e37cSMarcel Holtmann 		conn->link_policy = __le16_to_cpu(rp->policy);
128e4e8e37cSMarcel Holtmann 
129e4e8e37cSMarcel Holtmann 	hci_dev_unlock(hdev);
130e4e8e37cSMarcel Holtmann }
131e4e8e37cSMarcel Holtmann 
132a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
133a9de9248SMarcel Holtmann {
134a9de9248SMarcel Holtmann 	struct hci_rp_write_link_policy *rp = (void *) skb->data;
135a9de9248SMarcel Holtmann 	struct hci_conn *conn;
136a9de9248SMarcel Holtmann 	void *sent;
137a9de9248SMarcel Holtmann 
138a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
139a9de9248SMarcel Holtmann 
140a9de9248SMarcel Holtmann 	if (rp->status)
141a9de9248SMarcel Holtmann 		return;
142a9de9248SMarcel Holtmann 
143a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
14404837f64SMarcel Holtmann 	if (!sent)
145a9de9248SMarcel Holtmann 		return;
14604837f64SMarcel Holtmann 
14704837f64SMarcel Holtmann 	hci_dev_lock(hdev);
14804837f64SMarcel Holtmann 
149a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
150e4e8e37cSMarcel Holtmann 	if (conn)
15183985319SHarvey Harrison 		conn->link_policy = get_unaligned_le16(sent + 2);
15204837f64SMarcel Holtmann 
15304837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
1541da177e4SLinus Torvalds }
1551da177e4SLinus Torvalds 
156e4e8e37cSMarcel Holtmann static void hci_cc_read_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
157e4e8e37cSMarcel Holtmann {
158e4e8e37cSMarcel Holtmann 	struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
159e4e8e37cSMarcel Holtmann 
160e4e8e37cSMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
161e4e8e37cSMarcel Holtmann 
162e4e8e37cSMarcel Holtmann 	if (rp->status)
163e4e8e37cSMarcel Holtmann 		return;
164e4e8e37cSMarcel Holtmann 
165e4e8e37cSMarcel Holtmann 	hdev->link_policy = __le16_to_cpu(rp->policy);
166e4e8e37cSMarcel Holtmann }
167e4e8e37cSMarcel Holtmann 
168e4e8e37cSMarcel Holtmann static void hci_cc_write_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
169e4e8e37cSMarcel Holtmann {
170e4e8e37cSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
171e4e8e37cSMarcel Holtmann 	void *sent;
172e4e8e37cSMarcel Holtmann 
173e4e8e37cSMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
174e4e8e37cSMarcel Holtmann 
175e4e8e37cSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
176e4e8e37cSMarcel Holtmann 	if (!sent)
177e4e8e37cSMarcel Holtmann 		return;
178e4e8e37cSMarcel Holtmann 
179e4e8e37cSMarcel Holtmann 	if (!status)
180e4e8e37cSMarcel Holtmann 		hdev->link_policy = get_unaligned_le16(sent);
181e4e8e37cSMarcel Holtmann 
182e4e8e37cSMarcel Holtmann 	hci_req_complete(hdev, status);
183e4e8e37cSMarcel Holtmann }
184e4e8e37cSMarcel Holtmann 
185a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
1861da177e4SLinus Torvalds {
187a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
188a9de9248SMarcel Holtmann 
189a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
190a9de9248SMarcel Holtmann 
191a9de9248SMarcel Holtmann 	hci_req_complete(hdev, status);
192a9de9248SMarcel Holtmann }
193a9de9248SMarcel Holtmann 
194a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
195a9de9248SMarcel Holtmann {
196a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
1971da177e4SLinus Torvalds 	void *sent;
1981da177e4SLinus Torvalds 
199a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
2001da177e4SLinus Torvalds 
201f383f275SMarcel Holtmann 	if (status)
202f383f275SMarcel Holtmann 		return;
203f383f275SMarcel Holtmann 
204a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
2051da177e4SLinus Torvalds 	if (!sent)
206a9de9248SMarcel Holtmann 		return;
2071da177e4SLinus Torvalds 
208a9de9248SMarcel Holtmann 	memcpy(hdev->dev_name, sent, 248);
209a9de9248SMarcel Holtmann }
210a9de9248SMarcel Holtmann 
211a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
212a9de9248SMarcel Holtmann {
213a9de9248SMarcel Holtmann 	struct hci_rp_read_local_name *rp = (void *) skb->data;
214a9de9248SMarcel Holtmann 
215a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
216a9de9248SMarcel Holtmann 
217a9de9248SMarcel Holtmann 	if (rp->status)
218a9de9248SMarcel Holtmann 		return;
219a9de9248SMarcel Holtmann 
220a9de9248SMarcel Holtmann 	memcpy(hdev->dev_name, rp->name, 248);
221a9de9248SMarcel Holtmann }
222a9de9248SMarcel Holtmann 
223a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
224a9de9248SMarcel Holtmann {
225a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
226a9de9248SMarcel Holtmann 	void *sent;
227a9de9248SMarcel Holtmann 
228a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
229a9de9248SMarcel Holtmann 
230a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
231a9de9248SMarcel Holtmann 	if (!sent)
232a9de9248SMarcel Holtmann 		return;
2331da177e4SLinus Torvalds 
2341da177e4SLinus Torvalds 	if (!status) {
235a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
236a9de9248SMarcel Holtmann 
2371da177e4SLinus Torvalds 		if (param == AUTH_ENABLED)
2381da177e4SLinus Torvalds 			set_bit(HCI_AUTH, &hdev->flags);
2391da177e4SLinus Torvalds 		else
2401da177e4SLinus Torvalds 			clear_bit(HCI_AUTH, &hdev->flags);
2411da177e4SLinus Torvalds 	}
242a9de9248SMarcel Holtmann 
2431da177e4SLinus Torvalds 	hci_req_complete(hdev, status);
244a9de9248SMarcel Holtmann }
2451da177e4SLinus Torvalds 
246a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
247a9de9248SMarcel Holtmann {
248a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
249a9de9248SMarcel Holtmann 	void *sent;
250a9de9248SMarcel Holtmann 
251a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
252a9de9248SMarcel Holtmann 
253a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
2541da177e4SLinus Torvalds 	if (!sent)
255a9de9248SMarcel Holtmann 		return;
2561da177e4SLinus Torvalds 
2571da177e4SLinus Torvalds 	if (!status) {
258a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
259a9de9248SMarcel Holtmann 
2601da177e4SLinus Torvalds 		if (param)
2611da177e4SLinus Torvalds 			set_bit(HCI_ENCRYPT, &hdev->flags);
2621da177e4SLinus Torvalds 		else
2631da177e4SLinus Torvalds 			clear_bit(HCI_ENCRYPT, &hdev->flags);
2641da177e4SLinus Torvalds 	}
265a9de9248SMarcel Holtmann 
2661da177e4SLinus Torvalds 	hci_req_complete(hdev, status);
2671da177e4SLinus Torvalds }
2681da177e4SLinus Torvalds 
269a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
270a9de9248SMarcel Holtmann {
271a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
272a9de9248SMarcel Holtmann 	void *sent;
2731da177e4SLinus Torvalds 
274a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
275a9de9248SMarcel Holtmann 
276a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
2771da177e4SLinus Torvalds 	if (!sent)
278a9de9248SMarcel Holtmann 		return;
2791da177e4SLinus Torvalds 
2801da177e4SLinus Torvalds 	if (!status) {
281a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
282a9de9248SMarcel Holtmann 
2831da177e4SLinus Torvalds 		clear_bit(HCI_PSCAN, &hdev->flags);
2841da177e4SLinus Torvalds 		clear_bit(HCI_ISCAN, &hdev->flags);
285a9de9248SMarcel Holtmann 
2861da177e4SLinus Torvalds 		if (param & SCAN_INQUIRY)
2871da177e4SLinus Torvalds 			set_bit(HCI_ISCAN, &hdev->flags);
2881da177e4SLinus Torvalds 
2891da177e4SLinus Torvalds 		if (param & SCAN_PAGE)
2901da177e4SLinus Torvalds 			set_bit(HCI_PSCAN, &hdev->flags);
2911da177e4SLinus Torvalds 	}
292a9de9248SMarcel Holtmann 
2931da177e4SLinus Torvalds 	hci_req_complete(hdev, status);
2941da177e4SLinus Torvalds }
2951da177e4SLinus Torvalds 
296a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
297a9de9248SMarcel Holtmann {
298a9de9248SMarcel Holtmann 	struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
299a9de9248SMarcel Holtmann 
300a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
301a9de9248SMarcel Holtmann 
302a9de9248SMarcel Holtmann 	if (rp->status)
303a9de9248SMarcel Holtmann 		return;
304a9de9248SMarcel Holtmann 
305a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, rp->dev_class, 3);
306a9de9248SMarcel Holtmann 
307a9de9248SMarcel Holtmann 	BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
308a9de9248SMarcel Holtmann 		hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
309a9de9248SMarcel Holtmann }
310a9de9248SMarcel Holtmann 
311a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
312a9de9248SMarcel Holtmann {
313a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
314a9de9248SMarcel Holtmann 	void *sent;
315a9de9248SMarcel Holtmann 
316a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
317a9de9248SMarcel Holtmann 
318f383f275SMarcel Holtmann 	if (status)
319f383f275SMarcel Holtmann 		return;
320f383f275SMarcel Holtmann 
321a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
322a9de9248SMarcel Holtmann 	if (!sent)
323a9de9248SMarcel Holtmann 		return;
324a9de9248SMarcel Holtmann 
325a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, sent, 3);
326a9de9248SMarcel Holtmann }
327a9de9248SMarcel Holtmann 
328a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
329a9de9248SMarcel Holtmann {
330a9de9248SMarcel Holtmann 	struct hci_rp_read_voice_setting *rp = (void *) skb->data;
331a9de9248SMarcel Holtmann 	__u16 setting;
332a9de9248SMarcel Holtmann 
333a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
334a9de9248SMarcel Holtmann 
335a9de9248SMarcel Holtmann 	if (rp->status)
336a9de9248SMarcel Holtmann 		return;
337a9de9248SMarcel Holtmann 
338a9de9248SMarcel Holtmann 	setting = __le16_to_cpu(rp->voice_setting);
339a9de9248SMarcel Holtmann 
340a9de9248SMarcel Holtmann 	if (hdev->voice_setting == setting)
341a9de9248SMarcel Holtmann 		return;
342a9de9248SMarcel Holtmann 
343a9de9248SMarcel Holtmann 	hdev->voice_setting = setting;
344a9de9248SMarcel Holtmann 
345a9de9248SMarcel Holtmann 	BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
346a9de9248SMarcel Holtmann 
347a9de9248SMarcel Holtmann 	if (hdev->notify) {
348a9de9248SMarcel Holtmann 		tasklet_disable(&hdev->tx_task);
349a9de9248SMarcel Holtmann 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
350a9de9248SMarcel Holtmann 		tasklet_enable(&hdev->tx_task);
351a9de9248SMarcel Holtmann 	}
352a9de9248SMarcel Holtmann }
353a9de9248SMarcel Holtmann 
354a9de9248SMarcel Holtmann static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
355a9de9248SMarcel Holtmann {
356a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
357f383f275SMarcel Holtmann 	__u16 setting;
358a9de9248SMarcel Holtmann 	void *sent;
359a9de9248SMarcel Holtmann 
360a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
361a9de9248SMarcel Holtmann 
362f383f275SMarcel Holtmann 	if (status)
363f383f275SMarcel Holtmann 		return;
364f383f275SMarcel Holtmann 
365a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
366a9de9248SMarcel Holtmann 	if (!sent)
367a9de9248SMarcel Holtmann 		return;
368a9de9248SMarcel Holtmann 
369f383f275SMarcel Holtmann 	setting = get_unaligned_le16(sent);
3701da177e4SLinus Torvalds 
371f383f275SMarcel Holtmann 	if (hdev->voice_setting == setting)
372f383f275SMarcel Holtmann 		return;
373f383f275SMarcel Holtmann 
3741da177e4SLinus Torvalds 	hdev->voice_setting = setting;
3751da177e4SLinus Torvalds 
376a9de9248SMarcel Holtmann 	BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
3771da177e4SLinus Torvalds 
3781da177e4SLinus Torvalds 	if (hdev->notify) {
3791da177e4SLinus Torvalds 		tasklet_disable(&hdev->tx_task);
3801da177e4SLinus Torvalds 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
3811da177e4SLinus Torvalds 		tasklet_enable(&hdev->tx_task);
3821da177e4SLinus Torvalds 	}
3831da177e4SLinus Torvalds }
3841da177e4SLinus Torvalds 
385a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
3861da177e4SLinus Torvalds {
387a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
3881da177e4SLinus Torvalds 
389a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
3901da177e4SLinus Torvalds 
391a9de9248SMarcel Holtmann 	hci_req_complete(hdev, status);
3921143e5a6SMarcel Holtmann }
3931143e5a6SMarcel Holtmann 
394333140b5SMarcel Holtmann static void hci_cc_read_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
395333140b5SMarcel Holtmann {
396333140b5SMarcel Holtmann 	struct hci_rp_read_ssp_mode *rp = (void *) skb->data;
397333140b5SMarcel Holtmann 
398333140b5SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
399333140b5SMarcel Holtmann 
400333140b5SMarcel Holtmann 	if (rp->status)
401333140b5SMarcel Holtmann 		return;
402333140b5SMarcel Holtmann 
403333140b5SMarcel Holtmann 	hdev->ssp_mode = rp->mode;
404333140b5SMarcel Holtmann }
405333140b5SMarcel Holtmann 
406333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
407333140b5SMarcel Holtmann {
408333140b5SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
409333140b5SMarcel Holtmann 	void *sent;
410333140b5SMarcel Holtmann 
411333140b5SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
412333140b5SMarcel Holtmann 
413333140b5SMarcel Holtmann 	if (status)
414333140b5SMarcel Holtmann 		return;
415333140b5SMarcel Holtmann 
416333140b5SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
417333140b5SMarcel Holtmann 	if (!sent)
418333140b5SMarcel Holtmann 		return;
419333140b5SMarcel Holtmann 
420333140b5SMarcel Holtmann 	hdev->ssp_mode = *((__u8 *) sent);
421333140b5SMarcel Holtmann }
422333140b5SMarcel Holtmann 
423a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
424a9de9248SMarcel Holtmann {
425a9de9248SMarcel Holtmann 	struct hci_rp_read_local_version *rp = (void *) skb->data;
4261143e5a6SMarcel Holtmann 
427a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
4281143e5a6SMarcel Holtmann 
429a9de9248SMarcel Holtmann 	if (rp->status)
430a9de9248SMarcel Holtmann 		return;
4311143e5a6SMarcel Holtmann 
432a9de9248SMarcel Holtmann 	hdev->hci_ver = rp->hci_ver;
433e4e8e37cSMarcel Holtmann 	hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
434e4e8e37cSMarcel Holtmann 	hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
4351da177e4SLinus Torvalds 
436a9de9248SMarcel Holtmann 	BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name,
437a9de9248SMarcel Holtmann 					hdev->manufacturer,
438a9de9248SMarcel Holtmann 					hdev->hci_ver, hdev->hci_rev);
4391da177e4SLinus Torvalds }
4401da177e4SLinus Torvalds 
441a9de9248SMarcel Holtmann static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb)
442a9de9248SMarcel Holtmann {
443a9de9248SMarcel Holtmann 	struct hci_rp_read_local_commands *rp = (void *) skb->data;
444a9de9248SMarcel Holtmann 
445a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
446a9de9248SMarcel Holtmann 
447a9de9248SMarcel Holtmann 	if (rp->status)
448a9de9248SMarcel Holtmann 		return;
449a9de9248SMarcel Holtmann 
450a9de9248SMarcel Holtmann 	memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
451a9de9248SMarcel Holtmann }
452a9de9248SMarcel Holtmann 
453a9de9248SMarcel Holtmann static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb)
454a9de9248SMarcel Holtmann {
455a9de9248SMarcel Holtmann 	struct hci_rp_read_local_features *rp = (void *) skb->data;
456a9de9248SMarcel Holtmann 
457a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
458a9de9248SMarcel Holtmann 
459a9de9248SMarcel Holtmann 	if (rp->status)
460a9de9248SMarcel Holtmann 		return;
461a9de9248SMarcel Holtmann 
462a9de9248SMarcel Holtmann 	memcpy(hdev->features, rp->features, 8);
4631da177e4SLinus Torvalds 
4641da177e4SLinus Torvalds 	/* Adjust default settings according to features
4651da177e4SLinus Torvalds 	 * supported by device. */
466a9de9248SMarcel Holtmann 
4671da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_3SLOT)
4681da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
4691da177e4SLinus Torvalds 
4701da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_5SLOT)
4711da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
4721da177e4SLinus Torvalds 
4735b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV2) {
4741da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV2);
4755b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV2);
4765b7f9909SMarcel Holtmann 	}
4771da177e4SLinus Torvalds 
4785b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV3) {
4791da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV3);
4805b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV3);
4815b7f9909SMarcel Holtmann 	}
4825b7f9909SMarcel Holtmann 
4835b7f9909SMarcel Holtmann 	if (hdev->features[3] & LMP_ESCO)
4845b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV3);
4855b7f9909SMarcel Holtmann 
4865b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV4)
4875b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV4);
4885b7f9909SMarcel Holtmann 
4895b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV5)
4905b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV5);
4911da177e4SLinus Torvalds 
492a9de9248SMarcel Holtmann 	BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
493a9de9248SMarcel Holtmann 					hdev->features[0], hdev->features[1],
494a9de9248SMarcel Holtmann 					hdev->features[2], hdev->features[3],
495a9de9248SMarcel Holtmann 					hdev->features[4], hdev->features[5],
496a9de9248SMarcel Holtmann 					hdev->features[6], hdev->features[7]);
4971da177e4SLinus Torvalds }
4981da177e4SLinus Torvalds 
499a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
500a9de9248SMarcel Holtmann {
501a9de9248SMarcel Holtmann 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
502a9de9248SMarcel Holtmann 
503a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
504a9de9248SMarcel Holtmann 
505a9de9248SMarcel Holtmann 	if (rp->status)
506a9de9248SMarcel Holtmann 		return;
507a9de9248SMarcel Holtmann 
508a9de9248SMarcel Holtmann 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
509a9de9248SMarcel Holtmann 	hdev->sco_mtu  = rp->sco_mtu;
510a9de9248SMarcel Holtmann 	hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
511a9de9248SMarcel Holtmann 	hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
512da1f5198SMarcel Holtmann 
513da1f5198SMarcel Holtmann 	if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
514da1f5198SMarcel Holtmann 		hdev->sco_mtu  = 64;
515da1f5198SMarcel Holtmann 		hdev->sco_pkts = 8;
516da1f5198SMarcel Holtmann 	}
517da1f5198SMarcel Holtmann 
518da1f5198SMarcel Holtmann 	hdev->acl_cnt = hdev->acl_pkts;
519da1f5198SMarcel Holtmann 	hdev->sco_cnt = hdev->sco_pkts;
5201da177e4SLinus Torvalds 
521a9de9248SMarcel Holtmann 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name,
522a9de9248SMarcel Holtmann 					hdev->acl_mtu, hdev->acl_pkts,
523a9de9248SMarcel Holtmann 					hdev->sco_mtu, hdev->sco_pkts);
5241da177e4SLinus Torvalds }
5251da177e4SLinus Torvalds 
526a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
527a9de9248SMarcel Holtmann {
528a9de9248SMarcel Holtmann 	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
5291da177e4SLinus Torvalds 
530a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
531a9de9248SMarcel Holtmann 
532a9de9248SMarcel Holtmann 	if (!rp->status)
533a9de9248SMarcel Holtmann 		bacpy(&hdev->bdaddr, &rp->bdaddr);
534a9de9248SMarcel Holtmann 
535a9de9248SMarcel Holtmann 	hci_req_complete(hdev, rp->status);
5361da177e4SLinus Torvalds }
5371da177e4SLinus Torvalds 
538a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
539a9de9248SMarcel Holtmann {
540a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
541a9de9248SMarcel Holtmann 
542a9de9248SMarcel Holtmann 	if (status) {
543a9de9248SMarcel Holtmann 		hci_req_complete(hdev, status);
544a9de9248SMarcel Holtmann 
545a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
546a9de9248SMarcel Holtmann 	} else
547a9de9248SMarcel Holtmann 		set_bit(HCI_INQUIRY, &hdev->flags);
548a9de9248SMarcel Holtmann }
549a9de9248SMarcel Holtmann 
5501da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
5511da177e4SLinus Torvalds {
552a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
5531da177e4SLinus Torvalds 	struct hci_conn *conn;
5541da177e4SLinus Torvalds 
555a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
556a9de9248SMarcel Holtmann 
557a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
5581da177e4SLinus Torvalds 	if (!cp)
5591da177e4SLinus Torvalds 		return;
5601da177e4SLinus Torvalds 
5611da177e4SLinus Torvalds 	hci_dev_lock(hdev);
5621da177e4SLinus Torvalds 
5631da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
5641da177e4SLinus Torvalds 
565a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
5661da177e4SLinus Torvalds 
5671da177e4SLinus Torvalds 	if (status) {
5681da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
5694c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
5701da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
5711da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
5721da177e4SLinus Torvalds 				hci_conn_del(conn);
5734c67bc74SMarcel Holtmann 			} else
5744c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
5751da177e4SLinus Torvalds 		}
5761da177e4SLinus Torvalds 	} else {
5771da177e4SLinus Torvalds 		if (!conn) {
5781da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
5791da177e4SLinus Torvalds 			if (conn) {
5801da177e4SLinus Torvalds 				conn->out = 1;
5811da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
5821da177e4SLinus Torvalds 			} else
5831da177e4SLinus Torvalds 				BT_ERR("No memmory for new connection");
5841da177e4SLinus Torvalds 		}
5851da177e4SLinus Torvalds 	}
5861da177e4SLinus Torvalds 
5871da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
5881da177e4SLinus Torvalds }
5891da177e4SLinus Torvalds 
590a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
5911da177e4SLinus Torvalds {
592a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
5931da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
5941da177e4SLinus Torvalds 	__u16 handle;
5951da177e4SLinus Torvalds 
596b6a0dc82SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
597b6a0dc82SMarcel Holtmann 
598a9de9248SMarcel Holtmann 	if (!status)
599a9de9248SMarcel Holtmann 		return;
600a9de9248SMarcel Holtmann 
601a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
6021da177e4SLinus Torvalds 	if (!cp)
603a9de9248SMarcel Holtmann 		return;
6041da177e4SLinus Torvalds 
6051da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
6061da177e4SLinus Torvalds 
607a9de9248SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
6081da177e4SLinus Torvalds 
6091da177e4SLinus Torvalds 	hci_dev_lock(hdev);
6101da177e4SLinus Torvalds 
6111da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
6121da177e4SLinus Torvalds 	if (acl && (sco = acl->link)) {
6131da177e4SLinus Torvalds 		sco->state = BT_CLOSED;
6141da177e4SLinus Torvalds 
6151da177e4SLinus Torvalds 		hci_proto_connect_cfm(sco, status);
6161da177e4SLinus Torvalds 		hci_conn_del(sco);
6171da177e4SLinus Torvalds 	}
6181da177e4SLinus Torvalds 
6191da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
6201da177e4SLinus Torvalds }
6211da177e4SLinus Torvalds 
622f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
623f8558555SMarcel Holtmann {
624f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
625f8558555SMarcel Holtmann 	struct hci_conn *conn;
626f8558555SMarcel Holtmann 
627f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
628f8558555SMarcel Holtmann 
629f8558555SMarcel Holtmann 	if (!status)
630f8558555SMarcel Holtmann 		return;
631f8558555SMarcel Holtmann 
632f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
633f8558555SMarcel Holtmann 	if (!cp)
634f8558555SMarcel Holtmann 		return;
635f8558555SMarcel Holtmann 
636f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
637f8558555SMarcel Holtmann 
638f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
639f8558555SMarcel Holtmann 	if (conn) {
640f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
641f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
642f8558555SMarcel Holtmann 			hci_conn_put(conn);
643f8558555SMarcel Holtmann 		}
644f8558555SMarcel Holtmann 	}
645f8558555SMarcel Holtmann 
646f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
647f8558555SMarcel Holtmann }
648f8558555SMarcel Holtmann 
649f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
650f8558555SMarcel Holtmann {
651f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
652f8558555SMarcel Holtmann 	struct hci_conn *conn;
653f8558555SMarcel Holtmann 
654f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
655f8558555SMarcel Holtmann 
656f8558555SMarcel Holtmann 	if (!status)
657f8558555SMarcel Holtmann 		return;
658f8558555SMarcel Holtmann 
659f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
660f8558555SMarcel Holtmann 	if (!cp)
661f8558555SMarcel Holtmann 		return;
662f8558555SMarcel Holtmann 
663f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
664f8558555SMarcel Holtmann 
665f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
666f8558555SMarcel Holtmann 	if (conn) {
667f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
668f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
669f8558555SMarcel Holtmann 			hci_conn_put(conn);
670f8558555SMarcel Holtmann 		}
671f8558555SMarcel Holtmann 	}
672f8558555SMarcel Holtmann 
673f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
674f8558555SMarcel Holtmann }
675f8558555SMarcel Holtmann 
676a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
6771da177e4SLinus Torvalds {
678a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
679a9de9248SMarcel Holtmann }
6801da177e4SLinus Torvalds 
681769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
682769be974SMarcel Holtmann {
683769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
684769be974SMarcel Holtmann 	struct hci_conn *conn;
685769be974SMarcel Holtmann 
686769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
687769be974SMarcel Holtmann 
688769be974SMarcel Holtmann 	if (!status)
689769be974SMarcel Holtmann 		return;
690769be974SMarcel Holtmann 
691769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
692769be974SMarcel Holtmann 	if (!cp)
693769be974SMarcel Holtmann 		return;
694769be974SMarcel Holtmann 
695769be974SMarcel Holtmann 	hci_dev_lock(hdev);
696769be974SMarcel Holtmann 
697769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
698769be974SMarcel Holtmann 	if (conn) {
699769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
700769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
701769be974SMarcel Holtmann 			hci_conn_put(conn);
702769be974SMarcel Holtmann 		}
703769be974SMarcel Holtmann 	}
704769be974SMarcel Holtmann 
705769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
706769be974SMarcel Holtmann }
707769be974SMarcel Holtmann 
708769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
709769be974SMarcel Holtmann {
710769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
711769be974SMarcel Holtmann 	struct hci_conn *conn;
712769be974SMarcel Holtmann 
713769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
714769be974SMarcel Holtmann 
715769be974SMarcel Holtmann 	if (!status)
716769be974SMarcel Holtmann 		return;
717769be974SMarcel Holtmann 
718769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
719769be974SMarcel Holtmann 	if (!cp)
720769be974SMarcel Holtmann 		return;
721769be974SMarcel Holtmann 
722769be974SMarcel Holtmann 	hci_dev_lock(hdev);
723769be974SMarcel Holtmann 
724769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
725769be974SMarcel Holtmann 	if (conn) {
726769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
727769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
728769be974SMarcel Holtmann 			hci_conn_put(conn);
729769be974SMarcel Holtmann 		}
730769be974SMarcel Holtmann 	}
731769be974SMarcel Holtmann 
732769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
733769be974SMarcel Holtmann }
734769be974SMarcel Holtmann 
735a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
736a9de9248SMarcel Holtmann {
737b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
738b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
739b6a0dc82SMarcel Holtmann 	__u16 handle;
740b6a0dc82SMarcel Holtmann 
741a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
742b6a0dc82SMarcel Holtmann 
743b6a0dc82SMarcel Holtmann 	if (!status)
744b6a0dc82SMarcel Holtmann 		return;
745b6a0dc82SMarcel Holtmann 
746b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
747b6a0dc82SMarcel Holtmann 	if (!cp)
748b6a0dc82SMarcel Holtmann 		return;
749b6a0dc82SMarcel Holtmann 
750b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
751b6a0dc82SMarcel Holtmann 
752b6a0dc82SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
753b6a0dc82SMarcel Holtmann 
754b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
755b6a0dc82SMarcel Holtmann 
756b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
757b6a0dc82SMarcel Holtmann 	if (acl && (sco = acl->link)) {
758b6a0dc82SMarcel Holtmann 		sco->state = BT_CLOSED;
759b6a0dc82SMarcel Holtmann 
760b6a0dc82SMarcel Holtmann 		hci_proto_connect_cfm(sco, status);
761b6a0dc82SMarcel Holtmann 		hci_conn_del(sco);
762b6a0dc82SMarcel Holtmann 	}
763b6a0dc82SMarcel Holtmann 
764b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
765a9de9248SMarcel Holtmann }
766a9de9248SMarcel Holtmann 
767a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
768a9de9248SMarcel Holtmann {
769a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
77004837f64SMarcel Holtmann 	struct hci_conn *conn;
77104837f64SMarcel Holtmann 
772a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
773a9de9248SMarcel Holtmann 
774a9de9248SMarcel Holtmann 	if (!status)
775a9de9248SMarcel Holtmann 		return;
776a9de9248SMarcel Holtmann 
777a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
77804837f64SMarcel Holtmann 	if (!cp)
779a9de9248SMarcel Holtmann 		return;
78004837f64SMarcel Holtmann 
78104837f64SMarcel Holtmann 	hci_dev_lock(hdev);
78204837f64SMarcel Holtmann 
78304837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
784a9de9248SMarcel Holtmann 	if (conn)
78504837f64SMarcel Holtmann 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
78604837f64SMarcel Holtmann 
78704837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
78804837f64SMarcel Holtmann }
78904837f64SMarcel Holtmann 
790a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
791a9de9248SMarcel Holtmann {
792a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
79304837f64SMarcel Holtmann 	struct hci_conn *conn;
79404837f64SMarcel Holtmann 
795a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
796a9de9248SMarcel Holtmann 
797a9de9248SMarcel Holtmann 	if (!status)
798a9de9248SMarcel Holtmann 		return;
799a9de9248SMarcel Holtmann 
800a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
80104837f64SMarcel Holtmann 	if (!cp)
802a9de9248SMarcel Holtmann 		return;
80304837f64SMarcel Holtmann 
80404837f64SMarcel Holtmann 	hci_dev_lock(hdev);
80504837f64SMarcel Holtmann 
80604837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
807a9de9248SMarcel Holtmann 	if (conn)
80804837f64SMarcel Holtmann 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
80904837f64SMarcel Holtmann 
81004837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
81104837f64SMarcel Holtmann }
81204837f64SMarcel Holtmann 
8131da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
8141da177e4SLinus Torvalds {
8151da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
8161da177e4SLinus Torvalds 
8171da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, status);
8181da177e4SLinus Torvalds 
8191da177e4SLinus Torvalds 	clear_bit(HCI_INQUIRY, &hdev->flags);
820a9de9248SMarcel Holtmann 
8211da177e4SLinus Torvalds 	hci_req_complete(hdev, status);
8226bd57416SMarcel Holtmann 
823a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
8241da177e4SLinus Torvalds }
8251da177e4SLinus Torvalds 
8261da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
8271da177e4SLinus Torvalds {
82845bb4bf0SMarcel Holtmann 	struct inquiry_data data;
829a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
8301da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
8311da177e4SLinus Torvalds 
8321da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
8331da177e4SLinus Torvalds 
83445bb4bf0SMarcel Holtmann 	if (!num_rsp)
83545bb4bf0SMarcel Holtmann 		return;
83645bb4bf0SMarcel Holtmann 
8371da177e4SLinus Torvalds 	hci_dev_lock(hdev);
83845bb4bf0SMarcel Holtmann 
8391da177e4SLinus Torvalds 	for (; num_rsp; num_rsp--) {
8401da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
8411da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
8421da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
8431da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
8441da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
8451da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
8461da177e4SLinus Torvalds 		data.rssi		= 0x00;
84741a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
8481da177e4SLinus Torvalds 		info++;
8491da177e4SLinus Torvalds 		hci_inquiry_cache_update(hdev, &data);
8501da177e4SLinus Torvalds 	}
85145bb4bf0SMarcel Holtmann 
8521da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
8531da177e4SLinus Torvalds }
8541da177e4SLinus Torvalds 
855a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
8561da177e4SLinus Torvalds {
857a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
858a9de9248SMarcel Holtmann 	struct hci_conn *conn;
8591da177e4SLinus Torvalds 
860a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
86145bb4bf0SMarcel Holtmann 
8621da177e4SLinus Torvalds 	hci_dev_lock(hdev);
86345bb4bf0SMarcel Holtmann 
864a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
865a9de9248SMarcel Holtmann 	if (!conn)
866a9de9248SMarcel Holtmann 		goto unlock;
86745bb4bf0SMarcel Holtmann 
868a9de9248SMarcel Holtmann 	if (!ev->status) {
869a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
870769be974SMarcel Holtmann 
871769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
872769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
873769be974SMarcel Holtmann 			hci_conn_hold(conn);
874769be974SMarcel Holtmann 		} else
875a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
876a9de9248SMarcel Holtmann 
8777d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
8787d0db0a3SMarcel Holtmann 
879a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
880a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
881a9de9248SMarcel Holtmann 
882a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
883a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
884a9de9248SMarcel Holtmann 
885a9de9248SMarcel Holtmann 		/* Get remote features */
886a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
887a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
888a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
889769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
890769be974SMarcel Holtmann 							sizeof(cp), &cp);
89145bb4bf0SMarcel Holtmann 		}
892a9de9248SMarcel Holtmann 
893a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
894a8746417SMarcel Holtmann 		if (!conn->out && hdev->hci_ver < 3) {
895a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
896a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
897a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
898a8746417SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
899a8746417SMarcel Holtmann 							sizeof(cp), &cp);
900a9de9248SMarcel Holtmann 		}
901a9de9248SMarcel Holtmann 	} else
902a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
90345bb4bf0SMarcel Holtmann 
904a9de9248SMarcel Holtmann 	if (conn->type == ACL_LINK) {
905a9de9248SMarcel Holtmann 		struct hci_conn *sco = conn->link;
906a9de9248SMarcel Holtmann 		if (sco) {
907b6a0dc82SMarcel Holtmann 			if (!ev->status) {
908b6a0dc82SMarcel Holtmann 				if (lmp_esco_capable(hdev))
909b6a0dc82SMarcel Holtmann 					hci_setup_sync(sco, conn->handle);
910b6a0dc82SMarcel Holtmann 				else
911a9de9248SMarcel Holtmann 					hci_add_sco(sco, conn->handle);
912b6a0dc82SMarcel Holtmann 			} else {
913a9de9248SMarcel Holtmann 				hci_proto_connect_cfm(sco, ev->status);
914a9de9248SMarcel Holtmann 				hci_conn_del(sco);
915a9de9248SMarcel Holtmann 			}
9161da177e4SLinus Torvalds 		}
91745bb4bf0SMarcel Holtmann 	}
91845bb4bf0SMarcel Holtmann 
919769be974SMarcel Holtmann 	if (ev->status) {
920a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
921a9de9248SMarcel Holtmann 		hci_conn_del(conn);
922769be974SMarcel Holtmann 	}
923a9de9248SMarcel Holtmann 
924a9de9248SMarcel Holtmann unlock:
9251da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
926a9de9248SMarcel Holtmann 
927a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
9281da177e4SLinus Torvalds }
9291da177e4SLinus Torvalds 
9301da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
9311da177e4SLinus Torvalds {
932a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
9331da177e4SLinus Torvalds 	int mask = hdev->link_mode;
9341da177e4SLinus Torvalds 
935a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
9361da177e4SLinus Torvalds 					batostr(&ev->bdaddr), ev->link_type);
9371da177e4SLinus Torvalds 
9381da177e4SLinus Torvalds 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
9391da177e4SLinus Torvalds 
9401da177e4SLinus Torvalds 	if (mask & HCI_LM_ACCEPT) {
9411da177e4SLinus Torvalds 		/* Connection accepted */
942c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
9431da177e4SLinus Torvalds 		struct hci_conn *conn;
9441da177e4SLinus Torvalds 
9451da177e4SLinus Torvalds 		hci_dev_lock(hdev);
946b6a0dc82SMarcel Holtmann 
947c7bdd502SMarcel Holtmann 		if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr)))
948c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
949c7bdd502SMarcel Holtmann 
9501da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
9511da177e4SLinus Torvalds 		if (!conn) {
9521da177e4SLinus Torvalds 			if (!(conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr))) {
9531da177e4SLinus Torvalds 				BT_ERR("No memmory for new connection");
9541da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
9551da177e4SLinus Torvalds 				return;
9561da177e4SLinus Torvalds 			}
9571da177e4SLinus Torvalds 		}
958b6a0dc82SMarcel Holtmann 
9591da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
9601da177e4SLinus Torvalds 		conn->state = BT_CONNECT;
961b6a0dc82SMarcel Holtmann 
9621da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
9631da177e4SLinus Torvalds 
964b6a0dc82SMarcel Holtmann 		if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
965b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
966b6a0dc82SMarcel Holtmann 
9671da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
9681da177e4SLinus Torvalds 
9691da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
9701da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
9711da177e4SLinus Torvalds 			else
9721da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
9731da177e4SLinus Torvalds 
974b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ,
975b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
976b6a0dc82SMarcel Holtmann 		} else {
977b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
978b6a0dc82SMarcel Holtmann 
979b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
980a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
981b6a0dc82SMarcel Holtmann 
982b6a0dc82SMarcel Holtmann 			cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
983b6a0dc82SMarcel Holtmann 			cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
984b6a0dc82SMarcel Holtmann 			cp.max_latency    = cpu_to_le16(0xffff);
985b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
986b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
987b6a0dc82SMarcel Holtmann 
988b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
989b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
990b6a0dc82SMarcel Holtmann 		}
9911da177e4SLinus Torvalds 	} else {
9921da177e4SLinus Torvalds 		/* Connection rejected */
9931da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
9941da177e4SLinus Torvalds 
9951da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
9961da177e4SLinus Torvalds 		cp.reason = 0x0f;
997a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
9981da177e4SLinus Torvalds 	}
9991da177e4SLinus Torvalds }
10001da177e4SLinus Torvalds 
10011da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
10021da177e4SLinus Torvalds {
1003a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
100404837f64SMarcel Holtmann 	struct hci_conn *conn;
10051da177e4SLinus Torvalds 
10061da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
10071da177e4SLinus Torvalds 
10081da177e4SLinus Torvalds 	if (ev->status)
10091da177e4SLinus Torvalds 		return;
10101da177e4SLinus Torvalds 
10111da177e4SLinus Torvalds 	hci_dev_lock(hdev);
10121da177e4SLinus Torvalds 
101304837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
10141da177e4SLinus Torvalds 	if (conn) {
10151da177e4SLinus Torvalds 		conn->state = BT_CLOSED;
10167d0db0a3SMarcel Holtmann 
10177d0db0a3SMarcel Holtmann 		hci_conn_del_sysfs(conn);
10187d0db0a3SMarcel Holtmann 
10191da177e4SLinus Torvalds 		hci_proto_disconn_ind(conn, ev->reason);
10201da177e4SLinus Torvalds 		hci_conn_del(conn);
10211da177e4SLinus Torvalds 	}
10221da177e4SLinus Torvalds 
10231da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
10241da177e4SLinus Torvalds }
10251da177e4SLinus Torvalds 
1026a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1027a9de9248SMarcel Holtmann {
1028a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
1029a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1030a9de9248SMarcel Holtmann 
1031a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1032a9de9248SMarcel Holtmann 
1033a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1034a9de9248SMarcel Holtmann 
1035a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1036a9de9248SMarcel Holtmann 	if (conn) {
1037a9de9248SMarcel Holtmann 		if (!ev->status)
1038a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1039a9de9248SMarcel Holtmann 
1040a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1041a9de9248SMarcel Holtmann 
1042f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1043f8558555SMarcel Holtmann 			if (!ev->status && hdev->ssp_mode > 0 &&
1044f8558555SMarcel Holtmann 							conn->ssp_mode > 0) {
1045f8558555SMarcel Holtmann 				struct hci_cp_set_conn_encrypt cp;
1046f8558555SMarcel Holtmann 				cp.handle  = ev->handle;
1047f8558555SMarcel Holtmann 				cp.encrypt = 0x01;
1048f8558555SMarcel Holtmann 				hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT,
1049f8558555SMarcel Holtmann 							sizeof(cp), &cp);
1050f8558555SMarcel Holtmann 			} else {
1051f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
1052f8558555SMarcel Holtmann 				hci_proto_connect_cfm(conn, ev->status);
1053f8558555SMarcel Holtmann 				hci_conn_put(conn);
1054f8558555SMarcel Holtmann 			}
1055f8558555SMarcel Holtmann 		} else
1056a9de9248SMarcel Holtmann 			hci_auth_cfm(conn, ev->status);
1057a9de9248SMarcel Holtmann 
1058a9de9248SMarcel Holtmann 		if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
1059a9de9248SMarcel Holtmann 			if (!ev->status) {
1060a9de9248SMarcel Holtmann 				struct hci_cp_set_conn_encrypt cp;
1061f8558555SMarcel Holtmann 				cp.handle  = ev->handle;
1062f8558555SMarcel Holtmann 				cp.encrypt = 0x01;
1063f8558555SMarcel Holtmann 				hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT,
1064f8558555SMarcel Holtmann 							sizeof(cp), &cp);
1065a9de9248SMarcel Holtmann 			} else {
1066a9de9248SMarcel Holtmann 				clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1067a9de9248SMarcel Holtmann 				hci_encrypt_cfm(conn, ev->status, 0x00);
1068a9de9248SMarcel Holtmann 			}
1069a9de9248SMarcel Holtmann 		}
1070a9de9248SMarcel Holtmann 	}
1071a9de9248SMarcel Holtmann 
1072a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1073a9de9248SMarcel Holtmann }
1074a9de9248SMarcel Holtmann 
1075a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1076a9de9248SMarcel Holtmann {
1077a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1078a9de9248SMarcel Holtmann 
1079a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
1080a9de9248SMarcel Holtmann }
1081a9de9248SMarcel Holtmann 
1082a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1083a9de9248SMarcel Holtmann {
1084a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
1085a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1086a9de9248SMarcel Holtmann 
1087a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1088a9de9248SMarcel Holtmann 
1089a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1090a9de9248SMarcel Holtmann 
1091a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1092a9de9248SMarcel Holtmann 	if (conn) {
1093a9de9248SMarcel Holtmann 		if (!ev->status) {
1094ae293196SMarcel Holtmann 			if (ev->encrypt) {
1095ae293196SMarcel Holtmann 				/* Encryption implies authentication */
1096ae293196SMarcel Holtmann 				conn->link_mode |= HCI_LM_AUTH;
1097a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_ENCRYPT;
1098ae293196SMarcel Holtmann 			} else
1099a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_ENCRYPT;
1100a9de9248SMarcel Holtmann 		}
1101a9de9248SMarcel Holtmann 
1102a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1103a9de9248SMarcel Holtmann 
1104f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1105f8558555SMarcel Holtmann 			if (!ev->status)
1106f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
1107f8558555SMarcel Holtmann 
1108f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1109f8558555SMarcel Holtmann 			hci_conn_put(conn);
1110f8558555SMarcel Holtmann 		} else
1111a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, ev->encrypt);
1112a9de9248SMarcel Holtmann 	}
1113a9de9248SMarcel Holtmann 
1114a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1115a9de9248SMarcel Holtmann }
1116a9de9248SMarcel Holtmann 
1117a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1118a9de9248SMarcel Holtmann {
1119a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
1120a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1121a9de9248SMarcel Holtmann 
1122a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1123a9de9248SMarcel Holtmann 
1124a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1125a9de9248SMarcel Holtmann 
1126a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1127a9de9248SMarcel Holtmann 	if (conn) {
1128a9de9248SMarcel Holtmann 		if (!ev->status)
1129a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
1130a9de9248SMarcel Holtmann 
1131a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1132a9de9248SMarcel Holtmann 
1133a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
1134a9de9248SMarcel Holtmann 	}
1135a9de9248SMarcel Holtmann 
1136a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1137a9de9248SMarcel Holtmann }
1138a9de9248SMarcel Holtmann 
1139a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
1140a9de9248SMarcel Holtmann {
1141a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
1142a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1143a9de9248SMarcel Holtmann 
1144a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1145a9de9248SMarcel Holtmann 
1146a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1147a9de9248SMarcel Holtmann 
1148a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1149769be974SMarcel Holtmann 	if (conn) {
1150769be974SMarcel Holtmann 		if (!ev->status)
1151a9de9248SMarcel Holtmann 			memcpy(conn->features, ev->features, 8);
1152a9de9248SMarcel Holtmann 
1153769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1154769be974SMarcel Holtmann 			if (!ev->status && lmp_ssp_capable(hdev) &&
1155769be974SMarcel Holtmann 						lmp_ssp_capable(conn)) {
1156769be974SMarcel Holtmann 				struct hci_cp_read_remote_ext_features cp;
1157769be974SMarcel Holtmann 				cp.handle = ev->handle;
1158769be974SMarcel Holtmann 				cp.page = 0x01;
1159769be974SMarcel Holtmann 				hci_send_cmd(hdev,
1160769be974SMarcel Holtmann 					HCI_OP_READ_REMOTE_EXT_FEATURES,
1161769be974SMarcel Holtmann 							sizeof(cp), &cp);
1162769be974SMarcel Holtmann 			} else {
1163769be974SMarcel Holtmann 				conn->state = BT_CONNECTED;
1164769be974SMarcel Holtmann 				hci_proto_connect_cfm(conn, ev->status);
1165769be974SMarcel Holtmann 				hci_conn_put(conn);
1166769be974SMarcel Holtmann 			}
1167769be974SMarcel Holtmann 		}
1168769be974SMarcel Holtmann 	}
1169769be974SMarcel Holtmann 
1170a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1171a9de9248SMarcel Holtmann }
1172a9de9248SMarcel Holtmann 
1173a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
1174a9de9248SMarcel Holtmann {
1175a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1176a9de9248SMarcel Holtmann }
1177a9de9248SMarcel Holtmann 
1178a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1179a9de9248SMarcel Holtmann {
1180a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1181a9de9248SMarcel Holtmann }
1182a9de9248SMarcel Holtmann 
1183a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1184a9de9248SMarcel Holtmann {
1185a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
1186a9de9248SMarcel Holtmann 	__u16 opcode;
1187a9de9248SMarcel Holtmann 
1188a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
1189a9de9248SMarcel Holtmann 
1190a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
1191a9de9248SMarcel Holtmann 
1192a9de9248SMarcel Holtmann 	switch (opcode) {
1193a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
1194a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
1195a9de9248SMarcel Holtmann 		break;
1196a9de9248SMarcel Holtmann 
1197a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
1198a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
1199a9de9248SMarcel Holtmann 		break;
1200a9de9248SMarcel Holtmann 
1201a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
1202a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
1203a9de9248SMarcel Holtmann 		break;
1204a9de9248SMarcel Holtmann 
1205a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
1206a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
1207a9de9248SMarcel Holtmann 		break;
1208a9de9248SMarcel Holtmann 
1209e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
1210e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
1211e4e8e37cSMarcel Holtmann 		break;
1212e4e8e37cSMarcel Holtmann 
1213a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
1214a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
1215a9de9248SMarcel Holtmann 		break;
1216a9de9248SMarcel Holtmann 
1217e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
1218e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
1219e4e8e37cSMarcel Holtmann 		break;
1220e4e8e37cSMarcel Holtmann 
1221e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
1222e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
1223e4e8e37cSMarcel Holtmann 		break;
1224e4e8e37cSMarcel Holtmann 
1225a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
1226a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
1227a9de9248SMarcel Holtmann 		break;
1228a9de9248SMarcel Holtmann 
1229a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
1230a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
1231a9de9248SMarcel Holtmann 		break;
1232a9de9248SMarcel Holtmann 
1233a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
1234a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
1235a9de9248SMarcel Holtmann 		break;
1236a9de9248SMarcel Holtmann 
1237a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
1238a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
1239a9de9248SMarcel Holtmann 		break;
1240a9de9248SMarcel Holtmann 
1241a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
1242a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
1243a9de9248SMarcel Holtmann 		break;
1244a9de9248SMarcel Holtmann 
1245a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
1246a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
1247a9de9248SMarcel Holtmann 		break;
1248a9de9248SMarcel Holtmann 
1249a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
1250a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
1251a9de9248SMarcel Holtmann 		break;
1252a9de9248SMarcel Holtmann 
1253a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
1254a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
1255a9de9248SMarcel Holtmann 		break;
1256a9de9248SMarcel Holtmann 
1257a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
1258a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
1259a9de9248SMarcel Holtmann 		break;
1260a9de9248SMarcel Holtmann 
1261a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
1262a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
1263a9de9248SMarcel Holtmann 		break;
1264a9de9248SMarcel Holtmann 
1265a9de9248SMarcel Holtmann 	case HCI_OP_HOST_BUFFER_SIZE:
1266a9de9248SMarcel Holtmann 		hci_cc_host_buffer_size(hdev, skb);
1267a9de9248SMarcel Holtmann 		break;
1268a9de9248SMarcel Holtmann 
1269333140b5SMarcel Holtmann 	case HCI_OP_READ_SSP_MODE:
1270333140b5SMarcel Holtmann 		hci_cc_read_ssp_mode(hdev, skb);
1271333140b5SMarcel Holtmann 		break;
1272333140b5SMarcel Holtmann 
1273333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
1274333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
1275333140b5SMarcel Holtmann 		break;
1276333140b5SMarcel Holtmann 
1277a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
1278a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
1279a9de9248SMarcel Holtmann 		break;
1280a9de9248SMarcel Holtmann 
1281a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
1282a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
1283a9de9248SMarcel Holtmann 		break;
1284a9de9248SMarcel Holtmann 
1285a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
1286a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
1287a9de9248SMarcel Holtmann 		break;
1288a9de9248SMarcel Holtmann 
1289a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
1290a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
1291a9de9248SMarcel Holtmann 		break;
1292a9de9248SMarcel Holtmann 
1293a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
1294a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
1295a9de9248SMarcel Holtmann 		break;
1296a9de9248SMarcel Holtmann 
1297a9de9248SMarcel Holtmann 	default:
1298a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
1299a9de9248SMarcel Holtmann 		break;
1300a9de9248SMarcel Holtmann 	}
1301a9de9248SMarcel Holtmann 
1302a9de9248SMarcel Holtmann 	if (ev->ncmd) {
1303a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
1304a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
1305a9de9248SMarcel Holtmann 			hci_sched_cmd(hdev);
1306a9de9248SMarcel Holtmann 	}
1307a9de9248SMarcel Holtmann }
1308a9de9248SMarcel Holtmann 
1309a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
1310a9de9248SMarcel Holtmann {
1311a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
1312a9de9248SMarcel Holtmann 	__u16 opcode;
1313a9de9248SMarcel Holtmann 
1314a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
1315a9de9248SMarcel Holtmann 
1316a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
1317a9de9248SMarcel Holtmann 
1318a9de9248SMarcel Holtmann 	switch (opcode) {
1319a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
1320a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
1321a9de9248SMarcel Holtmann 		break;
1322a9de9248SMarcel Holtmann 
1323a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
1324a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
1325a9de9248SMarcel Holtmann 		break;
1326a9de9248SMarcel Holtmann 
1327a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
1328a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
1329a9de9248SMarcel Holtmann 		break;
1330a9de9248SMarcel Holtmann 
1331f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
1332f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
1333f8558555SMarcel Holtmann 		break;
1334f8558555SMarcel Holtmann 
1335f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
1336f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
1337f8558555SMarcel Holtmann 		break;
1338f8558555SMarcel Holtmann 
1339a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
1340a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
1341a9de9248SMarcel Holtmann 		break;
1342a9de9248SMarcel Holtmann 
1343769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
1344769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
1345769be974SMarcel Holtmann 		break;
1346769be974SMarcel Holtmann 
1347769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
1348769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
1349769be974SMarcel Holtmann 		break;
1350769be974SMarcel Holtmann 
1351a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
1352a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
1353a9de9248SMarcel Holtmann 		break;
1354a9de9248SMarcel Holtmann 
1355a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
1356a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
1357a9de9248SMarcel Holtmann 		break;
1358a9de9248SMarcel Holtmann 
1359a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
1360a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
1361a9de9248SMarcel Holtmann 		break;
1362a9de9248SMarcel Holtmann 
1363a9de9248SMarcel Holtmann 	default:
1364a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
1365a9de9248SMarcel Holtmann 		break;
1366a9de9248SMarcel Holtmann 	}
1367a9de9248SMarcel Holtmann 
1368a9de9248SMarcel Holtmann 	if (ev->ncmd) {
1369a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
1370a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
1371a9de9248SMarcel Holtmann 			hci_sched_cmd(hdev);
1372a9de9248SMarcel Holtmann 	}
1373a9de9248SMarcel Holtmann }
1374a9de9248SMarcel Holtmann 
1375a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1376a9de9248SMarcel Holtmann {
1377a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
1378a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1379a9de9248SMarcel Holtmann 
1380a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1381a9de9248SMarcel Holtmann 
1382a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1383a9de9248SMarcel Holtmann 
1384a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1385a9de9248SMarcel Holtmann 	if (conn) {
1386a9de9248SMarcel Holtmann 		if (!ev->status) {
1387a9de9248SMarcel Holtmann 			if (ev->role)
1388a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
1389a9de9248SMarcel Holtmann 			else
1390a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
1391a9de9248SMarcel Holtmann 		}
1392a9de9248SMarcel Holtmann 
1393a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend);
1394a9de9248SMarcel Holtmann 
1395a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
1396a9de9248SMarcel Holtmann 	}
1397a9de9248SMarcel Holtmann 
1398a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1399a9de9248SMarcel Holtmann }
1400a9de9248SMarcel Holtmann 
14011da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
14021da177e4SLinus Torvalds {
1403a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
14041ebb9252SMarcel Holtmann 	__le16 *ptr;
14051da177e4SLinus Torvalds 	int i;
14061da177e4SLinus Torvalds 
14071da177e4SLinus Torvalds 	skb_pull(skb, sizeof(*ev));
14081da177e4SLinus Torvalds 
14091da177e4SLinus Torvalds 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
14101da177e4SLinus Torvalds 
14111da177e4SLinus Torvalds 	if (skb->len < ev->num_hndl * 4) {
14121da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
14131da177e4SLinus Torvalds 		return;
14141da177e4SLinus Torvalds 	}
14151da177e4SLinus Torvalds 
14161da177e4SLinus Torvalds 	tasklet_disable(&hdev->tx_task);
14171da177e4SLinus Torvalds 
14181ebb9252SMarcel Holtmann 	for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) {
14191da177e4SLinus Torvalds 		struct hci_conn *conn;
14201da177e4SLinus Torvalds 		__u16  handle, count;
14211da177e4SLinus Torvalds 
142283985319SHarvey Harrison 		handle = get_unaligned_le16(ptr++);
142383985319SHarvey Harrison 		count  = get_unaligned_le16(ptr++);
14241da177e4SLinus Torvalds 
14251da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
14261da177e4SLinus Torvalds 		if (conn) {
14271da177e4SLinus Torvalds 			conn->sent -= count;
14281da177e4SLinus Torvalds 
14295b7f9909SMarcel Holtmann 			if (conn->type == ACL_LINK) {
14301da177e4SLinus Torvalds 				if ((hdev->acl_cnt += count) > hdev->acl_pkts)
14311da177e4SLinus Torvalds 					hdev->acl_cnt = hdev->acl_pkts;
14325b7f9909SMarcel Holtmann 			} else {
14335b7f9909SMarcel Holtmann 				if ((hdev->sco_cnt += count) > hdev->sco_pkts)
14345b7f9909SMarcel Holtmann 					hdev->sco_cnt = hdev->sco_pkts;
14351da177e4SLinus Torvalds 			}
14361da177e4SLinus Torvalds 		}
14371da177e4SLinus Torvalds 	}
1438a9de9248SMarcel Holtmann 
14391da177e4SLinus Torvalds 	hci_sched_tx(hdev);
14401da177e4SLinus Torvalds 
14411da177e4SLinus Torvalds 	tasklet_enable(&hdev->tx_task);
14421da177e4SLinus Torvalds }
14431da177e4SLinus Torvalds 
144404837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
14451da177e4SLinus Torvalds {
1446a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
144704837f64SMarcel Holtmann 	struct hci_conn *conn;
14481da177e4SLinus Torvalds 
14491da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
14501da177e4SLinus Torvalds 
14511da177e4SLinus Torvalds 	hci_dev_lock(hdev);
14521da177e4SLinus Torvalds 
145304837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
145404837f64SMarcel Holtmann 	if (conn) {
145504837f64SMarcel Holtmann 		conn->mode = ev->mode;
145604837f64SMarcel Holtmann 		conn->interval = __le16_to_cpu(ev->interval);
145704837f64SMarcel Holtmann 
145804837f64SMarcel Holtmann 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
145904837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
146004837f64SMarcel Holtmann 				conn->power_save = 1;
146104837f64SMarcel Holtmann 			else
146204837f64SMarcel Holtmann 				conn->power_save = 0;
146304837f64SMarcel Holtmann 		}
146404837f64SMarcel Holtmann 	}
146504837f64SMarcel Holtmann 
146604837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
146704837f64SMarcel Holtmann }
146804837f64SMarcel Holtmann 
14691da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
14701da177e4SLinus Torvalds {
1471a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
14721da177e4SLinus Torvalds }
14731da177e4SLinus Torvalds 
14741da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
14751da177e4SLinus Torvalds {
1476a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
14771da177e4SLinus Torvalds }
14781da177e4SLinus Torvalds 
14791da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
14801da177e4SLinus Torvalds {
1481a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
14821da177e4SLinus Torvalds }
14831da177e4SLinus Torvalds 
148404837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
148504837f64SMarcel Holtmann {
1486a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
148704837f64SMarcel Holtmann 	struct hci_conn *conn;
148804837f64SMarcel Holtmann 
148904837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
149004837f64SMarcel Holtmann 
149104837f64SMarcel Holtmann 	hci_dev_lock(hdev);
149204837f64SMarcel Holtmann 
149304837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
14941da177e4SLinus Torvalds 	if (conn && !ev->status) {
14951da177e4SLinus Torvalds 		struct inquiry_entry *ie;
14961da177e4SLinus Torvalds 
14971da177e4SLinus Torvalds 		if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst))) {
14981da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
14991da177e4SLinus Torvalds 			ie->timestamp = jiffies;
15001da177e4SLinus Torvalds 		}
15011da177e4SLinus Torvalds 	}
15021da177e4SLinus Torvalds 
15031da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
15041da177e4SLinus Torvalds }
15051da177e4SLinus Torvalds 
1506a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1507a8746417SMarcel Holtmann {
1508a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
1509a8746417SMarcel Holtmann 	struct hci_conn *conn;
1510a8746417SMarcel Holtmann 
1511a8746417SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1512a8746417SMarcel Holtmann 
1513a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
1514a8746417SMarcel Holtmann 
1515a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1516a8746417SMarcel Holtmann 	if (conn && !ev->status)
1517a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
1518a8746417SMarcel Holtmann 
1519a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
1520a8746417SMarcel Holtmann }
1521a8746417SMarcel Holtmann 
152285a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
152385a1e930SMarcel Holtmann {
1524a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
152585a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
152685a1e930SMarcel Holtmann 
152785a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
152885a1e930SMarcel Holtmann 
152985a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
153085a1e930SMarcel Holtmann 
153185a1e930SMarcel Holtmann 	if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr))) {
153285a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
153385a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
153485a1e930SMarcel Holtmann 	}
153585a1e930SMarcel Holtmann 
153685a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
153785a1e930SMarcel Holtmann }
153885a1e930SMarcel Holtmann 
1539a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
1540a9de9248SMarcel Holtmann {
1541a9de9248SMarcel Holtmann 	struct inquiry_data data;
1542a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
1543a9de9248SMarcel Holtmann 
1544a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1545a9de9248SMarcel Holtmann 
1546a9de9248SMarcel Holtmann 	if (!num_rsp)
1547a9de9248SMarcel Holtmann 		return;
1548a9de9248SMarcel Holtmann 
1549a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1550a9de9248SMarcel Holtmann 
1551a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
1552a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi_and_pscan_mode *info = (void *) (skb->data + 1);
1553a9de9248SMarcel Holtmann 
1554a9de9248SMarcel Holtmann 		for (; num_rsp; num_rsp--) {
1555a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
1556a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
1557a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
1558a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
1559a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
1560a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
1561a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
156241a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
1563a9de9248SMarcel Holtmann 			info++;
1564a9de9248SMarcel Holtmann 			hci_inquiry_cache_update(hdev, &data);
1565a9de9248SMarcel Holtmann 		}
1566a9de9248SMarcel Holtmann 	} else {
1567a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
1568a9de9248SMarcel Holtmann 
1569a9de9248SMarcel Holtmann 		for (; num_rsp; num_rsp--) {
1570a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
1571a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
1572a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
1573a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
1574a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
1575a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
1576a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
157741a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
1578a9de9248SMarcel Holtmann 			info++;
1579a9de9248SMarcel Holtmann 			hci_inquiry_cache_update(hdev, &data);
1580a9de9248SMarcel Holtmann 		}
1581a9de9248SMarcel Holtmann 	}
1582a9de9248SMarcel Holtmann 
1583a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1584a9de9248SMarcel Holtmann }
1585a9de9248SMarcel Holtmann 
1586a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
1587a9de9248SMarcel Holtmann {
158841a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
158941a96212SMarcel Holtmann 	struct hci_conn *conn;
159041a96212SMarcel Holtmann 
1591a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
159241a96212SMarcel Holtmann 
159341a96212SMarcel Holtmann 	hci_dev_lock(hdev);
159441a96212SMarcel Holtmann 
159541a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
159641a96212SMarcel Holtmann 	if (conn) {
1597769be974SMarcel Holtmann 		if (!ev->status && ev->page == 0x01) {
159841a96212SMarcel Holtmann 			struct inquiry_entry *ie;
159941a96212SMarcel Holtmann 
160041a96212SMarcel Holtmann 			if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst)))
160141a96212SMarcel Holtmann 				ie->data.ssp_mode = (ev->features[0] & 0x01);
160241a96212SMarcel Holtmann 
160341a96212SMarcel Holtmann 			conn->ssp_mode = (ev->features[0] & 0x01);
160441a96212SMarcel Holtmann 		}
160541a96212SMarcel Holtmann 
1606769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1607f8558555SMarcel Holtmann 			if (!ev->status && hdev->ssp_mode > 0 &&
1608f8558555SMarcel Holtmann 							conn->ssp_mode > 0) {
1609f8558555SMarcel Holtmann 				if (conn->out) {
1610f8558555SMarcel Holtmann 					struct hci_cp_auth_requested cp;
1611f8558555SMarcel Holtmann 					cp.handle = ev->handle;
1612f8558555SMarcel Holtmann 					hci_send_cmd(hdev,
1613f8558555SMarcel Holtmann 						HCI_OP_AUTH_REQUESTED,
1614f8558555SMarcel Holtmann 							sizeof(cp), &cp);
1615f8558555SMarcel Holtmann 				}
1616f8558555SMarcel Holtmann 			} else {
1617769be974SMarcel Holtmann 				conn->state = BT_CONNECTED;
1618769be974SMarcel Holtmann 				hci_proto_connect_cfm(conn, ev->status);
1619769be974SMarcel Holtmann 				hci_conn_put(conn);
1620769be974SMarcel Holtmann 			}
1621769be974SMarcel Holtmann 		}
1622f8558555SMarcel Holtmann 	}
1623769be974SMarcel Holtmann 
162441a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
1625a9de9248SMarcel Holtmann }
1626a9de9248SMarcel Holtmann 
1627a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1628a9de9248SMarcel Holtmann {
1629b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
1630b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
1631b6a0dc82SMarcel Holtmann 
1632b6a0dc82SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1633b6a0dc82SMarcel Holtmann 
1634b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1635b6a0dc82SMarcel Holtmann 
1636b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
16379dc0a3afSMarcel Holtmann 	if (!conn) {
16389dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
16399dc0a3afSMarcel Holtmann 			goto unlock;
16409dc0a3afSMarcel Holtmann 
16419dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1642b6a0dc82SMarcel Holtmann 		if (!conn)
1643b6a0dc82SMarcel Holtmann 			goto unlock;
1644b6a0dc82SMarcel Holtmann 
16459dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
16469dc0a3afSMarcel Holtmann 	}
16479dc0a3afSMarcel Holtmann 
1648b6a0dc82SMarcel Holtmann 	if (!ev->status) {
1649b6a0dc82SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1650b6a0dc82SMarcel Holtmann 		conn->state  = BT_CONNECTED;
16517d0db0a3SMarcel Holtmann 
16527d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
1653b6a0dc82SMarcel Holtmann 	} else
1654b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
1655b6a0dc82SMarcel Holtmann 
1656b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
1657b6a0dc82SMarcel Holtmann 	if (ev->status)
1658b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
1659b6a0dc82SMarcel Holtmann 
1660b6a0dc82SMarcel Holtmann unlock:
1661b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1662a9de9248SMarcel Holtmann }
1663a9de9248SMarcel Holtmann 
1664a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
1665a9de9248SMarcel Holtmann {
1666a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1667a9de9248SMarcel Holtmann }
1668a9de9248SMarcel Holtmann 
166904837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
167004837f64SMarcel Holtmann {
1671a9de9248SMarcel Holtmann 	struct hci_ev_sniff_subrate *ev = (void *) skb->data;
167204837f64SMarcel Holtmann 	struct hci_conn *conn;
167304837f64SMarcel Holtmann 
167404837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
167504837f64SMarcel Holtmann 
167604837f64SMarcel Holtmann 	hci_dev_lock(hdev);
167704837f64SMarcel Holtmann 
167804837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
167904837f64SMarcel Holtmann 	if (conn) {
168004837f64SMarcel Holtmann 	}
168104837f64SMarcel Holtmann 
168204837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
168304837f64SMarcel Holtmann }
168404837f64SMarcel Holtmann 
1685a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
1686a9de9248SMarcel Holtmann {
1687a9de9248SMarcel Holtmann 	struct inquiry_data data;
1688a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
1689a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
1690a9de9248SMarcel Holtmann 
1691a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1692a9de9248SMarcel Holtmann 
1693a9de9248SMarcel Holtmann 	if (!num_rsp)
1694a9de9248SMarcel Holtmann 		return;
1695a9de9248SMarcel Holtmann 
1696a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1697a9de9248SMarcel Holtmann 
1698a9de9248SMarcel Holtmann 	for (; num_rsp; num_rsp--) {
1699a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
1700a9de9248SMarcel Holtmann 		data.pscan_rep_mode     = info->pscan_rep_mode;
1701a9de9248SMarcel Holtmann 		data.pscan_period_mode  = info->pscan_period_mode;
1702a9de9248SMarcel Holtmann 		data.pscan_mode         = 0x00;
1703a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
1704a9de9248SMarcel Holtmann 		data.clock_offset       = info->clock_offset;
1705a9de9248SMarcel Holtmann 		data.rssi               = info->rssi;
170641a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
1707a9de9248SMarcel Holtmann 		info++;
1708a9de9248SMarcel Holtmann 		hci_inquiry_cache_update(hdev, &data);
1709a9de9248SMarcel Holtmann 	}
1710a9de9248SMarcel Holtmann 
1711a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1712a9de9248SMarcel Holtmann }
1713a9de9248SMarcel Holtmann 
17140493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
17150493684eSMarcel Holtmann {
17160493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
17170493684eSMarcel Holtmann 	struct hci_conn *conn;
17180493684eSMarcel Holtmann 
17190493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
17200493684eSMarcel Holtmann 
17210493684eSMarcel Holtmann 	hci_dev_lock(hdev);
17220493684eSMarcel Holtmann 
17230493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
17240493684eSMarcel Holtmann 	if (conn)
17250493684eSMarcel Holtmann 		hci_conn_hold(conn);
17260493684eSMarcel Holtmann 
17270493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
17280493684eSMarcel Holtmann }
17290493684eSMarcel Holtmann 
17300493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
17310493684eSMarcel Holtmann {
17320493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
17330493684eSMarcel Holtmann 	struct hci_conn *conn;
17340493684eSMarcel Holtmann 
17350493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
17360493684eSMarcel Holtmann 
17370493684eSMarcel Holtmann 	hci_dev_lock(hdev);
17380493684eSMarcel Holtmann 
17390493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
17400493684eSMarcel Holtmann 	if (conn)
17410493684eSMarcel Holtmann 		hci_conn_put(conn);
17420493684eSMarcel Holtmann 
17430493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
17440493684eSMarcel Holtmann }
17450493684eSMarcel Holtmann 
174641a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
174741a96212SMarcel Holtmann {
174841a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
174941a96212SMarcel Holtmann 	struct inquiry_entry *ie;
175041a96212SMarcel Holtmann 
175141a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
175241a96212SMarcel Holtmann 
175341a96212SMarcel Holtmann 	hci_dev_lock(hdev);
175441a96212SMarcel Holtmann 
175541a96212SMarcel Holtmann 	if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr)))
175641a96212SMarcel Holtmann 		ie->data.ssp_mode = (ev->features[0] & 0x01);
175741a96212SMarcel Holtmann 
175841a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
175941a96212SMarcel Holtmann }
176041a96212SMarcel Holtmann 
17611da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
17621da177e4SLinus Torvalds {
1763a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
1764a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
17651da177e4SLinus Torvalds 
17661da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
17671da177e4SLinus Torvalds 
1768a9de9248SMarcel Holtmann 	switch (event) {
17691da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
17701da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
17711da177e4SLinus Torvalds 		break;
17721da177e4SLinus Torvalds 
17731da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
17741da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
17751da177e4SLinus Torvalds 		break;
17761da177e4SLinus Torvalds 
1777a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
1778a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
177921d9e30eSMarcel Holtmann 		break;
178021d9e30eSMarcel Holtmann 
17811da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
17821da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
17831da177e4SLinus Torvalds 		break;
17841da177e4SLinus Torvalds 
17851da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
17861da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
17871da177e4SLinus Torvalds 		break;
17881da177e4SLinus Torvalds 
17891da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
17901da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
17911da177e4SLinus Torvalds 		break;
17921da177e4SLinus Torvalds 
1793a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
1794a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
1795a9de9248SMarcel Holtmann 		break;
1796a9de9248SMarcel Holtmann 
17971da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
17981da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
17991da177e4SLinus Torvalds 		break;
18001da177e4SLinus Torvalds 
1801a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
1802a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
1803a9de9248SMarcel Holtmann 		break;
1804a9de9248SMarcel Holtmann 
1805a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
1806a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
1807a9de9248SMarcel Holtmann 		break;
1808a9de9248SMarcel Holtmann 
1809a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_VERSION:
1810a9de9248SMarcel Holtmann 		hci_remote_version_evt(hdev, skb);
1811a9de9248SMarcel Holtmann 		break;
1812a9de9248SMarcel Holtmann 
1813a9de9248SMarcel Holtmann 	case HCI_EV_QOS_SETUP_COMPLETE:
1814a9de9248SMarcel Holtmann 		hci_qos_setup_complete_evt(hdev, skb);
1815a9de9248SMarcel Holtmann 		break;
1816a9de9248SMarcel Holtmann 
1817a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
1818a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
1819a9de9248SMarcel Holtmann 		break;
1820a9de9248SMarcel Holtmann 
1821a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
1822a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
1823a9de9248SMarcel Holtmann 		break;
1824a9de9248SMarcel Holtmann 
1825a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
1826a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
1827a9de9248SMarcel Holtmann 		break;
1828a9de9248SMarcel Holtmann 
1829a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
1830a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
1831a9de9248SMarcel Holtmann 		break;
1832a9de9248SMarcel Holtmann 
1833a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
1834a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
18351da177e4SLinus Torvalds 		break;
18361da177e4SLinus Torvalds 
18371da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
18381da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
18391da177e4SLinus Torvalds 		break;
18401da177e4SLinus Torvalds 
18411da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
18421da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
18431da177e4SLinus Torvalds 		break;
18441da177e4SLinus Torvalds 
18451da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
18461da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
18471da177e4SLinus Torvalds 		break;
18481da177e4SLinus Torvalds 
18491da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
18501da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
18511da177e4SLinus Torvalds 		break;
18521da177e4SLinus Torvalds 
1853a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
1854a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
1855a8746417SMarcel Holtmann 		break;
1856a8746417SMarcel Holtmann 
185785a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
185885a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
185985a1e930SMarcel Holtmann 		break;
186085a1e930SMarcel Holtmann 
1861a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
1862a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
1863a9de9248SMarcel Holtmann 		break;
1864a9de9248SMarcel Holtmann 
1865a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
1866a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
1867a9de9248SMarcel Holtmann 		break;
1868a9de9248SMarcel Holtmann 
1869a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
1870a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
1871a9de9248SMarcel Holtmann 		break;
1872a9de9248SMarcel Holtmann 
1873a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_CHANGED:
1874a9de9248SMarcel Holtmann 		hci_sync_conn_changed_evt(hdev, skb);
1875a9de9248SMarcel Holtmann 		break;
1876a9de9248SMarcel Holtmann 
187704837f64SMarcel Holtmann 	case HCI_EV_SNIFF_SUBRATE:
187804837f64SMarcel Holtmann 		hci_sniff_subrate_evt(hdev, skb);
187904837f64SMarcel Holtmann 		break;
188004837f64SMarcel Holtmann 
1881a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
1882a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
18831da177e4SLinus Torvalds 		break;
18841da177e4SLinus Torvalds 
18850493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
18860493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
18870493684eSMarcel Holtmann 		break;
18880493684eSMarcel Holtmann 
18890493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
18900493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
18910493684eSMarcel Holtmann 		break;
18920493684eSMarcel Holtmann 
189341a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
189441a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
189541a96212SMarcel Holtmann 		break;
189641a96212SMarcel Holtmann 
18971da177e4SLinus Torvalds 	default:
1898a9de9248SMarcel Holtmann 		BT_DBG("%s event 0x%x", hdev->name, event);
18991da177e4SLinus Torvalds 		break;
19001da177e4SLinus Torvalds 	}
19011da177e4SLinus Torvalds 
19021da177e4SLinus Torvalds 	kfree_skb(skb);
19031da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
19041da177e4SLinus Torvalds }
19051da177e4SLinus Torvalds 
19061da177e4SLinus Torvalds /* Generate internal stack event */
19071da177e4SLinus Torvalds void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
19081da177e4SLinus Torvalds {
19091da177e4SLinus Torvalds 	struct hci_event_hdr *hdr;
19101da177e4SLinus Torvalds 	struct hci_ev_stack_internal *ev;
19111da177e4SLinus Torvalds 	struct sk_buff *skb;
19121da177e4SLinus Torvalds 
19131da177e4SLinus Torvalds 	skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC);
19141da177e4SLinus Torvalds 	if (!skb)
19151da177e4SLinus Torvalds 		return;
19161da177e4SLinus Torvalds 
19171da177e4SLinus Torvalds 	hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE);
19181da177e4SLinus Torvalds 	hdr->evt  = HCI_EV_STACK_INTERNAL;
19191da177e4SLinus Torvalds 	hdr->plen = sizeof(*ev) + dlen;
19201da177e4SLinus Torvalds 
19211da177e4SLinus Torvalds 	ev  = (void *) skb_put(skb, sizeof(*ev) + dlen);
19221da177e4SLinus Torvalds 	ev->type = type;
19231da177e4SLinus Torvalds 	memcpy(ev->data, data, dlen);
19241da177e4SLinus Torvalds 
1925576c7d85SMarcel Holtmann 	bt_cb(skb)->incoming = 1;
1926a61bbcf2SPatrick McHardy 	__net_timestamp(skb);
1927576c7d85SMarcel Holtmann 
19280d48d939SMarcel Holtmann 	bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
19291da177e4SLinus Torvalds 	skb->dev = (void *) hdev;
19301da177e4SLinus Torvalds 	hci_send_to_sock(hdev, skb);
19311da177e4SLinus Torvalds 	kfree_skb(skb);
19321da177e4SLinus Torvalds }
1933