xref: /openbmc/linux/net/bluetooth/hci_event.c (revision 8962ee74)
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>
4270f23020SAndrei Emeltchenko #include <linux/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 
6123bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, 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 
17723bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, 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 
18623bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_RESET, 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 
23823bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, 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 
26123bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, 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);
2779fbcbb45SJohan Hedberg 		int old_pscan, old_iscan;
278a9de9248SMarcel Holtmann 
2799fbcbb45SJohan Hedberg 		old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
2809fbcbb45SJohan Hedberg 		old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
281a9de9248SMarcel Holtmann 
28273f22f62SJohan Hedberg 		if (param & SCAN_INQUIRY) {
2831da177e4SLinus Torvalds 			set_bit(HCI_ISCAN, &hdev->flags);
2849fbcbb45SJohan Hedberg 			if (!old_iscan)
28573f22f62SJohan Hedberg 				mgmt_discoverable(hdev->id, 1);
2869fbcbb45SJohan Hedberg 		} else if (old_iscan)
28773f22f62SJohan Hedberg 			mgmt_discoverable(hdev->id, 0);
2881da177e4SLinus Torvalds 
2899fbcbb45SJohan Hedberg 		if (param & SCAN_PAGE) {
2901da177e4SLinus Torvalds 			set_bit(HCI_PSCAN, &hdev->flags);
2919fbcbb45SJohan Hedberg 			if (!old_pscan)
2929fbcbb45SJohan Hedberg 				mgmt_connectable(hdev->id, 1);
2939fbcbb45SJohan Hedberg 		} else if (old_pscan)
2949fbcbb45SJohan Hedberg 			mgmt_connectable(hdev->id, 0);
2951da177e4SLinus Torvalds 	}
296a9de9248SMarcel Holtmann 
29723bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
2981da177e4SLinus Torvalds }
2991da177e4SLinus Torvalds 
300a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
301a9de9248SMarcel Holtmann {
302a9de9248SMarcel Holtmann 	struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
303a9de9248SMarcel Holtmann 
304a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
305a9de9248SMarcel Holtmann 
306a9de9248SMarcel Holtmann 	if (rp->status)
307a9de9248SMarcel Holtmann 		return;
308a9de9248SMarcel Holtmann 
309a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, rp->dev_class, 3);
310a9de9248SMarcel Holtmann 
311a9de9248SMarcel Holtmann 	BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
312a9de9248SMarcel Holtmann 		hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
313a9de9248SMarcel Holtmann }
314a9de9248SMarcel Holtmann 
315a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
316a9de9248SMarcel Holtmann {
317a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
318a9de9248SMarcel Holtmann 	void *sent;
319a9de9248SMarcel Holtmann 
320a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
321a9de9248SMarcel Holtmann 
322f383f275SMarcel Holtmann 	if (status)
323f383f275SMarcel Holtmann 		return;
324f383f275SMarcel Holtmann 
325a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
326a9de9248SMarcel Holtmann 	if (!sent)
327a9de9248SMarcel Holtmann 		return;
328a9de9248SMarcel Holtmann 
329a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, sent, 3);
330a9de9248SMarcel Holtmann }
331a9de9248SMarcel Holtmann 
332a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
333a9de9248SMarcel Holtmann {
334a9de9248SMarcel Holtmann 	struct hci_rp_read_voice_setting *rp = (void *) skb->data;
335a9de9248SMarcel Holtmann 	__u16 setting;
336a9de9248SMarcel Holtmann 
337a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
338a9de9248SMarcel Holtmann 
339a9de9248SMarcel Holtmann 	if (rp->status)
340a9de9248SMarcel Holtmann 		return;
341a9de9248SMarcel Holtmann 
342a9de9248SMarcel Holtmann 	setting = __le16_to_cpu(rp->voice_setting);
343a9de9248SMarcel Holtmann 
344a9de9248SMarcel Holtmann 	if (hdev->voice_setting == setting)
345a9de9248SMarcel Holtmann 		return;
346a9de9248SMarcel Holtmann 
347a9de9248SMarcel Holtmann 	hdev->voice_setting = setting;
348a9de9248SMarcel Holtmann 
349a9de9248SMarcel Holtmann 	BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
350a9de9248SMarcel Holtmann 
351a9de9248SMarcel Holtmann 	if (hdev->notify) {
352a9de9248SMarcel Holtmann 		tasklet_disable(&hdev->tx_task);
353a9de9248SMarcel Holtmann 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
354a9de9248SMarcel Holtmann 		tasklet_enable(&hdev->tx_task);
355a9de9248SMarcel Holtmann 	}
356a9de9248SMarcel Holtmann }
357a9de9248SMarcel Holtmann 
358a9de9248SMarcel Holtmann static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
359a9de9248SMarcel Holtmann {
360a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
361f383f275SMarcel Holtmann 	__u16 setting;
362a9de9248SMarcel Holtmann 	void *sent;
363a9de9248SMarcel Holtmann 
364a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
365a9de9248SMarcel Holtmann 
366f383f275SMarcel Holtmann 	if (status)
367f383f275SMarcel Holtmann 		return;
368f383f275SMarcel Holtmann 
369a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
370a9de9248SMarcel Holtmann 	if (!sent)
371a9de9248SMarcel Holtmann 		return;
372a9de9248SMarcel Holtmann 
373f383f275SMarcel Holtmann 	setting = get_unaligned_le16(sent);
3741da177e4SLinus Torvalds 
375f383f275SMarcel Holtmann 	if (hdev->voice_setting == setting)
376f383f275SMarcel Holtmann 		return;
377f383f275SMarcel Holtmann 
3781da177e4SLinus Torvalds 	hdev->voice_setting = setting;
3791da177e4SLinus Torvalds 
380a9de9248SMarcel Holtmann 	BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
3811da177e4SLinus Torvalds 
3821da177e4SLinus Torvalds 	if (hdev->notify) {
3831da177e4SLinus Torvalds 		tasklet_disable(&hdev->tx_task);
3841da177e4SLinus Torvalds 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
3851da177e4SLinus Torvalds 		tasklet_enable(&hdev->tx_task);
3861da177e4SLinus Torvalds 	}
3871da177e4SLinus Torvalds }
3881da177e4SLinus Torvalds 
389a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
3901da177e4SLinus Torvalds {
391a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
3921da177e4SLinus Torvalds 
393a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
3941da177e4SLinus Torvalds 
39523bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
3961143e5a6SMarcel Holtmann }
3971143e5a6SMarcel Holtmann 
398333140b5SMarcel Holtmann static void hci_cc_read_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
399333140b5SMarcel Holtmann {
400333140b5SMarcel Holtmann 	struct hci_rp_read_ssp_mode *rp = (void *) skb->data;
401333140b5SMarcel Holtmann 
402333140b5SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
403333140b5SMarcel Holtmann 
404333140b5SMarcel Holtmann 	if (rp->status)
405333140b5SMarcel Holtmann 		return;
406333140b5SMarcel Holtmann 
407333140b5SMarcel Holtmann 	hdev->ssp_mode = rp->mode;
408333140b5SMarcel Holtmann }
409333140b5SMarcel Holtmann 
410333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
411333140b5SMarcel Holtmann {
412333140b5SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
413333140b5SMarcel Holtmann 	void *sent;
414333140b5SMarcel Holtmann 
415333140b5SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
416333140b5SMarcel Holtmann 
417333140b5SMarcel Holtmann 	if (status)
418333140b5SMarcel Holtmann 		return;
419333140b5SMarcel Holtmann 
420333140b5SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
421333140b5SMarcel Holtmann 	if (!sent)
422333140b5SMarcel Holtmann 		return;
423333140b5SMarcel Holtmann 
424333140b5SMarcel Holtmann 	hdev->ssp_mode = *((__u8 *) sent);
425333140b5SMarcel Holtmann }
426333140b5SMarcel Holtmann 
427d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
428d5859e22SJohan Hedberg {
429d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
430d5859e22SJohan Hedberg 		return 2;
431d5859e22SJohan Hedberg 
432d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
433d5859e22SJohan Hedberg 		return 1;
434d5859e22SJohan Hedberg 
435d5859e22SJohan Hedberg 	if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
436d5859e22SJohan Hedberg 						hdev->lmp_subver == 0x0757)
437d5859e22SJohan Hedberg 		return 1;
438d5859e22SJohan Hedberg 
439d5859e22SJohan Hedberg 	if (hdev->manufacturer == 15) {
440d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
441d5859e22SJohan Hedberg 			return 1;
442d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
443d5859e22SJohan Hedberg 			return 1;
444d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
445d5859e22SJohan Hedberg 			return 1;
446d5859e22SJohan Hedberg 	}
447d5859e22SJohan Hedberg 
448d5859e22SJohan Hedberg 	if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
449d5859e22SJohan Hedberg 						hdev->lmp_subver == 0x1805)
450d5859e22SJohan Hedberg 		return 1;
451d5859e22SJohan Hedberg 
452d5859e22SJohan Hedberg 	return 0;
453d5859e22SJohan Hedberg }
454d5859e22SJohan Hedberg 
455d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev)
456d5859e22SJohan Hedberg {
457d5859e22SJohan Hedberg 	u8 mode;
458d5859e22SJohan Hedberg 
459d5859e22SJohan Hedberg 	mode = hci_get_inquiry_mode(hdev);
460d5859e22SJohan Hedberg 
461d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
462d5859e22SJohan Hedberg }
463d5859e22SJohan Hedberg 
464d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev)
465d5859e22SJohan Hedberg {
466d5859e22SJohan Hedberg 	/* The second byte is 0xff instead of 0x9f (two reserved bits
467d5859e22SJohan Hedberg 	 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
468d5859e22SJohan Hedberg 	 * command otherwise */
469d5859e22SJohan Hedberg 	u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
470d5859e22SJohan Hedberg 
471d5859e22SJohan Hedberg 	/* Events for 1.2 and newer controllers */
472d5859e22SJohan Hedberg 	if (hdev->lmp_ver > 1) {
473d5859e22SJohan Hedberg 		events[4] |= 0x01; /* Flow Specification Complete */
474d5859e22SJohan Hedberg 		events[4] |= 0x02; /* Inquiry Result with RSSI */
475d5859e22SJohan Hedberg 		events[4] |= 0x04; /* Read Remote Extended Features Complete */
476d5859e22SJohan Hedberg 		events[5] |= 0x08; /* Synchronous Connection Complete */
477d5859e22SJohan Hedberg 		events[5] |= 0x10; /* Synchronous Connection Changed */
478d5859e22SJohan Hedberg 	}
479d5859e22SJohan Hedberg 
480d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
481d5859e22SJohan Hedberg 		events[4] |= 0x04; /* Inquiry Result with RSSI */
482d5859e22SJohan Hedberg 
483d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_SNIFF_SUBR)
484d5859e22SJohan Hedberg 		events[5] |= 0x20; /* Sniff Subrating */
485d5859e22SJohan Hedberg 
486d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_PAUSE_ENC)
487d5859e22SJohan Hedberg 		events[5] |= 0x80; /* Encryption Key Refresh Complete */
488d5859e22SJohan Hedberg 
489d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
490d5859e22SJohan Hedberg 		events[5] |= 0x40; /* Extended Inquiry Result */
491d5859e22SJohan Hedberg 
492d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_NO_FLUSH)
493d5859e22SJohan Hedberg 		events[7] |= 0x01; /* Enhanced Flush Complete */
494d5859e22SJohan Hedberg 
495d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_LSTO)
496d5859e22SJohan Hedberg 		events[6] |= 0x80; /* Link Supervision Timeout Changed */
497d5859e22SJohan Hedberg 
498d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_SIMPLE_PAIR) {
499d5859e22SJohan Hedberg 		events[6] |= 0x01;	/* IO Capability Request */
500d5859e22SJohan Hedberg 		events[6] |= 0x02;	/* IO Capability Response */
501d5859e22SJohan Hedberg 		events[6] |= 0x04;	/* User Confirmation Request */
502d5859e22SJohan Hedberg 		events[6] |= 0x08;	/* User Passkey Request */
503d5859e22SJohan Hedberg 		events[6] |= 0x10;	/* Remote OOB Data Request */
504d5859e22SJohan Hedberg 		events[6] |= 0x20;	/* Simple Pairing Complete */
505d5859e22SJohan Hedberg 		events[7] |= 0x04;	/* User Passkey Notification */
506d5859e22SJohan Hedberg 		events[7] |= 0x08;	/* Keypress Notification */
507d5859e22SJohan Hedberg 		events[7] |= 0x10;	/* Remote Host Supported
508d5859e22SJohan Hedberg 					 * Features Notification */
509d5859e22SJohan Hedberg 	}
510d5859e22SJohan Hedberg 
511d5859e22SJohan Hedberg 	if (hdev->features[4] & LMP_LE)
512d5859e22SJohan Hedberg 		events[7] |= 0x20;	/* LE Meta-Event */
513d5859e22SJohan Hedberg 
514d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
515d5859e22SJohan Hedberg }
516d5859e22SJohan Hedberg 
517d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev)
518d5859e22SJohan Hedberg {
519d5859e22SJohan Hedberg 	hci_setup_event_mask(hdev);
520d5859e22SJohan Hedberg 
521d5859e22SJohan Hedberg 	if (hdev->lmp_ver > 1)
522d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
523d5859e22SJohan Hedberg 
524d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_SIMPLE_PAIR) {
525d5859e22SJohan Hedberg 		u8 mode = 0x01;
526d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
527d5859e22SJohan Hedberg 	}
528d5859e22SJohan Hedberg 
529d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
530d5859e22SJohan Hedberg 		hci_setup_inquiry_mode(hdev);
531d5859e22SJohan Hedberg 
532d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_INQ_TX_PWR)
533d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
534d5859e22SJohan Hedberg }
535d5859e22SJohan Hedberg 
536a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
537a9de9248SMarcel Holtmann {
538a9de9248SMarcel Holtmann 	struct hci_rp_read_local_version *rp = (void *) skb->data;
5391143e5a6SMarcel Holtmann 
540a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
5411143e5a6SMarcel Holtmann 
542a9de9248SMarcel Holtmann 	if (rp->status)
543a9de9248SMarcel Holtmann 		return;
5441143e5a6SMarcel Holtmann 
545a9de9248SMarcel Holtmann 	hdev->hci_ver = rp->hci_ver;
546e4e8e37cSMarcel Holtmann 	hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
547d5859e22SJohan Hedberg 	hdev->lmp_ver = rp->lmp_ver;
548e4e8e37cSMarcel Holtmann 	hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
549d5859e22SJohan Hedberg 	hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
5501da177e4SLinus Torvalds 
551a9de9248SMarcel Holtmann 	BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name,
552a9de9248SMarcel Holtmann 					hdev->manufacturer,
553a9de9248SMarcel Holtmann 					hdev->hci_ver, hdev->hci_rev);
554d5859e22SJohan Hedberg 
555d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags))
556d5859e22SJohan Hedberg 		hci_setup(hdev);
557d5859e22SJohan Hedberg }
558d5859e22SJohan Hedberg 
559d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev)
560d5859e22SJohan Hedberg {
561d5859e22SJohan Hedberg 	u16 link_policy = 0;
562d5859e22SJohan Hedberg 
563d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_RSWITCH)
564d5859e22SJohan Hedberg 		link_policy |= HCI_LP_RSWITCH;
565d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_HOLD)
566d5859e22SJohan Hedberg 		link_policy |= HCI_LP_HOLD;
567d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_SNIFF)
568d5859e22SJohan Hedberg 		link_policy |= HCI_LP_SNIFF;
569d5859e22SJohan Hedberg 	if (hdev->features[1] & LMP_PARK)
570d5859e22SJohan Hedberg 		link_policy |= HCI_LP_PARK;
571d5859e22SJohan Hedberg 
572d5859e22SJohan Hedberg 	link_policy = cpu_to_le16(link_policy);
573d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY,
574d5859e22SJohan Hedberg 					sizeof(link_policy), &link_policy);
5751da177e4SLinus Torvalds }
5761da177e4SLinus Torvalds 
577a9de9248SMarcel Holtmann static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb)
578a9de9248SMarcel Holtmann {
579a9de9248SMarcel Holtmann 	struct hci_rp_read_local_commands *rp = (void *) skb->data;
580a9de9248SMarcel Holtmann 
581a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
582a9de9248SMarcel Holtmann 
583a9de9248SMarcel Holtmann 	if (rp->status)
584d5859e22SJohan Hedberg 		goto done;
585a9de9248SMarcel Holtmann 
586a9de9248SMarcel Holtmann 	memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
587d5859e22SJohan Hedberg 
588d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
589d5859e22SJohan Hedberg 		hci_setup_link_policy(hdev);
590d5859e22SJohan Hedberg 
591d5859e22SJohan Hedberg done:
592d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
593a9de9248SMarcel Holtmann }
594a9de9248SMarcel Holtmann 
595a9de9248SMarcel Holtmann static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb)
596a9de9248SMarcel Holtmann {
597a9de9248SMarcel Holtmann 	struct hci_rp_read_local_features *rp = (void *) skb->data;
598a9de9248SMarcel Holtmann 
599a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
600a9de9248SMarcel Holtmann 
601a9de9248SMarcel Holtmann 	if (rp->status)
602a9de9248SMarcel Holtmann 		return;
603a9de9248SMarcel Holtmann 
604a9de9248SMarcel Holtmann 	memcpy(hdev->features, rp->features, 8);
6051da177e4SLinus Torvalds 
6061da177e4SLinus Torvalds 	/* Adjust default settings according to features
6071da177e4SLinus Torvalds 	 * supported by device. */
608a9de9248SMarcel Holtmann 
6091da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_3SLOT)
6101da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
6111da177e4SLinus Torvalds 
6121da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_5SLOT)
6131da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
6141da177e4SLinus Torvalds 
6155b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV2) {
6161da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV2);
6175b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV2);
6185b7f9909SMarcel Holtmann 	}
6191da177e4SLinus Torvalds 
6205b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV3) {
6211da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV3);
6225b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV3);
6235b7f9909SMarcel Holtmann 	}
6245b7f9909SMarcel Holtmann 
6255b7f9909SMarcel Holtmann 	if (hdev->features[3] & LMP_ESCO)
6265b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV3);
6275b7f9909SMarcel Holtmann 
6285b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV4)
6295b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV4);
6305b7f9909SMarcel Holtmann 
6315b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV5)
6325b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV5);
6331da177e4SLinus Torvalds 
634efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_2M)
635efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV3);
636efc7688bSMarcel Holtmann 
637efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_3M)
638efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_3EV3);
639efc7688bSMarcel Holtmann 
640efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_3S_ESCO)
641efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
642efc7688bSMarcel Holtmann 
643a9de9248SMarcel Holtmann 	BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
644a9de9248SMarcel Holtmann 					hdev->features[0], hdev->features[1],
645a9de9248SMarcel Holtmann 					hdev->features[2], hdev->features[3],
646a9de9248SMarcel Holtmann 					hdev->features[4], hdev->features[5],
647a9de9248SMarcel Holtmann 					hdev->features[6], hdev->features[7]);
6481da177e4SLinus Torvalds }
6491da177e4SLinus Torvalds 
650a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
651a9de9248SMarcel Holtmann {
652a9de9248SMarcel Holtmann 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
653a9de9248SMarcel Holtmann 
654a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
655a9de9248SMarcel Holtmann 
656a9de9248SMarcel Holtmann 	if (rp->status)
657a9de9248SMarcel Holtmann 		return;
658a9de9248SMarcel Holtmann 
659a9de9248SMarcel Holtmann 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
660a9de9248SMarcel Holtmann 	hdev->sco_mtu  = rp->sco_mtu;
661a9de9248SMarcel Holtmann 	hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
662a9de9248SMarcel Holtmann 	hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
663da1f5198SMarcel Holtmann 
664da1f5198SMarcel Holtmann 	if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
665da1f5198SMarcel Holtmann 		hdev->sco_mtu  = 64;
666da1f5198SMarcel Holtmann 		hdev->sco_pkts = 8;
667da1f5198SMarcel Holtmann 	}
668da1f5198SMarcel Holtmann 
669da1f5198SMarcel Holtmann 	hdev->acl_cnt = hdev->acl_pkts;
670da1f5198SMarcel Holtmann 	hdev->sco_cnt = hdev->sco_pkts;
6711da177e4SLinus Torvalds 
672a9de9248SMarcel Holtmann 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name,
673a9de9248SMarcel Holtmann 					hdev->acl_mtu, hdev->acl_pkts,
674a9de9248SMarcel Holtmann 					hdev->sco_mtu, hdev->sco_pkts);
6751da177e4SLinus Torvalds }
6761da177e4SLinus Torvalds 
677a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
678a9de9248SMarcel Holtmann {
679a9de9248SMarcel Holtmann 	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
6801da177e4SLinus Torvalds 
681a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
682a9de9248SMarcel Holtmann 
683a9de9248SMarcel Holtmann 	if (!rp->status)
684a9de9248SMarcel Holtmann 		bacpy(&hdev->bdaddr, &rp->bdaddr);
685a9de9248SMarcel Holtmann 
68623bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
68723bb5763SJohan Hedberg }
68823bb5763SJohan Hedberg 
68923bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
69023bb5763SJohan Hedberg {
69123bb5763SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
69223bb5763SJohan Hedberg 
69323bb5763SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
69423bb5763SJohan Hedberg 
69523bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
6961da177e4SLinus Torvalds }
6971da177e4SLinus Torvalds 
698b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
699b0916ea0SJohan Hedberg 							struct sk_buff *skb)
700b0916ea0SJohan Hedberg {
701b0916ea0SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
702b0916ea0SJohan Hedberg 
703b0916ea0SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
704b0916ea0SJohan Hedberg 
705b0916ea0SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
706b0916ea0SJohan Hedberg }
707b0916ea0SJohan Hedberg 
708d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
709d5859e22SJohan Hedberg {
710d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
711d5859e22SJohan Hedberg 
712d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
713d5859e22SJohan Hedberg 
714d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
715d5859e22SJohan Hedberg }
716d5859e22SJohan Hedberg 
717d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
718d5859e22SJohan Hedberg 							struct sk_buff *skb)
719d5859e22SJohan Hedberg {
720d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
721d5859e22SJohan Hedberg 
722d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
723d5859e22SJohan Hedberg 
724d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
725d5859e22SJohan Hedberg }
726d5859e22SJohan Hedberg 
727d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
728d5859e22SJohan Hedberg 							struct sk_buff *skb)
729d5859e22SJohan Hedberg {
730d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
731d5859e22SJohan Hedberg 
732d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
733d5859e22SJohan Hedberg 
734d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status);
735d5859e22SJohan Hedberg }
736d5859e22SJohan Hedberg 
737d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
738d5859e22SJohan Hedberg {
739d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
740d5859e22SJohan Hedberg 
741d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
742d5859e22SJohan Hedberg 
743d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
744d5859e22SJohan Hedberg }
745d5859e22SJohan Hedberg 
746a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
747a9de9248SMarcel Holtmann {
748a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
749a9de9248SMarcel Holtmann 
750a9de9248SMarcel Holtmann 	if (status) {
75123bb5763SJohan Hedberg 		hci_req_complete(hdev, HCI_OP_INQUIRY, status);
752a9de9248SMarcel Holtmann 
753a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
754a9de9248SMarcel Holtmann 	} else
755a9de9248SMarcel Holtmann 		set_bit(HCI_INQUIRY, &hdev->flags);
756a9de9248SMarcel Holtmann }
757a9de9248SMarcel Holtmann 
7581da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
7591da177e4SLinus Torvalds {
760a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
7611da177e4SLinus Torvalds 	struct hci_conn *conn;
7621da177e4SLinus Torvalds 
763a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
764a9de9248SMarcel Holtmann 
765a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
7661da177e4SLinus Torvalds 	if (!cp)
7671da177e4SLinus Torvalds 		return;
7681da177e4SLinus Torvalds 
7691da177e4SLinus Torvalds 	hci_dev_lock(hdev);
7701da177e4SLinus Torvalds 
7711da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
7721da177e4SLinus Torvalds 
773a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
7741da177e4SLinus Torvalds 
7751da177e4SLinus Torvalds 	if (status) {
7761da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
7774c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
7781da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
7791da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
7801da177e4SLinus Torvalds 				hci_conn_del(conn);
7814c67bc74SMarcel Holtmann 			} else
7824c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
7831da177e4SLinus Torvalds 		}
7841da177e4SLinus Torvalds 	} else {
7851da177e4SLinus Torvalds 		if (!conn) {
7861da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
7871da177e4SLinus Torvalds 			if (conn) {
7881da177e4SLinus Torvalds 				conn->out = 1;
7891da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
7901da177e4SLinus Torvalds 			} else
791893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
7921da177e4SLinus Torvalds 		}
7931da177e4SLinus Torvalds 	}
7941da177e4SLinus Torvalds 
7951da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
7961da177e4SLinus Torvalds }
7971da177e4SLinus Torvalds 
798a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
7991da177e4SLinus Torvalds {
800a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
8011da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
8021da177e4SLinus Torvalds 	__u16 handle;
8031da177e4SLinus Torvalds 
804b6a0dc82SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
805b6a0dc82SMarcel Holtmann 
806a9de9248SMarcel Holtmann 	if (!status)
807a9de9248SMarcel Holtmann 		return;
808a9de9248SMarcel Holtmann 
809a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
8101da177e4SLinus Torvalds 	if (!cp)
811a9de9248SMarcel Holtmann 		return;
8121da177e4SLinus Torvalds 
8131da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
8141da177e4SLinus Torvalds 
815a9de9248SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
8161da177e4SLinus Torvalds 
8171da177e4SLinus Torvalds 	hci_dev_lock(hdev);
8181da177e4SLinus Torvalds 
8191da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
8201da177e4SLinus Torvalds 	if (acl && (sco = acl->link)) {
8211da177e4SLinus Torvalds 		sco->state = BT_CLOSED;
8221da177e4SLinus Torvalds 
8231da177e4SLinus Torvalds 		hci_proto_connect_cfm(sco, status);
8241da177e4SLinus Torvalds 		hci_conn_del(sco);
8251da177e4SLinus Torvalds 	}
8261da177e4SLinus Torvalds 
8271da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
8281da177e4SLinus Torvalds }
8291da177e4SLinus Torvalds 
830f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
831f8558555SMarcel Holtmann {
832f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
833f8558555SMarcel Holtmann 	struct hci_conn *conn;
834f8558555SMarcel Holtmann 
835f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
836f8558555SMarcel Holtmann 
837f8558555SMarcel Holtmann 	if (!status)
838f8558555SMarcel Holtmann 		return;
839f8558555SMarcel Holtmann 
840f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
841f8558555SMarcel Holtmann 	if (!cp)
842f8558555SMarcel Holtmann 		return;
843f8558555SMarcel Holtmann 
844f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
845f8558555SMarcel Holtmann 
846f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
847f8558555SMarcel Holtmann 	if (conn) {
848f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
849f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
850f8558555SMarcel Holtmann 			hci_conn_put(conn);
851f8558555SMarcel Holtmann 		}
852f8558555SMarcel Holtmann 	}
853f8558555SMarcel Holtmann 
854f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
855f8558555SMarcel Holtmann }
856f8558555SMarcel Holtmann 
857f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
858f8558555SMarcel Holtmann {
859f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
860f8558555SMarcel Holtmann 	struct hci_conn *conn;
861f8558555SMarcel Holtmann 
862f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
863f8558555SMarcel Holtmann 
864f8558555SMarcel Holtmann 	if (!status)
865f8558555SMarcel Holtmann 		return;
866f8558555SMarcel Holtmann 
867f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
868f8558555SMarcel Holtmann 	if (!cp)
869f8558555SMarcel Holtmann 		return;
870f8558555SMarcel Holtmann 
871f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
872f8558555SMarcel Holtmann 
873f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
874f8558555SMarcel Holtmann 	if (conn) {
875f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
876f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
877f8558555SMarcel Holtmann 			hci_conn_put(conn);
878f8558555SMarcel Holtmann 		}
879f8558555SMarcel Holtmann 	}
880f8558555SMarcel Holtmann 
881f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
882f8558555SMarcel Holtmann }
883f8558555SMarcel Holtmann 
884127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
885392599b9SJohan Hedberg 						struct hci_conn *conn)
886392599b9SJohan Hedberg {
887392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
888392599b9SJohan Hedberg 		return 0;
889392599b9SJohan Hedberg 
890765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
891392599b9SJohan Hedberg 		return 0;
892392599b9SJohan Hedberg 
893392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
894392599b9SJohan Hedberg 	 * devices with sec_level HIGH */
895392599b9SJohan Hedberg 	if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) &&
896765c2a96SJohan Hedberg 				conn->pending_sec_level != BT_SECURITY_HIGH)
897392599b9SJohan Hedberg 		return 0;
898392599b9SJohan Hedberg 
899392599b9SJohan Hedberg 	return 1;
900392599b9SJohan Hedberg }
901392599b9SJohan Hedberg 
902a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
9031da177e4SLinus Torvalds {
904127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
905127178d2SJohan Hedberg 	struct hci_conn *conn;
906127178d2SJohan Hedberg 
907a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
908127178d2SJohan Hedberg 
909127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
910127178d2SJohan Hedberg 	 * checking for the need to do authentication */
911127178d2SJohan Hedberg 	if (!status)
912127178d2SJohan Hedberg 		return;
913127178d2SJohan Hedberg 
914127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
915127178d2SJohan Hedberg 	if (!cp)
916127178d2SJohan Hedberg 		return;
917127178d2SJohan Hedberg 
918127178d2SJohan Hedberg 	hci_dev_lock(hdev);
919127178d2SJohan Hedberg 
920127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
921127178d2SJohan Hedberg 	if (conn && hci_outgoing_auth_needed(hdev, conn)) {
922127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
923127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
924127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
925127178d2SJohan Hedberg 	}
926127178d2SJohan Hedberg 
927127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
928a9de9248SMarcel Holtmann }
9291da177e4SLinus Torvalds 
930769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
931769be974SMarcel Holtmann {
932769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
933769be974SMarcel Holtmann 	struct hci_conn *conn;
934769be974SMarcel Holtmann 
935769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
936769be974SMarcel Holtmann 
937769be974SMarcel Holtmann 	if (!status)
938769be974SMarcel Holtmann 		return;
939769be974SMarcel Holtmann 
940769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
941769be974SMarcel Holtmann 	if (!cp)
942769be974SMarcel Holtmann 		return;
943769be974SMarcel Holtmann 
944769be974SMarcel Holtmann 	hci_dev_lock(hdev);
945769be974SMarcel Holtmann 
946769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
947769be974SMarcel Holtmann 	if (conn) {
948769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
949769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
950769be974SMarcel Holtmann 			hci_conn_put(conn);
951769be974SMarcel Holtmann 		}
952769be974SMarcel Holtmann 	}
953769be974SMarcel Holtmann 
954769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
955769be974SMarcel Holtmann }
956769be974SMarcel Holtmann 
957769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
958769be974SMarcel Holtmann {
959769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
960769be974SMarcel Holtmann 	struct hci_conn *conn;
961769be974SMarcel Holtmann 
962769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
963769be974SMarcel Holtmann 
964769be974SMarcel Holtmann 	if (!status)
965769be974SMarcel Holtmann 		return;
966769be974SMarcel Holtmann 
967769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
968769be974SMarcel Holtmann 	if (!cp)
969769be974SMarcel Holtmann 		return;
970769be974SMarcel Holtmann 
971769be974SMarcel Holtmann 	hci_dev_lock(hdev);
972769be974SMarcel Holtmann 
973769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
974769be974SMarcel Holtmann 	if (conn) {
975769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
976769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
977769be974SMarcel Holtmann 			hci_conn_put(conn);
978769be974SMarcel Holtmann 		}
979769be974SMarcel Holtmann 	}
980769be974SMarcel Holtmann 
981769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
982769be974SMarcel Holtmann }
983769be974SMarcel Holtmann 
984a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
985a9de9248SMarcel Holtmann {
986b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
987b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
988b6a0dc82SMarcel Holtmann 	__u16 handle;
989b6a0dc82SMarcel Holtmann 
990a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
991b6a0dc82SMarcel Holtmann 
992b6a0dc82SMarcel Holtmann 	if (!status)
993b6a0dc82SMarcel Holtmann 		return;
994b6a0dc82SMarcel Holtmann 
995b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
996b6a0dc82SMarcel Holtmann 	if (!cp)
997b6a0dc82SMarcel Holtmann 		return;
998b6a0dc82SMarcel Holtmann 
999b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1000b6a0dc82SMarcel Holtmann 
1001b6a0dc82SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
1002b6a0dc82SMarcel Holtmann 
1003b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1004b6a0dc82SMarcel Holtmann 
1005b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
1006b6a0dc82SMarcel Holtmann 	if (acl && (sco = acl->link)) {
1007b6a0dc82SMarcel Holtmann 		sco->state = BT_CLOSED;
1008b6a0dc82SMarcel Holtmann 
1009b6a0dc82SMarcel Holtmann 		hci_proto_connect_cfm(sco, status);
1010b6a0dc82SMarcel Holtmann 		hci_conn_del(sco);
1011b6a0dc82SMarcel Holtmann 	}
1012b6a0dc82SMarcel Holtmann 
1013b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1014a9de9248SMarcel Holtmann }
1015a9de9248SMarcel Holtmann 
1016a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1017a9de9248SMarcel Holtmann {
1018a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
101904837f64SMarcel Holtmann 	struct hci_conn *conn;
102004837f64SMarcel Holtmann 
1021a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1022a9de9248SMarcel Holtmann 
1023a9de9248SMarcel Holtmann 	if (!status)
1024a9de9248SMarcel Holtmann 		return;
1025a9de9248SMarcel Holtmann 
1026a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
102704837f64SMarcel Holtmann 	if (!cp)
1028a9de9248SMarcel Holtmann 		return;
102904837f64SMarcel Holtmann 
103004837f64SMarcel Holtmann 	hci_dev_lock(hdev);
103104837f64SMarcel Holtmann 
103204837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1033e73439d8SMarcel Holtmann 	if (conn) {
103404837f64SMarcel Holtmann 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
103504837f64SMarcel Holtmann 
1036e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1037e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1038e73439d8SMarcel Holtmann 	}
1039e73439d8SMarcel Holtmann 
104004837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
104104837f64SMarcel Holtmann }
104204837f64SMarcel Holtmann 
1043a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1044a9de9248SMarcel Holtmann {
1045a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
104604837f64SMarcel Holtmann 	struct hci_conn *conn;
104704837f64SMarcel Holtmann 
1048a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1049a9de9248SMarcel Holtmann 
1050a9de9248SMarcel Holtmann 	if (!status)
1051a9de9248SMarcel Holtmann 		return;
1052a9de9248SMarcel Holtmann 
1053a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
105404837f64SMarcel Holtmann 	if (!cp)
1055a9de9248SMarcel Holtmann 		return;
105604837f64SMarcel Holtmann 
105704837f64SMarcel Holtmann 	hci_dev_lock(hdev);
105804837f64SMarcel Holtmann 
105904837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1060e73439d8SMarcel Holtmann 	if (conn) {
106104837f64SMarcel Holtmann 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
106204837f64SMarcel Holtmann 
1063e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1064e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1065e73439d8SMarcel Holtmann 	}
1066e73439d8SMarcel Holtmann 
106704837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
106804837f64SMarcel Holtmann }
106904837f64SMarcel Holtmann 
10701da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
10711da177e4SLinus Torvalds {
10721da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
10731da177e4SLinus Torvalds 
10741da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, status);
10751da177e4SLinus Torvalds 
10761da177e4SLinus Torvalds 	clear_bit(HCI_INQUIRY, &hdev->flags);
1077a9de9248SMarcel Holtmann 
107823bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY, status);
10796bd57416SMarcel Holtmann 
1080a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
10811da177e4SLinus Torvalds }
10821da177e4SLinus Torvalds 
10831da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
10841da177e4SLinus Torvalds {
108545bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1086a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
10871da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
10881da177e4SLinus Torvalds 
10891da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
10901da177e4SLinus Torvalds 
109145bb4bf0SMarcel Holtmann 	if (!num_rsp)
109245bb4bf0SMarcel Holtmann 		return;
109345bb4bf0SMarcel Holtmann 
10941da177e4SLinus Torvalds 	hci_dev_lock(hdev);
109545bb4bf0SMarcel Holtmann 
10961da177e4SLinus Torvalds 	for (; num_rsp; num_rsp--) {
10971da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
10981da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
10991da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
11001da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
11011da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
11021da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
11031da177e4SLinus Torvalds 		data.rssi		= 0x00;
110441a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
11051da177e4SLinus Torvalds 		info++;
11061da177e4SLinus Torvalds 		hci_inquiry_cache_update(hdev, &data);
11071da177e4SLinus Torvalds 	}
110845bb4bf0SMarcel Holtmann 
11091da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
11101da177e4SLinus Torvalds }
11111da177e4SLinus Torvalds 
1112a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
11131da177e4SLinus Torvalds {
1114a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
1115a9de9248SMarcel Holtmann 	struct hci_conn *conn;
11161da177e4SLinus Torvalds 
1117a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
111845bb4bf0SMarcel Holtmann 
11191da177e4SLinus Torvalds 	hci_dev_lock(hdev);
112045bb4bf0SMarcel Holtmann 
1121a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
11229499237aSMarcel Holtmann 	if (!conn) {
11239499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
11249499237aSMarcel Holtmann 			goto unlock;
11259499237aSMarcel Holtmann 
11269499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1127a9de9248SMarcel Holtmann 		if (!conn)
1128a9de9248SMarcel Holtmann 			goto unlock;
112945bb4bf0SMarcel Holtmann 
11309499237aSMarcel Holtmann 		conn->type = SCO_LINK;
11319499237aSMarcel Holtmann 	}
11329499237aSMarcel Holtmann 
1133a9de9248SMarcel Holtmann 	if (!ev->status) {
1134a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1135769be974SMarcel Holtmann 
1136769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1137769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
1138769be974SMarcel Holtmann 			hci_conn_hold(conn);
1139052b30b0SMarcel Holtmann 			conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1140f7520543SJohan Hedberg 			mgmt_connected(hdev->id, &ev->bdaddr);
1141769be974SMarcel Holtmann 		} else
1142a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
1143a9de9248SMarcel Holtmann 
11449eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
11457d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
11467d0db0a3SMarcel Holtmann 
1147a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1148a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1149a9de9248SMarcel Holtmann 
1150a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1151a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1152a9de9248SMarcel Holtmann 
1153a9de9248SMarcel Holtmann 		/* Get remote features */
1154a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1155a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1156a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1157769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1158769be974SMarcel Holtmann 							sizeof(cp), &cp);
115945bb4bf0SMarcel Holtmann 		}
1160a9de9248SMarcel Holtmann 
1161a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1162a8746417SMarcel Holtmann 		if (!conn->out && hdev->hci_ver < 3) {
1163a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1164a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1165a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1166a8746417SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
1167a8746417SMarcel Holtmann 							sizeof(cp), &cp);
1168a9de9248SMarcel Holtmann 		}
1169a9de9248SMarcel Holtmann 	} else
1170a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
117145bb4bf0SMarcel Holtmann 
1172e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
1173e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
117445bb4bf0SMarcel Holtmann 
1175769be974SMarcel Holtmann 	if (ev->status) {
1176a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1177a9de9248SMarcel Holtmann 		hci_conn_del(conn);
1178c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
1179c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1180a9de9248SMarcel Holtmann 
1181a9de9248SMarcel Holtmann unlock:
11821da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
1183a9de9248SMarcel Holtmann 
1184a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
11851da177e4SLinus Torvalds }
11861da177e4SLinus Torvalds 
11871da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
11881da177e4SLinus Torvalds {
1189a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
11901da177e4SLinus Torvalds 	int mask = hdev->link_mode;
11911da177e4SLinus Torvalds 
1192a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
11931da177e4SLinus Torvalds 					batostr(&ev->bdaddr), ev->link_type);
11941da177e4SLinus Torvalds 
11951da177e4SLinus Torvalds 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
11961da177e4SLinus Torvalds 
1197f0358568SJohan Hedberg 	if ((mask & HCI_LM_ACCEPT) && !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
11981da177e4SLinus Torvalds 		/* Connection accepted */
1199c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
12001da177e4SLinus Torvalds 		struct hci_conn *conn;
12011da177e4SLinus Torvalds 
12021da177e4SLinus Torvalds 		hci_dev_lock(hdev);
1203b6a0dc82SMarcel Holtmann 
1204cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1205cc11b9c1SAndrei Emeltchenko 		if (ie)
1206c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
1207c7bdd502SMarcel Holtmann 
12081da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
12091da177e4SLinus Torvalds 		if (!conn) {
1210cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1211cc11b9c1SAndrei Emeltchenko 			if (!conn) {
1212893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
12131da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
12141da177e4SLinus Torvalds 				return;
12151da177e4SLinus Torvalds 			}
12161da177e4SLinus Torvalds 		}
1217b6a0dc82SMarcel Holtmann 
12181da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
12191da177e4SLinus Torvalds 		conn->state = BT_CONNECT;
1220b6a0dc82SMarcel Holtmann 
12211da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
12221da177e4SLinus Torvalds 
1223b6a0dc82SMarcel Holtmann 		if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1224b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
1225b6a0dc82SMarcel Holtmann 
12261da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
12271da177e4SLinus Torvalds 
12281da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
12291da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
12301da177e4SLinus Torvalds 			else
12311da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
12321da177e4SLinus Torvalds 
1233b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ,
1234b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1235b6a0dc82SMarcel Holtmann 		} else {
1236b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
1237b6a0dc82SMarcel Holtmann 
1238b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
1239a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1240b6a0dc82SMarcel Holtmann 
1241b6a0dc82SMarcel Holtmann 			cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
1242b6a0dc82SMarcel Holtmann 			cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
1243b6a0dc82SMarcel Holtmann 			cp.max_latency    = cpu_to_le16(0xffff);
1244b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
1245b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
1246b6a0dc82SMarcel Holtmann 
1247b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1248b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1249b6a0dc82SMarcel Holtmann 		}
12501da177e4SLinus Torvalds 	} else {
12511da177e4SLinus Torvalds 		/* Connection rejected */
12521da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
12531da177e4SLinus Torvalds 
12541da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
12551da177e4SLinus Torvalds 		cp.reason = 0x0f;
1256a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
12571da177e4SLinus Torvalds 	}
12581da177e4SLinus Torvalds }
12591da177e4SLinus Torvalds 
12601da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
12611da177e4SLinus Torvalds {
1262a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
126304837f64SMarcel Holtmann 	struct hci_conn *conn;
12641da177e4SLinus Torvalds 
12651da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
12661da177e4SLinus Torvalds 
12678962ee74SJohan Hedberg 	if (ev->status) {
12688962ee74SJohan Hedberg 		mgmt_disconnect_failed(hdev->id);
12691da177e4SLinus Torvalds 		return;
12708962ee74SJohan Hedberg 	}
12711da177e4SLinus Torvalds 
12721da177e4SLinus Torvalds 	hci_dev_lock(hdev);
12731da177e4SLinus Torvalds 
127404837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1275f7520543SJohan Hedberg 	if (!conn)
1276f7520543SJohan Hedberg 		goto unlock;
1277f7520543SJohan Hedberg 
12781da177e4SLinus Torvalds 	conn->state = BT_CLOSED;
12797d0db0a3SMarcel Holtmann 
1280f7520543SJohan Hedberg 	if (conn->type == ACL_LINK)
1281f7520543SJohan Hedberg 		mgmt_disconnected(hdev->id, &conn->dst);
1282f7520543SJohan Hedberg 
12832950f21aSMarcel Holtmann 	hci_proto_disconn_cfm(conn, ev->reason);
12841da177e4SLinus Torvalds 	hci_conn_del(conn);
12851da177e4SLinus Torvalds 
1286f7520543SJohan Hedberg unlock:
12871da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
12881da177e4SLinus Torvalds }
12891da177e4SLinus Torvalds 
1290a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1291a9de9248SMarcel Holtmann {
1292a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
1293a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1294a9de9248SMarcel Holtmann 
1295a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1296a9de9248SMarcel Holtmann 
1297a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1298a9de9248SMarcel Holtmann 
1299a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1300a9de9248SMarcel Holtmann 	if (conn) {
1301765c2a96SJohan Hedberg 		if (!ev->status) {
1302a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1303765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
1304765c2a96SJohan Hedberg 		} else
1305da213f41SJohan Hedberg 			conn->sec_level = BT_SECURITY_LOW;
1306a9de9248SMarcel Holtmann 
1307a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1308a9de9248SMarcel Holtmann 
1309f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1310f8558555SMarcel Holtmann 			if (!ev->status && hdev->ssp_mode > 0 &&
1311f8558555SMarcel Holtmann 							conn->ssp_mode > 0) {
1312f8558555SMarcel Holtmann 				struct hci_cp_set_conn_encrypt cp;
1313f8558555SMarcel Holtmann 				cp.handle  = ev->handle;
1314f8558555SMarcel Holtmann 				cp.encrypt = 0x01;
1315f8558555SMarcel Holtmann 				hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT,
1316f8558555SMarcel Holtmann 							sizeof(cp), &cp);
1317f8558555SMarcel Holtmann 			} else {
1318f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
1319f8558555SMarcel Holtmann 				hci_proto_connect_cfm(conn, ev->status);
1320f8558555SMarcel Holtmann 				hci_conn_put(conn);
1321f8558555SMarcel Holtmann 			}
1322052b30b0SMarcel Holtmann 		} else {
1323a9de9248SMarcel Holtmann 			hci_auth_cfm(conn, ev->status);
1324a9de9248SMarcel Holtmann 
1325052b30b0SMarcel Holtmann 			hci_conn_hold(conn);
1326052b30b0SMarcel Holtmann 			conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1327052b30b0SMarcel Holtmann 			hci_conn_put(conn);
1328052b30b0SMarcel Holtmann 		}
1329052b30b0SMarcel Holtmann 
1330a9de9248SMarcel Holtmann 		if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
1331a9de9248SMarcel Holtmann 			if (!ev->status) {
1332a9de9248SMarcel Holtmann 				struct hci_cp_set_conn_encrypt cp;
1333f8558555SMarcel Holtmann 				cp.handle  = ev->handle;
1334f8558555SMarcel Holtmann 				cp.encrypt = 0x01;
1335f8558555SMarcel Holtmann 				hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT,
1336f8558555SMarcel Holtmann 							sizeof(cp), &cp);
1337a9de9248SMarcel Holtmann 			} else {
1338a9de9248SMarcel Holtmann 				clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1339a9de9248SMarcel Holtmann 				hci_encrypt_cfm(conn, ev->status, 0x00);
1340a9de9248SMarcel Holtmann 			}
1341a9de9248SMarcel Holtmann 		}
1342a9de9248SMarcel Holtmann 	}
1343a9de9248SMarcel Holtmann 
1344a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1345a9de9248SMarcel Holtmann }
1346a9de9248SMarcel Holtmann 
1347a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1348a9de9248SMarcel Holtmann {
1349127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
1350127178d2SJohan Hedberg 	struct hci_conn *conn;
1351127178d2SJohan Hedberg 
1352a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1353a9de9248SMarcel Holtmann 
1354a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
1355127178d2SJohan Hedberg 
1356127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1357127178d2SJohan Hedberg 
1358127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1359127178d2SJohan Hedberg 	if (conn && hci_outgoing_auth_needed(hdev, conn)) {
1360127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1361127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1362127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1363127178d2SJohan Hedberg 	}
1364127178d2SJohan Hedberg 
1365127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1366a9de9248SMarcel Holtmann }
1367a9de9248SMarcel Holtmann 
1368a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1369a9de9248SMarcel Holtmann {
1370a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
1371a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1372a9de9248SMarcel Holtmann 
1373a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1374a9de9248SMarcel Holtmann 
1375a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1376a9de9248SMarcel Holtmann 
1377a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1378a9de9248SMarcel Holtmann 	if (conn) {
1379a9de9248SMarcel Holtmann 		if (!ev->status) {
1380ae293196SMarcel Holtmann 			if (ev->encrypt) {
1381ae293196SMarcel Holtmann 				/* Encryption implies authentication */
1382ae293196SMarcel Holtmann 				conn->link_mode |= HCI_LM_AUTH;
1383a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_ENCRYPT;
1384ae293196SMarcel Holtmann 			} else
1385a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_ENCRYPT;
1386a9de9248SMarcel Holtmann 		}
1387a9de9248SMarcel Holtmann 
1388a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1389a9de9248SMarcel Holtmann 
1390f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1391f8558555SMarcel Holtmann 			if (!ev->status)
1392f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
1393f8558555SMarcel Holtmann 
1394f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1395f8558555SMarcel Holtmann 			hci_conn_put(conn);
1396f8558555SMarcel Holtmann 		} else
1397a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, ev->encrypt);
1398a9de9248SMarcel Holtmann 	}
1399a9de9248SMarcel Holtmann 
1400a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1401a9de9248SMarcel Holtmann }
1402a9de9248SMarcel Holtmann 
1403a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1404a9de9248SMarcel Holtmann {
1405a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
1406a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1407a9de9248SMarcel Holtmann 
1408a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1409a9de9248SMarcel Holtmann 
1410a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1411a9de9248SMarcel Holtmann 
1412a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1413a9de9248SMarcel Holtmann 	if (conn) {
1414a9de9248SMarcel Holtmann 		if (!ev->status)
1415a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
1416a9de9248SMarcel Holtmann 
1417a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1418a9de9248SMarcel Holtmann 
1419a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
1420a9de9248SMarcel Holtmann 	}
1421a9de9248SMarcel Holtmann 
1422a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1423a9de9248SMarcel Holtmann }
1424a9de9248SMarcel Holtmann 
1425a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
1426a9de9248SMarcel Holtmann {
1427a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
1428a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1429a9de9248SMarcel Holtmann 
1430a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1431a9de9248SMarcel Holtmann 
1432a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1433a9de9248SMarcel Holtmann 
1434a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1435ccd556feSJohan Hedberg 	if (!conn)
1436ccd556feSJohan Hedberg 		goto unlock;
1437ccd556feSJohan Hedberg 
1438769be974SMarcel Holtmann 	if (!ev->status)
1439a9de9248SMarcel Holtmann 		memcpy(conn->features, ev->features, 8);
1440a9de9248SMarcel Holtmann 
1441ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
1442ccd556feSJohan Hedberg 		goto unlock;
1443ccd556feSJohan Hedberg 
1444ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
1445769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
1446769be974SMarcel Holtmann 		cp.handle = ev->handle;
1447769be974SMarcel Holtmann 		cp.page = 0x01;
1448ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
1449769be974SMarcel Holtmann 							sizeof(cp), &cp);
1450392599b9SJohan Hedberg 		goto unlock;
1451392599b9SJohan Hedberg 	}
1452392599b9SJohan Hedberg 
1453127178d2SJohan Hedberg 	if (!ev->status) {
1454127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
1455127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
1456127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
1457127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
1458127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1459127178d2SJohan Hedberg 	}
1460392599b9SJohan Hedberg 
1461127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
1462769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
1463769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1464769be974SMarcel Holtmann 		hci_conn_put(conn);
1465769be974SMarcel Holtmann 	}
1466769be974SMarcel Holtmann 
1467ccd556feSJohan Hedberg unlock:
1468a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1469a9de9248SMarcel Holtmann }
1470a9de9248SMarcel Holtmann 
1471a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
1472a9de9248SMarcel Holtmann {
1473a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1474a9de9248SMarcel Holtmann }
1475a9de9248SMarcel Holtmann 
1476a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1477a9de9248SMarcel Holtmann {
1478a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1479a9de9248SMarcel Holtmann }
1480a9de9248SMarcel Holtmann 
1481a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1482a9de9248SMarcel Holtmann {
1483a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
1484a9de9248SMarcel Holtmann 	__u16 opcode;
1485a9de9248SMarcel Holtmann 
1486a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
1487a9de9248SMarcel Holtmann 
1488a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
1489a9de9248SMarcel Holtmann 
1490a9de9248SMarcel Holtmann 	switch (opcode) {
1491a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
1492a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
1493a9de9248SMarcel Holtmann 		break;
1494a9de9248SMarcel Holtmann 
1495a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
1496a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
1497a9de9248SMarcel Holtmann 		break;
1498a9de9248SMarcel Holtmann 
1499a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
1500a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
1501a9de9248SMarcel Holtmann 		break;
1502a9de9248SMarcel Holtmann 
1503a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
1504a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
1505a9de9248SMarcel Holtmann 		break;
1506a9de9248SMarcel Holtmann 
1507e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
1508e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
1509e4e8e37cSMarcel Holtmann 		break;
1510e4e8e37cSMarcel Holtmann 
1511a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
1512a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
1513a9de9248SMarcel Holtmann 		break;
1514a9de9248SMarcel Holtmann 
1515e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
1516e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
1517e4e8e37cSMarcel Holtmann 		break;
1518e4e8e37cSMarcel Holtmann 
1519e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
1520e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
1521e4e8e37cSMarcel Holtmann 		break;
1522e4e8e37cSMarcel Holtmann 
1523a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
1524a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
1525a9de9248SMarcel Holtmann 		break;
1526a9de9248SMarcel Holtmann 
1527a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
1528a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
1529a9de9248SMarcel Holtmann 		break;
1530a9de9248SMarcel Holtmann 
1531a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
1532a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
1533a9de9248SMarcel Holtmann 		break;
1534a9de9248SMarcel Holtmann 
1535a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
1536a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
1537a9de9248SMarcel Holtmann 		break;
1538a9de9248SMarcel Holtmann 
1539a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
1540a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
1541a9de9248SMarcel Holtmann 		break;
1542a9de9248SMarcel Holtmann 
1543a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
1544a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
1545a9de9248SMarcel Holtmann 		break;
1546a9de9248SMarcel Holtmann 
1547a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
1548a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
1549a9de9248SMarcel Holtmann 		break;
1550a9de9248SMarcel Holtmann 
1551a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
1552a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
1553a9de9248SMarcel Holtmann 		break;
1554a9de9248SMarcel Holtmann 
1555a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
1556a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
1557a9de9248SMarcel Holtmann 		break;
1558a9de9248SMarcel Holtmann 
1559a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
1560a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
1561a9de9248SMarcel Holtmann 		break;
1562a9de9248SMarcel Holtmann 
1563a9de9248SMarcel Holtmann 	case HCI_OP_HOST_BUFFER_SIZE:
1564a9de9248SMarcel Holtmann 		hci_cc_host_buffer_size(hdev, skb);
1565a9de9248SMarcel Holtmann 		break;
1566a9de9248SMarcel Holtmann 
1567333140b5SMarcel Holtmann 	case HCI_OP_READ_SSP_MODE:
1568333140b5SMarcel Holtmann 		hci_cc_read_ssp_mode(hdev, skb);
1569333140b5SMarcel Holtmann 		break;
1570333140b5SMarcel Holtmann 
1571333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
1572333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
1573333140b5SMarcel Holtmann 		break;
1574333140b5SMarcel Holtmann 
1575a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
1576a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
1577a9de9248SMarcel Holtmann 		break;
1578a9de9248SMarcel Holtmann 
1579a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
1580a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
1581a9de9248SMarcel Holtmann 		break;
1582a9de9248SMarcel Holtmann 
1583a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
1584a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
1585a9de9248SMarcel Holtmann 		break;
1586a9de9248SMarcel Holtmann 
1587a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
1588a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
1589a9de9248SMarcel Holtmann 		break;
1590a9de9248SMarcel Holtmann 
1591a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
1592a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
1593a9de9248SMarcel Holtmann 		break;
1594a9de9248SMarcel Holtmann 
159523bb5763SJohan Hedberg 	case HCI_OP_WRITE_CA_TIMEOUT:
159623bb5763SJohan Hedberg 		hci_cc_write_ca_timeout(hdev, skb);
159723bb5763SJohan Hedberg 		break;
159823bb5763SJohan Hedberg 
1599b0916ea0SJohan Hedberg 	case HCI_OP_DELETE_STORED_LINK_KEY:
1600b0916ea0SJohan Hedberg 		hci_cc_delete_stored_link_key(hdev, skb);
1601b0916ea0SJohan Hedberg 		break;
1602b0916ea0SJohan Hedberg 
1603d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_MASK:
1604d5859e22SJohan Hedberg 		hci_cc_set_event_mask(hdev, skb);
1605d5859e22SJohan Hedberg 		break;
1606d5859e22SJohan Hedberg 
1607d5859e22SJohan Hedberg 	case HCI_OP_WRITE_INQUIRY_MODE:
1608d5859e22SJohan Hedberg 		hci_cc_write_inquiry_mode(hdev, skb);
1609d5859e22SJohan Hedberg 		break;
1610d5859e22SJohan Hedberg 
1611d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
1612d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
1613d5859e22SJohan Hedberg 		break;
1614d5859e22SJohan Hedberg 
1615d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_FLT:
1616d5859e22SJohan Hedberg 		hci_cc_set_event_flt(hdev, skb);
1617d5859e22SJohan Hedberg 		break;
1618d5859e22SJohan Hedberg 
1619a9de9248SMarcel Holtmann 	default:
1620a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
1621a9de9248SMarcel Holtmann 		break;
1622a9de9248SMarcel Holtmann 	}
1623a9de9248SMarcel Holtmann 
1624a9de9248SMarcel Holtmann 	if (ev->ncmd) {
1625a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
1626a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
1627c78ae283SMarcel Holtmann 			tasklet_schedule(&hdev->cmd_task);
1628a9de9248SMarcel Holtmann 	}
1629a9de9248SMarcel Holtmann }
1630a9de9248SMarcel Holtmann 
1631a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
1632a9de9248SMarcel Holtmann {
1633a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
1634a9de9248SMarcel Holtmann 	__u16 opcode;
1635a9de9248SMarcel Holtmann 
1636a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
1637a9de9248SMarcel Holtmann 
1638a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
1639a9de9248SMarcel Holtmann 
1640a9de9248SMarcel Holtmann 	switch (opcode) {
1641a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
1642a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
1643a9de9248SMarcel Holtmann 		break;
1644a9de9248SMarcel Holtmann 
1645a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
1646a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
1647a9de9248SMarcel Holtmann 		break;
1648a9de9248SMarcel Holtmann 
1649a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
1650a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
1651a9de9248SMarcel Holtmann 		break;
1652a9de9248SMarcel Holtmann 
1653f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
1654f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
1655f8558555SMarcel Holtmann 		break;
1656f8558555SMarcel Holtmann 
1657f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
1658f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
1659f8558555SMarcel Holtmann 		break;
1660f8558555SMarcel Holtmann 
1661a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
1662a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
1663a9de9248SMarcel Holtmann 		break;
1664a9de9248SMarcel Holtmann 
1665769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
1666769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
1667769be974SMarcel Holtmann 		break;
1668769be974SMarcel Holtmann 
1669769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
1670769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
1671769be974SMarcel Holtmann 		break;
1672769be974SMarcel Holtmann 
1673a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
1674a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
1675a9de9248SMarcel Holtmann 		break;
1676a9de9248SMarcel Holtmann 
1677a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
1678a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
1679a9de9248SMarcel Holtmann 		break;
1680a9de9248SMarcel Holtmann 
1681a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
1682a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
1683a9de9248SMarcel Holtmann 		break;
1684a9de9248SMarcel Holtmann 
16858962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
16868962ee74SJohan Hedberg 		if (ev->status != 0)
16878962ee74SJohan Hedberg 			mgmt_disconnect_failed(hdev->id);
16888962ee74SJohan Hedberg 		break;
16898962ee74SJohan Hedberg 
1690a9de9248SMarcel Holtmann 	default:
1691a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
1692a9de9248SMarcel Holtmann 		break;
1693a9de9248SMarcel Holtmann 	}
1694a9de9248SMarcel Holtmann 
1695a9de9248SMarcel Holtmann 	if (ev->ncmd) {
1696a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
1697a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
1698c78ae283SMarcel Holtmann 			tasklet_schedule(&hdev->cmd_task);
1699a9de9248SMarcel Holtmann 	}
1700a9de9248SMarcel Holtmann }
1701a9de9248SMarcel Holtmann 
1702a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1703a9de9248SMarcel Holtmann {
1704a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
1705a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1706a9de9248SMarcel Holtmann 
1707a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1708a9de9248SMarcel Holtmann 
1709a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1710a9de9248SMarcel Holtmann 
1711a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1712a9de9248SMarcel Holtmann 	if (conn) {
1713a9de9248SMarcel Holtmann 		if (!ev->status) {
1714a9de9248SMarcel Holtmann 			if (ev->role)
1715a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
1716a9de9248SMarcel Holtmann 			else
1717a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
1718a9de9248SMarcel Holtmann 		}
1719a9de9248SMarcel Holtmann 
1720a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend);
1721a9de9248SMarcel Holtmann 
1722a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
1723a9de9248SMarcel Holtmann 	}
1724a9de9248SMarcel Holtmann 
1725a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1726a9de9248SMarcel Holtmann }
1727a9de9248SMarcel Holtmann 
17281da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
17291da177e4SLinus Torvalds {
1730a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
17311ebb9252SMarcel Holtmann 	__le16 *ptr;
17321da177e4SLinus Torvalds 	int i;
17331da177e4SLinus Torvalds 
17341da177e4SLinus Torvalds 	skb_pull(skb, sizeof(*ev));
17351da177e4SLinus Torvalds 
17361da177e4SLinus Torvalds 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
17371da177e4SLinus Torvalds 
17381da177e4SLinus Torvalds 	if (skb->len < ev->num_hndl * 4) {
17391da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
17401da177e4SLinus Torvalds 		return;
17411da177e4SLinus Torvalds 	}
17421da177e4SLinus Torvalds 
17431da177e4SLinus Torvalds 	tasklet_disable(&hdev->tx_task);
17441da177e4SLinus Torvalds 
17451ebb9252SMarcel Holtmann 	for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) {
17461da177e4SLinus Torvalds 		struct hci_conn *conn;
17471da177e4SLinus Torvalds 		__u16  handle, count;
17481da177e4SLinus Torvalds 
174983985319SHarvey Harrison 		handle = get_unaligned_le16(ptr++);
175083985319SHarvey Harrison 		count  = get_unaligned_le16(ptr++);
17511da177e4SLinus Torvalds 
17521da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
17531da177e4SLinus Torvalds 		if (conn) {
17541da177e4SLinus Torvalds 			conn->sent -= count;
17551da177e4SLinus Torvalds 
17565b7f9909SMarcel Holtmann 			if (conn->type == ACL_LINK) {
175770f23020SAndrei Emeltchenko 				hdev->acl_cnt += count;
175870f23020SAndrei Emeltchenko 				if (hdev->acl_cnt > hdev->acl_pkts)
17591da177e4SLinus Torvalds 					hdev->acl_cnt = hdev->acl_pkts;
17605b7f9909SMarcel Holtmann 			} else {
176170f23020SAndrei Emeltchenko 				hdev->sco_cnt += count;
176270f23020SAndrei Emeltchenko 				if (hdev->sco_cnt > hdev->sco_pkts)
17635b7f9909SMarcel Holtmann 					hdev->sco_cnt = hdev->sco_pkts;
17641da177e4SLinus Torvalds 			}
17651da177e4SLinus Torvalds 		}
17661da177e4SLinus Torvalds 	}
1767a9de9248SMarcel Holtmann 
1768c78ae283SMarcel Holtmann 	tasklet_schedule(&hdev->tx_task);
17691da177e4SLinus Torvalds 
17701da177e4SLinus Torvalds 	tasklet_enable(&hdev->tx_task);
17711da177e4SLinus Torvalds }
17721da177e4SLinus Torvalds 
177304837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
17741da177e4SLinus Torvalds {
1775a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
177604837f64SMarcel Holtmann 	struct hci_conn *conn;
17771da177e4SLinus Torvalds 
17781da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
17791da177e4SLinus Torvalds 
17801da177e4SLinus Torvalds 	hci_dev_lock(hdev);
17811da177e4SLinus Torvalds 
178204837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
178304837f64SMarcel Holtmann 	if (conn) {
178404837f64SMarcel Holtmann 		conn->mode = ev->mode;
178504837f64SMarcel Holtmann 		conn->interval = __le16_to_cpu(ev->interval);
178604837f64SMarcel Holtmann 
178704837f64SMarcel Holtmann 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
178804837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
178904837f64SMarcel Holtmann 				conn->power_save = 1;
179004837f64SMarcel Holtmann 			else
179104837f64SMarcel Holtmann 				conn->power_save = 0;
179204837f64SMarcel Holtmann 		}
1793e73439d8SMarcel Holtmann 
1794e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1795e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
179604837f64SMarcel Holtmann 	}
179704837f64SMarcel Holtmann 
179804837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
179904837f64SMarcel Holtmann }
180004837f64SMarcel Holtmann 
18011da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
18021da177e4SLinus Torvalds {
1803052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
1804052b30b0SMarcel Holtmann 	struct hci_conn *conn;
1805052b30b0SMarcel Holtmann 
1806a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1807052b30b0SMarcel Holtmann 
1808052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
1809052b30b0SMarcel Holtmann 
1810052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
18113d7a9d1cSMarcel Holtmann 	if (conn && conn->state == BT_CONNECTED) {
1812052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
1813052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
1814052b30b0SMarcel Holtmann 		hci_conn_put(conn);
1815052b30b0SMarcel Holtmann 	}
1816052b30b0SMarcel Holtmann 
181703b555e1SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->flags))
181803b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
181903b555e1SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
182003b555e1SJohan Hedberg 
1821052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
18221da177e4SLinus Torvalds }
18231da177e4SLinus Torvalds 
18241da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
18251da177e4SLinus Torvalds {
182655ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
182755ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
182855ed8ca1SJohan Hedberg 	struct hci_conn *conn;
182955ed8ca1SJohan Hedberg 	struct link_key *key;
183055ed8ca1SJohan Hedberg 
1831a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
183255ed8ca1SJohan Hedberg 
183355ed8ca1SJohan Hedberg 	if (!test_bit(HCI_LINK_KEYS, &hdev->flags))
183455ed8ca1SJohan Hedberg 		return;
183555ed8ca1SJohan Hedberg 
183655ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
183755ed8ca1SJohan Hedberg 
183855ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
183955ed8ca1SJohan Hedberg 	if (!key) {
184055ed8ca1SJohan Hedberg 		BT_DBG("%s link key not found for %s", hdev->name,
184155ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
184255ed8ca1SJohan Hedberg 		goto not_found;
184355ed8ca1SJohan Hedberg 	}
184455ed8ca1SJohan Hedberg 
184555ed8ca1SJohan Hedberg 	BT_DBG("%s found key type %u for %s", hdev->name, key->type,
184655ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
184755ed8ca1SJohan Hedberg 
184855ed8ca1SJohan Hedberg 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) && key->type == 0x03) {
184955ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
185055ed8ca1SJohan Hedberg 		goto not_found;
185155ed8ca1SJohan Hedberg 	}
185255ed8ca1SJohan Hedberg 
185355ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
185455ed8ca1SJohan Hedberg 
185555ed8ca1SJohan Hedberg 	if (key->type == 0x04 && conn && conn->auth_type != 0xff &&
185655ed8ca1SJohan Hedberg 						(conn->auth_type & 0x01)) {
185755ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring unauthenticated key", hdev->name);
185855ed8ca1SJohan Hedberg 		goto not_found;
185955ed8ca1SJohan Hedberg 	}
186055ed8ca1SJohan Hedberg 
186155ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
186255ed8ca1SJohan Hedberg 	memcpy(cp.link_key, key->val, 16);
186355ed8ca1SJohan Hedberg 
186455ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
186555ed8ca1SJohan Hedberg 
186655ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
186755ed8ca1SJohan Hedberg 
186855ed8ca1SJohan Hedberg 	return;
186955ed8ca1SJohan Hedberg 
187055ed8ca1SJohan Hedberg not_found:
187155ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
187255ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
18731da177e4SLinus Torvalds }
18741da177e4SLinus Torvalds 
18751da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
18761da177e4SLinus Torvalds {
1877052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
1878052b30b0SMarcel Holtmann 	struct hci_conn *conn;
187955ed8ca1SJohan Hedberg 	u8 pin_len = 0;
1880052b30b0SMarcel Holtmann 
1881a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1882052b30b0SMarcel Holtmann 
1883052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
1884052b30b0SMarcel Holtmann 
1885052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1886052b30b0SMarcel Holtmann 	if (conn) {
1887052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
1888052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1889052b30b0SMarcel Holtmann 		hci_conn_put(conn);
1890052b30b0SMarcel Holtmann 	}
1891052b30b0SMarcel Holtmann 
189255ed8ca1SJohan Hedberg 	if (test_bit(HCI_LINK_KEYS, &hdev->flags))
189355ed8ca1SJohan Hedberg 		hci_add_link_key(hdev, 1, &ev->bdaddr, ev->link_key,
189455ed8ca1SJohan Hedberg 							ev->key_type, pin_len);
189555ed8ca1SJohan Hedberg 
1896052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
18971da177e4SLinus Torvalds }
18981da177e4SLinus Torvalds 
189904837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
190004837f64SMarcel Holtmann {
1901a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
190204837f64SMarcel Holtmann 	struct hci_conn *conn;
190304837f64SMarcel Holtmann 
190404837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
190504837f64SMarcel Holtmann 
190604837f64SMarcel Holtmann 	hci_dev_lock(hdev);
190704837f64SMarcel Holtmann 
190804837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
19091da177e4SLinus Torvalds 	if (conn && !ev->status) {
19101da177e4SLinus Torvalds 		struct inquiry_entry *ie;
19111da177e4SLinus Torvalds 
1912cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
1913cc11b9c1SAndrei Emeltchenko 		if (ie) {
19141da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
19151da177e4SLinus Torvalds 			ie->timestamp = jiffies;
19161da177e4SLinus Torvalds 		}
19171da177e4SLinus Torvalds 	}
19181da177e4SLinus Torvalds 
19191da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
19201da177e4SLinus Torvalds }
19211da177e4SLinus Torvalds 
1922a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1923a8746417SMarcel Holtmann {
1924a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
1925a8746417SMarcel Holtmann 	struct hci_conn *conn;
1926a8746417SMarcel Holtmann 
1927a8746417SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1928a8746417SMarcel Holtmann 
1929a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
1930a8746417SMarcel Holtmann 
1931a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1932a8746417SMarcel Holtmann 	if (conn && !ev->status)
1933a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
1934a8746417SMarcel Holtmann 
1935a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
1936a8746417SMarcel Holtmann }
1937a8746417SMarcel Holtmann 
193885a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
193985a1e930SMarcel Holtmann {
1940a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
194185a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
194285a1e930SMarcel Holtmann 
194385a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
194485a1e930SMarcel Holtmann 
194585a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
194685a1e930SMarcel Holtmann 
1947cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1948cc11b9c1SAndrei Emeltchenko 	if (ie) {
194985a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
195085a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
195185a1e930SMarcel Holtmann 	}
195285a1e930SMarcel Holtmann 
195385a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
195485a1e930SMarcel Holtmann }
195585a1e930SMarcel Holtmann 
1956a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
1957a9de9248SMarcel Holtmann {
1958a9de9248SMarcel Holtmann 	struct inquiry_data data;
1959a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
1960a9de9248SMarcel Holtmann 
1961a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1962a9de9248SMarcel Holtmann 
1963a9de9248SMarcel Holtmann 	if (!num_rsp)
1964a9de9248SMarcel Holtmann 		return;
1965a9de9248SMarcel Holtmann 
1966a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1967a9de9248SMarcel Holtmann 
1968a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
1969a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi_and_pscan_mode *info = (void *) (skb->data + 1);
1970a9de9248SMarcel Holtmann 
1971a9de9248SMarcel Holtmann 		for (; num_rsp; num_rsp--) {
1972a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
1973a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
1974a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
1975a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
1976a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
1977a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
1978a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
197941a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
1980a9de9248SMarcel Holtmann 			info++;
1981a9de9248SMarcel Holtmann 			hci_inquiry_cache_update(hdev, &data);
1982a9de9248SMarcel Holtmann 		}
1983a9de9248SMarcel Holtmann 	} else {
1984a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
1985a9de9248SMarcel Holtmann 
1986a9de9248SMarcel Holtmann 		for (; num_rsp; num_rsp--) {
1987a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
1988a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
1989a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
1990a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
1991a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
1992a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
1993a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
199441a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
1995a9de9248SMarcel Holtmann 			info++;
1996a9de9248SMarcel Holtmann 			hci_inquiry_cache_update(hdev, &data);
1997a9de9248SMarcel Holtmann 		}
1998a9de9248SMarcel Holtmann 	}
1999a9de9248SMarcel Holtmann 
2000a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2001a9de9248SMarcel Holtmann }
2002a9de9248SMarcel Holtmann 
2003a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2004a9de9248SMarcel Holtmann {
200541a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
200641a96212SMarcel Holtmann 	struct hci_conn *conn;
200741a96212SMarcel Holtmann 
2008a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
200941a96212SMarcel Holtmann 
201041a96212SMarcel Holtmann 	hci_dev_lock(hdev);
201141a96212SMarcel Holtmann 
201241a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2013ccd556feSJohan Hedberg 	if (!conn)
2014ccd556feSJohan Hedberg 		goto unlock;
2015ccd556feSJohan Hedberg 
2016769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
201741a96212SMarcel Holtmann 		struct inquiry_entry *ie;
201841a96212SMarcel Holtmann 
2019cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2020cc11b9c1SAndrei Emeltchenko 		if (ie)
202141a96212SMarcel Holtmann 			ie->data.ssp_mode = (ev->features[0] & 0x01);
202241a96212SMarcel Holtmann 
202341a96212SMarcel Holtmann 		conn->ssp_mode = (ev->features[0] & 0x01);
202441a96212SMarcel Holtmann 	}
202541a96212SMarcel Holtmann 
2026ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2027ccd556feSJohan Hedberg 		goto unlock;
2028ccd556feSJohan Hedberg 
2029127178d2SJohan Hedberg 	if (!ev->status) {
2030127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2031127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2032127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2033127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2034127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2035127178d2SJohan Hedberg 	}
2036392599b9SJohan Hedberg 
2037127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2038769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2039769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2040769be974SMarcel Holtmann 		hci_conn_put(conn);
2041769be974SMarcel Holtmann 	}
2042769be974SMarcel Holtmann 
2043ccd556feSJohan Hedberg unlock:
204441a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
2045a9de9248SMarcel Holtmann }
2046a9de9248SMarcel Holtmann 
2047a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2048a9de9248SMarcel Holtmann {
2049b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2050b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
2051b6a0dc82SMarcel Holtmann 
2052b6a0dc82SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2053b6a0dc82SMarcel Holtmann 
2054b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
2055b6a0dc82SMarcel Holtmann 
2056b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
20579dc0a3afSMarcel Holtmann 	if (!conn) {
20589dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
20599dc0a3afSMarcel Holtmann 			goto unlock;
20609dc0a3afSMarcel Holtmann 
20619dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2062b6a0dc82SMarcel Holtmann 		if (!conn)
2063b6a0dc82SMarcel Holtmann 			goto unlock;
2064b6a0dc82SMarcel Holtmann 
20659dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
20669dc0a3afSMarcel Holtmann 	}
20679dc0a3afSMarcel Holtmann 
2068732547f9SMarcel Holtmann 	switch (ev->status) {
2069732547f9SMarcel Holtmann 	case 0x00:
2070732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
2071732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
2072732547f9SMarcel Holtmann 
20739eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
2074732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
2075732547f9SMarcel Holtmann 		break;
2076732547f9SMarcel Holtmann 
2077705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
2078732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
20791038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
2080732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
2081732547f9SMarcel Holtmann 		if (conn->out && conn->attempt < 2) {
2082efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2083efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
2084efc7688bSMarcel Holtmann 			hci_setup_sync(conn, conn->link->handle);
2085efc7688bSMarcel Holtmann 			goto unlock;
2086efc7688bSMarcel Holtmann 		}
2087732547f9SMarcel Holtmann 		/* fall through */
2088efc7688bSMarcel Holtmann 
2089732547f9SMarcel Holtmann 	default:
2090b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
2091732547f9SMarcel Holtmann 		break;
2092732547f9SMarcel Holtmann 	}
2093b6a0dc82SMarcel Holtmann 
2094b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
2095b6a0dc82SMarcel Holtmann 	if (ev->status)
2096b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
2097b6a0dc82SMarcel Holtmann 
2098b6a0dc82SMarcel Holtmann unlock:
2099b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
2100a9de9248SMarcel Holtmann }
2101a9de9248SMarcel Holtmann 
2102a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
2103a9de9248SMarcel Holtmann {
2104a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2105a9de9248SMarcel Holtmann }
2106a9de9248SMarcel Holtmann 
210704837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
210804837f64SMarcel Holtmann {
2109a9de9248SMarcel Holtmann 	struct hci_ev_sniff_subrate *ev = (void *) skb->data;
211004837f64SMarcel Holtmann 	struct hci_conn *conn;
211104837f64SMarcel Holtmann 
211204837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
211304837f64SMarcel Holtmann 
211404837f64SMarcel Holtmann 	hci_dev_lock(hdev);
211504837f64SMarcel Holtmann 
211604837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
211704837f64SMarcel Holtmann 	if (conn) {
211804837f64SMarcel Holtmann 	}
211904837f64SMarcel Holtmann 
212004837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
212104837f64SMarcel Holtmann }
212204837f64SMarcel Holtmann 
2123a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
2124a9de9248SMarcel Holtmann {
2125a9de9248SMarcel Holtmann 	struct inquiry_data data;
2126a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
2127a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2128a9de9248SMarcel Holtmann 
2129a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2130a9de9248SMarcel Holtmann 
2131a9de9248SMarcel Holtmann 	if (!num_rsp)
2132a9de9248SMarcel Holtmann 		return;
2133a9de9248SMarcel Holtmann 
2134a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2135a9de9248SMarcel Holtmann 
2136a9de9248SMarcel Holtmann 	for (; num_rsp; num_rsp--) {
2137a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
2138a9de9248SMarcel Holtmann 		data.pscan_rep_mode     = info->pscan_rep_mode;
2139a9de9248SMarcel Holtmann 		data.pscan_period_mode  = info->pscan_period_mode;
2140a9de9248SMarcel Holtmann 		data.pscan_mode         = 0x00;
2141a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
2142a9de9248SMarcel Holtmann 		data.clock_offset       = info->clock_offset;
2143a9de9248SMarcel Holtmann 		data.rssi               = info->rssi;
214441a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
2145a9de9248SMarcel Holtmann 		info++;
2146a9de9248SMarcel Holtmann 		hci_inquiry_cache_update(hdev, &data);
2147a9de9248SMarcel Holtmann 	}
2148a9de9248SMarcel Holtmann 
2149a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2150a9de9248SMarcel Holtmann }
2151a9de9248SMarcel Holtmann 
21520493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
21530493684eSMarcel Holtmann {
21540493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
21550493684eSMarcel Holtmann 	struct hci_conn *conn;
21560493684eSMarcel Holtmann 
21570493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
21580493684eSMarcel Holtmann 
21590493684eSMarcel Holtmann 	hci_dev_lock(hdev);
21600493684eSMarcel Holtmann 
21610493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
216203b555e1SJohan Hedberg 	if (!conn)
216303b555e1SJohan Hedberg 		goto unlock;
216403b555e1SJohan Hedberg 
21650493684eSMarcel Holtmann 	hci_conn_hold(conn);
21660493684eSMarcel Holtmann 
216703b555e1SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->flags))
216803b555e1SJohan Hedberg 		goto unlock;
216903b555e1SJohan Hedberg 
217003b555e1SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->flags) ||
217103b555e1SJohan Hedberg 			(conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
217203b555e1SJohan Hedberg 		/* FIXME: Do IO capa response based on information
217303b555e1SJohan Hedberg 		 * provided through the management interface */
217403b555e1SJohan Hedberg 	} else {
217503b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
217603b555e1SJohan Hedberg 
217703b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
217803b555e1SJohan Hedberg 		cp.reason = 0x16; /* Pairing not allowed */
217903b555e1SJohan Hedberg 
218003b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
218103b555e1SJohan Hedberg 							sizeof(cp), &cp);
218203b555e1SJohan Hedberg 	}
218303b555e1SJohan Hedberg 
218403b555e1SJohan Hedberg unlock:
218503b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
218603b555e1SJohan Hedberg }
218703b555e1SJohan Hedberg 
218803b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
218903b555e1SJohan Hedberg {
219003b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
219103b555e1SJohan Hedberg 	struct hci_conn *conn;
219203b555e1SJohan Hedberg 
219303b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
219403b555e1SJohan Hedberg 
219503b555e1SJohan Hedberg 	hci_dev_lock(hdev);
219603b555e1SJohan Hedberg 
219703b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
219803b555e1SJohan Hedberg 	if (!conn)
219903b555e1SJohan Hedberg 		goto unlock;
220003b555e1SJohan Hedberg 
220103b555e1SJohan Hedberg 	hci_conn_hold(conn);
220203b555e1SJohan Hedberg 
220303b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
220403b555e1SJohan Hedberg 	conn->remote_oob = ev->oob_data;
220503b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
220603b555e1SJohan Hedberg 
220703b555e1SJohan Hedberg unlock:
22080493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
22090493684eSMarcel Holtmann }
22100493684eSMarcel Holtmann 
22110493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
22120493684eSMarcel Holtmann {
22130493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
22140493684eSMarcel Holtmann 	struct hci_conn *conn;
22150493684eSMarcel Holtmann 
22160493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
22170493684eSMarcel Holtmann 
22180493684eSMarcel Holtmann 	hci_dev_lock(hdev);
22190493684eSMarcel Holtmann 
22200493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
22210493684eSMarcel Holtmann 	if (conn)
22220493684eSMarcel Holtmann 		hci_conn_put(conn);
22230493684eSMarcel Holtmann 
22240493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
22250493684eSMarcel Holtmann }
22260493684eSMarcel Holtmann 
222741a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
222841a96212SMarcel Holtmann {
222941a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
223041a96212SMarcel Holtmann 	struct inquiry_entry *ie;
223141a96212SMarcel Holtmann 
223241a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
223341a96212SMarcel Holtmann 
223441a96212SMarcel Holtmann 	hci_dev_lock(hdev);
223541a96212SMarcel Holtmann 
2236cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2237cc11b9c1SAndrei Emeltchenko 	if (ie)
223841a96212SMarcel Holtmann 		ie->data.ssp_mode = (ev->features[0] & 0x01);
223941a96212SMarcel Holtmann 
224041a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
224141a96212SMarcel Holtmann }
224241a96212SMarcel Holtmann 
22431da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
22441da177e4SLinus Torvalds {
2245a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
2246a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
22471da177e4SLinus Torvalds 
22481da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
22491da177e4SLinus Torvalds 
2250a9de9248SMarcel Holtmann 	switch (event) {
22511da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
22521da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
22531da177e4SLinus Torvalds 		break;
22541da177e4SLinus Torvalds 
22551da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
22561da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
22571da177e4SLinus Torvalds 		break;
22581da177e4SLinus Torvalds 
2259a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
2260a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
226121d9e30eSMarcel Holtmann 		break;
226221d9e30eSMarcel Holtmann 
22631da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
22641da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
22651da177e4SLinus Torvalds 		break;
22661da177e4SLinus Torvalds 
22671da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
22681da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
22691da177e4SLinus Torvalds 		break;
22701da177e4SLinus Torvalds 
22711da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
22721da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
22731da177e4SLinus Torvalds 		break;
22741da177e4SLinus Torvalds 
2275a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
2276a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
2277a9de9248SMarcel Holtmann 		break;
2278a9de9248SMarcel Holtmann 
22791da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
22801da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
22811da177e4SLinus Torvalds 		break;
22821da177e4SLinus Torvalds 
2283a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
2284a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
2285a9de9248SMarcel Holtmann 		break;
2286a9de9248SMarcel Holtmann 
2287a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
2288a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
2289a9de9248SMarcel Holtmann 		break;
2290a9de9248SMarcel Holtmann 
2291a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_VERSION:
2292a9de9248SMarcel Holtmann 		hci_remote_version_evt(hdev, skb);
2293a9de9248SMarcel Holtmann 		break;
2294a9de9248SMarcel Holtmann 
2295a9de9248SMarcel Holtmann 	case HCI_EV_QOS_SETUP_COMPLETE:
2296a9de9248SMarcel Holtmann 		hci_qos_setup_complete_evt(hdev, skb);
2297a9de9248SMarcel Holtmann 		break;
2298a9de9248SMarcel Holtmann 
2299a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
2300a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
2301a9de9248SMarcel Holtmann 		break;
2302a9de9248SMarcel Holtmann 
2303a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
2304a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
2305a9de9248SMarcel Holtmann 		break;
2306a9de9248SMarcel Holtmann 
2307a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
2308a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
2309a9de9248SMarcel Holtmann 		break;
2310a9de9248SMarcel Holtmann 
2311a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
2312a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
2313a9de9248SMarcel Holtmann 		break;
2314a9de9248SMarcel Holtmann 
2315a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
2316a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
23171da177e4SLinus Torvalds 		break;
23181da177e4SLinus Torvalds 
23191da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
23201da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
23211da177e4SLinus Torvalds 		break;
23221da177e4SLinus Torvalds 
23231da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
23241da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
23251da177e4SLinus Torvalds 		break;
23261da177e4SLinus Torvalds 
23271da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
23281da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
23291da177e4SLinus Torvalds 		break;
23301da177e4SLinus Torvalds 
23311da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
23321da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
23331da177e4SLinus Torvalds 		break;
23341da177e4SLinus Torvalds 
2335a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
2336a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
2337a8746417SMarcel Holtmann 		break;
2338a8746417SMarcel Holtmann 
233985a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
234085a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
234185a1e930SMarcel Holtmann 		break;
234285a1e930SMarcel Holtmann 
2343a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
2344a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
2345a9de9248SMarcel Holtmann 		break;
2346a9de9248SMarcel Holtmann 
2347a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
2348a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
2349a9de9248SMarcel Holtmann 		break;
2350a9de9248SMarcel Holtmann 
2351a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
2352a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
2353a9de9248SMarcel Holtmann 		break;
2354a9de9248SMarcel Holtmann 
2355a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_CHANGED:
2356a9de9248SMarcel Holtmann 		hci_sync_conn_changed_evt(hdev, skb);
2357a9de9248SMarcel Holtmann 		break;
2358a9de9248SMarcel Holtmann 
235904837f64SMarcel Holtmann 	case HCI_EV_SNIFF_SUBRATE:
236004837f64SMarcel Holtmann 		hci_sniff_subrate_evt(hdev, skb);
236104837f64SMarcel Holtmann 		break;
236204837f64SMarcel Holtmann 
2363a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
2364a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
23651da177e4SLinus Torvalds 		break;
23661da177e4SLinus Torvalds 
23670493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
23680493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
23690493684eSMarcel Holtmann 		break;
23700493684eSMarcel Holtmann 
237103b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
237203b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
237303b555e1SJohan Hedberg 		break;
237403b555e1SJohan Hedberg 
23750493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
23760493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
23770493684eSMarcel Holtmann 		break;
23780493684eSMarcel Holtmann 
237941a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
238041a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
238141a96212SMarcel Holtmann 		break;
238241a96212SMarcel Holtmann 
23831da177e4SLinus Torvalds 	default:
2384a9de9248SMarcel Holtmann 		BT_DBG("%s event 0x%x", hdev->name, event);
23851da177e4SLinus Torvalds 		break;
23861da177e4SLinus Torvalds 	}
23871da177e4SLinus Torvalds 
23881da177e4SLinus Torvalds 	kfree_skb(skb);
23891da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
23901da177e4SLinus Torvalds }
23911da177e4SLinus Torvalds 
23921da177e4SLinus Torvalds /* Generate internal stack event */
23931da177e4SLinus Torvalds void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
23941da177e4SLinus Torvalds {
23951da177e4SLinus Torvalds 	struct hci_event_hdr *hdr;
23961da177e4SLinus Torvalds 	struct hci_ev_stack_internal *ev;
23971da177e4SLinus Torvalds 	struct sk_buff *skb;
23981da177e4SLinus Torvalds 
23991da177e4SLinus Torvalds 	skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC);
24001da177e4SLinus Torvalds 	if (!skb)
24011da177e4SLinus Torvalds 		return;
24021da177e4SLinus Torvalds 
24031da177e4SLinus Torvalds 	hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE);
24041da177e4SLinus Torvalds 	hdr->evt  = HCI_EV_STACK_INTERNAL;
24051da177e4SLinus Torvalds 	hdr->plen = sizeof(*ev) + dlen;
24061da177e4SLinus Torvalds 
24071da177e4SLinus Torvalds 	ev  = (void *) skb_put(skb, sizeof(*ev) + dlen);
24081da177e4SLinus Torvalds 	ev->type = type;
24091da177e4SLinus Torvalds 	memcpy(ev->data, data, dlen);
24101da177e4SLinus Torvalds 
2411576c7d85SMarcel Holtmann 	bt_cb(skb)->incoming = 1;
2412a61bbcf2SPatrick McHardy 	__net_timestamp(skb);
2413576c7d85SMarcel Holtmann 
24140d48d939SMarcel Holtmann 	bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
24151da177e4SLinus Torvalds 	skb->dev = (void *) hdev;
2416eec8d2bcSJohan Hedberg 	hci_send_to_sock(hdev, skb, NULL);
24171da177e4SLinus Torvalds 	kfree_skb(skb);
24181da177e4SLinus Torvalds }
2419