xref: /openbmc/linux/net/bluetooth/hci_event.c (revision 392599b9)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds    BlueZ - Bluetooth protocol stack for Linux
32d0a0346SRon Shaffer    Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved.
41da177e4SLinus Torvalds 
51da177e4SLinus Torvalds    Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
61da177e4SLinus Torvalds 
71da177e4SLinus Torvalds    This program is free software; you can redistribute it and/or modify
81da177e4SLinus Torvalds    it under the terms of the GNU General Public License version 2 as
91da177e4SLinus Torvalds    published by the Free Software Foundation;
101da177e4SLinus Torvalds 
111da177e4SLinus Torvalds    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
121da177e4SLinus Torvalds    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
131da177e4SLinus Torvalds    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
141da177e4SLinus Torvalds    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
151da177e4SLinus Torvalds    CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
161da177e4SLinus Torvalds    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
171da177e4SLinus Torvalds    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
181da177e4SLinus Torvalds    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
191da177e4SLinus Torvalds 
201da177e4SLinus Torvalds    ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
211da177e4SLinus Torvalds    COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
221da177e4SLinus Torvalds    SOFTWARE IS DISCLAIMED.
231da177e4SLinus Torvalds */
241da177e4SLinus Torvalds 
251da177e4SLinus Torvalds /* Bluetooth HCI event handling. */
261da177e4SLinus Torvalds 
271da177e4SLinus Torvalds #include <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
587893ef971SGustavo F. Padovan 				BT_ERR("No memory 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 
680392599b9SJohan Hedberg static int hci_request_outgoing_auth(struct hci_dev *hdev,
681392599b9SJohan Hedberg 						struct hci_conn *conn)
682392599b9SJohan Hedberg {
683392599b9SJohan Hedberg 	struct hci_cp_auth_requested cp;
684392599b9SJohan Hedberg 
685392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
686392599b9SJohan Hedberg 		return 0;
687392599b9SJohan Hedberg 
688392599b9SJohan Hedberg 	if (conn->sec_level == BT_SECURITY_SDP)
689392599b9SJohan Hedberg 		return 0;
690392599b9SJohan Hedberg 
691392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
692392599b9SJohan Hedberg 	 * devices with sec_level HIGH */
693392599b9SJohan Hedberg 	if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) &&
694392599b9SJohan Hedberg 					conn->sec_level != BT_SECURITY_HIGH)
695392599b9SJohan Hedberg 		return 0;
696392599b9SJohan Hedberg 
697392599b9SJohan Hedberg 	cp.handle = __cpu_to_le16(conn->handle);
698392599b9SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
699392599b9SJohan Hedberg 
700392599b9SJohan Hedberg 	return 1;
701392599b9SJohan Hedberg }
702392599b9SJohan Hedberg 
703a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
7041da177e4SLinus Torvalds {
705a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
706a9de9248SMarcel Holtmann }
7071da177e4SLinus Torvalds 
708769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
709769be974SMarcel Holtmann {
710769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
711769be974SMarcel Holtmann 	struct hci_conn *conn;
712769be974SMarcel Holtmann 
713769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
714769be974SMarcel Holtmann 
715769be974SMarcel Holtmann 	if (!status)
716769be974SMarcel Holtmann 		return;
717769be974SMarcel Holtmann 
718769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
719769be974SMarcel Holtmann 	if (!cp)
720769be974SMarcel Holtmann 		return;
721769be974SMarcel Holtmann 
722769be974SMarcel Holtmann 	hci_dev_lock(hdev);
723769be974SMarcel Holtmann 
724769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
725769be974SMarcel Holtmann 	if (conn) {
726769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
727769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
728769be974SMarcel Holtmann 			hci_conn_put(conn);
729769be974SMarcel Holtmann 		}
730769be974SMarcel Holtmann 	}
731769be974SMarcel Holtmann 
732769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
733769be974SMarcel Holtmann }
734769be974SMarcel Holtmann 
735769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
736769be974SMarcel Holtmann {
737769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
738769be974SMarcel Holtmann 	struct hci_conn *conn;
739769be974SMarcel Holtmann 
740769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
741769be974SMarcel Holtmann 
742769be974SMarcel Holtmann 	if (!status)
743769be974SMarcel Holtmann 		return;
744769be974SMarcel Holtmann 
745769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
746769be974SMarcel Holtmann 	if (!cp)
747769be974SMarcel Holtmann 		return;
748769be974SMarcel Holtmann 
749769be974SMarcel Holtmann 	hci_dev_lock(hdev);
750769be974SMarcel Holtmann 
751769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
752769be974SMarcel Holtmann 	if (conn) {
753769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
754769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
755769be974SMarcel Holtmann 			hci_conn_put(conn);
756769be974SMarcel Holtmann 		}
757769be974SMarcel Holtmann 	}
758769be974SMarcel Holtmann 
759769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
760769be974SMarcel Holtmann }
761769be974SMarcel Holtmann 
762a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
763a9de9248SMarcel Holtmann {
764b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
765b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
766b6a0dc82SMarcel Holtmann 	__u16 handle;
767b6a0dc82SMarcel Holtmann 
768a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
769b6a0dc82SMarcel Holtmann 
770b6a0dc82SMarcel Holtmann 	if (!status)
771b6a0dc82SMarcel Holtmann 		return;
772b6a0dc82SMarcel Holtmann 
773b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
774b6a0dc82SMarcel Holtmann 	if (!cp)
775b6a0dc82SMarcel Holtmann 		return;
776b6a0dc82SMarcel Holtmann 
777b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
778b6a0dc82SMarcel Holtmann 
779b6a0dc82SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
780b6a0dc82SMarcel Holtmann 
781b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
782b6a0dc82SMarcel Holtmann 
783b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
784b6a0dc82SMarcel Holtmann 	if (acl && (sco = acl->link)) {
785b6a0dc82SMarcel Holtmann 		sco->state = BT_CLOSED;
786b6a0dc82SMarcel Holtmann 
787b6a0dc82SMarcel Holtmann 		hci_proto_connect_cfm(sco, status);
788b6a0dc82SMarcel Holtmann 		hci_conn_del(sco);
789b6a0dc82SMarcel Holtmann 	}
790b6a0dc82SMarcel Holtmann 
791b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
792a9de9248SMarcel Holtmann }
793a9de9248SMarcel Holtmann 
794a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
795a9de9248SMarcel Holtmann {
796a9de9248SMarcel Holtmann 	struct hci_cp_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_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));
811e73439d8SMarcel Holtmann 	if (conn) {
81204837f64SMarcel Holtmann 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
81304837f64SMarcel Holtmann 
814e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
815e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
816e73439d8SMarcel Holtmann 	}
817e73439d8SMarcel Holtmann 
81804837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
81904837f64SMarcel Holtmann }
82004837f64SMarcel Holtmann 
821a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
822a9de9248SMarcel Holtmann {
823a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
82404837f64SMarcel Holtmann 	struct hci_conn *conn;
82504837f64SMarcel Holtmann 
826a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
827a9de9248SMarcel Holtmann 
828a9de9248SMarcel Holtmann 	if (!status)
829a9de9248SMarcel Holtmann 		return;
830a9de9248SMarcel Holtmann 
831a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
83204837f64SMarcel Holtmann 	if (!cp)
833a9de9248SMarcel Holtmann 		return;
83404837f64SMarcel Holtmann 
83504837f64SMarcel Holtmann 	hci_dev_lock(hdev);
83604837f64SMarcel Holtmann 
83704837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
838e73439d8SMarcel Holtmann 	if (conn) {
83904837f64SMarcel Holtmann 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
84004837f64SMarcel Holtmann 
841e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
842e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
843e73439d8SMarcel Holtmann 	}
844e73439d8SMarcel Holtmann 
84504837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
84604837f64SMarcel Holtmann }
84704837f64SMarcel Holtmann 
8481da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
8491da177e4SLinus Torvalds {
8501da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
8511da177e4SLinus Torvalds 
8521da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, status);
8531da177e4SLinus Torvalds 
8541da177e4SLinus Torvalds 	clear_bit(HCI_INQUIRY, &hdev->flags);
855a9de9248SMarcel Holtmann 
8561da177e4SLinus Torvalds 	hci_req_complete(hdev, status);
8576bd57416SMarcel Holtmann 
858a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
8591da177e4SLinus Torvalds }
8601da177e4SLinus Torvalds 
8611da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
8621da177e4SLinus Torvalds {
86345bb4bf0SMarcel Holtmann 	struct inquiry_data data;
864a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
8651da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
8661da177e4SLinus Torvalds 
8671da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
8681da177e4SLinus Torvalds 
86945bb4bf0SMarcel Holtmann 	if (!num_rsp)
87045bb4bf0SMarcel Holtmann 		return;
87145bb4bf0SMarcel Holtmann 
8721da177e4SLinus Torvalds 	hci_dev_lock(hdev);
87345bb4bf0SMarcel Holtmann 
8741da177e4SLinus Torvalds 	for (; num_rsp; num_rsp--) {
8751da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
8761da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
8771da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
8781da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
8791da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
8801da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
8811da177e4SLinus Torvalds 		data.rssi		= 0x00;
88241a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
8831da177e4SLinus Torvalds 		info++;
8841da177e4SLinus Torvalds 		hci_inquiry_cache_update(hdev, &data);
8851da177e4SLinus Torvalds 	}
88645bb4bf0SMarcel Holtmann 
8871da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
8881da177e4SLinus Torvalds }
8891da177e4SLinus Torvalds 
890a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
8911da177e4SLinus Torvalds {
892a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
893a9de9248SMarcel Holtmann 	struct hci_conn *conn;
8941da177e4SLinus Torvalds 
895a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
89645bb4bf0SMarcel Holtmann 
8971da177e4SLinus Torvalds 	hci_dev_lock(hdev);
89845bb4bf0SMarcel Holtmann 
899a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
9009499237aSMarcel Holtmann 	if (!conn) {
9019499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
9029499237aSMarcel Holtmann 			goto unlock;
9039499237aSMarcel Holtmann 
9049499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
905a9de9248SMarcel Holtmann 		if (!conn)
906a9de9248SMarcel Holtmann 			goto unlock;
90745bb4bf0SMarcel Holtmann 
9089499237aSMarcel Holtmann 		conn->type = SCO_LINK;
9099499237aSMarcel Holtmann 	}
9109499237aSMarcel Holtmann 
911a9de9248SMarcel Holtmann 	if (!ev->status) {
912a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
913769be974SMarcel Holtmann 
914769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
915769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
916769be974SMarcel Holtmann 			hci_conn_hold(conn);
917052b30b0SMarcel Holtmann 			conn->disc_timeout = HCI_DISCONN_TIMEOUT;
918769be974SMarcel Holtmann 		} else
919a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
920a9de9248SMarcel Holtmann 
9219eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
9227d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
9237d0db0a3SMarcel Holtmann 
924a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
925a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
926a9de9248SMarcel Holtmann 
927a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
928a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
929a9de9248SMarcel Holtmann 
930a9de9248SMarcel Holtmann 		/* Get remote features */
931a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
932a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
933a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
934769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
935769be974SMarcel Holtmann 							sizeof(cp), &cp);
93645bb4bf0SMarcel Holtmann 		}
937a9de9248SMarcel Holtmann 
938a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
939a8746417SMarcel Holtmann 		if (!conn->out && hdev->hci_ver < 3) {
940a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
941a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
942a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
943a8746417SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
944a8746417SMarcel Holtmann 							sizeof(cp), &cp);
945a9de9248SMarcel Holtmann 		}
946a9de9248SMarcel Holtmann 	} else
947a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
94845bb4bf0SMarcel Holtmann 
949e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
950e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
95145bb4bf0SMarcel Holtmann 
952769be974SMarcel Holtmann 	if (ev->status) {
953a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
954a9de9248SMarcel Holtmann 		hci_conn_del(conn);
955c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
956c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
957a9de9248SMarcel Holtmann 
958a9de9248SMarcel Holtmann unlock:
9591da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
960a9de9248SMarcel Holtmann 
961a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
9621da177e4SLinus Torvalds }
9631da177e4SLinus Torvalds 
9641da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
9651da177e4SLinus Torvalds {
966a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
9671da177e4SLinus Torvalds 	int mask = hdev->link_mode;
9681da177e4SLinus Torvalds 
969a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
9701da177e4SLinus Torvalds 					batostr(&ev->bdaddr), ev->link_type);
9711da177e4SLinus Torvalds 
9721da177e4SLinus Torvalds 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
9731da177e4SLinus Torvalds 
974f0358568SJohan Hedberg 	if ((mask & HCI_LM_ACCEPT) && !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
9751da177e4SLinus Torvalds 		/* Connection accepted */
976c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
9771da177e4SLinus Torvalds 		struct hci_conn *conn;
9781da177e4SLinus Torvalds 
9791da177e4SLinus Torvalds 		hci_dev_lock(hdev);
980b6a0dc82SMarcel Holtmann 
981c7bdd502SMarcel Holtmann 		if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr)))
982c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
983c7bdd502SMarcel Holtmann 
9841da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
9851da177e4SLinus Torvalds 		if (!conn) {
9861da177e4SLinus Torvalds 			if (!(conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr))) {
987893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
9881da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
9891da177e4SLinus Torvalds 				return;
9901da177e4SLinus Torvalds 			}
9911da177e4SLinus Torvalds 		}
992b6a0dc82SMarcel Holtmann 
9931da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
9941da177e4SLinus Torvalds 		conn->state = BT_CONNECT;
995b6a0dc82SMarcel Holtmann 
9961da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
9971da177e4SLinus Torvalds 
998b6a0dc82SMarcel Holtmann 		if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
999b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
1000b6a0dc82SMarcel Holtmann 
10011da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
10021da177e4SLinus Torvalds 
10031da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
10041da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
10051da177e4SLinus Torvalds 			else
10061da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
10071da177e4SLinus Torvalds 
1008b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ,
1009b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1010b6a0dc82SMarcel Holtmann 		} else {
1011b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
1012b6a0dc82SMarcel Holtmann 
1013b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
1014a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1015b6a0dc82SMarcel Holtmann 
1016b6a0dc82SMarcel Holtmann 			cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
1017b6a0dc82SMarcel Holtmann 			cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
1018b6a0dc82SMarcel Holtmann 			cp.max_latency    = cpu_to_le16(0xffff);
1019b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
1020b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
1021b6a0dc82SMarcel Holtmann 
1022b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1023b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1024b6a0dc82SMarcel Holtmann 		}
10251da177e4SLinus Torvalds 	} else {
10261da177e4SLinus Torvalds 		/* Connection rejected */
10271da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
10281da177e4SLinus Torvalds 
10291da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
10301da177e4SLinus Torvalds 		cp.reason = 0x0f;
1031a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
10321da177e4SLinus Torvalds 	}
10331da177e4SLinus Torvalds }
10341da177e4SLinus Torvalds 
10351da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
10361da177e4SLinus Torvalds {
1037a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
103804837f64SMarcel Holtmann 	struct hci_conn *conn;
10391da177e4SLinus Torvalds 
10401da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
10411da177e4SLinus Torvalds 
10421da177e4SLinus Torvalds 	if (ev->status)
10431da177e4SLinus Torvalds 		return;
10441da177e4SLinus Torvalds 
10451da177e4SLinus Torvalds 	hci_dev_lock(hdev);
10461da177e4SLinus Torvalds 
104704837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
10481da177e4SLinus Torvalds 	if (conn) {
10491da177e4SLinus Torvalds 		conn->state = BT_CLOSED;
10507d0db0a3SMarcel Holtmann 
10512950f21aSMarcel Holtmann 		hci_proto_disconn_cfm(conn, ev->reason);
10521da177e4SLinus Torvalds 		hci_conn_del(conn);
10531da177e4SLinus Torvalds 	}
10541da177e4SLinus Torvalds 
10551da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
10561da177e4SLinus Torvalds }
10571da177e4SLinus Torvalds 
1058a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1059a9de9248SMarcel Holtmann {
1060a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
1061a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1062a9de9248SMarcel Holtmann 
1063a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1064a9de9248SMarcel Holtmann 
1065a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1066a9de9248SMarcel Holtmann 
1067a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1068a9de9248SMarcel Holtmann 	if (conn) {
1069a9de9248SMarcel Holtmann 		if (!ev->status)
1070a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1071da213f41SJohan Hedberg 		else
1072da213f41SJohan Hedberg 			conn->sec_level = BT_SECURITY_LOW;
1073a9de9248SMarcel Holtmann 
1074a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1075a9de9248SMarcel Holtmann 
1076f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1077f8558555SMarcel Holtmann 			if (!ev->status && hdev->ssp_mode > 0 &&
1078f8558555SMarcel Holtmann 							conn->ssp_mode > 0) {
1079f8558555SMarcel Holtmann 				struct hci_cp_set_conn_encrypt cp;
1080f8558555SMarcel Holtmann 				cp.handle  = ev->handle;
1081f8558555SMarcel Holtmann 				cp.encrypt = 0x01;
1082f8558555SMarcel Holtmann 				hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT,
1083f8558555SMarcel Holtmann 							sizeof(cp), &cp);
1084f8558555SMarcel Holtmann 			} else {
1085f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
1086f8558555SMarcel Holtmann 				hci_proto_connect_cfm(conn, ev->status);
1087f8558555SMarcel Holtmann 				hci_conn_put(conn);
1088f8558555SMarcel Holtmann 			}
1089052b30b0SMarcel Holtmann 		} else {
1090a9de9248SMarcel Holtmann 			hci_auth_cfm(conn, ev->status);
1091a9de9248SMarcel Holtmann 
1092052b30b0SMarcel Holtmann 			hci_conn_hold(conn);
1093052b30b0SMarcel Holtmann 			conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1094052b30b0SMarcel Holtmann 			hci_conn_put(conn);
1095052b30b0SMarcel Holtmann 		}
1096052b30b0SMarcel Holtmann 
1097a9de9248SMarcel Holtmann 		if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
1098a9de9248SMarcel Holtmann 			if (!ev->status) {
1099a9de9248SMarcel Holtmann 				struct hci_cp_set_conn_encrypt cp;
1100f8558555SMarcel Holtmann 				cp.handle  = ev->handle;
1101f8558555SMarcel Holtmann 				cp.encrypt = 0x01;
1102f8558555SMarcel Holtmann 				hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT,
1103f8558555SMarcel Holtmann 							sizeof(cp), &cp);
1104a9de9248SMarcel Holtmann 			} else {
1105a9de9248SMarcel Holtmann 				clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1106a9de9248SMarcel Holtmann 				hci_encrypt_cfm(conn, ev->status, 0x00);
1107a9de9248SMarcel Holtmann 			}
1108a9de9248SMarcel Holtmann 		}
1109a9de9248SMarcel Holtmann 	}
1110a9de9248SMarcel Holtmann 
1111a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1112a9de9248SMarcel Holtmann }
1113a9de9248SMarcel Holtmann 
1114a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1115a9de9248SMarcel Holtmann {
1116a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1117a9de9248SMarcel Holtmann 
1118a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
1119a9de9248SMarcel Holtmann }
1120a9de9248SMarcel Holtmann 
1121a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1122a9de9248SMarcel Holtmann {
1123a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
1124a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1125a9de9248SMarcel Holtmann 
1126a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1127a9de9248SMarcel Holtmann 
1128a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1129a9de9248SMarcel Holtmann 
1130a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1131a9de9248SMarcel Holtmann 	if (conn) {
1132a9de9248SMarcel Holtmann 		if (!ev->status) {
1133ae293196SMarcel Holtmann 			if (ev->encrypt) {
1134ae293196SMarcel Holtmann 				/* Encryption implies authentication */
1135ae293196SMarcel Holtmann 				conn->link_mode |= HCI_LM_AUTH;
1136a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_ENCRYPT;
1137ae293196SMarcel Holtmann 			} else
1138a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_ENCRYPT;
1139a9de9248SMarcel Holtmann 		}
1140a9de9248SMarcel Holtmann 
1141a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1142a9de9248SMarcel Holtmann 
1143f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1144f8558555SMarcel Holtmann 			if (!ev->status)
1145f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
1146f8558555SMarcel Holtmann 
1147f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1148f8558555SMarcel Holtmann 			hci_conn_put(conn);
1149f8558555SMarcel Holtmann 		} else
1150a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, ev->encrypt);
1151a9de9248SMarcel Holtmann 	}
1152a9de9248SMarcel Holtmann 
1153a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1154a9de9248SMarcel Holtmann }
1155a9de9248SMarcel Holtmann 
1156a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1157a9de9248SMarcel Holtmann {
1158a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
1159a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1160a9de9248SMarcel Holtmann 
1161a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1162a9de9248SMarcel Holtmann 
1163a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1164a9de9248SMarcel Holtmann 
1165a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1166a9de9248SMarcel Holtmann 	if (conn) {
1167a9de9248SMarcel Holtmann 		if (!ev->status)
1168a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
1169a9de9248SMarcel Holtmann 
1170a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1171a9de9248SMarcel Holtmann 
1172a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
1173a9de9248SMarcel Holtmann 	}
1174a9de9248SMarcel Holtmann 
1175a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1176a9de9248SMarcel Holtmann }
1177a9de9248SMarcel Holtmann 
1178a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
1179a9de9248SMarcel Holtmann {
1180a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
1181a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1182392599b9SJohan Hedberg 	int auth_requested;
1183a9de9248SMarcel Holtmann 
1184a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1185a9de9248SMarcel Holtmann 
1186a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1187a9de9248SMarcel Holtmann 
1188a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1189ccd556feSJohan Hedberg 	if (!conn)
1190ccd556feSJohan Hedberg 		goto unlock;
1191ccd556feSJohan Hedberg 
1192769be974SMarcel Holtmann 	if (!ev->status)
1193a9de9248SMarcel Holtmann 		memcpy(conn->features, ev->features, 8);
1194a9de9248SMarcel Holtmann 
1195ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
1196ccd556feSJohan Hedberg 		goto unlock;
1197ccd556feSJohan Hedberg 
1198ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
1199769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
1200769be974SMarcel Holtmann 		cp.handle = ev->handle;
1201769be974SMarcel Holtmann 		cp.page = 0x01;
1202ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
1203769be974SMarcel Holtmann 							sizeof(cp), &cp);
1204392599b9SJohan Hedberg 		goto unlock;
1205392599b9SJohan Hedberg 	}
1206392599b9SJohan Hedberg 
1207392599b9SJohan Hedberg 	if (!ev->status)
1208392599b9SJohan Hedberg 		auth_requested = hci_request_outgoing_auth(hdev, conn);
1209392599b9SJohan Hedberg 	else
1210392599b9SJohan Hedberg 		auth_requested = 0;
1211392599b9SJohan Hedberg 
1212392599b9SJohan Hedberg 	if (!auth_requested) {
1213769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
1214769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1215769be974SMarcel Holtmann 		hci_conn_put(conn);
1216769be974SMarcel Holtmann 	}
1217769be974SMarcel Holtmann 
1218ccd556feSJohan Hedberg unlock:
1219a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1220a9de9248SMarcel Holtmann }
1221a9de9248SMarcel Holtmann 
1222a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
1223a9de9248SMarcel Holtmann {
1224a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1225a9de9248SMarcel Holtmann }
1226a9de9248SMarcel Holtmann 
1227a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1228a9de9248SMarcel Holtmann {
1229a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1230a9de9248SMarcel Holtmann }
1231a9de9248SMarcel Holtmann 
1232a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1233a9de9248SMarcel Holtmann {
1234a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
1235a9de9248SMarcel Holtmann 	__u16 opcode;
1236a9de9248SMarcel Holtmann 
1237a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
1238a9de9248SMarcel Holtmann 
1239a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
1240a9de9248SMarcel Holtmann 
1241a9de9248SMarcel Holtmann 	switch (opcode) {
1242a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
1243a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
1244a9de9248SMarcel Holtmann 		break;
1245a9de9248SMarcel Holtmann 
1246a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
1247a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
1248a9de9248SMarcel Holtmann 		break;
1249a9de9248SMarcel Holtmann 
1250a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
1251a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
1252a9de9248SMarcel Holtmann 		break;
1253a9de9248SMarcel Holtmann 
1254a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
1255a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
1256a9de9248SMarcel Holtmann 		break;
1257a9de9248SMarcel Holtmann 
1258e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
1259e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
1260e4e8e37cSMarcel Holtmann 		break;
1261e4e8e37cSMarcel Holtmann 
1262a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
1263a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
1264a9de9248SMarcel Holtmann 		break;
1265a9de9248SMarcel Holtmann 
1266e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
1267e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
1268e4e8e37cSMarcel Holtmann 		break;
1269e4e8e37cSMarcel Holtmann 
1270e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
1271e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
1272e4e8e37cSMarcel Holtmann 		break;
1273e4e8e37cSMarcel Holtmann 
1274a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
1275a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
1276a9de9248SMarcel Holtmann 		break;
1277a9de9248SMarcel Holtmann 
1278a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
1279a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
1280a9de9248SMarcel Holtmann 		break;
1281a9de9248SMarcel Holtmann 
1282a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
1283a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
1284a9de9248SMarcel Holtmann 		break;
1285a9de9248SMarcel Holtmann 
1286a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
1287a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
1288a9de9248SMarcel Holtmann 		break;
1289a9de9248SMarcel Holtmann 
1290a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
1291a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
1292a9de9248SMarcel Holtmann 		break;
1293a9de9248SMarcel Holtmann 
1294a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
1295a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
1296a9de9248SMarcel Holtmann 		break;
1297a9de9248SMarcel Holtmann 
1298a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
1299a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
1300a9de9248SMarcel Holtmann 		break;
1301a9de9248SMarcel Holtmann 
1302a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
1303a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
1304a9de9248SMarcel Holtmann 		break;
1305a9de9248SMarcel Holtmann 
1306a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
1307a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
1308a9de9248SMarcel Holtmann 		break;
1309a9de9248SMarcel Holtmann 
1310a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
1311a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
1312a9de9248SMarcel Holtmann 		break;
1313a9de9248SMarcel Holtmann 
1314a9de9248SMarcel Holtmann 	case HCI_OP_HOST_BUFFER_SIZE:
1315a9de9248SMarcel Holtmann 		hci_cc_host_buffer_size(hdev, skb);
1316a9de9248SMarcel Holtmann 		break;
1317a9de9248SMarcel Holtmann 
1318333140b5SMarcel Holtmann 	case HCI_OP_READ_SSP_MODE:
1319333140b5SMarcel Holtmann 		hci_cc_read_ssp_mode(hdev, skb);
1320333140b5SMarcel Holtmann 		break;
1321333140b5SMarcel Holtmann 
1322333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
1323333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
1324333140b5SMarcel Holtmann 		break;
1325333140b5SMarcel Holtmann 
1326a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
1327a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
1328a9de9248SMarcel Holtmann 		break;
1329a9de9248SMarcel Holtmann 
1330a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
1331a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
1332a9de9248SMarcel Holtmann 		break;
1333a9de9248SMarcel Holtmann 
1334a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
1335a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
1336a9de9248SMarcel Holtmann 		break;
1337a9de9248SMarcel Holtmann 
1338a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
1339a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
1340a9de9248SMarcel Holtmann 		break;
1341a9de9248SMarcel Holtmann 
1342a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
1343a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
1344a9de9248SMarcel Holtmann 		break;
1345a9de9248SMarcel Holtmann 
1346a9de9248SMarcel Holtmann 	default:
1347a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
1348a9de9248SMarcel Holtmann 		break;
1349a9de9248SMarcel Holtmann 	}
1350a9de9248SMarcel Holtmann 
1351a9de9248SMarcel Holtmann 	if (ev->ncmd) {
1352a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
1353a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
1354c78ae283SMarcel Holtmann 			tasklet_schedule(&hdev->cmd_task);
1355a9de9248SMarcel Holtmann 	}
1356a9de9248SMarcel Holtmann }
1357a9de9248SMarcel Holtmann 
1358a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
1359a9de9248SMarcel Holtmann {
1360a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
1361a9de9248SMarcel Holtmann 	__u16 opcode;
1362a9de9248SMarcel Holtmann 
1363a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
1364a9de9248SMarcel Holtmann 
1365a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
1366a9de9248SMarcel Holtmann 
1367a9de9248SMarcel Holtmann 	switch (opcode) {
1368a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
1369a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
1370a9de9248SMarcel Holtmann 		break;
1371a9de9248SMarcel Holtmann 
1372a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
1373a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
1374a9de9248SMarcel Holtmann 		break;
1375a9de9248SMarcel Holtmann 
1376a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
1377a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
1378a9de9248SMarcel Holtmann 		break;
1379a9de9248SMarcel Holtmann 
1380f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
1381f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
1382f8558555SMarcel Holtmann 		break;
1383f8558555SMarcel Holtmann 
1384f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
1385f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
1386f8558555SMarcel Holtmann 		break;
1387f8558555SMarcel Holtmann 
1388a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
1389a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
1390a9de9248SMarcel Holtmann 		break;
1391a9de9248SMarcel Holtmann 
1392769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
1393769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
1394769be974SMarcel Holtmann 		break;
1395769be974SMarcel Holtmann 
1396769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
1397769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
1398769be974SMarcel Holtmann 		break;
1399769be974SMarcel Holtmann 
1400a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
1401a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
1402a9de9248SMarcel Holtmann 		break;
1403a9de9248SMarcel Holtmann 
1404a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
1405a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
1406a9de9248SMarcel Holtmann 		break;
1407a9de9248SMarcel Holtmann 
1408a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
1409a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
1410a9de9248SMarcel Holtmann 		break;
1411a9de9248SMarcel Holtmann 
1412a9de9248SMarcel Holtmann 	default:
1413a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
1414a9de9248SMarcel Holtmann 		break;
1415a9de9248SMarcel Holtmann 	}
1416a9de9248SMarcel Holtmann 
1417a9de9248SMarcel Holtmann 	if (ev->ncmd) {
1418a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
1419a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
1420c78ae283SMarcel Holtmann 			tasklet_schedule(&hdev->cmd_task);
1421a9de9248SMarcel Holtmann 	}
1422a9de9248SMarcel Holtmann }
1423a9de9248SMarcel Holtmann 
1424a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1425a9de9248SMarcel Holtmann {
1426a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
1427a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1428a9de9248SMarcel Holtmann 
1429a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1430a9de9248SMarcel Holtmann 
1431a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1432a9de9248SMarcel Holtmann 
1433a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1434a9de9248SMarcel Holtmann 	if (conn) {
1435a9de9248SMarcel Holtmann 		if (!ev->status) {
1436a9de9248SMarcel Holtmann 			if (ev->role)
1437a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
1438a9de9248SMarcel Holtmann 			else
1439a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
1440a9de9248SMarcel Holtmann 		}
1441a9de9248SMarcel Holtmann 
1442a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend);
1443a9de9248SMarcel Holtmann 
1444a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
1445a9de9248SMarcel Holtmann 	}
1446a9de9248SMarcel Holtmann 
1447a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1448a9de9248SMarcel Holtmann }
1449a9de9248SMarcel Holtmann 
14501da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
14511da177e4SLinus Torvalds {
1452a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
14531ebb9252SMarcel Holtmann 	__le16 *ptr;
14541da177e4SLinus Torvalds 	int i;
14551da177e4SLinus Torvalds 
14561da177e4SLinus Torvalds 	skb_pull(skb, sizeof(*ev));
14571da177e4SLinus Torvalds 
14581da177e4SLinus Torvalds 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
14591da177e4SLinus Torvalds 
14601da177e4SLinus Torvalds 	if (skb->len < ev->num_hndl * 4) {
14611da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
14621da177e4SLinus Torvalds 		return;
14631da177e4SLinus Torvalds 	}
14641da177e4SLinus Torvalds 
14651da177e4SLinus Torvalds 	tasklet_disable(&hdev->tx_task);
14661da177e4SLinus Torvalds 
14671ebb9252SMarcel Holtmann 	for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) {
14681da177e4SLinus Torvalds 		struct hci_conn *conn;
14691da177e4SLinus Torvalds 		__u16  handle, count;
14701da177e4SLinus Torvalds 
147183985319SHarvey Harrison 		handle = get_unaligned_le16(ptr++);
147283985319SHarvey Harrison 		count  = get_unaligned_le16(ptr++);
14731da177e4SLinus Torvalds 
14741da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
14751da177e4SLinus Torvalds 		if (conn) {
14761da177e4SLinus Torvalds 			conn->sent -= count;
14771da177e4SLinus Torvalds 
14785b7f9909SMarcel Holtmann 			if (conn->type == ACL_LINK) {
14791da177e4SLinus Torvalds 				if ((hdev->acl_cnt += count) > hdev->acl_pkts)
14801da177e4SLinus Torvalds 					hdev->acl_cnt = hdev->acl_pkts;
14815b7f9909SMarcel Holtmann 			} else {
14825b7f9909SMarcel Holtmann 				if ((hdev->sco_cnt += count) > hdev->sco_pkts)
14835b7f9909SMarcel Holtmann 					hdev->sco_cnt = hdev->sco_pkts;
14841da177e4SLinus Torvalds 			}
14851da177e4SLinus Torvalds 		}
14861da177e4SLinus Torvalds 	}
1487a9de9248SMarcel Holtmann 
1488c78ae283SMarcel Holtmann 	tasklet_schedule(&hdev->tx_task);
14891da177e4SLinus Torvalds 
14901da177e4SLinus Torvalds 	tasklet_enable(&hdev->tx_task);
14911da177e4SLinus Torvalds }
14921da177e4SLinus Torvalds 
149304837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
14941da177e4SLinus Torvalds {
1495a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
149604837f64SMarcel Holtmann 	struct hci_conn *conn;
14971da177e4SLinus Torvalds 
14981da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
14991da177e4SLinus Torvalds 
15001da177e4SLinus Torvalds 	hci_dev_lock(hdev);
15011da177e4SLinus Torvalds 
150204837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
150304837f64SMarcel Holtmann 	if (conn) {
150404837f64SMarcel Holtmann 		conn->mode = ev->mode;
150504837f64SMarcel Holtmann 		conn->interval = __le16_to_cpu(ev->interval);
150604837f64SMarcel Holtmann 
150704837f64SMarcel Holtmann 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
150804837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
150904837f64SMarcel Holtmann 				conn->power_save = 1;
151004837f64SMarcel Holtmann 			else
151104837f64SMarcel Holtmann 				conn->power_save = 0;
151204837f64SMarcel Holtmann 		}
1513e73439d8SMarcel Holtmann 
1514e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1515e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
151604837f64SMarcel Holtmann 	}
151704837f64SMarcel Holtmann 
151804837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
151904837f64SMarcel Holtmann }
152004837f64SMarcel Holtmann 
15211da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
15221da177e4SLinus Torvalds {
1523052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
1524052b30b0SMarcel Holtmann 	struct hci_conn *conn;
1525052b30b0SMarcel Holtmann 
1526a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1527052b30b0SMarcel Holtmann 
1528052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
1529052b30b0SMarcel Holtmann 
1530052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
15313d7a9d1cSMarcel Holtmann 	if (conn && conn->state == BT_CONNECTED) {
1532052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
1533052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
1534052b30b0SMarcel Holtmann 		hci_conn_put(conn);
1535052b30b0SMarcel Holtmann 	}
1536052b30b0SMarcel Holtmann 
1537052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
15381da177e4SLinus Torvalds }
15391da177e4SLinus Torvalds 
15401da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
15411da177e4SLinus Torvalds {
1542a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
15431da177e4SLinus Torvalds }
15441da177e4SLinus Torvalds 
15451da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
15461da177e4SLinus Torvalds {
1547052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
1548052b30b0SMarcel Holtmann 	struct hci_conn *conn;
1549052b30b0SMarcel Holtmann 
1550a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1551052b30b0SMarcel Holtmann 
1552052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
1553052b30b0SMarcel Holtmann 
1554052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1555052b30b0SMarcel Holtmann 	if (conn) {
1556052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
1557052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1558052b30b0SMarcel Holtmann 		hci_conn_put(conn);
1559052b30b0SMarcel Holtmann 	}
1560052b30b0SMarcel Holtmann 
1561052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
15621da177e4SLinus Torvalds }
15631da177e4SLinus Torvalds 
156404837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
156504837f64SMarcel Holtmann {
1566a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
156704837f64SMarcel Holtmann 	struct hci_conn *conn;
156804837f64SMarcel Holtmann 
156904837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
157004837f64SMarcel Holtmann 
157104837f64SMarcel Holtmann 	hci_dev_lock(hdev);
157204837f64SMarcel Holtmann 
157304837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
15741da177e4SLinus Torvalds 	if (conn && !ev->status) {
15751da177e4SLinus Torvalds 		struct inquiry_entry *ie;
15761da177e4SLinus Torvalds 
15771da177e4SLinus Torvalds 		if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst))) {
15781da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
15791da177e4SLinus Torvalds 			ie->timestamp = jiffies;
15801da177e4SLinus Torvalds 		}
15811da177e4SLinus Torvalds 	}
15821da177e4SLinus Torvalds 
15831da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
15841da177e4SLinus Torvalds }
15851da177e4SLinus Torvalds 
1586a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1587a8746417SMarcel Holtmann {
1588a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
1589a8746417SMarcel Holtmann 	struct hci_conn *conn;
1590a8746417SMarcel Holtmann 
1591a8746417SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1592a8746417SMarcel Holtmann 
1593a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
1594a8746417SMarcel Holtmann 
1595a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1596a8746417SMarcel Holtmann 	if (conn && !ev->status)
1597a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
1598a8746417SMarcel Holtmann 
1599a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
1600a8746417SMarcel Holtmann }
1601a8746417SMarcel Holtmann 
160285a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
160385a1e930SMarcel Holtmann {
1604a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
160585a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
160685a1e930SMarcel Holtmann 
160785a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
160885a1e930SMarcel Holtmann 
160985a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
161085a1e930SMarcel Holtmann 
161185a1e930SMarcel Holtmann 	if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr))) {
161285a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
161385a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
161485a1e930SMarcel Holtmann 	}
161585a1e930SMarcel Holtmann 
161685a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
161785a1e930SMarcel Holtmann }
161885a1e930SMarcel Holtmann 
1619a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
1620a9de9248SMarcel Holtmann {
1621a9de9248SMarcel Holtmann 	struct inquiry_data data;
1622a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
1623a9de9248SMarcel Holtmann 
1624a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1625a9de9248SMarcel Holtmann 
1626a9de9248SMarcel Holtmann 	if (!num_rsp)
1627a9de9248SMarcel Holtmann 		return;
1628a9de9248SMarcel Holtmann 
1629a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1630a9de9248SMarcel Holtmann 
1631a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
1632a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi_and_pscan_mode *info = (void *) (skb->data + 1);
1633a9de9248SMarcel Holtmann 
1634a9de9248SMarcel Holtmann 		for (; num_rsp; num_rsp--) {
1635a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
1636a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
1637a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
1638a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
1639a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
1640a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
1641a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
164241a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
1643a9de9248SMarcel Holtmann 			info++;
1644a9de9248SMarcel Holtmann 			hci_inquiry_cache_update(hdev, &data);
1645a9de9248SMarcel Holtmann 		}
1646a9de9248SMarcel Holtmann 	} else {
1647a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
1648a9de9248SMarcel Holtmann 
1649a9de9248SMarcel Holtmann 		for (; num_rsp; num_rsp--) {
1650a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
1651a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
1652a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
1653a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
1654a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
1655a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
1656a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
165741a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
1658a9de9248SMarcel Holtmann 			info++;
1659a9de9248SMarcel Holtmann 			hci_inquiry_cache_update(hdev, &data);
1660a9de9248SMarcel Holtmann 		}
1661a9de9248SMarcel Holtmann 	}
1662a9de9248SMarcel Holtmann 
1663a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1664a9de9248SMarcel Holtmann }
1665a9de9248SMarcel Holtmann 
1666a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
1667a9de9248SMarcel Holtmann {
166841a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
166941a96212SMarcel Holtmann 	struct hci_conn *conn;
1670392599b9SJohan Hedberg 	int auth_requested;
167141a96212SMarcel Holtmann 
1672a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
167341a96212SMarcel Holtmann 
167441a96212SMarcel Holtmann 	hci_dev_lock(hdev);
167541a96212SMarcel Holtmann 
167641a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1677ccd556feSJohan Hedberg 	if (!conn)
1678ccd556feSJohan Hedberg 		goto unlock;
1679ccd556feSJohan Hedberg 
1680769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
168141a96212SMarcel Holtmann 		struct inquiry_entry *ie;
168241a96212SMarcel Holtmann 
168341a96212SMarcel Holtmann 		if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst)))
168441a96212SMarcel Holtmann 			ie->data.ssp_mode = (ev->features[0] & 0x01);
168541a96212SMarcel Holtmann 
168641a96212SMarcel Holtmann 		conn->ssp_mode = (ev->features[0] & 0x01);
168741a96212SMarcel Holtmann 	}
168841a96212SMarcel Holtmann 
1689ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
1690ccd556feSJohan Hedberg 		goto unlock;
1691ccd556feSJohan Hedberg 
1692392599b9SJohan Hedberg 	if (!ev->status)
1693392599b9SJohan Hedberg 		auth_requested = hci_request_outgoing_auth(hdev, conn);
1694392599b9SJohan Hedberg 	else
1695392599b9SJohan Hedberg 		auth_requested = 0;
1696392599b9SJohan Hedberg 
1697392599b9SJohan Hedberg 	if (!auth_requested) {
1698769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
1699769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1700769be974SMarcel Holtmann 		hci_conn_put(conn);
1701769be974SMarcel Holtmann 	}
1702769be974SMarcel Holtmann 
1703ccd556feSJohan Hedberg unlock:
170441a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
1705a9de9248SMarcel Holtmann }
1706a9de9248SMarcel Holtmann 
1707a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1708a9de9248SMarcel Holtmann {
1709b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
1710b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
1711b6a0dc82SMarcel Holtmann 
1712b6a0dc82SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1713b6a0dc82SMarcel Holtmann 
1714b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1715b6a0dc82SMarcel Holtmann 
1716b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
17179dc0a3afSMarcel Holtmann 	if (!conn) {
17189dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
17199dc0a3afSMarcel Holtmann 			goto unlock;
17209dc0a3afSMarcel Holtmann 
17219dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1722b6a0dc82SMarcel Holtmann 		if (!conn)
1723b6a0dc82SMarcel Holtmann 			goto unlock;
1724b6a0dc82SMarcel Holtmann 
17259dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
17269dc0a3afSMarcel Holtmann 	}
17279dc0a3afSMarcel Holtmann 
1728732547f9SMarcel Holtmann 	switch (ev->status) {
1729732547f9SMarcel Holtmann 	case 0x00:
1730732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1731732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
1732732547f9SMarcel Holtmann 
17339eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
1734732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
1735732547f9SMarcel Holtmann 		break;
1736732547f9SMarcel Holtmann 
1737705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
1738732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
17391038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
1740732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
1741732547f9SMarcel Holtmann 		if (conn->out && conn->attempt < 2) {
1742efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
1743efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
1744efc7688bSMarcel Holtmann 			hci_setup_sync(conn, conn->link->handle);
1745efc7688bSMarcel Holtmann 			goto unlock;
1746efc7688bSMarcel Holtmann 		}
1747732547f9SMarcel Holtmann 		/* fall through */
1748efc7688bSMarcel Holtmann 
1749732547f9SMarcel Holtmann 	default:
1750b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
1751732547f9SMarcel Holtmann 		break;
1752732547f9SMarcel Holtmann 	}
1753b6a0dc82SMarcel Holtmann 
1754b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
1755b6a0dc82SMarcel Holtmann 	if (ev->status)
1756b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
1757b6a0dc82SMarcel Holtmann 
1758b6a0dc82SMarcel Holtmann unlock:
1759b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1760a9de9248SMarcel Holtmann }
1761a9de9248SMarcel Holtmann 
1762a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
1763a9de9248SMarcel Holtmann {
1764a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1765a9de9248SMarcel Holtmann }
1766a9de9248SMarcel Holtmann 
176704837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
176804837f64SMarcel Holtmann {
1769a9de9248SMarcel Holtmann 	struct hci_ev_sniff_subrate *ev = (void *) skb->data;
177004837f64SMarcel Holtmann 	struct hci_conn *conn;
177104837f64SMarcel Holtmann 
177204837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
177304837f64SMarcel Holtmann 
177404837f64SMarcel Holtmann 	hci_dev_lock(hdev);
177504837f64SMarcel Holtmann 
177604837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
177704837f64SMarcel Holtmann 	if (conn) {
177804837f64SMarcel Holtmann 	}
177904837f64SMarcel Holtmann 
178004837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
178104837f64SMarcel Holtmann }
178204837f64SMarcel Holtmann 
1783a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
1784a9de9248SMarcel Holtmann {
1785a9de9248SMarcel Holtmann 	struct inquiry_data data;
1786a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
1787a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
1788a9de9248SMarcel Holtmann 
1789a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1790a9de9248SMarcel Holtmann 
1791a9de9248SMarcel Holtmann 	if (!num_rsp)
1792a9de9248SMarcel Holtmann 		return;
1793a9de9248SMarcel Holtmann 
1794a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1795a9de9248SMarcel Holtmann 
1796a9de9248SMarcel Holtmann 	for (; num_rsp; num_rsp--) {
1797a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
1798a9de9248SMarcel Holtmann 		data.pscan_rep_mode     = info->pscan_rep_mode;
1799a9de9248SMarcel Holtmann 		data.pscan_period_mode  = info->pscan_period_mode;
1800a9de9248SMarcel Holtmann 		data.pscan_mode         = 0x00;
1801a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
1802a9de9248SMarcel Holtmann 		data.clock_offset       = info->clock_offset;
1803a9de9248SMarcel Holtmann 		data.rssi               = info->rssi;
180441a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
1805a9de9248SMarcel Holtmann 		info++;
1806a9de9248SMarcel Holtmann 		hci_inquiry_cache_update(hdev, &data);
1807a9de9248SMarcel Holtmann 	}
1808a9de9248SMarcel Holtmann 
1809a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1810a9de9248SMarcel Holtmann }
1811a9de9248SMarcel Holtmann 
18120493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
18130493684eSMarcel Holtmann {
18140493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
18150493684eSMarcel Holtmann 	struct hci_conn *conn;
18160493684eSMarcel Holtmann 
18170493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
18180493684eSMarcel Holtmann 
18190493684eSMarcel Holtmann 	hci_dev_lock(hdev);
18200493684eSMarcel Holtmann 
18210493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
18220493684eSMarcel Holtmann 	if (conn)
18230493684eSMarcel Holtmann 		hci_conn_hold(conn);
18240493684eSMarcel Holtmann 
18250493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
18260493684eSMarcel Holtmann }
18270493684eSMarcel Holtmann 
18280493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
18290493684eSMarcel Holtmann {
18300493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
18310493684eSMarcel Holtmann 	struct hci_conn *conn;
18320493684eSMarcel Holtmann 
18330493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
18340493684eSMarcel Holtmann 
18350493684eSMarcel Holtmann 	hci_dev_lock(hdev);
18360493684eSMarcel Holtmann 
18370493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
18380493684eSMarcel Holtmann 	if (conn)
18390493684eSMarcel Holtmann 		hci_conn_put(conn);
18400493684eSMarcel Holtmann 
18410493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
18420493684eSMarcel Holtmann }
18430493684eSMarcel Holtmann 
184441a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
184541a96212SMarcel Holtmann {
184641a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
184741a96212SMarcel Holtmann 	struct inquiry_entry *ie;
184841a96212SMarcel Holtmann 
184941a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
185041a96212SMarcel Holtmann 
185141a96212SMarcel Holtmann 	hci_dev_lock(hdev);
185241a96212SMarcel Holtmann 
185341a96212SMarcel Holtmann 	if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr)))
185441a96212SMarcel Holtmann 		ie->data.ssp_mode = (ev->features[0] & 0x01);
185541a96212SMarcel Holtmann 
185641a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
185741a96212SMarcel Holtmann }
185841a96212SMarcel Holtmann 
18591da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
18601da177e4SLinus Torvalds {
1861a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
1862a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
18631da177e4SLinus Torvalds 
18641da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
18651da177e4SLinus Torvalds 
1866a9de9248SMarcel Holtmann 	switch (event) {
18671da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
18681da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
18691da177e4SLinus Torvalds 		break;
18701da177e4SLinus Torvalds 
18711da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
18721da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
18731da177e4SLinus Torvalds 		break;
18741da177e4SLinus Torvalds 
1875a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
1876a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
187721d9e30eSMarcel Holtmann 		break;
187821d9e30eSMarcel Holtmann 
18791da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
18801da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
18811da177e4SLinus Torvalds 		break;
18821da177e4SLinus Torvalds 
18831da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
18841da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
18851da177e4SLinus Torvalds 		break;
18861da177e4SLinus Torvalds 
18871da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
18881da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
18891da177e4SLinus Torvalds 		break;
18901da177e4SLinus Torvalds 
1891a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
1892a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
1893a9de9248SMarcel Holtmann 		break;
1894a9de9248SMarcel Holtmann 
18951da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
18961da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
18971da177e4SLinus Torvalds 		break;
18981da177e4SLinus Torvalds 
1899a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
1900a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
1901a9de9248SMarcel Holtmann 		break;
1902a9de9248SMarcel Holtmann 
1903a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
1904a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
1905a9de9248SMarcel Holtmann 		break;
1906a9de9248SMarcel Holtmann 
1907a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_VERSION:
1908a9de9248SMarcel Holtmann 		hci_remote_version_evt(hdev, skb);
1909a9de9248SMarcel Holtmann 		break;
1910a9de9248SMarcel Holtmann 
1911a9de9248SMarcel Holtmann 	case HCI_EV_QOS_SETUP_COMPLETE:
1912a9de9248SMarcel Holtmann 		hci_qos_setup_complete_evt(hdev, skb);
1913a9de9248SMarcel Holtmann 		break;
1914a9de9248SMarcel Holtmann 
1915a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
1916a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
1917a9de9248SMarcel Holtmann 		break;
1918a9de9248SMarcel Holtmann 
1919a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
1920a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
1921a9de9248SMarcel Holtmann 		break;
1922a9de9248SMarcel Holtmann 
1923a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
1924a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
1925a9de9248SMarcel Holtmann 		break;
1926a9de9248SMarcel Holtmann 
1927a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
1928a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
1929a9de9248SMarcel Holtmann 		break;
1930a9de9248SMarcel Holtmann 
1931a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
1932a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
19331da177e4SLinus Torvalds 		break;
19341da177e4SLinus Torvalds 
19351da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
19361da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
19371da177e4SLinus Torvalds 		break;
19381da177e4SLinus Torvalds 
19391da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
19401da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
19411da177e4SLinus Torvalds 		break;
19421da177e4SLinus Torvalds 
19431da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
19441da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
19451da177e4SLinus Torvalds 		break;
19461da177e4SLinus Torvalds 
19471da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
19481da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
19491da177e4SLinus Torvalds 		break;
19501da177e4SLinus Torvalds 
1951a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
1952a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
1953a8746417SMarcel Holtmann 		break;
1954a8746417SMarcel Holtmann 
195585a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
195685a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
195785a1e930SMarcel Holtmann 		break;
195885a1e930SMarcel Holtmann 
1959a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
1960a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
1961a9de9248SMarcel Holtmann 		break;
1962a9de9248SMarcel Holtmann 
1963a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
1964a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
1965a9de9248SMarcel Holtmann 		break;
1966a9de9248SMarcel Holtmann 
1967a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
1968a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
1969a9de9248SMarcel Holtmann 		break;
1970a9de9248SMarcel Holtmann 
1971a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_CHANGED:
1972a9de9248SMarcel Holtmann 		hci_sync_conn_changed_evt(hdev, skb);
1973a9de9248SMarcel Holtmann 		break;
1974a9de9248SMarcel Holtmann 
197504837f64SMarcel Holtmann 	case HCI_EV_SNIFF_SUBRATE:
197604837f64SMarcel Holtmann 		hci_sniff_subrate_evt(hdev, skb);
197704837f64SMarcel Holtmann 		break;
197804837f64SMarcel Holtmann 
1979a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
1980a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
19811da177e4SLinus Torvalds 		break;
19821da177e4SLinus Torvalds 
19830493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
19840493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
19850493684eSMarcel Holtmann 		break;
19860493684eSMarcel Holtmann 
19870493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
19880493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
19890493684eSMarcel Holtmann 		break;
19900493684eSMarcel Holtmann 
199141a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
199241a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
199341a96212SMarcel Holtmann 		break;
199441a96212SMarcel Holtmann 
19951da177e4SLinus Torvalds 	default:
1996a9de9248SMarcel Holtmann 		BT_DBG("%s event 0x%x", hdev->name, event);
19971da177e4SLinus Torvalds 		break;
19981da177e4SLinus Torvalds 	}
19991da177e4SLinus Torvalds 
20001da177e4SLinus Torvalds 	kfree_skb(skb);
20011da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
20021da177e4SLinus Torvalds }
20031da177e4SLinus Torvalds 
20041da177e4SLinus Torvalds /* Generate internal stack event */
20051da177e4SLinus Torvalds void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
20061da177e4SLinus Torvalds {
20071da177e4SLinus Torvalds 	struct hci_event_hdr *hdr;
20081da177e4SLinus Torvalds 	struct hci_ev_stack_internal *ev;
20091da177e4SLinus Torvalds 	struct sk_buff *skb;
20101da177e4SLinus Torvalds 
20111da177e4SLinus Torvalds 	skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC);
20121da177e4SLinus Torvalds 	if (!skb)
20131da177e4SLinus Torvalds 		return;
20141da177e4SLinus Torvalds 
20151da177e4SLinus Torvalds 	hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE);
20161da177e4SLinus Torvalds 	hdr->evt  = HCI_EV_STACK_INTERNAL;
20171da177e4SLinus Torvalds 	hdr->plen = sizeof(*ev) + dlen;
20181da177e4SLinus Torvalds 
20191da177e4SLinus Torvalds 	ev  = (void *) skb_put(skb, sizeof(*ev) + dlen);
20201da177e4SLinus Torvalds 	ev->type = type;
20211da177e4SLinus Torvalds 	memcpy(ev->data, data, dlen);
20221da177e4SLinus Torvalds 
2023576c7d85SMarcel Holtmann 	bt_cb(skb)->incoming = 1;
2024a61bbcf2SPatrick McHardy 	__net_timestamp(skb);
2025576c7d85SMarcel Holtmann 
20260d48d939SMarcel Holtmann 	bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
20271da177e4SLinus Torvalds 	skb->dev = (void *) hdev;
20281da177e4SLinus Torvalds 	hci_send_to_sock(hdev, skb);
20291da177e4SLinus Torvalds 	kfree_skb(skb);
20301da177e4SLinus Torvalds }
2031