xref: /openbmc/linux/net/bluetooth/hci_event.c (revision 2950f21a)
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 /* Handle HCI Event packets */
491da177e4SLinus Torvalds 
50a9de9248SMarcel Holtmann static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
511da177e4SLinus Torvalds {
52a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
531da177e4SLinus Torvalds 
54a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
551da177e4SLinus Torvalds 
56a9de9248SMarcel Holtmann 	if (status)
57a9de9248SMarcel Holtmann 		return;
581da177e4SLinus Torvalds 
591da177e4SLinus Torvalds 	clear_bit(HCI_INQUIRY, &hdev->flags);
60a9de9248SMarcel Holtmann 
611da177e4SLinus Torvalds 	hci_req_complete(hdev, status);
62a9de9248SMarcel Holtmann 
63a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
641da177e4SLinus Torvalds }
656bd57416SMarcel Holtmann 
66a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
671da177e4SLinus Torvalds {
68a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
69a9de9248SMarcel Holtmann 
70a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
71a9de9248SMarcel Holtmann 
72a9de9248SMarcel Holtmann 	if (status)
73a9de9248SMarcel Holtmann 		return;
74a9de9248SMarcel Holtmann 
75a9de9248SMarcel Holtmann 	clear_bit(HCI_INQUIRY, &hdev->flags);
76a9de9248SMarcel Holtmann 
77a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
78a9de9248SMarcel Holtmann }
79a9de9248SMarcel Holtmann 
80a9de9248SMarcel Holtmann static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, struct sk_buff *skb)
81a9de9248SMarcel Holtmann {
82a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
83a9de9248SMarcel Holtmann }
84a9de9248SMarcel Holtmann 
85a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
86a9de9248SMarcel Holtmann {
87a9de9248SMarcel Holtmann 	struct hci_rp_role_discovery *rp = (void *) skb->data;
881da177e4SLinus Torvalds 	struct hci_conn *conn;
891da177e4SLinus Torvalds 
90a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
911da177e4SLinus Torvalds 
92a9de9248SMarcel Holtmann 	if (rp->status)
93a9de9248SMarcel Holtmann 		return;
941da177e4SLinus Torvalds 
951da177e4SLinus Torvalds 	hci_dev_lock(hdev);
961da177e4SLinus Torvalds 
97a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
981da177e4SLinus Torvalds 	if (conn) {
99a9de9248SMarcel Holtmann 		if (rp->role)
1001da177e4SLinus Torvalds 			conn->link_mode &= ~HCI_LM_MASTER;
1011da177e4SLinus Torvalds 		else
1021da177e4SLinus Torvalds 			conn->link_mode |= HCI_LM_MASTER;
1031da177e4SLinus Torvalds 	}
1041da177e4SLinus Torvalds 
1051da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
106a9de9248SMarcel Holtmann }
1071da177e4SLinus Torvalds 
108e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
109e4e8e37cSMarcel Holtmann {
110e4e8e37cSMarcel Holtmann 	struct hci_rp_read_link_policy *rp = (void *) skb->data;
111e4e8e37cSMarcel Holtmann 	struct hci_conn *conn;
112e4e8e37cSMarcel Holtmann 
113e4e8e37cSMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
114e4e8e37cSMarcel Holtmann 
115e4e8e37cSMarcel Holtmann 	if (rp->status)
116e4e8e37cSMarcel Holtmann 		return;
117e4e8e37cSMarcel Holtmann 
118e4e8e37cSMarcel Holtmann 	hci_dev_lock(hdev);
119e4e8e37cSMarcel Holtmann 
120e4e8e37cSMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
121e4e8e37cSMarcel Holtmann 	if (conn)
122e4e8e37cSMarcel Holtmann 		conn->link_policy = __le16_to_cpu(rp->policy);
123e4e8e37cSMarcel Holtmann 
124e4e8e37cSMarcel Holtmann 	hci_dev_unlock(hdev);
125e4e8e37cSMarcel Holtmann }
126e4e8e37cSMarcel Holtmann 
127a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
128a9de9248SMarcel Holtmann {
129a9de9248SMarcel Holtmann 	struct hci_rp_write_link_policy *rp = (void *) skb->data;
130a9de9248SMarcel Holtmann 	struct hci_conn *conn;
131a9de9248SMarcel Holtmann 	void *sent;
132a9de9248SMarcel Holtmann 
133a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
134a9de9248SMarcel Holtmann 
135a9de9248SMarcel Holtmann 	if (rp->status)
136a9de9248SMarcel Holtmann 		return;
137a9de9248SMarcel Holtmann 
138a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
13904837f64SMarcel Holtmann 	if (!sent)
140a9de9248SMarcel Holtmann 		return;
14104837f64SMarcel Holtmann 
14204837f64SMarcel Holtmann 	hci_dev_lock(hdev);
14304837f64SMarcel Holtmann 
144a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
145e4e8e37cSMarcel Holtmann 	if (conn)
14683985319SHarvey Harrison 		conn->link_policy = get_unaligned_le16(sent + 2);
14704837f64SMarcel Holtmann 
14804837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
1491da177e4SLinus Torvalds }
1501da177e4SLinus Torvalds 
151e4e8e37cSMarcel Holtmann static void hci_cc_read_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
152e4e8e37cSMarcel Holtmann {
153e4e8e37cSMarcel Holtmann 	struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
154e4e8e37cSMarcel Holtmann 
155e4e8e37cSMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
156e4e8e37cSMarcel Holtmann 
157e4e8e37cSMarcel Holtmann 	if (rp->status)
158e4e8e37cSMarcel Holtmann 		return;
159e4e8e37cSMarcel Holtmann 
160e4e8e37cSMarcel Holtmann 	hdev->link_policy = __le16_to_cpu(rp->policy);
161e4e8e37cSMarcel Holtmann }
162e4e8e37cSMarcel Holtmann 
163e4e8e37cSMarcel Holtmann static void hci_cc_write_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
164e4e8e37cSMarcel Holtmann {
165e4e8e37cSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
166e4e8e37cSMarcel Holtmann 	void *sent;
167e4e8e37cSMarcel Holtmann 
168e4e8e37cSMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
169e4e8e37cSMarcel Holtmann 
170e4e8e37cSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
171e4e8e37cSMarcel Holtmann 	if (!sent)
172e4e8e37cSMarcel Holtmann 		return;
173e4e8e37cSMarcel Holtmann 
174e4e8e37cSMarcel Holtmann 	if (!status)
175e4e8e37cSMarcel Holtmann 		hdev->link_policy = get_unaligned_le16(sent);
176e4e8e37cSMarcel Holtmann 
177e4e8e37cSMarcel Holtmann 	hci_req_complete(hdev, status);
178e4e8e37cSMarcel Holtmann }
179e4e8e37cSMarcel Holtmann 
180a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
1811da177e4SLinus Torvalds {
182a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
183a9de9248SMarcel Holtmann 
184a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
185a9de9248SMarcel Holtmann 
186a9de9248SMarcel Holtmann 	hci_req_complete(hdev, status);
187a9de9248SMarcel Holtmann }
188a9de9248SMarcel Holtmann 
189a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
190a9de9248SMarcel Holtmann {
191a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
1921da177e4SLinus Torvalds 	void *sent;
1931da177e4SLinus Torvalds 
194a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1951da177e4SLinus Torvalds 
196f383f275SMarcel Holtmann 	if (status)
197f383f275SMarcel Holtmann 		return;
198f383f275SMarcel Holtmann 
199a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
2001da177e4SLinus Torvalds 	if (!sent)
201a9de9248SMarcel Holtmann 		return;
2021da177e4SLinus Torvalds 
203a9de9248SMarcel Holtmann 	memcpy(hdev->dev_name, sent, 248);
204a9de9248SMarcel Holtmann }
205a9de9248SMarcel Holtmann 
206a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
207a9de9248SMarcel Holtmann {
208a9de9248SMarcel Holtmann 	struct hci_rp_read_local_name *rp = (void *) skb->data;
209a9de9248SMarcel Holtmann 
210a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
211a9de9248SMarcel Holtmann 
212a9de9248SMarcel Holtmann 	if (rp->status)
213a9de9248SMarcel Holtmann 		return;
214a9de9248SMarcel Holtmann 
215a9de9248SMarcel Holtmann 	memcpy(hdev->dev_name, rp->name, 248);
216a9de9248SMarcel Holtmann }
217a9de9248SMarcel Holtmann 
218a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
219a9de9248SMarcel Holtmann {
220a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
221a9de9248SMarcel Holtmann 	void *sent;
222a9de9248SMarcel Holtmann 
223a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
224a9de9248SMarcel Holtmann 
225a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
226a9de9248SMarcel Holtmann 	if (!sent)
227a9de9248SMarcel Holtmann 		return;
2281da177e4SLinus Torvalds 
2291da177e4SLinus Torvalds 	if (!status) {
230a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
231a9de9248SMarcel Holtmann 
2321da177e4SLinus Torvalds 		if (param == AUTH_ENABLED)
2331da177e4SLinus Torvalds 			set_bit(HCI_AUTH, &hdev->flags);
2341da177e4SLinus Torvalds 		else
2351da177e4SLinus Torvalds 			clear_bit(HCI_AUTH, &hdev->flags);
2361da177e4SLinus Torvalds 	}
237a9de9248SMarcel Holtmann 
2381da177e4SLinus Torvalds 	hci_req_complete(hdev, status);
239a9de9248SMarcel Holtmann }
2401da177e4SLinus Torvalds 
241a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
242a9de9248SMarcel Holtmann {
243a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
244a9de9248SMarcel Holtmann 	void *sent;
245a9de9248SMarcel Holtmann 
246a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
247a9de9248SMarcel Holtmann 
248a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
2491da177e4SLinus Torvalds 	if (!sent)
250a9de9248SMarcel Holtmann 		return;
2511da177e4SLinus Torvalds 
2521da177e4SLinus Torvalds 	if (!status) {
253a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
254a9de9248SMarcel Holtmann 
2551da177e4SLinus Torvalds 		if (param)
2561da177e4SLinus Torvalds 			set_bit(HCI_ENCRYPT, &hdev->flags);
2571da177e4SLinus Torvalds 		else
2581da177e4SLinus Torvalds 			clear_bit(HCI_ENCRYPT, &hdev->flags);
2591da177e4SLinus Torvalds 	}
260a9de9248SMarcel Holtmann 
2611da177e4SLinus Torvalds 	hci_req_complete(hdev, status);
2621da177e4SLinus Torvalds }
2631da177e4SLinus Torvalds 
264a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
265a9de9248SMarcel Holtmann {
266a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
267a9de9248SMarcel Holtmann 	void *sent;
2681da177e4SLinus Torvalds 
269a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
270a9de9248SMarcel Holtmann 
271a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
2721da177e4SLinus Torvalds 	if (!sent)
273a9de9248SMarcel Holtmann 		return;
2741da177e4SLinus Torvalds 
2751da177e4SLinus Torvalds 	if (!status) {
276a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
277a9de9248SMarcel Holtmann 
2781da177e4SLinus Torvalds 		clear_bit(HCI_PSCAN, &hdev->flags);
2791da177e4SLinus Torvalds 		clear_bit(HCI_ISCAN, &hdev->flags);
280a9de9248SMarcel Holtmann 
2811da177e4SLinus Torvalds 		if (param & SCAN_INQUIRY)
2821da177e4SLinus Torvalds 			set_bit(HCI_ISCAN, &hdev->flags);
2831da177e4SLinus Torvalds 
2841da177e4SLinus Torvalds 		if (param & SCAN_PAGE)
2851da177e4SLinus Torvalds 			set_bit(HCI_PSCAN, &hdev->flags);
2861da177e4SLinus Torvalds 	}
287a9de9248SMarcel Holtmann 
2881da177e4SLinus Torvalds 	hci_req_complete(hdev, status);
2891da177e4SLinus Torvalds }
2901da177e4SLinus Torvalds 
291a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
292a9de9248SMarcel Holtmann {
293a9de9248SMarcel Holtmann 	struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
294a9de9248SMarcel Holtmann 
295a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
296a9de9248SMarcel Holtmann 
297a9de9248SMarcel Holtmann 	if (rp->status)
298a9de9248SMarcel Holtmann 		return;
299a9de9248SMarcel Holtmann 
300a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, rp->dev_class, 3);
301a9de9248SMarcel Holtmann 
302a9de9248SMarcel Holtmann 	BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
303a9de9248SMarcel Holtmann 		hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
304a9de9248SMarcel Holtmann }
305a9de9248SMarcel Holtmann 
306a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
307a9de9248SMarcel Holtmann {
308a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
309a9de9248SMarcel Holtmann 	void *sent;
310a9de9248SMarcel Holtmann 
311a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
312a9de9248SMarcel Holtmann 
313f383f275SMarcel Holtmann 	if (status)
314f383f275SMarcel Holtmann 		return;
315f383f275SMarcel Holtmann 
316a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
317a9de9248SMarcel Holtmann 	if (!sent)
318a9de9248SMarcel Holtmann 		return;
319a9de9248SMarcel Holtmann 
320a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, sent, 3);
321a9de9248SMarcel Holtmann }
322a9de9248SMarcel Holtmann 
323a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
324a9de9248SMarcel Holtmann {
325a9de9248SMarcel Holtmann 	struct hci_rp_read_voice_setting *rp = (void *) skb->data;
326a9de9248SMarcel Holtmann 	__u16 setting;
327a9de9248SMarcel Holtmann 
328a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
329a9de9248SMarcel Holtmann 
330a9de9248SMarcel Holtmann 	if (rp->status)
331a9de9248SMarcel Holtmann 		return;
332a9de9248SMarcel Holtmann 
333a9de9248SMarcel Holtmann 	setting = __le16_to_cpu(rp->voice_setting);
334a9de9248SMarcel Holtmann 
335a9de9248SMarcel Holtmann 	if (hdev->voice_setting == setting)
336a9de9248SMarcel Holtmann 		return;
337a9de9248SMarcel Holtmann 
338a9de9248SMarcel Holtmann 	hdev->voice_setting = setting;
339a9de9248SMarcel Holtmann 
340a9de9248SMarcel Holtmann 	BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
341a9de9248SMarcel Holtmann 
342a9de9248SMarcel Holtmann 	if (hdev->notify) {
343a9de9248SMarcel Holtmann 		tasklet_disable(&hdev->tx_task);
344a9de9248SMarcel Holtmann 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
345a9de9248SMarcel Holtmann 		tasklet_enable(&hdev->tx_task);
346a9de9248SMarcel Holtmann 	}
347a9de9248SMarcel Holtmann }
348a9de9248SMarcel Holtmann 
349a9de9248SMarcel Holtmann static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
350a9de9248SMarcel Holtmann {
351a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
352f383f275SMarcel Holtmann 	__u16 setting;
353a9de9248SMarcel Holtmann 	void *sent;
354a9de9248SMarcel Holtmann 
355a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
356a9de9248SMarcel Holtmann 
357f383f275SMarcel Holtmann 	if (status)
358f383f275SMarcel Holtmann 		return;
359f383f275SMarcel Holtmann 
360a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
361a9de9248SMarcel Holtmann 	if (!sent)
362a9de9248SMarcel Holtmann 		return;
363a9de9248SMarcel Holtmann 
364f383f275SMarcel Holtmann 	setting = get_unaligned_le16(sent);
3651da177e4SLinus Torvalds 
366f383f275SMarcel Holtmann 	if (hdev->voice_setting == setting)
367f383f275SMarcel Holtmann 		return;
368f383f275SMarcel Holtmann 
3691da177e4SLinus Torvalds 	hdev->voice_setting = setting;
3701da177e4SLinus Torvalds 
371a9de9248SMarcel Holtmann 	BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
3721da177e4SLinus Torvalds 
3731da177e4SLinus Torvalds 	if (hdev->notify) {
3741da177e4SLinus Torvalds 		tasklet_disable(&hdev->tx_task);
3751da177e4SLinus Torvalds 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
3761da177e4SLinus Torvalds 		tasklet_enable(&hdev->tx_task);
3771da177e4SLinus Torvalds 	}
3781da177e4SLinus Torvalds }
3791da177e4SLinus Torvalds 
380a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
3811da177e4SLinus Torvalds {
382a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
3831da177e4SLinus Torvalds 
384a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
3851da177e4SLinus Torvalds 
386a9de9248SMarcel Holtmann 	hci_req_complete(hdev, status);
3871143e5a6SMarcel Holtmann }
3881143e5a6SMarcel Holtmann 
389333140b5SMarcel Holtmann static void hci_cc_read_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
390333140b5SMarcel Holtmann {
391333140b5SMarcel Holtmann 	struct hci_rp_read_ssp_mode *rp = (void *) skb->data;
392333140b5SMarcel Holtmann 
393333140b5SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
394333140b5SMarcel Holtmann 
395333140b5SMarcel Holtmann 	if (rp->status)
396333140b5SMarcel Holtmann 		return;
397333140b5SMarcel Holtmann 
398333140b5SMarcel Holtmann 	hdev->ssp_mode = rp->mode;
399333140b5SMarcel Holtmann }
400333140b5SMarcel Holtmann 
401333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
402333140b5SMarcel Holtmann {
403333140b5SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
404333140b5SMarcel Holtmann 	void *sent;
405333140b5SMarcel Holtmann 
406333140b5SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
407333140b5SMarcel Holtmann 
408333140b5SMarcel Holtmann 	if (status)
409333140b5SMarcel Holtmann 		return;
410333140b5SMarcel Holtmann 
411333140b5SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
412333140b5SMarcel Holtmann 	if (!sent)
413333140b5SMarcel Holtmann 		return;
414333140b5SMarcel Holtmann 
415333140b5SMarcel Holtmann 	hdev->ssp_mode = *((__u8 *) sent);
416333140b5SMarcel Holtmann }
417333140b5SMarcel Holtmann 
418a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
419a9de9248SMarcel Holtmann {
420a9de9248SMarcel Holtmann 	struct hci_rp_read_local_version *rp = (void *) skb->data;
4211143e5a6SMarcel Holtmann 
422a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
4231143e5a6SMarcel Holtmann 
424a9de9248SMarcel Holtmann 	if (rp->status)
425a9de9248SMarcel Holtmann 		return;
4261143e5a6SMarcel Holtmann 
427a9de9248SMarcel Holtmann 	hdev->hci_ver = rp->hci_ver;
428e4e8e37cSMarcel Holtmann 	hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
429e4e8e37cSMarcel Holtmann 	hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
4301da177e4SLinus Torvalds 
431a9de9248SMarcel Holtmann 	BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name,
432a9de9248SMarcel Holtmann 					hdev->manufacturer,
433a9de9248SMarcel Holtmann 					hdev->hci_ver, hdev->hci_rev);
4341da177e4SLinus Torvalds }
4351da177e4SLinus Torvalds 
436a9de9248SMarcel Holtmann static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb)
437a9de9248SMarcel Holtmann {
438a9de9248SMarcel Holtmann 	struct hci_rp_read_local_commands *rp = (void *) skb->data;
439a9de9248SMarcel Holtmann 
440a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
441a9de9248SMarcel Holtmann 
442a9de9248SMarcel Holtmann 	if (rp->status)
443a9de9248SMarcel Holtmann 		return;
444a9de9248SMarcel Holtmann 
445a9de9248SMarcel Holtmann 	memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
446a9de9248SMarcel Holtmann }
447a9de9248SMarcel Holtmann 
448a9de9248SMarcel Holtmann static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb)
449a9de9248SMarcel Holtmann {
450a9de9248SMarcel Holtmann 	struct hci_rp_read_local_features *rp = (void *) skb->data;
451a9de9248SMarcel Holtmann 
452a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
453a9de9248SMarcel Holtmann 
454a9de9248SMarcel Holtmann 	if (rp->status)
455a9de9248SMarcel Holtmann 		return;
456a9de9248SMarcel Holtmann 
457a9de9248SMarcel Holtmann 	memcpy(hdev->features, rp->features, 8);
4581da177e4SLinus Torvalds 
4591da177e4SLinus Torvalds 	/* Adjust default settings according to features
4601da177e4SLinus Torvalds 	 * supported by device. */
461a9de9248SMarcel Holtmann 
4621da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_3SLOT)
4631da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
4641da177e4SLinus Torvalds 
4651da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_5SLOT)
4661da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
4671da177e4SLinus Torvalds 
4685b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV2) {
4691da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV2);
4705b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV2);
4715b7f9909SMarcel Holtmann 	}
4721da177e4SLinus Torvalds 
4735b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV3) {
4741da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV3);
4755b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV3);
4765b7f9909SMarcel Holtmann 	}
4775b7f9909SMarcel Holtmann 
4785b7f9909SMarcel Holtmann 	if (hdev->features[3] & LMP_ESCO)
4795b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV3);
4805b7f9909SMarcel Holtmann 
4815b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV4)
4825b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV4);
4835b7f9909SMarcel Holtmann 
4845b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV5)
4855b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV5);
4861da177e4SLinus Torvalds 
487efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_2M)
488efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV3);
489efc7688bSMarcel Holtmann 
490efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_3M)
491efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_3EV3);
492efc7688bSMarcel Holtmann 
493efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_3S_ESCO)
494efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
495efc7688bSMarcel Holtmann 
496a9de9248SMarcel Holtmann 	BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
497a9de9248SMarcel Holtmann 					hdev->features[0], hdev->features[1],
498a9de9248SMarcel Holtmann 					hdev->features[2], hdev->features[3],
499a9de9248SMarcel Holtmann 					hdev->features[4], hdev->features[5],
500a9de9248SMarcel Holtmann 					hdev->features[6], hdev->features[7]);
5011da177e4SLinus Torvalds }
5021da177e4SLinus Torvalds 
503a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
504a9de9248SMarcel Holtmann {
505a9de9248SMarcel Holtmann 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
506a9de9248SMarcel Holtmann 
507a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
508a9de9248SMarcel Holtmann 
509a9de9248SMarcel Holtmann 	if (rp->status)
510a9de9248SMarcel Holtmann 		return;
511a9de9248SMarcel Holtmann 
512a9de9248SMarcel Holtmann 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
513a9de9248SMarcel Holtmann 	hdev->sco_mtu  = rp->sco_mtu;
514a9de9248SMarcel Holtmann 	hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
515a9de9248SMarcel Holtmann 	hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
516da1f5198SMarcel Holtmann 
517da1f5198SMarcel Holtmann 	if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
518da1f5198SMarcel Holtmann 		hdev->sco_mtu  = 64;
519da1f5198SMarcel Holtmann 		hdev->sco_pkts = 8;
520da1f5198SMarcel Holtmann 	}
521da1f5198SMarcel Holtmann 
522da1f5198SMarcel Holtmann 	hdev->acl_cnt = hdev->acl_pkts;
523da1f5198SMarcel Holtmann 	hdev->sco_cnt = hdev->sco_pkts;
5241da177e4SLinus Torvalds 
525a9de9248SMarcel Holtmann 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name,
526a9de9248SMarcel Holtmann 					hdev->acl_mtu, hdev->acl_pkts,
527a9de9248SMarcel Holtmann 					hdev->sco_mtu, hdev->sco_pkts);
5281da177e4SLinus Torvalds }
5291da177e4SLinus Torvalds 
530a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
531a9de9248SMarcel Holtmann {
532a9de9248SMarcel Holtmann 	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
5331da177e4SLinus Torvalds 
534a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
535a9de9248SMarcel Holtmann 
536a9de9248SMarcel Holtmann 	if (!rp->status)
537a9de9248SMarcel Holtmann 		bacpy(&hdev->bdaddr, &rp->bdaddr);
538a9de9248SMarcel Holtmann 
539a9de9248SMarcel Holtmann 	hci_req_complete(hdev, rp->status);
5401da177e4SLinus Torvalds }
5411da177e4SLinus Torvalds 
542a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
543a9de9248SMarcel Holtmann {
544a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
545a9de9248SMarcel Holtmann 
546a9de9248SMarcel Holtmann 	if (status) {
547a9de9248SMarcel Holtmann 		hci_req_complete(hdev, status);
548a9de9248SMarcel Holtmann 
549a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
550a9de9248SMarcel Holtmann 	} else
551a9de9248SMarcel Holtmann 		set_bit(HCI_INQUIRY, &hdev->flags);
552a9de9248SMarcel Holtmann }
553a9de9248SMarcel Holtmann 
5541da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
5551da177e4SLinus Torvalds {
556a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
5571da177e4SLinus Torvalds 	struct hci_conn *conn;
5581da177e4SLinus Torvalds 
559a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
560a9de9248SMarcel Holtmann 
561a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
5621da177e4SLinus Torvalds 	if (!cp)
5631da177e4SLinus Torvalds 		return;
5641da177e4SLinus Torvalds 
5651da177e4SLinus Torvalds 	hci_dev_lock(hdev);
5661da177e4SLinus Torvalds 
5671da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
5681da177e4SLinus Torvalds 
569a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
5701da177e4SLinus Torvalds 
5711da177e4SLinus Torvalds 	if (status) {
5721da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
5734c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
5741da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
5751da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
5761da177e4SLinus Torvalds 				hci_conn_del(conn);
5774c67bc74SMarcel Holtmann 			} else
5784c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
5791da177e4SLinus Torvalds 		}
5801da177e4SLinus Torvalds 	} else {
5811da177e4SLinus Torvalds 		if (!conn) {
5821da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
5831da177e4SLinus Torvalds 			if (conn) {
5841da177e4SLinus Torvalds 				conn->out = 1;
5851da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
5861da177e4SLinus Torvalds 			} else
5871da177e4SLinus Torvalds 				BT_ERR("No memmory for new connection");
5881da177e4SLinus Torvalds 		}
5891da177e4SLinus Torvalds 	}
5901da177e4SLinus Torvalds 
5911da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
5921da177e4SLinus Torvalds }
5931da177e4SLinus Torvalds 
594a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
5951da177e4SLinus Torvalds {
596a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
5971da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
5981da177e4SLinus Torvalds 	__u16 handle;
5991da177e4SLinus Torvalds 
600b6a0dc82SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
601b6a0dc82SMarcel Holtmann 
602a9de9248SMarcel Holtmann 	if (!status)
603a9de9248SMarcel Holtmann 		return;
604a9de9248SMarcel Holtmann 
605a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
6061da177e4SLinus Torvalds 	if (!cp)
607a9de9248SMarcel Holtmann 		return;
6081da177e4SLinus Torvalds 
6091da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
6101da177e4SLinus Torvalds 
611a9de9248SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
6121da177e4SLinus Torvalds 
6131da177e4SLinus Torvalds 	hci_dev_lock(hdev);
6141da177e4SLinus Torvalds 
6151da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
6161da177e4SLinus Torvalds 	if (acl && (sco = acl->link)) {
6171da177e4SLinus Torvalds 		sco->state = BT_CLOSED;
6181da177e4SLinus Torvalds 
6191da177e4SLinus Torvalds 		hci_proto_connect_cfm(sco, status);
6201da177e4SLinus Torvalds 		hci_conn_del(sco);
6211da177e4SLinus Torvalds 	}
6221da177e4SLinus Torvalds 
6231da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
6241da177e4SLinus Torvalds }
6251da177e4SLinus Torvalds 
626f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
627f8558555SMarcel Holtmann {
628f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
629f8558555SMarcel Holtmann 	struct hci_conn *conn;
630f8558555SMarcel Holtmann 
631f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
632f8558555SMarcel Holtmann 
633f8558555SMarcel Holtmann 	if (!status)
634f8558555SMarcel Holtmann 		return;
635f8558555SMarcel Holtmann 
636f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
637f8558555SMarcel Holtmann 	if (!cp)
638f8558555SMarcel Holtmann 		return;
639f8558555SMarcel Holtmann 
640f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
641f8558555SMarcel Holtmann 
642f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
643f8558555SMarcel Holtmann 	if (conn) {
644f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
645f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
646f8558555SMarcel Holtmann 			hci_conn_put(conn);
647f8558555SMarcel Holtmann 		}
648f8558555SMarcel Holtmann 	}
649f8558555SMarcel Holtmann 
650f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
651f8558555SMarcel Holtmann }
652f8558555SMarcel Holtmann 
653f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
654f8558555SMarcel Holtmann {
655f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
656f8558555SMarcel Holtmann 	struct hci_conn *conn;
657f8558555SMarcel Holtmann 
658f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
659f8558555SMarcel Holtmann 
660f8558555SMarcel Holtmann 	if (!status)
661f8558555SMarcel Holtmann 		return;
662f8558555SMarcel Holtmann 
663f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
664f8558555SMarcel Holtmann 	if (!cp)
665f8558555SMarcel Holtmann 		return;
666f8558555SMarcel Holtmann 
667f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
668f8558555SMarcel Holtmann 
669f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
670f8558555SMarcel Holtmann 	if (conn) {
671f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
672f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
673f8558555SMarcel Holtmann 			hci_conn_put(conn);
674f8558555SMarcel Holtmann 		}
675f8558555SMarcel Holtmann 	}
676f8558555SMarcel Holtmann 
677f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
678f8558555SMarcel Holtmann }
679f8558555SMarcel Holtmann 
680a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
6811da177e4SLinus Torvalds {
682a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
683a9de9248SMarcel Holtmann }
6841da177e4SLinus Torvalds 
685769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
686769be974SMarcel Holtmann {
687769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
688769be974SMarcel Holtmann 	struct hci_conn *conn;
689769be974SMarcel Holtmann 
690769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
691769be974SMarcel Holtmann 
692769be974SMarcel Holtmann 	if (!status)
693769be974SMarcel Holtmann 		return;
694769be974SMarcel Holtmann 
695769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
696769be974SMarcel Holtmann 	if (!cp)
697769be974SMarcel Holtmann 		return;
698769be974SMarcel Holtmann 
699769be974SMarcel Holtmann 	hci_dev_lock(hdev);
700769be974SMarcel Holtmann 
701769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
702769be974SMarcel Holtmann 	if (conn) {
703769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
704769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
705769be974SMarcel Holtmann 			hci_conn_put(conn);
706769be974SMarcel Holtmann 		}
707769be974SMarcel Holtmann 	}
708769be974SMarcel Holtmann 
709769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
710769be974SMarcel Holtmann }
711769be974SMarcel Holtmann 
712769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
713769be974SMarcel Holtmann {
714769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
715769be974SMarcel Holtmann 	struct hci_conn *conn;
716769be974SMarcel Holtmann 
717769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
718769be974SMarcel Holtmann 
719769be974SMarcel Holtmann 	if (!status)
720769be974SMarcel Holtmann 		return;
721769be974SMarcel Holtmann 
722769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
723769be974SMarcel Holtmann 	if (!cp)
724769be974SMarcel Holtmann 		return;
725769be974SMarcel Holtmann 
726769be974SMarcel Holtmann 	hci_dev_lock(hdev);
727769be974SMarcel Holtmann 
728769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
729769be974SMarcel Holtmann 	if (conn) {
730769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
731769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
732769be974SMarcel Holtmann 			hci_conn_put(conn);
733769be974SMarcel Holtmann 		}
734769be974SMarcel Holtmann 	}
735769be974SMarcel Holtmann 
736769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
737769be974SMarcel Holtmann }
738769be974SMarcel Holtmann 
739a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
740a9de9248SMarcel Holtmann {
741b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
742b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
743b6a0dc82SMarcel Holtmann 	__u16 handle;
744b6a0dc82SMarcel Holtmann 
745a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
746b6a0dc82SMarcel Holtmann 
747b6a0dc82SMarcel Holtmann 	if (!status)
748b6a0dc82SMarcel Holtmann 		return;
749b6a0dc82SMarcel Holtmann 
750b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
751b6a0dc82SMarcel Holtmann 	if (!cp)
752b6a0dc82SMarcel Holtmann 		return;
753b6a0dc82SMarcel Holtmann 
754b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
755b6a0dc82SMarcel Holtmann 
756b6a0dc82SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
757b6a0dc82SMarcel Holtmann 
758b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
759b6a0dc82SMarcel Holtmann 
760b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
761b6a0dc82SMarcel Holtmann 	if (acl && (sco = acl->link)) {
762b6a0dc82SMarcel Holtmann 		sco->state = BT_CLOSED;
763b6a0dc82SMarcel Holtmann 
764b6a0dc82SMarcel Holtmann 		hci_proto_connect_cfm(sco, status);
765b6a0dc82SMarcel Holtmann 		hci_conn_del(sco);
766b6a0dc82SMarcel Holtmann 	}
767b6a0dc82SMarcel Holtmann 
768b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
769a9de9248SMarcel Holtmann }
770a9de9248SMarcel Holtmann 
771a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
772a9de9248SMarcel Holtmann {
773a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
77404837f64SMarcel Holtmann 	struct hci_conn *conn;
77504837f64SMarcel Holtmann 
776a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
777a9de9248SMarcel Holtmann 
778a9de9248SMarcel Holtmann 	if (!status)
779a9de9248SMarcel Holtmann 		return;
780a9de9248SMarcel Holtmann 
781a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
78204837f64SMarcel Holtmann 	if (!cp)
783a9de9248SMarcel Holtmann 		return;
78404837f64SMarcel Holtmann 
78504837f64SMarcel Holtmann 	hci_dev_lock(hdev);
78604837f64SMarcel Holtmann 
78704837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
788a9de9248SMarcel Holtmann 	if (conn)
78904837f64SMarcel Holtmann 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
79004837f64SMarcel Holtmann 
79104837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
79204837f64SMarcel Holtmann }
79304837f64SMarcel Holtmann 
794a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
795a9de9248SMarcel Holtmann {
796a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
79704837f64SMarcel Holtmann 	struct hci_conn *conn;
79804837f64SMarcel Holtmann 
799a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
800a9de9248SMarcel Holtmann 
801a9de9248SMarcel Holtmann 	if (!status)
802a9de9248SMarcel Holtmann 		return;
803a9de9248SMarcel Holtmann 
804a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
80504837f64SMarcel Holtmann 	if (!cp)
806a9de9248SMarcel Holtmann 		return;
80704837f64SMarcel Holtmann 
80804837f64SMarcel Holtmann 	hci_dev_lock(hdev);
80904837f64SMarcel Holtmann 
81004837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
811a9de9248SMarcel Holtmann 	if (conn)
81204837f64SMarcel Holtmann 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
81304837f64SMarcel Holtmann 
81404837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
81504837f64SMarcel Holtmann }
81604837f64SMarcel Holtmann 
8171da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
8181da177e4SLinus Torvalds {
8191da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
8201da177e4SLinus Torvalds 
8211da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, status);
8221da177e4SLinus Torvalds 
8231da177e4SLinus Torvalds 	clear_bit(HCI_INQUIRY, &hdev->flags);
824a9de9248SMarcel Holtmann 
8251da177e4SLinus Torvalds 	hci_req_complete(hdev, status);
8266bd57416SMarcel Holtmann 
827a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
8281da177e4SLinus Torvalds }
8291da177e4SLinus Torvalds 
8301da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
8311da177e4SLinus Torvalds {
83245bb4bf0SMarcel Holtmann 	struct inquiry_data data;
833a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
8341da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
8351da177e4SLinus Torvalds 
8361da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
8371da177e4SLinus Torvalds 
83845bb4bf0SMarcel Holtmann 	if (!num_rsp)
83945bb4bf0SMarcel Holtmann 		return;
84045bb4bf0SMarcel Holtmann 
8411da177e4SLinus Torvalds 	hci_dev_lock(hdev);
84245bb4bf0SMarcel Holtmann 
8431da177e4SLinus Torvalds 	for (; num_rsp; num_rsp--) {
8441da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
8451da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
8461da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
8471da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
8481da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
8491da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
8501da177e4SLinus Torvalds 		data.rssi		= 0x00;
85141a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
8521da177e4SLinus Torvalds 		info++;
8531da177e4SLinus Torvalds 		hci_inquiry_cache_update(hdev, &data);
8541da177e4SLinus Torvalds 	}
85545bb4bf0SMarcel Holtmann 
8561da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
8571da177e4SLinus Torvalds }
8581da177e4SLinus Torvalds 
859a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
8601da177e4SLinus Torvalds {
861a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
862a9de9248SMarcel Holtmann 	struct hci_conn *conn;
8631da177e4SLinus Torvalds 
864a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
86545bb4bf0SMarcel Holtmann 
8661da177e4SLinus Torvalds 	hci_dev_lock(hdev);
86745bb4bf0SMarcel Holtmann 
868a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
869a9de9248SMarcel Holtmann 	if (!conn)
870a9de9248SMarcel Holtmann 		goto unlock;
87145bb4bf0SMarcel Holtmann 
872a9de9248SMarcel Holtmann 	if (!ev->status) {
873a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
874769be974SMarcel Holtmann 
875769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
876769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
877769be974SMarcel Holtmann 			hci_conn_hold(conn);
878769be974SMarcel Holtmann 		} else
879a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
880a9de9248SMarcel Holtmann 
8817d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
8827d0db0a3SMarcel Holtmann 
883a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
884a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
885a9de9248SMarcel Holtmann 
886a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
887a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
888a9de9248SMarcel Holtmann 
889a9de9248SMarcel Holtmann 		/* Get remote features */
890a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
891a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
892a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
893769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
894769be974SMarcel Holtmann 							sizeof(cp), &cp);
89545bb4bf0SMarcel Holtmann 		}
896a9de9248SMarcel Holtmann 
897a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
898a8746417SMarcel Holtmann 		if (!conn->out && hdev->hci_ver < 3) {
899a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
900a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
901a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
902a8746417SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
903a8746417SMarcel Holtmann 							sizeof(cp), &cp);
904a9de9248SMarcel Holtmann 		}
905a9de9248SMarcel Holtmann 	} else
906a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
90745bb4bf0SMarcel Holtmann 
908a9de9248SMarcel Holtmann 	if (conn->type == ACL_LINK) {
909a9de9248SMarcel Holtmann 		struct hci_conn *sco = conn->link;
910a9de9248SMarcel Holtmann 		if (sco) {
911b6a0dc82SMarcel Holtmann 			if (!ev->status) {
912b6a0dc82SMarcel Holtmann 				if (lmp_esco_capable(hdev))
913b6a0dc82SMarcel Holtmann 					hci_setup_sync(sco, conn->handle);
914b6a0dc82SMarcel Holtmann 				else
915a9de9248SMarcel Holtmann 					hci_add_sco(sco, conn->handle);
916b6a0dc82SMarcel Holtmann 			} else {
917a9de9248SMarcel Holtmann 				hci_proto_connect_cfm(sco, ev->status);
918a9de9248SMarcel Holtmann 				hci_conn_del(sco);
919a9de9248SMarcel Holtmann 			}
9201da177e4SLinus Torvalds 		}
92145bb4bf0SMarcel Holtmann 	}
92245bb4bf0SMarcel Holtmann 
923769be974SMarcel Holtmann 	if (ev->status) {
924a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
925a9de9248SMarcel Holtmann 		hci_conn_del(conn);
926c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
927c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
928a9de9248SMarcel Holtmann 
929a9de9248SMarcel Holtmann unlock:
9301da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
931a9de9248SMarcel Holtmann 
932a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
9331da177e4SLinus Torvalds }
9341da177e4SLinus Torvalds 
9351da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
9361da177e4SLinus Torvalds {
937a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
9381da177e4SLinus Torvalds 	int mask = hdev->link_mode;
9391da177e4SLinus Torvalds 
940a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
9411da177e4SLinus Torvalds 					batostr(&ev->bdaddr), ev->link_type);
9421da177e4SLinus Torvalds 
9431da177e4SLinus Torvalds 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
9441da177e4SLinus Torvalds 
9451da177e4SLinus Torvalds 	if (mask & HCI_LM_ACCEPT) {
9461da177e4SLinus Torvalds 		/* Connection accepted */
947c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
9481da177e4SLinus Torvalds 		struct hci_conn *conn;
9491da177e4SLinus Torvalds 
9501da177e4SLinus Torvalds 		hci_dev_lock(hdev);
951b6a0dc82SMarcel Holtmann 
952c7bdd502SMarcel Holtmann 		if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr)))
953c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
954c7bdd502SMarcel Holtmann 
9551da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
9561da177e4SLinus Torvalds 		if (!conn) {
9571da177e4SLinus Torvalds 			if (!(conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr))) {
9581da177e4SLinus Torvalds 				BT_ERR("No memmory for new connection");
9591da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
9601da177e4SLinus Torvalds 				return;
9611da177e4SLinus Torvalds 			}
9621da177e4SLinus Torvalds 		}
963b6a0dc82SMarcel Holtmann 
9641da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
9651da177e4SLinus Torvalds 		conn->state = BT_CONNECT;
966b6a0dc82SMarcel Holtmann 
9671da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
9681da177e4SLinus Torvalds 
969b6a0dc82SMarcel Holtmann 		if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
970b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
971b6a0dc82SMarcel Holtmann 
9721da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
9731da177e4SLinus Torvalds 
9741da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
9751da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
9761da177e4SLinus Torvalds 			else
9771da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
9781da177e4SLinus Torvalds 
979b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ,
980b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
981b6a0dc82SMarcel Holtmann 		} else {
982b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
983b6a0dc82SMarcel Holtmann 
984b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
985a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
986b6a0dc82SMarcel Holtmann 
987b6a0dc82SMarcel Holtmann 			cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
988b6a0dc82SMarcel Holtmann 			cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
989b6a0dc82SMarcel Holtmann 			cp.max_latency    = cpu_to_le16(0xffff);
990b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
991b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
992b6a0dc82SMarcel Holtmann 
993b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
994b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
995b6a0dc82SMarcel Holtmann 		}
9961da177e4SLinus Torvalds 	} else {
9971da177e4SLinus Torvalds 		/* Connection rejected */
9981da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
9991da177e4SLinus Torvalds 
10001da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
10011da177e4SLinus Torvalds 		cp.reason = 0x0f;
1002a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
10031da177e4SLinus Torvalds 	}
10041da177e4SLinus Torvalds }
10051da177e4SLinus Torvalds 
10061da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
10071da177e4SLinus Torvalds {
1008a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
100904837f64SMarcel Holtmann 	struct hci_conn *conn;
10101da177e4SLinus Torvalds 
10111da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
10121da177e4SLinus Torvalds 
10131da177e4SLinus Torvalds 	if (ev->status)
10141da177e4SLinus Torvalds 		return;
10151da177e4SLinus Torvalds 
10161da177e4SLinus Torvalds 	hci_dev_lock(hdev);
10171da177e4SLinus Torvalds 
101804837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
10191da177e4SLinus Torvalds 	if (conn) {
10201da177e4SLinus Torvalds 		conn->state = BT_CLOSED;
10217d0db0a3SMarcel Holtmann 
10227d0db0a3SMarcel Holtmann 		hci_conn_del_sysfs(conn);
10237d0db0a3SMarcel Holtmann 
10242950f21aSMarcel Holtmann 		hci_proto_disconn_cfm(conn, ev->reason);
10251da177e4SLinus Torvalds 		hci_conn_del(conn);
10261da177e4SLinus Torvalds 	}
10271da177e4SLinus Torvalds 
10281da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
10291da177e4SLinus Torvalds }
10301da177e4SLinus Torvalds 
1031a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1032a9de9248SMarcel Holtmann {
1033a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
1034a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1035a9de9248SMarcel Holtmann 
1036a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1037a9de9248SMarcel Holtmann 
1038a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1039a9de9248SMarcel Holtmann 
1040a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1041a9de9248SMarcel Holtmann 	if (conn) {
1042a9de9248SMarcel Holtmann 		if (!ev->status)
1043a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1044a9de9248SMarcel Holtmann 
1045a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1046a9de9248SMarcel Holtmann 
1047f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1048f8558555SMarcel Holtmann 			if (!ev->status && hdev->ssp_mode > 0 &&
1049f8558555SMarcel Holtmann 							conn->ssp_mode > 0) {
1050f8558555SMarcel Holtmann 				struct hci_cp_set_conn_encrypt cp;
1051f8558555SMarcel Holtmann 				cp.handle  = ev->handle;
1052f8558555SMarcel Holtmann 				cp.encrypt = 0x01;
1053f8558555SMarcel Holtmann 				hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT,
1054f8558555SMarcel Holtmann 							sizeof(cp), &cp);
1055f8558555SMarcel Holtmann 			} else {
1056f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
1057f8558555SMarcel Holtmann 				hci_proto_connect_cfm(conn, ev->status);
1058f8558555SMarcel Holtmann 				hci_conn_put(conn);
1059f8558555SMarcel Holtmann 			}
1060f8558555SMarcel Holtmann 		} else
1061a9de9248SMarcel Holtmann 			hci_auth_cfm(conn, ev->status);
1062a9de9248SMarcel Holtmann 
1063a9de9248SMarcel Holtmann 		if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
1064a9de9248SMarcel Holtmann 			if (!ev->status) {
1065a9de9248SMarcel Holtmann 				struct hci_cp_set_conn_encrypt cp;
1066f8558555SMarcel Holtmann 				cp.handle  = ev->handle;
1067f8558555SMarcel Holtmann 				cp.encrypt = 0x01;
1068f8558555SMarcel Holtmann 				hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT,
1069f8558555SMarcel Holtmann 							sizeof(cp), &cp);
1070a9de9248SMarcel Holtmann 			} else {
1071a9de9248SMarcel Holtmann 				clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1072a9de9248SMarcel Holtmann 				hci_encrypt_cfm(conn, ev->status, 0x00);
1073a9de9248SMarcel Holtmann 			}
1074a9de9248SMarcel Holtmann 		}
1075a9de9248SMarcel Holtmann 	}
1076a9de9248SMarcel Holtmann 
1077a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1078a9de9248SMarcel Holtmann }
1079a9de9248SMarcel Holtmann 
1080a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1081a9de9248SMarcel Holtmann {
1082a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1083a9de9248SMarcel Holtmann 
1084a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
1085a9de9248SMarcel Holtmann }
1086a9de9248SMarcel Holtmann 
1087a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1088a9de9248SMarcel Holtmann {
1089a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
1090a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1091a9de9248SMarcel Holtmann 
1092a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1093a9de9248SMarcel Holtmann 
1094a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1095a9de9248SMarcel Holtmann 
1096a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1097a9de9248SMarcel Holtmann 	if (conn) {
1098a9de9248SMarcel Holtmann 		if (!ev->status) {
1099ae293196SMarcel Holtmann 			if (ev->encrypt) {
1100ae293196SMarcel Holtmann 				/* Encryption implies authentication */
1101ae293196SMarcel Holtmann 				conn->link_mode |= HCI_LM_AUTH;
1102a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_ENCRYPT;
1103ae293196SMarcel Holtmann 			} else
1104a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_ENCRYPT;
1105a9de9248SMarcel Holtmann 		}
1106a9de9248SMarcel Holtmann 
1107a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1108a9de9248SMarcel Holtmann 
1109f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1110f8558555SMarcel Holtmann 			if (!ev->status)
1111f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
1112f8558555SMarcel Holtmann 
1113f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1114f8558555SMarcel Holtmann 			hci_conn_put(conn);
1115f8558555SMarcel Holtmann 		} else
1116a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, ev->encrypt);
1117a9de9248SMarcel Holtmann 	}
1118a9de9248SMarcel Holtmann 
1119a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1120a9de9248SMarcel Holtmann }
1121a9de9248SMarcel Holtmann 
1122a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1123a9de9248SMarcel Holtmann {
1124a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
1125a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1126a9de9248SMarcel Holtmann 
1127a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1128a9de9248SMarcel Holtmann 
1129a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1130a9de9248SMarcel Holtmann 
1131a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1132a9de9248SMarcel Holtmann 	if (conn) {
1133a9de9248SMarcel Holtmann 		if (!ev->status)
1134a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
1135a9de9248SMarcel Holtmann 
1136a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1137a9de9248SMarcel Holtmann 
1138a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
1139a9de9248SMarcel Holtmann 	}
1140a9de9248SMarcel Holtmann 
1141a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1142a9de9248SMarcel Holtmann }
1143a9de9248SMarcel Holtmann 
1144a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
1145a9de9248SMarcel Holtmann {
1146a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
1147a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1148a9de9248SMarcel Holtmann 
1149a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1150a9de9248SMarcel Holtmann 
1151a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1152a9de9248SMarcel Holtmann 
1153a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1154769be974SMarcel Holtmann 	if (conn) {
1155769be974SMarcel Holtmann 		if (!ev->status)
1156a9de9248SMarcel Holtmann 			memcpy(conn->features, ev->features, 8);
1157a9de9248SMarcel Holtmann 
1158769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1159769be974SMarcel Holtmann 			if (!ev->status && lmp_ssp_capable(hdev) &&
1160769be974SMarcel Holtmann 						lmp_ssp_capable(conn)) {
1161769be974SMarcel Holtmann 				struct hci_cp_read_remote_ext_features cp;
1162769be974SMarcel Holtmann 				cp.handle = ev->handle;
1163769be974SMarcel Holtmann 				cp.page = 0x01;
1164769be974SMarcel Holtmann 				hci_send_cmd(hdev,
1165769be974SMarcel Holtmann 					HCI_OP_READ_REMOTE_EXT_FEATURES,
1166769be974SMarcel Holtmann 							sizeof(cp), &cp);
1167769be974SMarcel Holtmann 			} else {
1168769be974SMarcel Holtmann 				conn->state = BT_CONNECTED;
1169769be974SMarcel Holtmann 				hci_proto_connect_cfm(conn, ev->status);
1170769be974SMarcel Holtmann 				hci_conn_put(conn);
1171769be974SMarcel Holtmann 			}
1172769be974SMarcel Holtmann 		}
1173769be974SMarcel Holtmann 	}
1174769be974SMarcel Holtmann 
1175a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1176a9de9248SMarcel Holtmann }
1177a9de9248SMarcel Holtmann 
1178a9de9248SMarcel Holtmann static inline void hci_remote_version_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_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1184a9de9248SMarcel Holtmann {
1185a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1186a9de9248SMarcel Holtmann }
1187a9de9248SMarcel Holtmann 
1188a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1189a9de9248SMarcel Holtmann {
1190a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
1191a9de9248SMarcel Holtmann 	__u16 opcode;
1192a9de9248SMarcel Holtmann 
1193a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
1194a9de9248SMarcel Holtmann 
1195a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
1196a9de9248SMarcel Holtmann 
1197a9de9248SMarcel Holtmann 	switch (opcode) {
1198a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
1199a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
1200a9de9248SMarcel Holtmann 		break;
1201a9de9248SMarcel Holtmann 
1202a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
1203a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
1204a9de9248SMarcel Holtmann 		break;
1205a9de9248SMarcel Holtmann 
1206a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
1207a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
1208a9de9248SMarcel Holtmann 		break;
1209a9de9248SMarcel Holtmann 
1210a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
1211a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
1212a9de9248SMarcel Holtmann 		break;
1213a9de9248SMarcel Holtmann 
1214e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
1215e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
1216e4e8e37cSMarcel Holtmann 		break;
1217e4e8e37cSMarcel Holtmann 
1218a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
1219a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
1220a9de9248SMarcel Holtmann 		break;
1221a9de9248SMarcel Holtmann 
1222e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
1223e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
1224e4e8e37cSMarcel Holtmann 		break;
1225e4e8e37cSMarcel Holtmann 
1226e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
1227e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
1228e4e8e37cSMarcel Holtmann 		break;
1229e4e8e37cSMarcel Holtmann 
1230a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
1231a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
1232a9de9248SMarcel Holtmann 		break;
1233a9de9248SMarcel Holtmann 
1234a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
1235a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
1236a9de9248SMarcel Holtmann 		break;
1237a9de9248SMarcel Holtmann 
1238a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
1239a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
1240a9de9248SMarcel Holtmann 		break;
1241a9de9248SMarcel Holtmann 
1242a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
1243a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
1244a9de9248SMarcel Holtmann 		break;
1245a9de9248SMarcel Holtmann 
1246a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
1247a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
1248a9de9248SMarcel Holtmann 		break;
1249a9de9248SMarcel Holtmann 
1250a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
1251a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
1252a9de9248SMarcel Holtmann 		break;
1253a9de9248SMarcel Holtmann 
1254a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
1255a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
1256a9de9248SMarcel Holtmann 		break;
1257a9de9248SMarcel Holtmann 
1258a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
1259a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
1260a9de9248SMarcel Holtmann 		break;
1261a9de9248SMarcel Holtmann 
1262a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
1263a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
1264a9de9248SMarcel Holtmann 		break;
1265a9de9248SMarcel Holtmann 
1266a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
1267a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
1268a9de9248SMarcel Holtmann 		break;
1269a9de9248SMarcel Holtmann 
1270a9de9248SMarcel Holtmann 	case HCI_OP_HOST_BUFFER_SIZE:
1271a9de9248SMarcel Holtmann 		hci_cc_host_buffer_size(hdev, skb);
1272a9de9248SMarcel Holtmann 		break;
1273a9de9248SMarcel Holtmann 
1274333140b5SMarcel Holtmann 	case HCI_OP_READ_SSP_MODE:
1275333140b5SMarcel Holtmann 		hci_cc_read_ssp_mode(hdev, skb);
1276333140b5SMarcel Holtmann 		break;
1277333140b5SMarcel Holtmann 
1278333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
1279333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
1280333140b5SMarcel Holtmann 		break;
1281333140b5SMarcel Holtmann 
1282a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
1283a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
1284a9de9248SMarcel Holtmann 		break;
1285a9de9248SMarcel Holtmann 
1286a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
1287a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
1288a9de9248SMarcel Holtmann 		break;
1289a9de9248SMarcel Holtmann 
1290a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
1291a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
1292a9de9248SMarcel Holtmann 		break;
1293a9de9248SMarcel Holtmann 
1294a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
1295a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
1296a9de9248SMarcel Holtmann 		break;
1297a9de9248SMarcel Holtmann 
1298a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
1299a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
1300a9de9248SMarcel Holtmann 		break;
1301a9de9248SMarcel Holtmann 
1302a9de9248SMarcel Holtmann 	default:
1303a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
1304a9de9248SMarcel Holtmann 		break;
1305a9de9248SMarcel Holtmann 	}
1306a9de9248SMarcel Holtmann 
1307a9de9248SMarcel Holtmann 	if (ev->ncmd) {
1308a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
1309a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
1310a9de9248SMarcel Holtmann 			hci_sched_cmd(hdev);
1311a9de9248SMarcel Holtmann 	}
1312a9de9248SMarcel Holtmann }
1313a9de9248SMarcel Holtmann 
1314a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
1315a9de9248SMarcel Holtmann {
1316a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
1317a9de9248SMarcel Holtmann 	__u16 opcode;
1318a9de9248SMarcel Holtmann 
1319a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
1320a9de9248SMarcel Holtmann 
1321a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
1322a9de9248SMarcel Holtmann 
1323a9de9248SMarcel Holtmann 	switch (opcode) {
1324a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
1325a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
1326a9de9248SMarcel Holtmann 		break;
1327a9de9248SMarcel Holtmann 
1328a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
1329a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
1330a9de9248SMarcel Holtmann 		break;
1331a9de9248SMarcel Holtmann 
1332a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
1333a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
1334a9de9248SMarcel Holtmann 		break;
1335a9de9248SMarcel Holtmann 
1336f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
1337f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
1338f8558555SMarcel Holtmann 		break;
1339f8558555SMarcel Holtmann 
1340f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
1341f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
1342f8558555SMarcel Holtmann 		break;
1343f8558555SMarcel Holtmann 
1344a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
1345a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
1346a9de9248SMarcel Holtmann 		break;
1347a9de9248SMarcel Holtmann 
1348769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
1349769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
1350769be974SMarcel Holtmann 		break;
1351769be974SMarcel Holtmann 
1352769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
1353769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
1354769be974SMarcel Holtmann 		break;
1355769be974SMarcel Holtmann 
1356a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
1357a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
1358a9de9248SMarcel Holtmann 		break;
1359a9de9248SMarcel Holtmann 
1360a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
1361a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
1362a9de9248SMarcel Holtmann 		break;
1363a9de9248SMarcel Holtmann 
1364a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
1365a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
1366a9de9248SMarcel Holtmann 		break;
1367a9de9248SMarcel Holtmann 
1368a9de9248SMarcel Holtmann 	default:
1369a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
1370a9de9248SMarcel Holtmann 		break;
1371a9de9248SMarcel Holtmann 	}
1372a9de9248SMarcel Holtmann 
1373a9de9248SMarcel Holtmann 	if (ev->ncmd) {
1374a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
1375a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
1376a9de9248SMarcel Holtmann 			hci_sched_cmd(hdev);
1377a9de9248SMarcel Holtmann 	}
1378a9de9248SMarcel Holtmann }
1379a9de9248SMarcel Holtmann 
1380a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1381a9de9248SMarcel Holtmann {
1382a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
1383a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1384a9de9248SMarcel Holtmann 
1385a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1386a9de9248SMarcel Holtmann 
1387a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1388a9de9248SMarcel Holtmann 
1389a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1390a9de9248SMarcel Holtmann 	if (conn) {
1391a9de9248SMarcel Holtmann 		if (!ev->status) {
1392a9de9248SMarcel Holtmann 			if (ev->role)
1393a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
1394a9de9248SMarcel Holtmann 			else
1395a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
1396a9de9248SMarcel Holtmann 		}
1397a9de9248SMarcel Holtmann 
1398a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend);
1399a9de9248SMarcel Holtmann 
1400a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
1401a9de9248SMarcel Holtmann 	}
1402a9de9248SMarcel Holtmann 
1403a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1404a9de9248SMarcel Holtmann }
1405a9de9248SMarcel Holtmann 
14061da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
14071da177e4SLinus Torvalds {
1408a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
14091ebb9252SMarcel Holtmann 	__le16 *ptr;
14101da177e4SLinus Torvalds 	int i;
14111da177e4SLinus Torvalds 
14121da177e4SLinus Torvalds 	skb_pull(skb, sizeof(*ev));
14131da177e4SLinus Torvalds 
14141da177e4SLinus Torvalds 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
14151da177e4SLinus Torvalds 
14161da177e4SLinus Torvalds 	if (skb->len < ev->num_hndl * 4) {
14171da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
14181da177e4SLinus Torvalds 		return;
14191da177e4SLinus Torvalds 	}
14201da177e4SLinus Torvalds 
14211da177e4SLinus Torvalds 	tasklet_disable(&hdev->tx_task);
14221da177e4SLinus Torvalds 
14231ebb9252SMarcel Holtmann 	for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) {
14241da177e4SLinus Torvalds 		struct hci_conn *conn;
14251da177e4SLinus Torvalds 		__u16  handle, count;
14261da177e4SLinus Torvalds 
142783985319SHarvey Harrison 		handle = get_unaligned_le16(ptr++);
142883985319SHarvey Harrison 		count  = get_unaligned_le16(ptr++);
14291da177e4SLinus Torvalds 
14301da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
14311da177e4SLinus Torvalds 		if (conn) {
14321da177e4SLinus Torvalds 			conn->sent -= count;
14331da177e4SLinus Torvalds 
14345b7f9909SMarcel Holtmann 			if (conn->type == ACL_LINK) {
14351da177e4SLinus Torvalds 				if ((hdev->acl_cnt += count) > hdev->acl_pkts)
14361da177e4SLinus Torvalds 					hdev->acl_cnt = hdev->acl_pkts;
14375b7f9909SMarcel Holtmann 			} else {
14385b7f9909SMarcel Holtmann 				if ((hdev->sco_cnt += count) > hdev->sco_pkts)
14395b7f9909SMarcel Holtmann 					hdev->sco_cnt = hdev->sco_pkts;
14401da177e4SLinus Torvalds 			}
14411da177e4SLinus Torvalds 		}
14421da177e4SLinus Torvalds 	}
1443a9de9248SMarcel Holtmann 
14441da177e4SLinus Torvalds 	hci_sched_tx(hdev);
14451da177e4SLinus Torvalds 
14461da177e4SLinus Torvalds 	tasklet_enable(&hdev->tx_task);
14471da177e4SLinus Torvalds }
14481da177e4SLinus Torvalds 
144904837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
14501da177e4SLinus Torvalds {
1451a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
145204837f64SMarcel Holtmann 	struct hci_conn *conn;
14531da177e4SLinus Torvalds 
14541da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
14551da177e4SLinus Torvalds 
14561da177e4SLinus Torvalds 	hci_dev_lock(hdev);
14571da177e4SLinus Torvalds 
145804837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
145904837f64SMarcel Holtmann 	if (conn) {
146004837f64SMarcel Holtmann 		conn->mode = ev->mode;
146104837f64SMarcel Holtmann 		conn->interval = __le16_to_cpu(ev->interval);
146204837f64SMarcel Holtmann 
146304837f64SMarcel Holtmann 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
146404837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
146504837f64SMarcel Holtmann 				conn->power_save = 1;
146604837f64SMarcel Holtmann 			else
146704837f64SMarcel Holtmann 				conn->power_save = 0;
146804837f64SMarcel Holtmann 		}
146904837f64SMarcel Holtmann 	}
147004837f64SMarcel Holtmann 
147104837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
147204837f64SMarcel Holtmann }
147304837f64SMarcel Holtmann 
14741da177e4SLinus Torvalds static inline void hci_pin_code_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_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
14801da177e4SLinus Torvalds {
1481a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
14821da177e4SLinus Torvalds }
14831da177e4SLinus Torvalds 
14841da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
14851da177e4SLinus Torvalds {
1486a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
14871da177e4SLinus Torvalds }
14881da177e4SLinus Torvalds 
148904837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
149004837f64SMarcel Holtmann {
1491a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
149204837f64SMarcel Holtmann 	struct hci_conn *conn;
149304837f64SMarcel Holtmann 
149404837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
149504837f64SMarcel Holtmann 
149604837f64SMarcel Holtmann 	hci_dev_lock(hdev);
149704837f64SMarcel Holtmann 
149804837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
14991da177e4SLinus Torvalds 	if (conn && !ev->status) {
15001da177e4SLinus Torvalds 		struct inquiry_entry *ie;
15011da177e4SLinus Torvalds 
15021da177e4SLinus Torvalds 		if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst))) {
15031da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
15041da177e4SLinus Torvalds 			ie->timestamp = jiffies;
15051da177e4SLinus Torvalds 		}
15061da177e4SLinus Torvalds 	}
15071da177e4SLinus Torvalds 
15081da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
15091da177e4SLinus Torvalds }
15101da177e4SLinus Torvalds 
1511a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1512a8746417SMarcel Holtmann {
1513a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
1514a8746417SMarcel Holtmann 	struct hci_conn *conn;
1515a8746417SMarcel Holtmann 
1516a8746417SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1517a8746417SMarcel Holtmann 
1518a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
1519a8746417SMarcel Holtmann 
1520a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1521a8746417SMarcel Holtmann 	if (conn && !ev->status)
1522a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
1523a8746417SMarcel Holtmann 
1524a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
1525a8746417SMarcel Holtmann }
1526a8746417SMarcel Holtmann 
152785a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
152885a1e930SMarcel Holtmann {
1529a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
153085a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
153185a1e930SMarcel Holtmann 
153285a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
153385a1e930SMarcel Holtmann 
153485a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
153585a1e930SMarcel Holtmann 
153685a1e930SMarcel Holtmann 	if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr))) {
153785a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
153885a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
153985a1e930SMarcel Holtmann 	}
154085a1e930SMarcel Holtmann 
154185a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
154285a1e930SMarcel Holtmann }
154385a1e930SMarcel Holtmann 
1544a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
1545a9de9248SMarcel Holtmann {
1546a9de9248SMarcel Holtmann 	struct inquiry_data data;
1547a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
1548a9de9248SMarcel Holtmann 
1549a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1550a9de9248SMarcel Holtmann 
1551a9de9248SMarcel Holtmann 	if (!num_rsp)
1552a9de9248SMarcel Holtmann 		return;
1553a9de9248SMarcel Holtmann 
1554a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1555a9de9248SMarcel Holtmann 
1556a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
1557a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi_and_pscan_mode *info = (void *) (skb->data + 1);
1558a9de9248SMarcel Holtmann 
1559a9de9248SMarcel Holtmann 		for (; num_rsp; num_rsp--) {
1560a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
1561a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
1562a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
1563a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
1564a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
1565a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
1566a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
156741a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
1568a9de9248SMarcel Holtmann 			info++;
1569a9de9248SMarcel Holtmann 			hci_inquiry_cache_update(hdev, &data);
1570a9de9248SMarcel Holtmann 		}
1571a9de9248SMarcel Holtmann 	} else {
1572a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
1573a9de9248SMarcel Holtmann 
1574a9de9248SMarcel Holtmann 		for (; num_rsp; num_rsp--) {
1575a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
1576a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
1577a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
1578a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
1579a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
1580a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
1581a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
158241a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
1583a9de9248SMarcel Holtmann 			info++;
1584a9de9248SMarcel Holtmann 			hci_inquiry_cache_update(hdev, &data);
1585a9de9248SMarcel Holtmann 		}
1586a9de9248SMarcel Holtmann 	}
1587a9de9248SMarcel Holtmann 
1588a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1589a9de9248SMarcel Holtmann }
1590a9de9248SMarcel Holtmann 
1591a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
1592a9de9248SMarcel Holtmann {
159341a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
159441a96212SMarcel Holtmann 	struct hci_conn *conn;
159541a96212SMarcel Holtmann 
1596a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
159741a96212SMarcel Holtmann 
159841a96212SMarcel Holtmann 	hci_dev_lock(hdev);
159941a96212SMarcel Holtmann 
160041a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
160141a96212SMarcel Holtmann 	if (conn) {
1602769be974SMarcel Holtmann 		if (!ev->status && ev->page == 0x01) {
160341a96212SMarcel Holtmann 			struct inquiry_entry *ie;
160441a96212SMarcel Holtmann 
160541a96212SMarcel Holtmann 			if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst)))
160641a96212SMarcel Holtmann 				ie->data.ssp_mode = (ev->features[0] & 0x01);
160741a96212SMarcel Holtmann 
160841a96212SMarcel Holtmann 			conn->ssp_mode = (ev->features[0] & 0x01);
160941a96212SMarcel Holtmann 		}
161041a96212SMarcel Holtmann 
1611769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1612f8558555SMarcel Holtmann 			if (!ev->status && hdev->ssp_mode > 0 &&
16138c1b2355SMarcel Holtmann 					conn->ssp_mode > 0 && conn->out &&
16148c1b2355SMarcel Holtmann 					conn->sec_level != BT_SECURITY_SDP) {
1615f8558555SMarcel Holtmann 				struct hci_cp_auth_requested cp;
1616f8558555SMarcel Holtmann 				cp.handle = ev->handle;
1617f1c08ca5SMarcel Holtmann 				hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED,
1618f8558555SMarcel Holtmann 							sizeof(cp), &cp);
1619f8558555SMarcel Holtmann 			} else {
1620769be974SMarcel Holtmann 				conn->state = BT_CONNECTED;
1621769be974SMarcel Holtmann 				hci_proto_connect_cfm(conn, ev->status);
1622769be974SMarcel Holtmann 				hci_conn_put(conn);
1623769be974SMarcel Holtmann 			}
1624769be974SMarcel Holtmann 		}
1625f8558555SMarcel Holtmann 	}
1626769be974SMarcel Holtmann 
162741a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
1628a9de9248SMarcel Holtmann }
1629a9de9248SMarcel Holtmann 
1630a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1631a9de9248SMarcel Holtmann {
1632b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
1633b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
1634b6a0dc82SMarcel Holtmann 
1635b6a0dc82SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1636b6a0dc82SMarcel Holtmann 
1637b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1638b6a0dc82SMarcel Holtmann 
1639b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
16409dc0a3afSMarcel Holtmann 	if (!conn) {
16419dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
16429dc0a3afSMarcel Holtmann 			goto unlock;
16439dc0a3afSMarcel Holtmann 
16449dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1645b6a0dc82SMarcel Holtmann 		if (!conn)
1646b6a0dc82SMarcel Holtmann 			goto unlock;
1647b6a0dc82SMarcel Holtmann 
16489dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
16499dc0a3afSMarcel Holtmann 	}
16509dc0a3afSMarcel Holtmann 
1651efc7688bSMarcel Holtmann 	if (conn->out && ev->status == 0x1c && conn->attempt < 2) {
1652efc7688bSMarcel Holtmann 		conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
1653efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
1654efc7688bSMarcel Holtmann 		hci_setup_sync(conn, conn->link->handle);
1655efc7688bSMarcel Holtmann 		goto unlock;
1656efc7688bSMarcel Holtmann 	}
1657efc7688bSMarcel Holtmann 
1658b6a0dc82SMarcel Holtmann 	if (!ev->status) {
1659b6a0dc82SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1660b6a0dc82SMarcel Holtmann 		conn->state  = BT_CONNECTED;
16617d0db0a3SMarcel Holtmann 
16627d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
1663b6a0dc82SMarcel Holtmann 	} else
1664b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
1665b6a0dc82SMarcel Holtmann 
1666b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
1667b6a0dc82SMarcel Holtmann 	if (ev->status)
1668b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
1669b6a0dc82SMarcel Holtmann 
1670b6a0dc82SMarcel Holtmann unlock:
1671b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1672a9de9248SMarcel Holtmann }
1673a9de9248SMarcel Holtmann 
1674a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
1675a9de9248SMarcel Holtmann {
1676a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1677a9de9248SMarcel Holtmann }
1678a9de9248SMarcel Holtmann 
167904837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
168004837f64SMarcel Holtmann {
1681a9de9248SMarcel Holtmann 	struct hci_ev_sniff_subrate *ev = (void *) skb->data;
168204837f64SMarcel Holtmann 	struct hci_conn *conn;
168304837f64SMarcel Holtmann 
168404837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
168504837f64SMarcel Holtmann 
168604837f64SMarcel Holtmann 	hci_dev_lock(hdev);
168704837f64SMarcel Holtmann 
168804837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
168904837f64SMarcel Holtmann 	if (conn) {
169004837f64SMarcel Holtmann 	}
169104837f64SMarcel Holtmann 
169204837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
169304837f64SMarcel Holtmann }
169404837f64SMarcel Holtmann 
1695a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
1696a9de9248SMarcel Holtmann {
1697a9de9248SMarcel Holtmann 	struct inquiry_data data;
1698a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
1699a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
1700a9de9248SMarcel Holtmann 
1701a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1702a9de9248SMarcel Holtmann 
1703a9de9248SMarcel Holtmann 	if (!num_rsp)
1704a9de9248SMarcel Holtmann 		return;
1705a9de9248SMarcel Holtmann 
1706a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1707a9de9248SMarcel Holtmann 
1708a9de9248SMarcel Holtmann 	for (; num_rsp; num_rsp--) {
1709a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
1710a9de9248SMarcel Holtmann 		data.pscan_rep_mode     = info->pscan_rep_mode;
1711a9de9248SMarcel Holtmann 		data.pscan_period_mode  = info->pscan_period_mode;
1712a9de9248SMarcel Holtmann 		data.pscan_mode         = 0x00;
1713a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
1714a9de9248SMarcel Holtmann 		data.clock_offset       = info->clock_offset;
1715a9de9248SMarcel Holtmann 		data.rssi               = info->rssi;
171641a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
1717a9de9248SMarcel Holtmann 		info++;
1718a9de9248SMarcel Holtmann 		hci_inquiry_cache_update(hdev, &data);
1719a9de9248SMarcel Holtmann 	}
1720a9de9248SMarcel Holtmann 
1721a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1722a9de9248SMarcel Holtmann }
1723a9de9248SMarcel Holtmann 
17240493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
17250493684eSMarcel Holtmann {
17260493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
17270493684eSMarcel Holtmann 	struct hci_conn *conn;
17280493684eSMarcel Holtmann 
17290493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
17300493684eSMarcel Holtmann 
17310493684eSMarcel Holtmann 	hci_dev_lock(hdev);
17320493684eSMarcel Holtmann 
17330493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
17340493684eSMarcel Holtmann 	if (conn)
17350493684eSMarcel Holtmann 		hci_conn_hold(conn);
17360493684eSMarcel Holtmann 
17370493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
17380493684eSMarcel Holtmann }
17390493684eSMarcel Holtmann 
17400493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
17410493684eSMarcel Holtmann {
17420493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
17430493684eSMarcel Holtmann 	struct hci_conn *conn;
17440493684eSMarcel Holtmann 
17450493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
17460493684eSMarcel Holtmann 
17470493684eSMarcel Holtmann 	hci_dev_lock(hdev);
17480493684eSMarcel Holtmann 
17490493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
17500493684eSMarcel Holtmann 	if (conn)
17510493684eSMarcel Holtmann 		hci_conn_put(conn);
17520493684eSMarcel Holtmann 
17530493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
17540493684eSMarcel Holtmann }
17550493684eSMarcel Holtmann 
175641a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
175741a96212SMarcel Holtmann {
175841a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
175941a96212SMarcel Holtmann 	struct inquiry_entry *ie;
176041a96212SMarcel Holtmann 
176141a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
176241a96212SMarcel Holtmann 
176341a96212SMarcel Holtmann 	hci_dev_lock(hdev);
176441a96212SMarcel Holtmann 
176541a96212SMarcel Holtmann 	if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr)))
176641a96212SMarcel Holtmann 		ie->data.ssp_mode = (ev->features[0] & 0x01);
176741a96212SMarcel Holtmann 
176841a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
176941a96212SMarcel Holtmann }
177041a96212SMarcel Holtmann 
17711da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
17721da177e4SLinus Torvalds {
1773a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
1774a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
17751da177e4SLinus Torvalds 
17761da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
17771da177e4SLinus Torvalds 
1778a9de9248SMarcel Holtmann 	switch (event) {
17791da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
17801da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
17811da177e4SLinus Torvalds 		break;
17821da177e4SLinus Torvalds 
17831da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
17841da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
17851da177e4SLinus Torvalds 		break;
17861da177e4SLinus Torvalds 
1787a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
1788a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
178921d9e30eSMarcel Holtmann 		break;
179021d9e30eSMarcel Holtmann 
17911da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
17921da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
17931da177e4SLinus Torvalds 		break;
17941da177e4SLinus Torvalds 
17951da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
17961da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
17971da177e4SLinus Torvalds 		break;
17981da177e4SLinus Torvalds 
17991da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
18001da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
18011da177e4SLinus Torvalds 		break;
18021da177e4SLinus Torvalds 
1803a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
1804a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
1805a9de9248SMarcel Holtmann 		break;
1806a9de9248SMarcel Holtmann 
18071da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
18081da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
18091da177e4SLinus Torvalds 		break;
18101da177e4SLinus Torvalds 
1811a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
1812a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
1813a9de9248SMarcel Holtmann 		break;
1814a9de9248SMarcel Holtmann 
1815a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
1816a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
1817a9de9248SMarcel Holtmann 		break;
1818a9de9248SMarcel Holtmann 
1819a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_VERSION:
1820a9de9248SMarcel Holtmann 		hci_remote_version_evt(hdev, skb);
1821a9de9248SMarcel Holtmann 		break;
1822a9de9248SMarcel Holtmann 
1823a9de9248SMarcel Holtmann 	case HCI_EV_QOS_SETUP_COMPLETE:
1824a9de9248SMarcel Holtmann 		hci_qos_setup_complete_evt(hdev, skb);
1825a9de9248SMarcel Holtmann 		break;
1826a9de9248SMarcel Holtmann 
1827a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
1828a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
1829a9de9248SMarcel Holtmann 		break;
1830a9de9248SMarcel Holtmann 
1831a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
1832a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
1833a9de9248SMarcel Holtmann 		break;
1834a9de9248SMarcel Holtmann 
1835a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
1836a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
1837a9de9248SMarcel Holtmann 		break;
1838a9de9248SMarcel Holtmann 
1839a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
1840a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
1841a9de9248SMarcel Holtmann 		break;
1842a9de9248SMarcel Holtmann 
1843a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
1844a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
18451da177e4SLinus Torvalds 		break;
18461da177e4SLinus Torvalds 
18471da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
18481da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
18491da177e4SLinus Torvalds 		break;
18501da177e4SLinus Torvalds 
18511da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
18521da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
18531da177e4SLinus Torvalds 		break;
18541da177e4SLinus Torvalds 
18551da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
18561da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
18571da177e4SLinus Torvalds 		break;
18581da177e4SLinus Torvalds 
18591da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
18601da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
18611da177e4SLinus Torvalds 		break;
18621da177e4SLinus Torvalds 
1863a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
1864a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
1865a8746417SMarcel Holtmann 		break;
1866a8746417SMarcel Holtmann 
186785a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
186885a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
186985a1e930SMarcel Holtmann 		break;
187085a1e930SMarcel Holtmann 
1871a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
1872a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
1873a9de9248SMarcel Holtmann 		break;
1874a9de9248SMarcel Holtmann 
1875a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
1876a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
1877a9de9248SMarcel Holtmann 		break;
1878a9de9248SMarcel Holtmann 
1879a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
1880a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
1881a9de9248SMarcel Holtmann 		break;
1882a9de9248SMarcel Holtmann 
1883a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_CHANGED:
1884a9de9248SMarcel Holtmann 		hci_sync_conn_changed_evt(hdev, skb);
1885a9de9248SMarcel Holtmann 		break;
1886a9de9248SMarcel Holtmann 
188704837f64SMarcel Holtmann 	case HCI_EV_SNIFF_SUBRATE:
188804837f64SMarcel Holtmann 		hci_sniff_subrate_evt(hdev, skb);
188904837f64SMarcel Holtmann 		break;
189004837f64SMarcel Holtmann 
1891a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
1892a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
18931da177e4SLinus Torvalds 		break;
18941da177e4SLinus Torvalds 
18950493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
18960493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
18970493684eSMarcel Holtmann 		break;
18980493684eSMarcel Holtmann 
18990493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
19000493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
19010493684eSMarcel Holtmann 		break;
19020493684eSMarcel Holtmann 
190341a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
190441a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
190541a96212SMarcel Holtmann 		break;
190641a96212SMarcel Holtmann 
19071da177e4SLinus Torvalds 	default:
1908a9de9248SMarcel Holtmann 		BT_DBG("%s event 0x%x", hdev->name, event);
19091da177e4SLinus Torvalds 		break;
19101da177e4SLinus Torvalds 	}
19111da177e4SLinus Torvalds 
19121da177e4SLinus Torvalds 	kfree_skb(skb);
19131da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
19141da177e4SLinus Torvalds }
19151da177e4SLinus Torvalds 
19161da177e4SLinus Torvalds /* Generate internal stack event */
19171da177e4SLinus Torvalds void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
19181da177e4SLinus Torvalds {
19191da177e4SLinus Torvalds 	struct hci_event_hdr *hdr;
19201da177e4SLinus Torvalds 	struct hci_ev_stack_internal *ev;
19211da177e4SLinus Torvalds 	struct sk_buff *skb;
19221da177e4SLinus Torvalds 
19231da177e4SLinus Torvalds 	skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC);
19241da177e4SLinus Torvalds 	if (!skb)
19251da177e4SLinus Torvalds 		return;
19261da177e4SLinus Torvalds 
19271da177e4SLinus Torvalds 	hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE);
19281da177e4SLinus Torvalds 	hdr->evt  = HCI_EV_STACK_INTERNAL;
19291da177e4SLinus Torvalds 	hdr->plen = sizeof(*ev) + dlen;
19301da177e4SLinus Torvalds 
19311da177e4SLinus Torvalds 	ev  = (void *) skb_put(skb, sizeof(*ev) + dlen);
19321da177e4SLinus Torvalds 	ev->type = type;
19331da177e4SLinus Torvalds 	memcpy(ev->data, data, dlen);
19341da177e4SLinus Torvalds 
1935576c7d85SMarcel Holtmann 	bt_cb(skb)->incoming = 1;
1936a61bbcf2SPatrick McHardy 	__net_timestamp(skb);
1937576c7d85SMarcel Holtmann 
19380d48d939SMarcel Holtmann 	bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
19391da177e4SLinus Torvalds 	skb->dev = (void *) hdev;
19401da177e4SLinus Torvalds 	hci_send_to_sock(hdev, skb);
19411da177e4SLinus Torvalds 	kfree_skb(skb);
19421da177e4SLinus Torvalds }
1943