blob: 8efb9c0d9b2c9b36428324d3f782b052e25fc25a [file] [log] [blame]
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 BlueZ - Bluetooth protocol stack for Linux
Ron Shaffer2d0a0342010-05-28 11:53:46 -04003 Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004
5 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation;
10
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
14 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090015 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
16 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070018 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090020 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070022 SOFTWARE IS DISCLAIMED.
23*/
24
25/* Bluetooth HCI event handling. */
26
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <asm/unaligned.h>
28
29#include <net/bluetooth/bluetooth.h>
30#include <net/bluetooth/hci_core.h>
Mikel Astizf0d6a0e2012-08-09 09:52:30 +020031#include <net/bluetooth/mgmt.h>
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +030032#include <net/bluetooth/a2mp.h>
Andrei Emeltchenko903e4542012-09-27 17:26:09 +030033#include <net/bluetooth/amp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034
Linus Torvalds1da177e2005-04-16 15:20:36 -070035/* Handle HCI Event packets */
36
Marcel Holtmanna9de9242007-10-20 13:33:56 +020037static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070038{
Marcel Holtmanna9de9242007-10-20 13:33:56 +020039 __u8 status = *((__u8 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -070040
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +030041 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -070042
Andre Guedese6d465c2011-11-09 17:14:26 -030043 if (status) {
44 hci_dev_lock(hdev);
45 mgmt_stop_discovery_failed(hdev, status);
46 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +020047 return;
Andre Guedese6d465c2011-11-09 17:14:26 -030048 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070049
Andre Guedes89352e72011-11-04 14:16:53 -030050 clear_bit(HCI_INQUIRY, &hdev->flags);
51
Johan Hedberg56e5cb82011-11-08 20:40:16 +020052 hci_dev_lock(hdev);
Johan Hedbergff9ef572012-01-04 14:23:45 +020053 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Johan Hedberg56e5cb82011-11-08 20:40:16 +020054 hci_dev_unlock(hdev);
Marcel Holtmann6bd57412006-11-18 22:14:22 +010055
Marcel Holtmanna9de9242007-10-20 13:33:56 +020056 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -070057}
58
Andre Guedes4d934832012-03-21 00:03:35 -030059static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
60{
61 __u8 status = *((__u8 *) skb->data);
62
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +030063 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedesae854a72012-03-21 00:03:36 -030064
65 if (status)
66 return;
67
68 set_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
Andre Guedes4d934832012-03-21 00:03:35 -030069}
70
Marcel Holtmanna9de9242007-10-20 13:33:56 +020071static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070072{
Marcel Holtmanna9de9242007-10-20 13:33:56 +020073 __u8 status = *((__u8 *) skb->data);
74
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +030075 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +020076
77 if (status)
78 return;
79
Andre Guedesae854a72012-03-21 00:03:36 -030080 clear_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
81
Marcel Holtmanna9de9242007-10-20 13:33:56 +020082 hci_conn_check_pending(hdev);
83}
84
Gustavo Padovan807deac2012-05-17 00:36:24 -030085static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev,
86 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +020087{
88 BT_DBG("%s", hdev->name);
89}
90
91static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
92{
93 struct hci_rp_role_discovery *rp = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -070094 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -070095
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +030096 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -070097
Marcel Holtmanna9de9242007-10-20 13:33:56 +020098 if (rp->status)
99 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200101 hci_dev_lock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200103 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
104 if (conn) {
105 if (rp->role)
106 conn->link_mode &= ~HCI_LM_MASTER;
107 else
108 conn->link_mode |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200110
111 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112}
113
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200114static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
115{
116 struct hci_rp_read_link_policy *rp = (void *) skb->data;
117 struct hci_conn *conn;
118
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300119 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200120
121 if (rp->status)
122 return;
123
124 hci_dev_lock(hdev);
125
126 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
127 if (conn)
128 conn->link_policy = __le16_to_cpu(rp->policy);
129
130 hci_dev_unlock(hdev);
131}
132
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200133static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200135 struct hci_rp_write_link_policy *rp = (void *) skb->data;
136 struct hci_conn *conn;
137 void *sent;
138
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300139 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200140
141 if (rp->status)
142 return;
143
144 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
145 if (!sent)
146 return;
147
148 hci_dev_lock(hdev);
149
150 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200151 if (conn)
Harvey Harrison83985312008-05-02 16:25:46 -0700152 conn->link_policy = get_unaligned_le16(sent + 2);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200153
154 hci_dev_unlock(hdev);
155}
156
Gustavo Padovan807deac2012-05-17 00:36:24 -0300157static void hci_cc_read_def_link_policy(struct hci_dev *hdev,
158 struct sk_buff *skb)
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200159{
160 struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
161
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300162 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200163
164 if (rp->status)
165 return;
166
167 hdev->link_policy = __le16_to_cpu(rp->policy);
168}
169
Gustavo Padovan807deac2012-05-17 00:36:24 -0300170static void hci_cc_write_def_link_policy(struct hci_dev *hdev,
171 struct sk_buff *skb)
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200172{
173 __u8 status = *((__u8 *) skb->data);
174 void *sent;
175
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300176 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200177
178 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
179 if (!sent)
180 return;
181
182 if (!status)
183 hdev->link_policy = get_unaligned_le16(sent);
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200184}
185
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200186static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
187{
188 __u8 status = *((__u8 *) skb->data);
189
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300190 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200191
Gustavo F. Padovan10572132011-03-16 15:36:29 -0300192 clear_bit(HCI_RESET, &hdev->flags);
193
Johan Hedberga297e972012-02-21 17:55:47 +0200194 /* Reset all non-persistent flags */
Johan Hedberg2cc6fb02013-03-15 17:06:57 -0500195 hdev->dev_flags &= ~HCI_PERSISTENT_MASK;
Andre Guedes69775ff2012-02-23 16:50:05 +0200196
197 hdev->discovery.state = DISCOVERY_STOPPED;
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100198 hdev->inq_tx_power = HCI_TX_POWER_INVALID;
199 hdev->adv_tx_power = HCI_TX_POWER_INVALID;
Johan Hedberg3f0f5242012-11-08 01:23:00 +0100200
201 memset(hdev->adv_data, 0, sizeof(hdev->adv_data));
202 hdev->adv_data_len = 0;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200203}
204
205static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
206{
207 __u8 status = *((__u8 *) skb->data);
208 void *sent;
209
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300210 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200211
212 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
213 if (!sent)
214 return;
215
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200216 hci_dev_lock(hdev);
217
Johan Hedbergf51d5b22012-02-22 18:17:32 +0200218 if (test_bit(HCI_MGMT, &hdev->dev_flags))
219 mgmt_set_local_name_complete(hdev, sent, status);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +0200220 else if (!status)
221 memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
Johan Hedbergf51d5b22012-02-22 18:17:32 +0200222
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200223 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200224}
225
226static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
227{
228 struct hci_rp_read_local_name *rp = (void *) skb->data;
229
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300230 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200231
232 if (rp->status)
233 return;
234
Johan Hedbergdb99b5f2012-02-22 20:14:22 +0200235 if (test_bit(HCI_SETUP, &hdev->dev_flags))
236 memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200237}
238
239static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
240{
241 __u8 status = *((__u8 *) skb->data);
242 void *sent;
243
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300244 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200245
246 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
247 if (!sent)
248 return;
249
250 if (!status) {
251 __u8 param = *((__u8 *) sent);
252
253 if (param == AUTH_ENABLED)
254 set_bit(HCI_AUTH, &hdev->flags);
255 else
256 clear_bit(HCI_AUTH, &hdev->flags);
257 }
258
Johan Hedberg33ef95e2012-02-16 23:56:27 +0200259 if (test_bit(HCI_MGMT, &hdev->dev_flags))
260 mgmt_auth_enable_complete(hdev, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200261}
262
263static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
264{
265 __u8 status = *((__u8 *) skb->data);
266 void *sent;
267
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300268 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200269
270 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
271 if (!sent)
272 return;
273
274 if (!status) {
275 __u8 param = *((__u8 *) sent);
276
277 if (param)
278 set_bit(HCI_ENCRYPT, &hdev->flags);
279 else
280 clear_bit(HCI_ENCRYPT, &hdev->flags);
281 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200282}
283
284static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
285{
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200286 __u8 param, status = *((__u8 *) skb->data);
287 int old_pscan, old_iscan;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200288 void *sent;
289
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300290 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200291
292 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
293 if (!sent)
294 return;
295
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200296 param = *((__u8 *) sent);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200297
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200298 hci_dev_lock(hdev);
299
Mikel Astizfa1bd912012-08-09 09:52:29 +0200300 if (status) {
Johan Hedberg744cf192011-11-08 20:40:14 +0200301 mgmt_write_scan_failed(hdev, param, status);
Johan Hedberg2d7cee52011-11-07 22:16:03 +0200302 hdev->discov_timeout = 0;
303 goto done;
304 }
305
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200306 old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
307 old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200308
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200309 if (param & SCAN_INQUIRY) {
310 set_bit(HCI_ISCAN, &hdev->flags);
311 if (!old_iscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200312 mgmt_discoverable(hdev, 1);
Johan Hedberg16ab91a2011-11-07 22:16:02 +0200313 if (hdev->discov_timeout > 0) {
314 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
315 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300316 to);
Johan Hedberg16ab91a2011-11-07 22:16:02 +0200317 }
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200318 } else if (old_iscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200319 mgmt_discoverable(hdev, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200320
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200321 if (param & SCAN_PAGE) {
322 set_bit(HCI_PSCAN, &hdev->flags);
323 if (!old_pscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200324 mgmt_connectable(hdev, 1);
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200325 } else if (old_pscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200326 mgmt_connectable(hdev, 0);
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200327
328done:
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200329 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200330}
331
332static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
333{
334 struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
335
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300336 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200337
338 if (rp->status)
339 return;
340
341 memcpy(hdev->dev_class, rp->dev_class, 3);
342
343 BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300344 hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200345}
346
347static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
348{
349 __u8 status = *((__u8 *) skb->data);
350 void *sent;
351
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300352 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200353
354 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
355 if (!sent)
356 return;
357
Marcel Holtmann7f9a9032012-02-22 18:38:01 +0100358 hci_dev_lock(hdev);
359
360 if (status == 0)
361 memcpy(hdev->dev_class, sent, 3);
362
363 if (test_bit(HCI_MGMT, &hdev->dev_flags))
364 mgmt_set_class_of_dev_complete(hdev, sent, status);
365
366 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200367}
368
369static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
370{
371 struct hci_rp_read_voice_setting *rp = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372 __u16 setting;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200373
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300374 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200375
376 if (rp->status)
377 return;
378
379 setting = __le16_to_cpu(rp->voice_setting);
380
Marcel Holtmannf383f272008-07-14 20:13:47 +0200381 if (hdev->voice_setting == setting)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200382 return;
383
384 hdev->voice_setting = setting;
385
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300386 BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200387
Gustavo F. Padovan3c547112011-12-14 22:58:44 -0200388 if (hdev->notify)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200389 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200390}
391
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300392static void hci_cc_write_voice_setting(struct hci_dev *hdev,
393 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200394{
395 __u8 status = *((__u8 *) skb->data);
Marcel Holtmannf383f272008-07-14 20:13:47 +0200396 __u16 setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397 void *sent;
398
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300399 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400
Marcel Holtmannf383f272008-07-14 20:13:47 +0200401 if (status)
402 return;
403
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200404 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
405 if (!sent)
406 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407
Marcel Holtmannf383f272008-07-14 20:13:47 +0200408 setting = get_unaligned_le16(sent);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409
Marcel Holtmannf383f272008-07-14 20:13:47 +0200410 if (hdev->voice_setting == setting)
411 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412
Marcel Holtmannf383f272008-07-14 20:13:47 +0200413 hdev->voice_setting = setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300415 BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
Marcel Holtmannf383f272008-07-14 20:13:47 +0200416
Gustavo F. Padovan3c547112011-12-14 22:58:44 -0200417 if (hdev->notify)
Marcel Holtmannf383f272008-07-14 20:13:47 +0200418 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419}
420
Marcel Holtmann333140b2008-07-14 20:13:48 +0200421static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
422{
423 __u8 status = *((__u8 *) skb->data);
Johan Hedberg5ed8eb22012-10-25 00:09:51 +0300424 struct hci_cp_write_ssp_mode *sent;
Marcel Holtmann333140b2008-07-14 20:13:48 +0200425
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300426 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann333140b2008-07-14 20:13:48 +0200427
Marcel Holtmann333140b2008-07-14 20:13:48 +0200428 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
429 if (!sent)
430 return;
431
Johan Hedberg5ed8eb22012-10-25 00:09:51 +0300432 if (!status) {
433 if (sent->mode)
434 hdev->host_features[0] |= LMP_HOST_SSP;
435 else
436 hdev->host_features[0] &= ~LMP_HOST_SSP;
437 }
438
Johan Hedberged2c4ee2012-02-17 00:56:28 +0200439 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg5ed8eb22012-10-25 00:09:51 +0300440 mgmt_ssp_enable_complete(hdev, sent->mode, status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +0200441 else if (!status) {
Johan Hedberg5ed8eb22012-10-25 00:09:51 +0300442 if (sent->mode)
Johan Hedbergc0ecddc2012-02-22 12:38:31 +0200443 set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
444 else
445 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
446 }
Marcel Holtmann333140b2008-07-14 20:13:48 +0200447}
448
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200449static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
450{
451 struct hci_rp_read_local_version *rp = (void *) skb->data;
452
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300453 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200454
455 if (rp->status)
Johan Hedberg42c6b122013-03-05 20:37:49 +0200456 return;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200457
458 hdev->hci_ver = rp->hci_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200459 hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200460 hdev->lmp_ver = rp->lmp_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200461 hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200462 hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200463
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300464 BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300465 hdev->manufacturer, hdev->hci_ver, hdev->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200466}
467
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300468static void hci_cc_read_local_commands(struct hci_dev *hdev,
469 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200470{
471 struct hci_rp_read_local_commands *rp = (void *) skb->data;
472
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300473 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200474
Johan Hedberg2177bab2013-03-05 20:37:43 +0200475 if (!rp->status)
476 memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200477}
478
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300479static void hci_cc_read_local_features(struct hci_dev *hdev,
480 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200481{
482 struct hci_rp_read_local_features *rp = (void *) skb->data;
483
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300484 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200485
486 if (rp->status)
487 return;
488
489 memcpy(hdev->features, rp->features, 8);
490
491 /* Adjust default settings according to features
492 * supported by device. */
493
494 if (hdev->features[0] & LMP_3SLOT)
495 hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
496
497 if (hdev->features[0] & LMP_5SLOT)
498 hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
499
500 if (hdev->features[1] & LMP_HV2) {
501 hdev->pkt_type |= (HCI_HV2);
502 hdev->esco_type |= (ESCO_HV2);
503 }
504
505 if (hdev->features[1] & LMP_HV3) {
506 hdev->pkt_type |= (HCI_HV3);
507 hdev->esco_type |= (ESCO_HV3);
508 }
509
Andre Guedes45db810f2012-07-24 15:03:49 -0300510 if (lmp_esco_capable(hdev))
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200511 hdev->esco_type |= (ESCO_EV3);
512
513 if (hdev->features[4] & LMP_EV4)
514 hdev->esco_type |= (ESCO_EV4);
515
516 if (hdev->features[4] & LMP_EV5)
517 hdev->esco_type |= (ESCO_EV5);
518
Marcel Holtmannefc76882009-02-06 09:13:37 +0100519 if (hdev->features[5] & LMP_EDR_ESCO_2M)
520 hdev->esco_type |= (ESCO_2EV3);
521
522 if (hdev->features[5] & LMP_EDR_ESCO_3M)
523 hdev->esco_type |= (ESCO_3EV3);
524
525 if (hdev->features[5] & LMP_EDR_3S_ESCO)
526 hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
527
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200528 BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300529 hdev->features[0], hdev->features[1],
530 hdev->features[2], hdev->features[3],
531 hdev->features[4], hdev->features[5],
532 hdev->features[6], hdev->features[7]);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200533}
534
Andre Guedes971e3a42011-06-30 19:20:52 -0300535static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300536 struct sk_buff *skb)
Andre Guedes971e3a42011-06-30 19:20:52 -0300537{
538 struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
539
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300540 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andre Guedes971e3a42011-06-30 19:20:52 -0300541
542 if (rp->status)
Johan Hedberg42c6b122013-03-05 20:37:49 +0200543 return;
Andre Guedes971e3a42011-06-30 19:20:52 -0300544
Andre Guedesb5b32b62011-12-30 10:34:04 -0300545 switch (rp->page) {
546 case 0:
547 memcpy(hdev->features, rp->features, 8);
548 break;
549 case 1:
550 memcpy(hdev->host_features, rp->features, 8);
551 break;
552 }
Andre Guedes971e3a42011-06-30 19:20:52 -0300553}
554
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200555static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300556 struct sk_buff *skb)
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200557{
558 struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
559
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300560 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200561
Johan Hedberg42c6b122013-03-05 20:37:49 +0200562 if (!rp->status)
563 hdev->flow_ctl_mode = rp->mode;
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200564}
565
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200566static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
567{
568 struct hci_rp_read_buffer_size *rp = (void *) skb->data;
569
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300570 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200571
572 if (rp->status)
573 return;
574
575 hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu);
576 hdev->sco_mtu = rp->sco_mtu;
577 hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
578 hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
579
580 if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
581 hdev->sco_mtu = 64;
582 hdev->sco_pkts = 8;
583 }
584
585 hdev->acl_cnt = hdev->acl_pkts;
586 hdev->sco_cnt = hdev->sco_pkts;
587
Gustavo Padovan807deac2012-05-17 00:36:24 -0300588 BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
589 hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200590}
591
592static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
593{
594 struct hci_rp_read_bd_addr *rp = (void *) skb->data;
595
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300596 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200597
598 if (!rp->status)
599 bacpy(&hdev->bdaddr, &rp->bdaddr);
Johan Hedberg23bb5762010-12-21 23:01:27 +0200600}
601
Johan Hedbergf332ec62013-03-15 17:07:11 -0500602static void hci_cc_read_page_scan_activity(struct hci_dev *hdev,
603 struct sk_buff *skb)
604{
605 struct hci_rp_read_page_scan_activity *rp = (void *) skb->data;
606
607 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
608
609 if (test_bit(HCI_INIT, &hdev->flags) && !rp->status) {
610 hdev->page_scan_interval = __le16_to_cpu(rp->interval);
611 hdev->page_scan_window = __le16_to_cpu(rp->window);
612 }
613}
614
Johan Hedberg4a3ee762013-03-15 17:07:12 -0500615static void hci_cc_write_page_scan_activity(struct hci_dev *hdev,
616 struct sk_buff *skb)
617{
618 u8 status = *((u8 *) skb->data);
619 struct hci_cp_write_page_scan_activity *sent;
620
621 BT_DBG("%s status 0x%2.2x", hdev->name, status);
622
623 if (status)
624 return;
625
626 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY);
627 if (!sent)
628 return;
629
630 hdev->page_scan_interval = __le16_to_cpu(sent->interval);
631 hdev->page_scan_window = __le16_to_cpu(sent->window);
632}
633
Johan Hedbergf332ec62013-03-15 17:07:11 -0500634static void hci_cc_read_page_scan_type(struct hci_dev *hdev,
635 struct sk_buff *skb)
636{
637 struct hci_rp_read_page_scan_type *rp = (void *) skb->data;
638
639 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
640
641 if (test_bit(HCI_INIT, &hdev->flags) && !rp->status)
642 hdev->page_scan_type = rp->type;
643}
644
Johan Hedberg4a3ee762013-03-15 17:07:12 -0500645static void hci_cc_write_page_scan_type(struct hci_dev *hdev,
646 struct sk_buff *skb)
647{
648 u8 status = *((u8 *) skb->data);
649 u8 *type;
650
651 BT_DBG("%s status 0x%2.2x", hdev->name, status);
652
653 if (status)
654 return;
655
656 type = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE);
657 if (type)
658 hdev->page_scan_type = *type;
659}
660
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200661static void hci_cc_read_data_block_size(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300662 struct sk_buff *skb)
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200663{
664 struct hci_rp_read_data_block_size *rp = (void *) skb->data;
665
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300666 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200667
668 if (rp->status)
669 return;
670
671 hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
672 hdev->block_len = __le16_to_cpu(rp->block_len);
673 hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
674
675 hdev->block_cnt = hdev->num_blocks;
676
677 BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300678 hdev->block_cnt, hdev->block_len);
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200679}
680
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300681static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300682 struct sk_buff *skb)
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300683{
684 struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
685
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300686 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300687
688 if (rp->status)
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +0300689 goto a2mp_rsp;
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300690
691 hdev->amp_status = rp->amp_status;
692 hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
693 hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
694 hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
695 hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
696 hdev->amp_type = rp->amp_type;
697 hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
698 hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
699 hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
700 hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
701
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +0300702a2mp_rsp:
703 a2mp_send_getinfo_rsp(hdev);
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300704}
705
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300706static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev,
707 struct sk_buff *skb)
708{
709 struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data;
710 struct amp_assoc *assoc = &hdev->loc_assoc;
711 size_t rem_len, frag_len;
712
713 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
714
715 if (rp->status)
716 goto a2mp_rsp;
717
718 frag_len = skb->len - sizeof(*rp);
719 rem_len = __le16_to_cpu(rp->rem_len);
720
721 if (rem_len > frag_len) {
Andrei Emeltchenko2e430be32012-09-28 14:44:23 +0300722 BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len);
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300723
724 memcpy(assoc->data + assoc->offset, rp->frag, frag_len);
725 assoc->offset += frag_len;
726
727 /* Read other fragments */
728 amp_read_loc_assoc_frag(hdev, rp->phy_handle);
729
730 return;
731 }
732
733 memcpy(assoc->data + assoc->offset, rp->frag, rem_len);
734 assoc->len = assoc->offset + rem_len;
735 assoc->offset = 0;
736
737a2mp_rsp:
738 /* Send A2MP Rsp when all fragments are received */
739 a2mp_send_getampassoc_rsp(hdev, rp->status);
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +0300740 a2mp_send_create_phy_link_req(hdev, rp->status);
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300741}
742
Johan Hedbergd5859e22011-01-25 01:19:58 +0200743static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300744 struct sk_buff *skb)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200745{
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700746 struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
Johan Hedbergd5859e22011-01-25 01:19:58 +0200747
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300748 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200749
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700750 if (!rp->status)
751 hdev->inq_tx_power = rp->tx_power;
Johan Hedbergd5859e22011-01-25 01:19:58 +0200752}
753
Johan Hedberg980e1a52011-01-22 06:10:07 +0200754static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
755{
756 struct hci_rp_pin_code_reply *rp = (void *) skb->data;
757 struct hci_cp_pin_code_reply *cp;
758 struct hci_conn *conn;
759
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300760 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200761
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200762 hci_dev_lock(hdev);
763
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200764 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200765 mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200766
Mikel Astizfa1bd912012-08-09 09:52:29 +0200767 if (rp->status)
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200768 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +0200769
770 cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
771 if (!cp)
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200772 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +0200773
774 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
775 if (conn)
776 conn->pin_length = cp->pin_len;
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200777
778unlock:
779 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200780}
781
782static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
783{
784 struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
785
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300786 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200787
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200788 hci_dev_lock(hdev);
789
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200790 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200791 mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300792 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200793
794 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200795}
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200796
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300797static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
798 struct sk_buff *skb)
799{
800 struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
801
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300802 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300803
804 if (rp->status)
805 return;
806
807 hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
808 hdev->le_pkts = rp->le_max_pkt;
809
810 hdev->le_cnt = hdev->le_pkts;
811
812 BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300813}
Johan Hedberg980e1a52011-01-22 06:10:07 +0200814
Johan Hedberg60e77322013-01-22 14:01:59 +0200815static void hci_cc_le_read_local_features(struct hci_dev *hdev,
816 struct sk_buff *skb)
817{
818 struct hci_rp_le_read_local_features *rp = (void *) skb->data;
819
820 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
821
822 if (!rp->status)
823 memcpy(hdev->le_features, rp->features, 8);
Johan Hedberg60e77322013-01-22 14:01:59 +0200824}
825
Johan Hedberg8fa19092012-10-19 20:57:49 +0300826static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
827 struct sk_buff *skb)
828{
829 struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data;
830
831 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
832
Johan Hedberg04b4edc2013-03-15 17:07:01 -0500833 if (!rp->status)
Johan Hedberg8fa19092012-10-19 20:57:49 +0300834 hdev->adv_tx_power = rp->tx_power;
Johan Hedberg8fa19092012-10-19 20:57:49 +0300835}
836
Johan Hedberga5c29682011-02-19 12:05:57 -0300837static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
838{
839 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
840
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300841 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberga5c29682011-02-19 12:05:57 -0300842
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200843 hci_dev_lock(hdev);
844
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200845 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300846 mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
847 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200848
849 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -0300850}
851
852static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300853 struct sk_buff *skb)
Johan Hedberga5c29682011-02-19 12:05:57 -0300854{
855 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
856
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300857 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberga5c29682011-02-19 12:05:57 -0300858
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200859 hci_dev_lock(hdev);
860
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200861 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200862 mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300863 ACL_LINK, 0, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200864
865 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -0300866}
867
Brian Gix1143d452011-11-23 08:28:34 -0800868static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
869{
870 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
871
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300872 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -0800873
874 hci_dev_lock(hdev);
875
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200876 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +0200877 mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300878 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -0800879
880 hci_dev_unlock(hdev);
881}
882
883static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300884 struct sk_buff *skb)
Brian Gix1143d452011-11-23 08:28:34 -0800885{
886 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
887
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300888 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -0800889
890 hci_dev_lock(hdev);
891
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200892 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Brian Gix1143d452011-11-23 08:28:34 -0800893 mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300894 ACL_LINK, 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -0800895
896 hci_dev_unlock(hdev);
897}
898
Szymon Jancc35938b2011-03-22 13:12:21 +0100899static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300900 struct sk_buff *skb)
Szymon Jancc35938b2011-03-22 13:12:21 +0100901{
902 struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
903
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300904 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Szymon Jancc35938b2011-03-22 13:12:21 +0100905
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200906 hci_dev_lock(hdev);
Johan Hedberg744cf192011-11-08 20:40:14 +0200907 mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
Szymon Jancc35938b2011-03-22 13:12:21 +0100908 rp->randomizer, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200909 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +0100910}
911
Johan Hedbergc1d5dc42012-11-08 01:23:01 +0100912static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
913{
914 __u8 *sent, status = *((__u8 *) skb->data);
915
916 BT_DBG("%s status 0x%2.2x", hdev->name, status);
917
918 sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE);
919 if (!sent)
920 return;
921
922 hci_dev_lock(hdev);
923
924 if (!status) {
925 if (*sent)
926 set_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
927 else
928 clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
929 }
930
Johan Hedberg04b4edc2013-03-15 17:07:01 -0500931 if (!test_bit(HCI_INIT, &hdev->flags)) {
932 struct hci_request req;
Johan Hedbergc1d5dc42012-11-08 01:23:01 +0100933
Johan Hedberg04b4edc2013-03-15 17:07:01 -0500934 hci_req_init(&req, hdev);
935 hci_update_ad(&req);
936 hci_req_run(&req, NULL);
937 }
938
939 hci_dev_unlock(hdev);
Johan Hedbergc1d5dc42012-11-08 01:23:01 +0100940}
941
Andre Guedes07f7fa52011-12-02 21:13:31 +0900942static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
943{
944 __u8 status = *((__u8 *) skb->data);
945
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300946 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -0300947
Andre Guedes3fd24152012-02-03 17:48:01 -0300948 if (status) {
949 hci_dev_lock(hdev);
950 mgmt_start_discovery_failed(hdev, status);
951 hci_dev_unlock(hdev);
952 return;
953 }
Andre Guedes07f7fa52011-12-02 21:13:31 +0900954}
955
Andre Guedeseb9d91f2011-05-26 16:23:52 -0300956static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300957 struct sk_buff *skb)
Andre Guedeseb9d91f2011-05-26 16:23:52 -0300958{
959 struct hci_cp_le_set_scan_enable *cp;
960 __u8 status = *((__u8 *) skb->data);
961
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300962 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedeseb9d91f2011-05-26 16:23:52 -0300963
Andre Guedeseb9d91f2011-05-26 16:23:52 -0300964 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
965 if (!cp)
966 return;
967
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +0200968 switch (cp->enable) {
969 case LE_SCANNING_ENABLED:
Andre Guedes3fd24152012-02-03 17:48:01 -0300970 if (status) {
971 hci_dev_lock(hdev);
972 mgmt_start_discovery_failed(hdev, status);
973 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -0300974 return;
Andre Guedes3fd24152012-02-03 17:48:01 -0300975 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -0300976
Andre Guedesd23264a2011-11-25 20:53:38 -0300977 set_bit(HCI_LE_SCAN, &hdev->dev_flags);
978
Andre Guedesa8f13c82011-09-09 18:56:24 -0300979 hci_dev_lock(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -0300980 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedesa8f13c82011-09-09 18:56:24 -0300981 hci_dev_unlock(hdev);
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +0200982 break;
983
984 case LE_SCANNING_DISABLED:
Andre Guedesc9ecc482012-03-15 16:52:08 -0300985 if (status) {
986 hci_dev_lock(hdev);
987 mgmt_stop_discovery_failed(hdev, status);
988 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -0300989 return;
Andre Guedesc9ecc482012-03-15 16:52:08 -0300990 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -0300991
Andre Guedesd23264a2011-11-25 20:53:38 -0300992 clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
993
Andre Guedesbc3dd332012-03-06 19:37:06 -0300994 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
995 hdev->discovery.state == DISCOVERY_FINDING) {
Andre Guedes5e0452c2012-02-17 20:39:38 -0300996 mgmt_interleaved_discovery(hdev);
997 } else {
998 hci_dev_lock(hdev);
999 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1000 hci_dev_unlock(hdev);
1001 }
1002
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001003 break;
1004
1005 default:
1006 BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
1007 break;
Andre Guedes35815082011-05-26 16:23:53 -03001008 }
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001009}
1010
Johan Hedbergcf1d0812013-01-22 14:02:00 +02001011static void hci_cc_le_read_white_list_size(struct hci_dev *hdev,
1012 struct sk_buff *skb)
1013{
1014 struct hci_rp_le_read_white_list_size *rp = (void *) skb->data;
1015
1016 BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size);
1017
1018 if (!rp->status)
1019 hdev->le_white_list_size = rp->size;
Johan Hedbergcf1d0812013-01-22 14:02:00 +02001020}
1021
Johan Hedberg9b008c02013-01-22 14:02:01 +02001022static void hci_cc_le_read_supported_states(struct hci_dev *hdev,
1023 struct sk_buff *skb)
1024{
1025 struct hci_rp_le_read_supported_states *rp = (void *) skb->data;
1026
1027 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1028
1029 if (!rp->status)
1030 memcpy(hdev->le_states, rp->le_states, 8);
Johan Hedberg9b008c02013-01-22 14:02:01 +02001031}
1032
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001033static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1034 struct sk_buff *skb)
Andre Guedesf9b49302011-06-30 19:20:53 -03001035{
Johan Hedberg06199cf2012-02-22 16:37:11 +02001036 struct hci_cp_write_le_host_supported *sent;
Andre Guedesf9b49302011-06-30 19:20:53 -03001037 __u8 status = *((__u8 *) skb->data);
1038
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001039 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedesf9b49302011-06-30 19:20:53 -03001040
Johan Hedberg06199cf2012-02-22 16:37:11 +02001041 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
Johan Hedberg8f984df2012-02-28 01:07:22 +02001042 if (!sent)
Andre Guedesf9b49302011-06-30 19:20:53 -03001043 return;
1044
Johan Hedberg8f984df2012-02-28 01:07:22 +02001045 if (!status) {
1046 if (sent->le)
1047 hdev->host_features[0] |= LMP_HOST_LE;
1048 else
1049 hdev->host_features[0] &= ~LMP_HOST_LE;
Johan Hedberg53b2caa2012-10-24 21:11:59 +03001050
1051 if (sent->simul)
1052 hdev->host_features[0] |= LMP_HOST_LE_BREDR;
1053 else
1054 hdev->host_features[0] &= ~LMP_HOST_LE_BREDR;
Johan Hedberg8f984df2012-02-28 01:07:22 +02001055 }
1056
1057 if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001058 !test_bit(HCI_INIT, &hdev->flags))
Johan Hedberg8f984df2012-02-28 01:07:22 +02001059 mgmt_le_enable_complete(hdev, sent->le, status);
Andre Guedesf9b49302011-06-30 19:20:53 -03001060}
1061
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001062static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
1063 struct sk_buff *skb)
1064{
1065 struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data;
1066
1067 BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
1068 hdev->name, rp->status, rp->phy_handle);
1069
1070 if (rp->status)
1071 return;
1072
1073 amp_write_rem_assoc_continue(hdev, rp->phy_handle);
1074}
1075
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001076static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001077{
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001078 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001079
1080 if (status) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001081 hci_conn_check_pending(hdev);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001082 hci_dev_lock(hdev);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001083 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Andre Guedes7a135102011-11-09 17:14:25 -03001084 mgmt_start_discovery_failed(hdev, status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001085 hci_dev_unlock(hdev);
Johan Hedberg314b2382011-04-27 10:29:57 -04001086 return;
1087 }
1088
Andre Guedes89352e72011-11-04 14:16:53 -03001089 set_bit(HCI_INQUIRY, &hdev->flags);
1090
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001091 hci_dev_lock(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -03001092 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001093 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001094}
1095
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001096static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001098 struct hci_cp_create_conn *cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001101 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001102
1103 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 if (!cp)
1105 return;
1106
1107 hci_dev_lock(hdev);
1108
1109 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1110
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001111 BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112
1113 if (status) {
1114 if (conn && conn->state == BT_CONNECT) {
Marcel Holtmann4c67bc72006-10-15 17:30:56 +02001115 if (status != 0x0c || conn->attempt > 2) {
1116 conn->state = BT_CLOSED;
1117 hci_proto_connect_cfm(conn, status);
1118 hci_conn_del(conn);
1119 } else
1120 conn->state = BT_CONNECT2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 }
1122 } else {
1123 if (!conn) {
1124 conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
1125 if (conn) {
Johan Hedberga0c808b2012-01-16 09:49:58 +02001126 conn->out = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127 conn->link_mode |= HCI_LM_MASTER;
1128 } else
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001129 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130 }
1131 }
1132
1133 hci_dev_unlock(hdev);
1134}
1135
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001136static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001138 struct hci_cp_add_sco *cp;
1139 struct hci_conn *acl, *sco;
1140 __u16 handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001142 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001143
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001144 if (!status)
1145 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001147 cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
1148 if (!cp)
1149 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001151 handle = __le16_to_cpu(cp->handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001153 BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001154
1155 hci_dev_lock(hdev);
1156
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001157 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001158 if (acl) {
1159 sco = acl->link;
1160 if (sco) {
1161 sco->state = BT_CLOSED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001162
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001163 hci_proto_connect_cfm(sco, status);
1164 hci_conn_del(sco);
1165 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001166 }
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001167
1168 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169}
1170
Marcel Holtmannf8558552008-07-14 20:13:49 +02001171static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1172{
1173 struct hci_cp_auth_requested *cp;
1174 struct hci_conn *conn;
1175
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001176 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannf8558552008-07-14 20:13:49 +02001177
1178 if (!status)
1179 return;
1180
1181 cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1182 if (!cp)
1183 return;
1184
1185 hci_dev_lock(hdev);
1186
1187 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1188 if (conn) {
1189 if (conn->state == BT_CONFIG) {
1190 hci_proto_connect_cfm(conn, status);
1191 hci_conn_put(conn);
1192 }
1193 }
1194
1195 hci_dev_unlock(hdev);
1196}
1197
1198static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1199{
1200 struct hci_cp_set_conn_encrypt *cp;
1201 struct hci_conn *conn;
1202
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001203 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannf8558552008-07-14 20:13:49 +02001204
1205 if (!status)
1206 return;
1207
1208 cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1209 if (!cp)
1210 return;
1211
1212 hci_dev_lock(hdev);
1213
1214 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1215 if (conn) {
1216 if (conn->state == BT_CONFIG) {
1217 hci_proto_connect_cfm(conn, status);
1218 hci_conn_put(conn);
1219 }
1220 }
1221
1222 hci_dev_unlock(hdev);
1223}
1224
Johan Hedberg127178d2010-11-18 22:22:29 +02001225static int hci_outgoing_auth_needed(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001226 struct hci_conn *conn)
Johan Hedberg392599b2010-11-18 22:22:28 +02001227{
Johan Hedberg392599b2010-11-18 22:22:28 +02001228 if (conn->state != BT_CONFIG || !conn->out)
1229 return 0;
1230
Johan Hedberg765c2a92011-01-19 12:06:52 +05301231 if (conn->pending_sec_level == BT_SECURITY_SDP)
Johan Hedberg392599b2010-11-18 22:22:28 +02001232 return 0;
1233
1234 /* Only request authentication for SSP connections or non-SSP
Vinicius Costa Gomese9bf2bf2011-09-02 14:51:20 -03001235 * devices with sec_level HIGH or if MITM protection is requested */
Gustavo Padovan807deac2012-05-17 00:36:24 -03001236 if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
1237 conn->pending_sec_level != BT_SECURITY_HIGH)
Johan Hedberg392599b2010-11-18 22:22:28 +02001238 return 0;
1239
Johan Hedberg392599b2010-11-18 22:22:28 +02001240 return 1;
1241}
1242
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001243static int hci_resolve_name(struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001244 struct inquiry_entry *e)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001245{
1246 struct hci_cp_remote_name_req cp;
1247
1248 memset(&cp, 0, sizeof(cp));
1249
1250 bacpy(&cp.bdaddr, &e->data.bdaddr);
1251 cp.pscan_rep_mode = e->data.pscan_rep_mode;
1252 cp.pscan_mode = e->data.pscan_mode;
1253 cp.clock_offset = e->data.clock_offset;
1254
1255 return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1256}
1257
Johan Hedbergb644ba32012-01-17 21:48:47 +02001258static bool hci_resolve_next_name(struct hci_dev *hdev)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001259{
1260 struct discovery_state *discov = &hdev->discovery;
1261 struct inquiry_entry *e;
1262
Johan Hedbergb644ba32012-01-17 21:48:47 +02001263 if (list_empty(&discov->resolve))
1264 return false;
1265
1266 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
Ram Malovanyc8100892012-07-19 10:26:09 +03001267 if (!e)
1268 return false;
1269
Johan Hedbergb644ba32012-01-17 21:48:47 +02001270 if (hci_resolve_name(hdev, e) == 0) {
1271 e->name_state = NAME_PENDING;
1272 return true;
1273 }
1274
1275 return false;
1276}
1277
1278static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001279 bdaddr_t *bdaddr, u8 *name, u8 name_len)
Johan Hedbergb644ba32012-01-17 21:48:47 +02001280{
1281 struct discovery_state *discov = &hdev->discovery;
1282 struct inquiry_entry *e;
1283
1284 if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001285 mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
1286 name_len, conn->dev_class);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001287
1288 if (discov->state == DISCOVERY_STOPPED)
1289 return;
1290
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001291 if (discov->state == DISCOVERY_STOPPING)
1292 goto discov_complete;
1293
1294 if (discov->state != DISCOVERY_RESOLVING)
1295 return;
1296
1297 e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
Ram Malovany7cc83802012-07-19 10:26:10 +03001298 /* If the device was not found in a list of found devices names of which
1299 * are pending. there is no need to continue resolving a next name as it
1300 * will be done upon receiving another Remote Name Request Complete
1301 * Event */
1302 if (!e)
1303 return;
1304
1305 list_del(&e->list);
1306 if (name) {
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001307 e->name_state = NAME_KNOWN;
Ram Malovany7cc83802012-07-19 10:26:10 +03001308 mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1309 e->data.rssi, name, name_len);
Ram Malovanyc3e7c0d2012-07-19 10:26:11 +03001310 } else {
1311 e->name_state = NAME_NOT_KNOWN;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001312 }
1313
Johan Hedbergb644ba32012-01-17 21:48:47 +02001314 if (hci_resolve_next_name(hdev))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001315 return;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001316
1317discov_complete:
1318 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1319}
1320
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001321static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
1322{
Johan Hedberg127178d2010-11-18 22:22:29 +02001323 struct hci_cp_remote_name_req *cp;
1324 struct hci_conn *conn;
1325
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001326 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedberg127178d2010-11-18 22:22:29 +02001327
1328 /* If successful wait for the name req complete event before
1329 * checking for the need to do authentication */
1330 if (!status)
1331 return;
1332
1333 cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1334 if (!cp)
1335 return;
1336
1337 hci_dev_lock(hdev);
1338
1339 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001340
1341 if (test_bit(HCI_MGMT, &hdev->dev_flags))
1342 hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1343
Johan Hedberg79c6c702011-04-28 11:28:55 -07001344 if (!conn)
1345 goto unlock;
1346
1347 if (!hci_outgoing_auth_needed(hdev, conn))
1348 goto unlock;
1349
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001350 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02001351 struct hci_cp_auth_requested cp;
1352 cp.handle = __cpu_to_le16(conn->handle);
1353 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1354 }
1355
Johan Hedberg79c6c702011-04-28 11:28:55 -07001356unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02001357 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001358}
1359
Marcel Holtmann769be972008-07-14 20:13:49 +02001360static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1361{
1362 struct hci_cp_read_remote_features *cp;
1363 struct hci_conn *conn;
1364
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001365 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann769be972008-07-14 20:13:49 +02001366
1367 if (!status)
1368 return;
1369
1370 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1371 if (!cp)
1372 return;
1373
1374 hci_dev_lock(hdev);
1375
1376 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1377 if (conn) {
1378 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001379 hci_proto_connect_cfm(conn, status);
1380 hci_conn_put(conn);
1381 }
1382 }
1383
1384 hci_dev_unlock(hdev);
1385}
1386
1387static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1388{
1389 struct hci_cp_read_remote_ext_features *cp;
1390 struct hci_conn *conn;
1391
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001392 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann769be972008-07-14 20:13:49 +02001393
1394 if (!status)
1395 return;
1396
1397 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1398 if (!cp)
1399 return;
1400
1401 hci_dev_lock(hdev);
1402
1403 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1404 if (conn) {
1405 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001406 hci_proto_connect_cfm(conn, status);
1407 hci_conn_put(conn);
1408 }
1409 }
1410
1411 hci_dev_unlock(hdev);
1412}
1413
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001414static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1415{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001416 struct hci_cp_setup_sync_conn *cp;
1417 struct hci_conn *acl, *sco;
1418 __u16 handle;
1419
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001420 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001421
1422 if (!status)
1423 return;
1424
1425 cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1426 if (!cp)
1427 return;
1428
1429 handle = __le16_to_cpu(cp->handle);
1430
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001431 BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001432
1433 hci_dev_lock(hdev);
1434
1435 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001436 if (acl) {
1437 sco = acl->link;
1438 if (sco) {
1439 sco->state = BT_CLOSED;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001440
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001441 hci_proto_connect_cfm(sco, status);
1442 hci_conn_del(sco);
1443 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001444 }
1445
1446 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001447}
1448
1449static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1450{
1451 struct hci_cp_sniff_mode *cp;
1452 struct hci_conn *conn;
1453
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001454 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001455
1456 if (!status)
1457 return;
1458
1459 cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
1460 if (!cp)
1461 return;
1462
1463 hci_dev_lock(hdev);
1464
1465 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001466 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001467 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001468
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001469 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001470 hci_sco_setup(conn, status);
1471 }
1472
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001473 hci_dev_unlock(hdev);
1474}
1475
1476static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1477{
1478 struct hci_cp_exit_sniff_mode *cp;
1479 struct hci_conn *conn;
1480
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001481 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001482
1483 if (!status)
1484 return;
1485
1486 cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
1487 if (!cp)
1488 return;
1489
1490 hci_dev_lock(hdev);
1491
1492 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001493 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001494 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001495
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001496 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001497 hci_sco_setup(conn, status);
1498 }
1499
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001500 hci_dev_unlock(hdev);
1501}
1502
Johan Hedberg88c3df12012-02-09 14:27:38 +02001503static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
1504{
1505 struct hci_cp_disconnect *cp;
1506 struct hci_conn *conn;
1507
1508 if (!status)
1509 return;
1510
1511 cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
1512 if (!cp)
1513 return;
1514
1515 hci_dev_lock(hdev);
1516
1517 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1518 if (conn)
1519 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001520 conn->dst_type, status);
Johan Hedberg88c3df12012-02-09 14:27:38 +02001521
1522 hci_dev_unlock(hdev);
1523}
1524
Ville Tervofcd89c02011-02-10 22:38:47 -03001525static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1526{
Ville Tervofcd89c02011-02-10 22:38:47 -03001527 struct hci_conn *conn;
1528
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001529 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Ville Tervofcd89c02011-02-10 22:38:47 -03001530
Ville Tervofcd89c02011-02-10 22:38:47 -03001531 if (status) {
Andre Guedesf00a06a2012-07-27 15:10:13 -03001532 hci_dev_lock(hdev);
Ville Tervofcd89c02011-02-10 22:38:47 -03001533
Andre Guedes0c95ab72012-07-27 15:10:14 -03001534 conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
Andre Guedesf00a06a2012-07-27 15:10:13 -03001535 if (!conn) {
1536 hci_dev_unlock(hdev);
1537 return;
1538 }
1539
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001540 BT_DBG("%s bdaddr %pMR conn %p", hdev->name, &conn->dst, conn);
Andre Guedesf00a06a2012-07-27 15:10:13 -03001541
1542 conn->state = BT_CLOSED;
Andre Guedes0c95ab72012-07-27 15:10:14 -03001543 mgmt_connect_failed(hdev, &conn->dst, conn->type,
Andre Guedesf00a06a2012-07-27 15:10:13 -03001544 conn->dst_type, status);
1545 hci_proto_connect_cfm(conn, status);
1546 hci_conn_del(conn);
1547
1548 hci_dev_unlock(hdev);
1549 }
Ville Tervofcd89c02011-02-10 22:38:47 -03001550}
1551
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001552static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
1553{
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001554 struct hci_cp_create_phy_link *cp;
1555
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001556 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001557
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001558 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
1559 if (!cp)
1560 return;
1561
Andrei Emeltchenkoe58917b2012-10-31 15:46:33 +02001562 hci_dev_lock(hdev);
1563
1564 if (status) {
1565 struct hci_conn *hcon;
1566
1567 hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle);
1568 if (hcon)
1569 hci_conn_del(hcon);
1570 } else {
1571 amp_write_remote_assoc(hdev, cp->phy_handle);
1572 }
1573
1574 hci_dev_unlock(hdev);
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001575}
1576
Andrei Emeltchenko0b26ab92012-09-27 17:26:24 +03001577static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
1578{
1579 struct hci_cp_accept_phy_link *cp;
1580
1581 BT_DBG("%s status 0x%2.2x", hdev->name, status);
1582
1583 if (status)
1584 return;
1585
1586 cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
1587 if (!cp)
1588 return;
1589
1590 amp_write_remote_assoc(hdev, cp->phy_handle);
1591}
1592
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001593static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001594{
1595 __u8 status = *((__u8 *) skb->data);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001596 struct discovery_state *discov = &hdev->discovery;
1597 struct inquiry_entry *e;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001598
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001599 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001600
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001601 hci_conn_check_pending(hdev);
Andre Guedes89352e72011-11-04 14:16:53 -03001602
1603 if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
1604 return;
1605
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001606 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001607 return;
1608
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001609 hci_dev_lock(hdev);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001610
Andre Guedes343f9352012-02-17 20:39:37 -03001611 if (discov->state != DISCOVERY_FINDING)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001612 goto unlock;
1613
1614 if (list_empty(&discov->resolve)) {
1615 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1616 goto unlock;
1617 }
1618
1619 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1620 if (e && hci_resolve_name(hdev, e) == 0) {
1621 e->name_state = NAME_PENDING;
1622 hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
1623 } else {
1624 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1625 }
1626
1627unlock:
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001628 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001629}
1630
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001631static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632{
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001633 struct inquiry_data data;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001634 struct inquiry_info *info = (void *) (skb->data + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001635 int num_rsp = *((__u8 *) skb->data);
1636
1637 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1638
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001639 if (!num_rsp)
1640 return;
1641
Andre Guedes1519cc12012-03-21 00:03:38 -03001642 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
1643 return;
1644
Linus Torvalds1da177e2005-04-16 15:20:36 -07001645 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001646
Johan Hedberge17acd42011-03-30 23:57:16 +03001647 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg388fc8f2012-02-23 00:38:59 +02001648 bool name_known, ssp;
Johan Hedberg31754052012-01-04 13:39:52 +02001649
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650 bacpy(&data.bdaddr, &info->bdaddr);
1651 data.pscan_rep_mode = info->pscan_rep_mode;
1652 data.pscan_period_mode = info->pscan_period_mode;
1653 data.pscan_mode = info->pscan_mode;
1654 memcpy(data.dev_class, info->dev_class, 3);
1655 data.clock_offset = info->clock_offset;
1656 data.rssi = 0x00;
Marcel Holtmann41a96212008-07-14 20:13:48 +02001657 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02001658
Johan Hedberg388fc8f2012-02-23 00:38:59 +02001659 name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02001660 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001661 info->dev_class, 0, !name_known, ssp, NULL,
1662 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001663 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001664
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665 hci_dev_unlock(hdev);
1666}
1667
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001668static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001670 struct hci_ev_conn_complete *ev = (void *) skb->data;
1671 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001673 BT_DBG("%s", hdev->name);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001674
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001676
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001677 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann94992372009-04-19 19:30:03 +02001678 if (!conn) {
1679 if (ev->link_type != SCO_LINK)
1680 goto unlock;
1681
1682 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1683 if (!conn)
1684 goto unlock;
1685
1686 conn->type = SCO_LINK;
1687 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001688
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001689 if (!ev->status) {
1690 conn->handle = __le16_to_cpu(ev->handle);
Marcel Holtmann769be972008-07-14 20:13:49 +02001691
1692 if (conn->type == ACL_LINK) {
1693 conn->state = BT_CONFIG;
1694 hci_conn_hold(conn);
Szymon Janca9ea3ed2012-07-19 14:46:08 +02001695
1696 if (!conn->out && !hci_conn_ssp_enabled(conn) &&
1697 !hci_find_link_key(hdev, &ev->bdaddr))
1698 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
1699 else
1700 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Marcel Holtmann769be972008-07-14 20:13:49 +02001701 } else
1702 conn->state = BT_CONNECTED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001703
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07001704 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001705 hci_conn_add_sysfs(conn);
1706
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001707 if (test_bit(HCI_AUTH, &hdev->flags))
1708 conn->link_mode |= HCI_LM_AUTH;
1709
1710 if (test_bit(HCI_ENCRYPT, &hdev->flags))
1711 conn->link_mode |= HCI_LM_ENCRYPT;
1712
1713 /* Get remote features */
1714 if (conn->type == ACL_LINK) {
1715 struct hci_cp_read_remote_features cp;
1716 cp.handle = ev->handle;
Marcel Holtmann769be972008-07-14 20:13:49 +02001717 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001718 sizeof(cp), &cp);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001719 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001720
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001721 /* Set packet type for incoming connection */
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +02001722 if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001723 struct hci_cp_change_conn_ptype cp;
1724 cp.handle = ev->handle;
Marcel Holtmanna8746412008-07-14 20:13:46 +02001725 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001726 hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
1727 &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001728 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02001729 } else {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001730 conn->state = BT_CLOSED;
Johan Hedberg17d5c042011-01-22 06:09:08 +02001731 if (conn->type == ACL_LINK)
Johan Hedberg744cf192011-11-08 20:40:14 +02001732 mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001733 conn->dst_type, ev->status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02001734 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001735
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001736 if (conn->type == ACL_LINK)
1737 hci_sco_setup(conn, ev->status);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001738
Marcel Holtmann769be972008-07-14 20:13:49 +02001739 if (ev->status) {
1740 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001741 hci_conn_del(conn);
Marcel Holtmannc89b6e62009-01-15 21:57:03 +01001742 } else if (ev->link_type != ACL_LINK)
1743 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001744
1745unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001746 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001747
1748 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749}
1750
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001751void hci_conn_accept(struct hci_conn *conn, int mask)
1752{
1753 struct hci_dev *hdev = conn->hdev;
1754
1755 BT_DBG("conn %p", conn);
1756
1757 conn->state = BT_CONFIG;
1758
1759 if (!lmp_esco_capable(hdev)) {
1760 struct hci_cp_accept_conn_req cp;
1761
1762 bacpy(&cp.bdaddr, &conn->dst);
1763
1764 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
1765 cp.role = 0x00; /* Become master */
1766 else
1767 cp.role = 0x01; /* Remain slave */
1768
1769 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), &cp);
1770 } else /* lmp_esco_capable(hdev)) */ {
1771 struct hci_cp_accept_sync_conn_req cp;
1772
1773 bacpy(&cp.bdaddr, &conn->dst);
1774 cp.pkt_type = cpu_to_le16(conn->pkt_type);
1775
1776 cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
1777 cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
1778 cp.max_latency = __constant_cpu_to_le16(0xffff);
1779 cp.content_format = cpu_to_le16(hdev->voice_setting);
1780 cp.retrans_effort = 0xff;
1781
1782 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1783 sizeof(cp), &cp);
1784 }
1785}
1786
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001787static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001788{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001789 struct hci_ev_conn_request *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001790 int mask = hdev->link_mode;
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001791 __u8 flags = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001792
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001793 BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001794 ev->link_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001795
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001796 mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type,
1797 &flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001798
Szymon Janc138d22e2011-02-17 16:44:23 +01001799 if ((mask & HCI_LM_ACCEPT) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001800 !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001801 /* Connection accepted */
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001802 struct inquiry_entry *ie;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804
1805 hci_dev_lock(hdev);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001806
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001807 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1808 if (ie)
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001809 memcpy(ie->data.dev_class, ev->dev_class, 3);
1810
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001811 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
1812 &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001813 if (!conn) {
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001814 conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1815 if (!conn) {
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001816 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817 hci_dev_unlock(hdev);
1818 return;
1819 }
1820 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001821
Linus Torvalds1da177e2005-04-16 15:20:36 -07001822 memcpy(conn->dev_class, ev->dev_class, 3);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001823
Linus Torvalds1da177e2005-04-16 15:20:36 -07001824 hci_dev_unlock(hdev);
1825
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001826 if (ev->link_type == ACL_LINK ||
1827 (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) {
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001828 struct hci_cp_accept_conn_req cp;
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001829 conn->state = BT_CONNECT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001831 bacpy(&cp.bdaddr, &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001833 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
1834 cp.role = 0x00; /* Become master */
1835 else
1836 cp.role = 0x01; /* Remain slave */
1837
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001838 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
1839 &cp);
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001840 } else if (!(flags & HCI_PROTO_DEFER)) {
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001841 struct hci_cp_accept_sync_conn_req cp;
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001842 conn->state = BT_CONNECT;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001843
1844 bacpy(&cp.bdaddr, &ev->bdaddr);
Marcel Holtmanna8746412008-07-14 20:13:46 +02001845 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001846
Andrei Emeltchenko82781e62012-05-25 11:38:27 +03001847 cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
1848 cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
1849 cp.max_latency = __constant_cpu_to_le16(0xffff);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001850 cp.content_format = cpu_to_le16(hdev->voice_setting);
1851 cp.retrans_effort = 0xff;
1852
1853 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001854 sizeof(cp), &cp);
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001855 } else {
1856 conn->state = BT_CONNECT2;
1857 hci_proto_connect_cfm(conn, 0);
1858 hci_conn_put(conn);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001859 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860 } else {
1861 /* Connection rejected */
1862 struct hci_cp_reject_conn_req cp;
1863
1864 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02001865 cp.reason = HCI_ERROR_REJ_BAD_ADDR;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001866 hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867 }
1868}
1869
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02001870static u8 hci_to_mgmt_reason(u8 err)
1871{
1872 switch (err) {
1873 case HCI_ERROR_CONNECTION_TIMEOUT:
1874 return MGMT_DEV_DISCONN_TIMEOUT;
1875 case HCI_ERROR_REMOTE_USER_TERM:
1876 case HCI_ERROR_REMOTE_LOW_RESOURCES:
1877 case HCI_ERROR_REMOTE_POWER_OFF:
1878 return MGMT_DEV_DISCONN_REMOTE;
1879 case HCI_ERROR_LOCAL_HOST_TERM:
1880 return MGMT_DEV_DISCONN_LOCAL_HOST;
1881 default:
1882 return MGMT_DEV_DISCONN_UNKNOWN;
1883 }
1884}
1885
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001886static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001887{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001888 struct hci_ev_disconn_complete *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02001889 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001891 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893 hci_dev_lock(hdev);
1894
Marcel Holtmann04837f62006-07-03 10:02:33 +02001895 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergf7520542011-01-20 12:34:39 +02001896 if (!conn)
1897 goto unlock;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001898
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001899 if (ev->status == 0)
1900 conn->state = BT_CLOSED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901
Johan Hedbergb644ba32012-01-17 21:48:47 +02001902 if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001903 (conn->type == ACL_LINK || conn->type == LE_LINK)) {
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02001904 if (ev->status) {
Johan Hedberg88c3df12012-02-09 14:27:38 +02001905 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001906 conn->dst_type, ev->status);
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02001907 } else {
1908 u8 reason = hci_to_mgmt_reason(ev->reason);
1909
Johan Hedbergafc747a2012-01-15 18:11:07 +02001910 mgmt_device_disconnected(hdev, &conn->dst, conn->type,
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02001911 conn->dst_type, reason);
1912 }
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001913 }
Johan Hedbergf7520542011-01-20 12:34:39 +02001914
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001915 if (ev->status == 0) {
Vishal Agarwal6ec5bca2012-04-16 14:44:44 +05301916 if (conn->type == ACL_LINK && conn->flush_key)
1917 hci_remove_link_key(hdev, &conn->dst);
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001918 hci_proto_disconn_cfm(conn, ev->reason);
1919 hci_conn_del(conn);
1920 }
Johan Hedbergf7520542011-01-20 12:34:39 +02001921
1922unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001923 hci_dev_unlock(hdev);
1924}
1925
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001926static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001927{
1928 struct hci_ev_auth_complete *ev = (void *) skb->data;
1929 struct hci_conn *conn;
1930
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001931 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001932
1933 hci_dev_lock(hdev);
1934
1935 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001936 if (!conn)
1937 goto unlock;
1938
1939 if (!ev->status) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02001940 if (!hci_conn_ssp_enabled(conn) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001941 test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001942 BT_INFO("re-auth of legacy device is not possible.");
Johan Hedberg2a611692011-02-19 12:06:00 -03001943 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001944 conn->link_mode |= HCI_LM_AUTH;
1945 conn->sec_level = conn->pending_sec_level;
Johan Hedberg2a611692011-02-19 12:06:00 -03001946 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001947 } else {
Johan Hedbergbab73cb2012-02-09 16:07:29 +02001948 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001949 ev->status);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001950 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001951
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001952 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
1953 clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001954
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001955 if (conn->state == BT_CONFIG) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02001956 if (!ev->status && hci_conn_ssp_enabled(conn)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001957 struct hci_cp_set_conn_encrypt cp;
1958 cp.handle = ev->handle;
1959 cp.encrypt = 0x01;
1960 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03001961 &cp);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001962 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001963 conn->state = BT_CONNECTED;
1964 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001965 hci_conn_put(conn);
1966 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001967 } else {
1968 hci_auth_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001969
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001970 hci_conn_hold(conn);
1971 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1972 hci_conn_put(conn);
1973 }
1974
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001975 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001976 if (!ev->status) {
1977 struct hci_cp_set_conn_encrypt cp;
1978 cp.handle = ev->handle;
1979 cp.encrypt = 0x01;
1980 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03001981 &cp);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001982 } else {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001983 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001984 hci_encrypt_cfm(conn, ev->status, 0x00);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001985 }
1986 }
1987
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001988unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001989 hci_dev_unlock(hdev);
1990}
1991
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001992static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001993{
Johan Hedberg127178d2010-11-18 22:22:29 +02001994 struct hci_ev_remote_name *ev = (void *) skb->data;
1995 struct hci_conn *conn;
1996
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001997 BT_DBG("%s", hdev->name);
1998
1999 hci_conn_check_pending(hdev);
Johan Hedberg127178d2010-11-18 22:22:29 +02002000
2001 hci_dev_lock(hdev);
2002
2003 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002004
2005 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
2006 goto check_auth;
2007
2008 if (ev->status == 0)
2009 hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002010 strnlen(ev->name, HCI_MAX_NAME_LENGTH));
Johan Hedbergb644ba32012-01-17 21:48:47 +02002011 else
2012 hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
2013
2014check_auth:
Johan Hedberg79c6c702011-04-28 11:28:55 -07002015 if (!conn)
2016 goto unlock;
2017
2018 if (!hci_outgoing_auth_needed(hdev, conn))
2019 goto unlock;
2020
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002021 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002022 struct hci_cp_auth_requested cp;
2023 cp.handle = __cpu_to_le16(conn->handle);
2024 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
2025 }
2026
Johan Hedberg79c6c702011-04-28 11:28:55 -07002027unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02002028 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002029}
2030
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002031static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002032{
2033 struct hci_ev_encrypt_change *ev = (void *) skb->data;
2034 struct hci_conn *conn;
2035
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002036 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002037
2038 hci_dev_lock(hdev);
2039
2040 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2041 if (conn) {
2042 if (!ev->status) {
Marcel Holtmannae293192008-07-14 20:13:45 +02002043 if (ev->encrypt) {
2044 /* Encryption implies authentication */
2045 conn->link_mode |= HCI_LM_AUTH;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002046 conn->link_mode |= HCI_LM_ENCRYPT;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03002047 conn->sec_level = conn->pending_sec_level;
Marcel Holtmannae293192008-07-14 20:13:45 +02002048 } else
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002049 conn->link_mode &= ~HCI_LM_ENCRYPT;
2050 }
2051
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002052 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002053
Gustavo Padovana7d77232012-05-13 03:20:07 -03002054 if (ev->status && conn->state == BT_CONNECTED) {
Andre Guedesbed71742013-01-30 11:50:56 -03002055 hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
Gustavo Padovana7d77232012-05-13 03:20:07 -03002056 hci_conn_put(conn);
2057 goto unlock;
2058 }
2059
Marcel Holtmannf8558552008-07-14 20:13:49 +02002060 if (conn->state == BT_CONFIG) {
2061 if (!ev->status)
2062 conn->state = BT_CONNECTED;
2063
2064 hci_proto_connect_cfm(conn, ev->status);
2065 hci_conn_put(conn);
2066 } else
2067 hci_encrypt_cfm(conn, ev->status, ev->encrypt);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002068 }
2069
Gustavo Padovana7d77232012-05-13 03:20:07 -03002070unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002071 hci_dev_unlock(hdev);
2072}
2073
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002074static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
2075 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002076{
2077 struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2078 struct hci_conn *conn;
2079
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002080 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002081
2082 hci_dev_lock(hdev);
2083
2084 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2085 if (conn) {
2086 if (!ev->status)
2087 conn->link_mode |= HCI_LM_SECURE;
2088
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002089 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002090
2091 hci_key_change_cfm(conn, ev->status);
2092 }
2093
2094 hci_dev_unlock(hdev);
2095}
2096
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002097static void hci_remote_features_evt(struct hci_dev *hdev,
2098 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002099{
2100 struct hci_ev_remote_features *ev = (void *) skb->data;
2101 struct hci_conn *conn;
2102
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002103 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002104
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002105 hci_dev_lock(hdev);
2106
2107 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02002108 if (!conn)
2109 goto unlock;
Marcel Holtmann769be972008-07-14 20:13:49 +02002110
Johan Hedbergccd556f2010-11-10 17:11:51 +02002111 if (!ev->status)
2112 memcpy(conn->features, ev->features, 8);
2113
2114 if (conn->state != BT_CONFIG)
2115 goto unlock;
2116
2117 if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2118 struct hci_cp_read_remote_ext_features cp;
2119 cp.handle = ev->handle;
2120 cp.page = 0x01;
2121 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002122 sizeof(cp), &cp);
Johan Hedberg392599b2010-11-18 22:22:28 +02002123 goto unlock;
2124 }
2125
Johan Hedberg671267b2012-05-12 16:11:50 -03002126 if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002127 struct hci_cp_remote_name_req cp;
2128 memset(&cp, 0, sizeof(cp));
2129 bacpy(&cp.bdaddr, &conn->dst);
2130 cp.pscan_rep_mode = 0x02;
2131 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002132 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2133 mgmt_device_connected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002134 conn->dst_type, 0, NULL, 0,
2135 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02002136
Johan Hedberg127178d2010-11-18 22:22:29 +02002137 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02002138 conn->state = BT_CONNECTED;
2139 hci_proto_connect_cfm(conn, ev->status);
2140 hci_conn_put(conn);
Marcel Holtmann769be972008-07-14 20:13:49 +02002141 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002142
Johan Hedbergccd556f2010-11-10 17:11:51 +02002143unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002144 hci_dev_unlock(hdev);
2145}
2146
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002147static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002148{
2149 struct hci_ev_cmd_complete *ev = (void *) skb->data;
Johan Hedberg9238f362013-03-05 20:37:48 +02002150 u8 status = skb->data[sizeof(*ev)];
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002151 __u16 opcode;
2152
2153 skb_pull(skb, sizeof(*ev));
2154
2155 opcode = __le16_to_cpu(ev->opcode);
2156
2157 switch (opcode) {
2158 case HCI_OP_INQUIRY_CANCEL:
2159 hci_cc_inquiry_cancel(hdev, skb);
2160 break;
2161
Andre Guedes4d934832012-03-21 00:03:35 -03002162 case HCI_OP_PERIODIC_INQ:
2163 hci_cc_periodic_inq(hdev, skb);
2164 break;
2165
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002166 case HCI_OP_EXIT_PERIODIC_INQ:
2167 hci_cc_exit_periodic_inq(hdev, skb);
2168 break;
2169
2170 case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2171 hci_cc_remote_name_req_cancel(hdev, skb);
2172 break;
2173
2174 case HCI_OP_ROLE_DISCOVERY:
2175 hci_cc_role_discovery(hdev, skb);
2176 break;
2177
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002178 case HCI_OP_READ_LINK_POLICY:
2179 hci_cc_read_link_policy(hdev, skb);
2180 break;
2181
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002182 case HCI_OP_WRITE_LINK_POLICY:
2183 hci_cc_write_link_policy(hdev, skb);
2184 break;
2185
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002186 case HCI_OP_READ_DEF_LINK_POLICY:
2187 hci_cc_read_def_link_policy(hdev, skb);
2188 break;
2189
2190 case HCI_OP_WRITE_DEF_LINK_POLICY:
2191 hci_cc_write_def_link_policy(hdev, skb);
2192 break;
2193
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002194 case HCI_OP_RESET:
2195 hci_cc_reset(hdev, skb);
2196 break;
2197
2198 case HCI_OP_WRITE_LOCAL_NAME:
2199 hci_cc_write_local_name(hdev, skb);
2200 break;
2201
2202 case HCI_OP_READ_LOCAL_NAME:
2203 hci_cc_read_local_name(hdev, skb);
2204 break;
2205
2206 case HCI_OP_WRITE_AUTH_ENABLE:
2207 hci_cc_write_auth_enable(hdev, skb);
2208 break;
2209
2210 case HCI_OP_WRITE_ENCRYPT_MODE:
2211 hci_cc_write_encrypt_mode(hdev, skb);
2212 break;
2213
2214 case HCI_OP_WRITE_SCAN_ENABLE:
2215 hci_cc_write_scan_enable(hdev, skb);
2216 break;
2217
2218 case HCI_OP_READ_CLASS_OF_DEV:
2219 hci_cc_read_class_of_dev(hdev, skb);
2220 break;
2221
2222 case HCI_OP_WRITE_CLASS_OF_DEV:
2223 hci_cc_write_class_of_dev(hdev, skb);
2224 break;
2225
2226 case HCI_OP_READ_VOICE_SETTING:
2227 hci_cc_read_voice_setting(hdev, skb);
2228 break;
2229
2230 case HCI_OP_WRITE_VOICE_SETTING:
2231 hci_cc_write_voice_setting(hdev, skb);
2232 break;
2233
Marcel Holtmann333140b2008-07-14 20:13:48 +02002234 case HCI_OP_WRITE_SSP_MODE:
2235 hci_cc_write_ssp_mode(hdev, skb);
2236 break;
2237
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002238 case HCI_OP_READ_LOCAL_VERSION:
2239 hci_cc_read_local_version(hdev, skb);
2240 break;
2241
2242 case HCI_OP_READ_LOCAL_COMMANDS:
2243 hci_cc_read_local_commands(hdev, skb);
2244 break;
2245
2246 case HCI_OP_READ_LOCAL_FEATURES:
2247 hci_cc_read_local_features(hdev, skb);
2248 break;
2249
Andre Guedes971e3a42011-06-30 19:20:52 -03002250 case HCI_OP_READ_LOCAL_EXT_FEATURES:
2251 hci_cc_read_local_ext_features(hdev, skb);
2252 break;
2253
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002254 case HCI_OP_READ_BUFFER_SIZE:
2255 hci_cc_read_buffer_size(hdev, skb);
2256 break;
2257
2258 case HCI_OP_READ_BD_ADDR:
2259 hci_cc_read_bd_addr(hdev, skb);
2260 break;
2261
Johan Hedbergf332ec62013-03-15 17:07:11 -05002262 case HCI_OP_READ_PAGE_SCAN_ACTIVITY:
2263 hci_cc_read_page_scan_activity(hdev, skb);
2264 break;
2265
Johan Hedberg4a3ee762013-03-15 17:07:12 -05002266 case HCI_OP_WRITE_PAGE_SCAN_ACTIVITY:
2267 hci_cc_write_page_scan_activity(hdev, skb);
2268 break;
2269
Johan Hedbergf332ec62013-03-15 17:07:11 -05002270 case HCI_OP_READ_PAGE_SCAN_TYPE:
2271 hci_cc_read_page_scan_type(hdev, skb);
2272 break;
2273
Johan Hedberg4a3ee762013-03-15 17:07:12 -05002274 case HCI_OP_WRITE_PAGE_SCAN_TYPE:
2275 hci_cc_write_page_scan_type(hdev, skb);
2276 break;
2277
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +02002278 case HCI_OP_READ_DATA_BLOCK_SIZE:
2279 hci_cc_read_data_block_size(hdev, skb);
2280 break;
2281
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +02002282 case HCI_OP_READ_FLOW_CONTROL_MODE:
2283 hci_cc_read_flow_control_mode(hdev, skb);
2284 break;
2285
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +03002286 case HCI_OP_READ_LOCAL_AMP_INFO:
2287 hci_cc_read_local_amp_info(hdev, skb);
2288 break;
2289
Andrei Emeltchenko903e4542012-09-27 17:26:09 +03002290 case HCI_OP_READ_LOCAL_AMP_ASSOC:
2291 hci_cc_read_local_amp_assoc(hdev, skb);
2292 break;
2293
Johan Hedbergd5859e22011-01-25 01:19:58 +02002294 case HCI_OP_READ_INQ_RSP_TX_POWER:
2295 hci_cc_read_inq_rsp_tx_power(hdev, skb);
2296 break;
2297
Johan Hedberg980e1a52011-01-22 06:10:07 +02002298 case HCI_OP_PIN_CODE_REPLY:
2299 hci_cc_pin_code_reply(hdev, skb);
2300 break;
2301
2302 case HCI_OP_PIN_CODE_NEG_REPLY:
2303 hci_cc_pin_code_neg_reply(hdev, skb);
2304 break;
2305
Szymon Jancc35938b2011-03-22 13:12:21 +01002306 case HCI_OP_READ_LOCAL_OOB_DATA:
2307 hci_cc_read_local_oob_data_reply(hdev, skb);
2308 break;
2309
Ville Tervo6ed58ec2011-02-10 22:38:48 -03002310 case HCI_OP_LE_READ_BUFFER_SIZE:
2311 hci_cc_le_read_buffer_size(hdev, skb);
2312 break;
2313
Johan Hedberg60e77322013-01-22 14:01:59 +02002314 case HCI_OP_LE_READ_LOCAL_FEATURES:
2315 hci_cc_le_read_local_features(hdev, skb);
2316 break;
2317
Johan Hedberg8fa19092012-10-19 20:57:49 +03002318 case HCI_OP_LE_READ_ADV_TX_POWER:
2319 hci_cc_le_read_adv_tx_power(hdev, skb);
2320 break;
2321
Johan Hedberga5c29682011-02-19 12:05:57 -03002322 case HCI_OP_USER_CONFIRM_REPLY:
2323 hci_cc_user_confirm_reply(hdev, skb);
2324 break;
2325
2326 case HCI_OP_USER_CONFIRM_NEG_REPLY:
2327 hci_cc_user_confirm_neg_reply(hdev, skb);
2328 break;
2329
Brian Gix1143d452011-11-23 08:28:34 -08002330 case HCI_OP_USER_PASSKEY_REPLY:
2331 hci_cc_user_passkey_reply(hdev, skb);
2332 break;
2333
2334 case HCI_OP_USER_PASSKEY_NEG_REPLY:
2335 hci_cc_user_passkey_neg_reply(hdev, skb);
Szymon Janc16cde992012-04-13 12:32:42 +02002336 break;
Andre Guedes07f7fa52011-12-02 21:13:31 +09002337
2338 case HCI_OP_LE_SET_SCAN_PARAM:
2339 hci_cc_le_set_scan_param(hdev, skb);
Brian Gix1143d452011-11-23 08:28:34 -08002340 break;
2341
Johan Hedbergc1d5dc42012-11-08 01:23:01 +01002342 case HCI_OP_LE_SET_ADV_ENABLE:
2343 hci_cc_le_set_adv_enable(hdev, skb);
2344 break;
2345
Andre Guedeseb9d91f2011-05-26 16:23:52 -03002346 case HCI_OP_LE_SET_SCAN_ENABLE:
2347 hci_cc_le_set_scan_enable(hdev, skb);
2348 break;
2349
Johan Hedbergcf1d0812013-01-22 14:02:00 +02002350 case HCI_OP_LE_READ_WHITE_LIST_SIZE:
2351 hci_cc_le_read_white_list_size(hdev, skb);
2352 break;
2353
Johan Hedberg9b008c02013-01-22 14:02:01 +02002354 case HCI_OP_LE_READ_SUPPORTED_STATES:
2355 hci_cc_le_read_supported_states(hdev, skb);
2356 break;
2357
Andre Guedesf9b49302011-06-30 19:20:53 -03002358 case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2359 hci_cc_write_le_host_supported(hdev, skb);
2360 break;
2361
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03002362 case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
2363 hci_cc_write_remote_amp_assoc(hdev, skb);
2364 break;
2365
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002366 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002367 BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002368 break;
2369 }
2370
Johan Hedbergad82cdd2013-03-09 09:53:50 +02002371 if (opcode != HCI_OP_NOP)
Ville Tervo6bd32322011-02-16 16:32:41 +02002372 del_timer(&hdev->cmd_timer);
2373
Johan Hedbergad82cdd2013-03-09 09:53:50 +02002374 hci_req_cmd_complete(hdev, opcode, status);
Johan Hedberg9238f362013-03-05 20:37:48 +02002375
Szymon Jancdbccd792012-12-11 08:51:19 +01002376 if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002377 atomic_set(&hdev->cmd_cnt, 1);
2378 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002379 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002380 }
2381}
2382
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002383static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002384{
2385 struct hci_ev_cmd_status *ev = (void *) skb->data;
2386 __u16 opcode;
2387
2388 skb_pull(skb, sizeof(*ev));
2389
2390 opcode = __le16_to_cpu(ev->opcode);
2391
2392 switch (opcode) {
2393 case HCI_OP_INQUIRY:
2394 hci_cs_inquiry(hdev, ev->status);
2395 break;
2396
2397 case HCI_OP_CREATE_CONN:
2398 hci_cs_create_conn(hdev, ev->status);
2399 break;
2400
2401 case HCI_OP_ADD_SCO:
2402 hci_cs_add_sco(hdev, ev->status);
2403 break;
2404
Marcel Holtmannf8558552008-07-14 20:13:49 +02002405 case HCI_OP_AUTH_REQUESTED:
2406 hci_cs_auth_requested(hdev, ev->status);
2407 break;
2408
2409 case HCI_OP_SET_CONN_ENCRYPT:
2410 hci_cs_set_conn_encrypt(hdev, ev->status);
2411 break;
2412
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002413 case HCI_OP_REMOTE_NAME_REQ:
2414 hci_cs_remote_name_req(hdev, ev->status);
2415 break;
2416
Marcel Holtmann769be972008-07-14 20:13:49 +02002417 case HCI_OP_READ_REMOTE_FEATURES:
2418 hci_cs_read_remote_features(hdev, ev->status);
2419 break;
2420
2421 case HCI_OP_READ_REMOTE_EXT_FEATURES:
2422 hci_cs_read_remote_ext_features(hdev, ev->status);
2423 break;
2424
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002425 case HCI_OP_SETUP_SYNC_CONN:
2426 hci_cs_setup_sync_conn(hdev, ev->status);
2427 break;
2428
2429 case HCI_OP_SNIFF_MODE:
2430 hci_cs_sniff_mode(hdev, ev->status);
2431 break;
2432
2433 case HCI_OP_EXIT_SNIFF_MODE:
2434 hci_cs_exit_sniff_mode(hdev, ev->status);
2435 break;
2436
Johan Hedberg8962ee72011-01-20 12:40:27 +02002437 case HCI_OP_DISCONNECT:
Johan Hedberg88c3df12012-02-09 14:27:38 +02002438 hci_cs_disconnect(hdev, ev->status);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002439 break;
2440
Ville Tervofcd89c02011-02-10 22:38:47 -03002441 case HCI_OP_LE_CREATE_CONN:
2442 hci_cs_le_create_conn(hdev, ev->status);
2443 break;
2444
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03002445 case HCI_OP_CREATE_PHY_LINK:
2446 hci_cs_create_phylink(hdev, ev->status);
2447 break;
2448
Andrei Emeltchenko0b26ab92012-09-27 17:26:24 +03002449 case HCI_OP_ACCEPT_PHY_LINK:
2450 hci_cs_accept_phylink(hdev, ev->status);
2451 break;
2452
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002453 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002454 BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002455 break;
2456 }
2457
Johan Hedbergad82cdd2013-03-09 09:53:50 +02002458 if (opcode != HCI_OP_NOP)
Ville Tervo6bd32322011-02-16 16:32:41 +02002459 del_timer(&hdev->cmd_timer);
2460
Andre Guedes33720452013-03-27 20:04:55 -03002461 hci_req_cmd_complete(hdev, opcode, ev->status);
Johan Hedberg9238f362013-03-05 20:37:48 +02002462
Gustavo F. Padovan10572132011-03-16 15:36:29 -03002463 if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002464 atomic_set(&hdev->cmd_cnt, 1);
2465 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002466 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002467 }
2468}
2469
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002470static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002471{
2472 struct hci_ev_role_change *ev = (void *) skb->data;
2473 struct hci_conn *conn;
2474
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002475 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002476
2477 hci_dev_lock(hdev);
2478
2479 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2480 if (conn) {
2481 if (!ev->status) {
2482 if (ev->role)
2483 conn->link_mode &= ~HCI_LM_MASTER;
2484 else
2485 conn->link_mode |= HCI_LM_MASTER;
2486 }
2487
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002488 clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002489
2490 hci_role_switch_cfm(conn, ev->status, ev->role);
2491 }
2492
2493 hci_dev_unlock(hdev);
2494}
2495
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002496static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002498 struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002499 int i;
2500
Andrei Emeltchenko32ac5b92011-12-19 16:31:29 +02002501 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
2502 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2503 return;
2504 }
2505
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002506 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
Gustavo Padovan807deac2012-05-17 00:36:24 -03002507 ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002508 BT_DBG("%s bad parameters", hdev->name);
2509 return;
2510 }
2511
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002512 BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2513
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002514 for (i = 0; i < ev->num_hndl; i++) {
2515 struct hci_comp_pkts_info *info = &ev->handles[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002516 struct hci_conn *conn;
2517 __u16 handle, count;
2518
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002519 handle = __le16_to_cpu(info->handle);
2520 count = __le16_to_cpu(info->count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002521
2522 conn = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002523 if (!conn)
2524 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002525
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002526 conn->sent -= count;
2527
2528 switch (conn->type) {
2529 case ACL_LINK:
2530 hdev->acl_cnt += count;
2531 if (hdev->acl_cnt > hdev->acl_pkts)
2532 hdev->acl_cnt = hdev->acl_pkts;
2533 break;
2534
2535 case LE_LINK:
2536 if (hdev->le_pkts) {
2537 hdev->le_cnt += count;
2538 if (hdev->le_cnt > hdev->le_pkts)
2539 hdev->le_cnt = hdev->le_pkts;
2540 } else {
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02002541 hdev->acl_cnt += count;
2542 if (hdev->acl_cnt > hdev->acl_pkts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002543 hdev->acl_cnt = hdev->acl_pkts;
2544 }
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002545 break;
2546
2547 case SCO_LINK:
2548 hdev->sco_cnt += count;
2549 if (hdev->sco_cnt > hdev->sco_pkts)
2550 hdev->sco_cnt = hdev->sco_pkts;
2551 break;
2552
2553 default:
2554 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2555 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002556 }
2557 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002558
Gustavo F. Padovan3eff45e2011-12-15 00:50:02 -02002559 queue_work(hdev->workqueue, &hdev->tx_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560}
2561
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002562static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
2563 __u16 handle)
2564{
2565 struct hci_chan *chan;
2566
2567 switch (hdev->dev_type) {
2568 case HCI_BREDR:
2569 return hci_conn_hash_lookup_handle(hdev, handle);
2570 case HCI_AMP:
2571 chan = hci_chan_lookup_handle(hdev, handle);
2572 if (chan)
2573 return chan->conn;
2574 break;
2575 default:
2576 BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type);
2577 break;
2578 }
2579
2580 return NULL;
2581}
2582
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002583static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002584{
2585 struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
2586 int i;
2587
2588 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
2589 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2590 return;
2591 }
2592
2593 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
Gustavo Padovan807deac2012-05-17 00:36:24 -03002594 ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002595 BT_DBG("%s bad parameters", hdev->name);
2596 return;
2597 }
2598
2599 BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002600 ev->num_hndl);
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002601
2602 for (i = 0; i < ev->num_hndl; i++) {
2603 struct hci_comp_blocks_info *info = &ev->handles[i];
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002604 struct hci_conn *conn = NULL;
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002605 __u16 handle, block_count;
2606
2607 handle = __le16_to_cpu(info->handle);
2608 block_count = __le16_to_cpu(info->blocks);
2609
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002610 conn = __hci_conn_lookup_handle(hdev, handle);
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002611 if (!conn)
2612 continue;
2613
2614 conn->sent -= block_count;
2615
2616 switch (conn->type) {
2617 case ACL_LINK:
Andrei Emeltchenkobd1eb662012-10-10 17:38:30 +03002618 case AMP_LINK:
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002619 hdev->block_cnt += block_count;
2620 if (hdev->block_cnt > hdev->num_blocks)
2621 hdev->block_cnt = hdev->num_blocks;
2622 break;
2623
2624 default:
2625 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2626 break;
2627 }
2628 }
2629
2630 queue_work(hdev->workqueue, &hdev->tx_work);
2631}
2632
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002633static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002634{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002635 struct hci_ev_mode_change *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002636 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002637
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002638 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002639
2640 hci_dev_lock(hdev);
2641
Marcel Holtmann04837f62006-07-03 10:02:33 +02002642 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2643 if (conn) {
2644 conn->mode = ev->mode;
2645 conn->interval = __le16_to_cpu(ev->interval);
2646
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002647 if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
2648 &conn->flags)) {
Marcel Holtmann04837f62006-07-03 10:02:33 +02002649 if (conn->mode == HCI_CM_ACTIVE)
Johan Hedberg58a681e2012-01-16 06:47:28 +02002650 set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002651 else
Johan Hedberg58a681e2012-01-16 06:47:28 +02002652 clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002653 }
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002654
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002655 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002656 hci_sco_setup(conn, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002657 }
2658
2659 hci_dev_unlock(hdev);
2660}
2661
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002662static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002663{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002664 struct hci_ev_pin_code_req *ev = (void *) skb->data;
2665 struct hci_conn *conn;
2666
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002667 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002668
2669 hci_dev_lock(hdev);
2670
2671 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002672 if (!conn)
2673 goto unlock;
2674
2675 if (conn->state == BT_CONNECTED) {
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002676 hci_conn_hold(conn);
2677 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2678 hci_conn_put(conn);
2679 }
2680
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002681 if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02002682 hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002683 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002684 else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002685 u8 secure;
2686
2687 if (conn->pending_sec_level == BT_SECURITY_HIGH)
2688 secure = 1;
2689 else
2690 secure = 0;
2691
Johan Hedberg744cf192011-11-08 20:40:14 +02002692 mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002693 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002694
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002695unlock:
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002696 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002697}
2698
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002699static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002700{
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002701 struct hci_ev_link_key_req *ev = (void *) skb->data;
2702 struct hci_cp_link_key_reply cp;
2703 struct hci_conn *conn;
2704 struct link_key *key;
2705
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002706 BT_DBG("%s", hdev->name);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002707
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002708 if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002709 return;
2710
2711 hci_dev_lock(hdev);
2712
2713 key = hci_find_link_key(hdev, &ev->bdaddr);
2714 if (!key) {
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03002715 BT_DBG("%s link key not found for %pMR", hdev->name,
2716 &ev->bdaddr);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002717 goto not_found;
2718 }
2719
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03002720 BT_DBG("%s found key type %u for %pMR", hdev->name, key->type,
2721 &ev->bdaddr);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002722
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002723 if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002724 key->type == HCI_LK_DEBUG_COMBINATION) {
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002725 BT_DBG("%s ignoring debug key", hdev->name);
2726 goto not_found;
2727 }
2728
2729 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002730 if (conn) {
2731 if (key->type == HCI_LK_UNAUTH_COMBINATION &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002732 conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002733 BT_DBG("%s ignoring unauthenticated key", hdev->name);
2734 goto not_found;
2735 }
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002736
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002737 if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002738 conn->pending_sec_level == BT_SECURITY_HIGH) {
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002739 BT_DBG("%s ignoring key unauthenticated for high security",
2740 hdev->name);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002741 goto not_found;
2742 }
2743
2744 conn->key_type = key->type;
2745 conn->pin_length = key->pin_len;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002746 }
2747
2748 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03002749 memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002750
2751 hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
2752
2753 hci_dev_unlock(hdev);
2754
2755 return;
2756
2757not_found:
2758 hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
2759 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002760}
2761
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002762static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002763{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002764 struct hci_ev_link_key_notify *ev = (void *) skb->data;
2765 struct hci_conn *conn;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002766 u8 pin_len = 0;
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002767
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002768 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002769
2770 hci_dev_lock(hdev);
2771
2772 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2773 if (conn) {
2774 hci_conn_hold(conn);
2775 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002776 pin_len = conn->pin_length;
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +02002777
2778 if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
2779 conn->key_type = ev->key_type;
2780
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002781 hci_conn_put(conn);
2782 }
2783
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002784 if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedbergd25e28a2011-04-28 11:28:59 -07002785 hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002786 ev->key_type, pin_len);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002787
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002788 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002789}
2790
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002791static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04837f62006-07-03 10:02:33 +02002792{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002793 struct hci_ev_clock_offset *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002794 struct hci_conn *conn;
2795
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002796 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002797
2798 hci_dev_lock(hdev);
2799
2800 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002801 if (conn && !ev->status) {
2802 struct inquiry_entry *ie;
2803
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002804 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2805 if (ie) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002806 ie->data.clock_offset = ev->clock_offset;
2807 ie->timestamp = jiffies;
2808 }
2809 }
2810
2811 hci_dev_unlock(hdev);
2812}
2813
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002814static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna8746412008-07-14 20:13:46 +02002815{
2816 struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2817 struct hci_conn *conn;
2818
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002819 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna8746412008-07-14 20:13:46 +02002820
2821 hci_dev_lock(hdev);
2822
2823 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2824 if (conn && !ev->status)
2825 conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2826
2827 hci_dev_unlock(hdev);
2828}
2829
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002830static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002831{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002832 struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002833 struct inquiry_entry *ie;
2834
2835 BT_DBG("%s", hdev->name);
2836
2837 hci_dev_lock(hdev);
2838
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002839 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2840 if (ie) {
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002841 ie->data.pscan_rep_mode = ev->pscan_rep_mode;
2842 ie->timestamp = jiffies;
2843 }
2844
2845 hci_dev_unlock(hdev);
2846}
2847
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002848static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
2849 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002850{
2851 struct inquiry_data data;
2852 int num_rsp = *((__u8 *) skb->data);
Johan Hedberg388fc8f2012-02-23 00:38:59 +02002853 bool name_known, ssp;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002854
2855 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2856
2857 if (!num_rsp)
2858 return;
2859
Andre Guedes1519cc12012-03-21 00:03:38 -03002860 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
2861 return;
2862
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002863 hci_dev_lock(hdev);
2864
2865 if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
Szymon Janc138d22e2011-02-17 16:44:23 +01002866 struct inquiry_info_with_rssi_and_pscan_mode *info;
2867 info = (void *) (skb->data + 1);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002868
Johan Hedberge17acd42011-03-30 23:57:16 +03002869 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002870 bacpy(&data.bdaddr, &info->bdaddr);
2871 data.pscan_rep_mode = info->pscan_rep_mode;
2872 data.pscan_period_mode = info->pscan_period_mode;
2873 data.pscan_mode = info->pscan_mode;
2874 memcpy(data.dev_class, info->dev_class, 3);
2875 data.clock_offset = info->clock_offset;
2876 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002877 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02002878
2879 name_known = hci_inquiry_cache_update(hdev, &data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002880 false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02002881 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002882 info->dev_class, info->rssi,
2883 !name_known, ssp, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002884 }
2885 } else {
2886 struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2887
Johan Hedberge17acd42011-03-30 23:57:16 +03002888 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002889 bacpy(&data.bdaddr, &info->bdaddr);
2890 data.pscan_rep_mode = info->pscan_rep_mode;
2891 data.pscan_period_mode = info->pscan_period_mode;
2892 data.pscan_mode = 0x00;
2893 memcpy(data.dev_class, info->dev_class, 3);
2894 data.clock_offset = info->clock_offset;
2895 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002896 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02002897 name_known = hci_inquiry_cache_update(hdev, &data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002898 false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02002899 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002900 info->dev_class, info->rssi,
2901 !name_known, ssp, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002902 }
2903 }
2904
2905 hci_dev_unlock(hdev);
2906}
2907
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002908static void hci_remote_ext_features_evt(struct hci_dev *hdev,
2909 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002910{
Marcel Holtmann41a96212008-07-14 20:13:48 +02002911 struct hci_ev_remote_ext_features *ev = (void *) skb->data;
2912 struct hci_conn *conn;
2913
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002914 BT_DBG("%s", hdev->name);
Marcel Holtmann41a96212008-07-14 20:13:48 +02002915
Marcel Holtmann41a96212008-07-14 20:13:48 +02002916 hci_dev_lock(hdev);
2917
2918 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02002919 if (!conn)
2920 goto unlock;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002921
Johan Hedbergccd556f2010-11-10 17:11:51 +02002922 if (!ev->status && ev->page == 0x01) {
2923 struct inquiry_entry *ie;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002924
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002925 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2926 if (ie)
Johan Hedberg02b7cc62012-02-28 02:28:43 +02002927 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
Marcel Holtmann769be972008-07-14 20:13:49 +02002928
Johan Hedberg02b7cc62012-02-28 02:28:43 +02002929 if (ev->features[0] & LMP_HOST_SSP)
Johan Hedberg58a681e2012-01-16 06:47:28 +02002930 set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
Marcel Holtmann41a96212008-07-14 20:13:48 +02002931 }
2932
Johan Hedbergccd556f2010-11-10 17:11:51 +02002933 if (conn->state != BT_CONFIG)
2934 goto unlock;
2935
Johan Hedberg671267b2012-05-12 16:11:50 -03002936 if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002937 struct hci_cp_remote_name_req cp;
2938 memset(&cp, 0, sizeof(cp));
2939 bacpy(&cp.bdaddr, &conn->dst);
2940 cp.pscan_rep_mode = 0x02;
2941 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002942 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2943 mgmt_device_connected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002944 conn->dst_type, 0, NULL, 0,
2945 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02002946
Johan Hedberg127178d2010-11-18 22:22:29 +02002947 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02002948 conn->state = BT_CONNECTED;
2949 hci_proto_connect_cfm(conn, ev->status);
2950 hci_conn_put(conn);
2951 }
2952
2953unlock:
Marcel Holtmann41a96212008-07-14 20:13:48 +02002954 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002955}
2956
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002957static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
2958 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002959{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002960 struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2961 struct hci_conn *conn;
2962
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002963 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002964
2965 hci_dev_lock(hdev);
2966
2967 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann9dc0a3a2008-07-14 20:13:46 +02002968 if (!conn) {
2969 if (ev->link_type == ESCO_LINK)
2970 goto unlock;
2971
2972 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2973 if (!conn)
2974 goto unlock;
2975
2976 conn->type = SCO_LINK;
2977 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002978
Marcel Holtmann732547f2009-04-19 19:14:14 +02002979 switch (ev->status) {
2980 case 0x00:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002981 conn->handle = __le16_to_cpu(ev->handle);
2982 conn->state = BT_CONNECTED;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002983
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07002984 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002985 hci_conn_add_sysfs(conn);
Marcel Holtmann732547f2009-04-19 19:14:14 +02002986 break;
2987
Stephen Coe705e5712010-02-16 11:29:44 -05002988 case 0x11: /* Unsupported Feature or Parameter Value */
Marcel Holtmann732547f2009-04-19 19:14:14 +02002989 case 0x1c: /* SCO interval rejected */
Nick Pelly1038a002010-02-03 11:42:26 -08002990 case 0x1a: /* Unsupported Remote Feature */
Marcel Holtmann732547f2009-04-19 19:14:14 +02002991 case 0x1f: /* Unspecified error */
2992 if (conn->out && conn->attempt < 2) {
2993 conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2994 (hdev->esco_type & EDR_ESCO_MASK);
2995 hci_setup_sync(conn, conn->link->handle);
2996 goto unlock;
2997 }
2998 /* fall through */
2999
3000 default:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003001 conn->state = BT_CLOSED;
Marcel Holtmann732547f2009-04-19 19:14:14 +02003002 break;
3003 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003004
3005 hci_proto_connect_cfm(conn, ev->status);
3006 if (ev->status)
3007 hci_conn_del(conn);
3008
3009unlock:
3010 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003011}
3012
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003013static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
3014 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003015{
3016 struct inquiry_data data;
3017 struct extended_inquiry_info *info = (void *) (skb->data + 1);
3018 int num_rsp = *((__u8 *) skb->data);
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303019 size_t eir_len;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003020
3021 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3022
3023 if (!num_rsp)
3024 return;
3025
Andre Guedes1519cc12012-03-21 00:03:38 -03003026 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
3027 return;
3028
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003029 hci_dev_lock(hdev);
3030
Johan Hedberge17acd42011-03-30 23:57:16 +03003031 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003032 bool name_known, ssp;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003033
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003034 bacpy(&data.bdaddr, &info->bdaddr);
Szymon Janc138d22e2011-02-17 16:44:23 +01003035 data.pscan_rep_mode = info->pscan_rep_mode;
3036 data.pscan_period_mode = info->pscan_period_mode;
3037 data.pscan_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003038 memcpy(data.dev_class, info->dev_class, 3);
Szymon Janc138d22e2011-02-17 16:44:23 +01003039 data.clock_offset = info->clock_offset;
3040 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003041 data.ssp_mode = 0x01;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003042
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003043 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg4ddb1932012-01-15 20:04:43 +02003044 name_known = eir_has_data_type(info->data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003045 sizeof(info->data),
3046 EIR_NAME_COMPLETE);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003047 else
3048 name_known = true;
3049
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003050 name_known = hci_inquiry_cache_update(hdev, &data, name_known,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003051 &ssp);
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303052 eir_len = eir_get_length(info->data, sizeof(info->data));
Johan Hedberg48264f02011-11-09 13:58:58 +02003053 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003054 info->dev_class, info->rssi, !name_known,
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303055 ssp, info->data, eir_len);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003056 }
3057
3058 hci_dev_unlock(hdev);
3059}
3060
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003061static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
3062 struct sk_buff *skb)
3063{
3064 struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
3065 struct hci_conn *conn;
3066
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003067 BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003068 __le16_to_cpu(ev->handle));
3069
3070 hci_dev_lock(hdev);
3071
3072 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3073 if (!conn)
3074 goto unlock;
3075
3076 if (!ev->status)
3077 conn->sec_level = conn->pending_sec_level;
3078
3079 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
3080
3081 if (ev->status && conn->state == BT_CONNECTED) {
Andre Guedesbed71742013-01-30 11:50:56 -03003082 hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003083 hci_conn_put(conn);
3084 goto unlock;
3085 }
3086
3087 if (conn->state == BT_CONFIG) {
3088 if (!ev->status)
3089 conn->state = BT_CONNECTED;
3090
3091 hci_proto_connect_cfm(conn, ev->status);
3092 hci_conn_put(conn);
3093 } else {
3094 hci_auth_cfm(conn, ev->status);
3095
3096 hci_conn_hold(conn);
3097 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
3098 hci_conn_put(conn);
3099 }
3100
3101unlock:
3102 hci_dev_unlock(hdev);
3103}
3104
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003105static u8 hci_get_auth_req(struct hci_conn *conn)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003106{
3107 /* If remote requests dedicated bonding follow that lead */
3108 if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
3109 /* If both remote and local IO capabilities allow MITM
3110 * protection then require it, otherwise don't */
3111 if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
3112 return 0x02;
3113 else
3114 return 0x03;
3115 }
3116
3117 /* If remote requests no-bonding follow that lead */
3118 if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
Waldemar Rymarkiewicz58797bf2011-04-28 12:07:58 +02003119 return conn->remote_auth | (conn->auth_type & 0x01);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003120
3121 return conn->auth_type;
3122}
3123
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003124static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04936842008-07-14 20:13:48 +02003125{
3126 struct hci_ev_io_capa_request *ev = (void *) skb->data;
3127 struct hci_conn *conn;
3128
3129 BT_DBG("%s", hdev->name);
3130
3131 hci_dev_lock(hdev);
3132
3133 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003134 if (!conn)
3135 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003136
Johan Hedberg03b555e2011-01-04 15:40:05 +02003137 hci_conn_hold(conn);
3138
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003139 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02003140 goto unlock;
3141
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003142 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
Gustavo Padovan807deac2012-05-17 00:36:24 -03003143 (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003144 struct hci_cp_io_capability_reply cp;
3145
3146 bacpy(&cp.bdaddr, &ev->bdaddr);
Hemant Gupta7a7f1e72012-01-16 13:34:29 +05303147 /* Change the IO capability from KeyboardDisplay
3148 * to DisplayYesNo as it is not supported by BT spec. */
3149 cp.capability = (conn->io_capability == 0x04) ?
3150 0x01 : conn->io_capability;
Johan Hedberg7cbc9bd2011-04-28 11:29:04 -07003151 conn->auth_type = hci_get_auth_req(conn);
3152 cp.authentication = conn->auth_type;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003153
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03003154 if (hci_find_remote_oob_data(hdev, &conn->dst) &&
3155 (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
Szymon Jancce85ee12011-03-22 13:12:23 +01003156 cp.oob_data = 0x01;
3157 else
3158 cp.oob_data = 0x00;
3159
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003160 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003161 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003162 } else {
3163 struct hci_cp_io_capability_neg_reply cp;
3164
3165 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02003166 cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003167
3168 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003169 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003170 }
3171
3172unlock:
3173 hci_dev_unlock(hdev);
3174}
3175
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003176static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
Johan Hedberg03b555e2011-01-04 15:40:05 +02003177{
3178 struct hci_ev_io_capa_reply *ev = (void *) skb->data;
3179 struct hci_conn *conn;
3180
3181 BT_DBG("%s", hdev->name);
3182
3183 hci_dev_lock(hdev);
3184
3185 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3186 if (!conn)
3187 goto unlock;
3188
Johan Hedberg03b555e2011-01-04 15:40:05 +02003189 conn->remote_cap = ev->capability;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003190 conn->remote_auth = ev->authentication;
Johan Hedberg58a681e2012-01-16 06:47:28 +02003191 if (ev->oob_data)
3192 set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003193
3194unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003195 hci_dev_unlock(hdev);
3196}
3197
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003198static void hci_user_confirm_request_evt(struct hci_dev *hdev,
3199 struct sk_buff *skb)
Johan Hedberga5c29682011-02-19 12:05:57 -03003200{
3201 struct hci_ev_user_confirm_req *ev = (void *) skb->data;
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003202 int loc_mitm, rem_mitm, confirm_hint = 0;
Johan Hedberg7a828902011-04-28 11:28:53 -07003203 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003204
3205 BT_DBG("%s", hdev->name);
3206
3207 hci_dev_lock(hdev);
3208
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003209 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg7a828902011-04-28 11:28:53 -07003210 goto unlock;
Johan Hedberga5c29682011-02-19 12:05:57 -03003211
Johan Hedberg7a828902011-04-28 11:28:53 -07003212 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3213 if (!conn)
3214 goto unlock;
3215
3216 loc_mitm = (conn->auth_type & 0x01);
3217 rem_mitm = (conn->remote_auth & 0x01);
3218
3219 /* If we require MITM but the remote device can't provide that
3220 * (it has NoInputNoOutput) then reject the confirmation
3221 * request. The only exception is when we're dedicated bonding
3222 * initiators (connect_cfm_cb set) since then we always have the MITM
3223 * bit set. */
3224 if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
3225 BT_DBG("Rejecting request: remote device can't provide MITM");
3226 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003227 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberg7a828902011-04-28 11:28:53 -07003228 goto unlock;
3229 }
3230
3231 /* If no side requires MITM protection; auto-accept */
3232 if ((!loc_mitm || conn->remote_cap == 0x03) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03003233 (!rem_mitm || conn->io_capability == 0x03)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003234
3235 /* If we're not the initiators request authorization to
3236 * proceed from user space (mgmt_user_confirm with
3237 * confirm_hint set to 1). */
Johan Hedberg51a8efd2012-01-16 06:10:31 +02003238 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003239 BT_DBG("Confirming auto-accept as acceptor");
3240 confirm_hint = 1;
3241 goto confirm;
3242 }
3243
Johan Hedberg9f616562011-04-28 11:28:54 -07003244 BT_DBG("Auto-accept of user confirmation with %ums delay",
Gustavo Padovan807deac2012-05-17 00:36:24 -03003245 hdev->auto_accept_delay);
Johan Hedberg9f616562011-04-28 11:28:54 -07003246
3247 if (hdev->auto_accept_delay > 0) {
3248 int delay = msecs_to_jiffies(hdev->auto_accept_delay);
3249 mod_timer(&conn->auto_accept_timer, jiffies + delay);
3250 goto unlock;
3251 }
3252
Johan Hedberg7a828902011-04-28 11:28:53 -07003253 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003254 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberg7a828902011-04-28 11:28:53 -07003255 goto unlock;
3256 }
3257
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003258confirm:
Johan Hedberg272d90d2012-02-09 15:26:12 +02003259 mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003260 confirm_hint);
Johan Hedberg7a828902011-04-28 11:28:53 -07003261
3262unlock:
Johan Hedberga5c29682011-02-19 12:05:57 -03003263 hci_dev_unlock(hdev);
3264}
3265
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003266static void hci_user_passkey_request_evt(struct hci_dev *hdev,
3267 struct sk_buff *skb)
Brian Gix1143d452011-11-23 08:28:34 -08003268{
3269 struct hci_ev_user_passkey_req *ev = (void *) skb->data;
3270
3271 BT_DBG("%s", hdev->name);
3272
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003273 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +02003274 mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
Brian Gix1143d452011-11-23 08:28:34 -08003275}
3276
Johan Hedberg92a25252012-09-06 18:39:26 +03003277static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
3278 struct sk_buff *skb)
3279{
3280 struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
3281 struct hci_conn *conn;
3282
3283 BT_DBG("%s", hdev->name);
3284
3285 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3286 if (!conn)
3287 return;
3288
3289 conn->passkey_notify = __le32_to_cpu(ev->passkey);
3290 conn->passkey_entered = 0;
3291
3292 if (test_bit(HCI_MGMT, &hdev->dev_flags))
3293 mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
3294 conn->dst_type, conn->passkey_notify,
3295 conn->passkey_entered);
3296}
3297
3298static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
3299{
3300 struct hci_ev_keypress_notify *ev = (void *) skb->data;
3301 struct hci_conn *conn;
3302
3303 BT_DBG("%s", hdev->name);
3304
3305 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3306 if (!conn)
3307 return;
3308
3309 switch (ev->type) {
3310 case HCI_KEYPRESS_STARTED:
3311 conn->passkey_entered = 0;
3312 return;
3313
3314 case HCI_KEYPRESS_ENTERED:
3315 conn->passkey_entered++;
3316 break;
3317
3318 case HCI_KEYPRESS_ERASED:
3319 conn->passkey_entered--;
3320 break;
3321
3322 case HCI_KEYPRESS_CLEARED:
3323 conn->passkey_entered = 0;
3324 break;
3325
3326 case HCI_KEYPRESS_COMPLETED:
3327 return;
3328 }
3329
3330 if (test_bit(HCI_MGMT, &hdev->dev_flags))
3331 mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
3332 conn->dst_type, conn->passkey_notify,
3333 conn->passkey_entered);
3334}
3335
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003336static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
3337 struct sk_buff *skb)
Marcel Holtmann04936842008-07-14 20:13:48 +02003338{
3339 struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
3340 struct hci_conn *conn;
3341
3342 BT_DBG("%s", hdev->name);
3343
3344 hci_dev_lock(hdev);
3345
3346 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg2a611692011-02-19 12:06:00 -03003347 if (!conn)
3348 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003349
Johan Hedberg2a611692011-02-19 12:06:00 -03003350 /* To avoid duplicate auth_failed events to user space we check
3351 * the HCI_CONN_AUTH_PEND flag which will be set if we
3352 * initiated the authentication. A traditional auth_complete
3353 * event gets always produced as initiator and is also mapped to
3354 * the mgmt_auth_failed event */
Mikel Astizfa1bd912012-08-09 09:52:29 +02003355 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status)
Johan Hedbergbab73cb2012-02-09 16:07:29 +02003356 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003357 ev->status);
Johan Hedberg2a611692011-02-19 12:06:00 -03003358
3359 hci_conn_put(conn);
3360
3361unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003362 hci_dev_unlock(hdev);
3363}
3364
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003365static void hci_remote_host_features_evt(struct hci_dev *hdev,
3366 struct sk_buff *skb)
Marcel Holtmann41a96212008-07-14 20:13:48 +02003367{
3368 struct hci_ev_remote_host_features *ev = (void *) skb->data;
3369 struct inquiry_entry *ie;
3370
3371 BT_DBG("%s", hdev->name);
3372
3373 hci_dev_lock(hdev);
3374
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003375 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3376 if (ie)
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003377 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003378
3379 hci_dev_unlock(hdev);
3380}
3381
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003382static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
3383 struct sk_buff *skb)
Szymon Janc2763eda2011-03-22 13:12:22 +01003384{
3385 struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
3386 struct oob_data *data;
3387
3388 BT_DBG("%s", hdev->name);
3389
3390 hci_dev_lock(hdev);
3391
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003392 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Szymon Jance1ba1f12011-04-06 13:01:59 +02003393 goto unlock;
3394
Szymon Janc2763eda2011-03-22 13:12:22 +01003395 data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
3396 if (data) {
3397 struct hci_cp_remote_oob_data_reply cp;
3398
3399 bacpy(&cp.bdaddr, &ev->bdaddr);
3400 memcpy(cp.hash, data->hash, sizeof(cp.hash));
3401 memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
3402
3403 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03003404 &cp);
Szymon Janc2763eda2011-03-22 13:12:22 +01003405 } else {
3406 struct hci_cp_remote_oob_data_neg_reply cp;
3407
3408 bacpy(&cp.bdaddr, &ev->bdaddr);
3409 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03003410 &cp);
Szymon Janc2763eda2011-03-22 13:12:22 +01003411 }
3412
Szymon Jance1ba1f12011-04-06 13:01:59 +02003413unlock:
Szymon Janc2763eda2011-03-22 13:12:22 +01003414 hci_dev_unlock(hdev);
3415}
3416
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03003417static void hci_phy_link_complete_evt(struct hci_dev *hdev,
3418 struct sk_buff *skb)
3419{
3420 struct hci_ev_phy_link_complete *ev = (void *) skb->data;
3421 struct hci_conn *hcon, *bredr_hcon;
3422
3423 BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle,
3424 ev->status);
3425
3426 hci_dev_lock(hdev);
3427
3428 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3429 if (!hcon) {
3430 hci_dev_unlock(hdev);
3431 return;
3432 }
3433
3434 if (ev->status) {
3435 hci_conn_del(hcon);
3436 hci_dev_unlock(hdev);
3437 return;
3438 }
3439
3440 bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon;
3441
3442 hcon->state = BT_CONNECTED;
3443 bacpy(&hcon->dst, &bredr_hcon->dst);
3444
3445 hci_conn_hold(hcon);
3446 hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
3447 hci_conn_put(hcon);
3448
3449 hci_conn_hold_device(hcon);
3450 hci_conn_add_sysfs(hcon);
3451
Andrei Emeltchenkocf70ff22012-10-31 15:46:36 +02003452 amp_physical_cfm(bredr_hcon, hcon);
3453
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03003454 hci_dev_unlock(hdev);
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03003455}
3456
Andrei Emeltchenko27695fb2012-10-25 15:20:45 +03003457static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3458{
3459 struct hci_ev_logical_link_complete *ev = (void *) skb->data;
3460 struct hci_conn *hcon;
3461 struct hci_chan *hchan;
3462 struct amp_mgr *mgr;
3463
3464 BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x",
3465 hdev->name, le16_to_cpu(ev->handle), ev->phy_handle,
3466 ev->status);
3467
3468 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3469 if (!hcon)
3470 return;
3471
3472 /* Create AMP hchan */
3473 hchan = hci_chan_create(hcon);
3474 if (!hchan)
3475 return;
3476
3477 hchan->handle = le16_to_cpu(ev->handle);
3478
3479 BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan);
3480
3481 mgr = hcon->amp_mgr;
3482 if (mgr && mgr->bredr_chan) {
3483 struct l2cap_chan *bredr_chan = mgr->bredr_chan;
3484
3485 l2cap_chan_lock(bredr_chan);
3486
3487 bredr_chan->conn->mtu = hdev->block_mtu;
3488 l2cap_logical_cfm(bredr_chan, hchan, 0);
3489 hci_conn_hold(hcon);
3490
3491 l2cap_chan_unlock(bredr_chan);
3492 }
3493}
3494
Andrei Emeltchenko606e2a12012-10-31 15:46:31 +02003495static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,
3496 struct sk_buff *skb)
3497{
3498 struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data;
3499 struct hci_chan *hchan;
3500
3501 BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name,
3502 le16_to_cpu(ev->handle), ev->status);
3503
3504 if (ev->status)
3505 return;
3506
3507 hci_dev_lock(hdev);
3508
3509 hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle));
3510 if (!hchan)
3511 goto unlock;
3512
3513 amp_destroy_logical_link(hchan, ev->reason);
3514
3515unlock:
3516 hci_dev_unlock(hdev);
3517}
3518
Andrei Emeltchenko9eef6b32012-10-31 15:46:32 +02003519static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev,
3520 struct sk_buff *skb)
3521{
3522 struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data;
3523 struct hci_conn *hcon;
3524
3525 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3526
3527 if (ev->status)
3528 return;
3529
3530 hci_dev_lock(hdev);
3531
3532 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3533 if (hcon) {
3534 hcon->state = BT_CLOSED;
3535 hci_conn_del(hcon);
3536 }
3537
3538 hci_dev_unlock(hdev);
3539}
3540
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003541static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Ville Tervofcd89c02011-02-10 22:38:47 -03003542{
3543 struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3544 struct hci_conn *conn;
3545
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003546 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Ville Tervofcd89c02011-02-10 22:38:47 -03003547
3548 hci_dev_lock(hdev);
3549
Andre Guedesb47a09b2012-07-27 15:10:15 -03003550 conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
Ville Tervob62f3282011-02-10 22:38:50 -03003551 if (!conn) {
3552 conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3553 if (!conn) {
3554 BT_ERR("No memory for new connection");
Andre Guedes230fd162012-07-27 15:10:10 -03003555 goto unlock;
Ville Tervob62f3282011-02-10 22:38:50 -03003556 }
Andre Guedes29b79882011-05-31 14:20:54 -03003557
3558 conn->dst_type = ev->bdaddr_type;
Andre Guedesb9b343d2012-07-27 15:10:11 -03003559
3560 if (ev->role == LE_CONN_ROLE_MASTER) {
3561 conn->out = true;
3562 conn->link_mode |= HCI_LM_MASTER;
3563 }
Ville Tervob62f3282011-02-10 22:38:50 -03003564 }
Ville Tervofcd89c02011-02-10 22:38:47 -03003565
Andre Guedescd17dec2012-07-27 15:10:16 -03003566 if (ev->status) {
3567 mgmt_connect_failed(hdev, &conn->dst, conn->type,
3568 conn->dst_type, ev->status);
3569 hci_proto_connect_cfm(conn, ev->status);
3570 conn->state = BT_CLOSED;
3571 hci_conn_del(conn);
3572 goto unlock;
3573 }
3574
Johan Hedbergb644ba32012-01-17 21:48:47 +02003575 if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3576 mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003577 conn->dst_type, 0, NULL, 0, NULL);
Vinicius Costa Gomes83bc71b2011-05-06 18:41:43 -03003578
Vinicius Costa Gomes7b5c0d52011-06-09 18:50:50 -03003579 conn->sec_level = BT_SECURITY_LOW;
Ville Tervofcd89c02011-02-10 22:38:47 -03003580 conn->handle = __le16_to_cpu(ev->handle);
3581 conn->state = BT_CONNECTED;
3582
3583 hci_conn_hold_device(conn);
3584 hci_conn_add_sysfs(conn);
3585
3586 hci_proto_connect_cfm(conn, ev->status);
3587
3588unlock:
3589 hci_dev_unlock(hdev);
3590}
3591
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003592static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
Andre Guedes9aa04c92011-05-26 16:23:51 -03003593{
Andre Guedese95beb42011-09-26 20:48:35 -03003594 u8 num_reports = skb->data[0];
3595 void *ptr = &skb->data[1];
Andre Guedes3c9e9192012-01-10 18:20:50 -03003596 s8 rssi;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003597
Andre Guedese95beb42011-09-26 20:48:35 -03003598 while (num_reports--) {
3599 struct hci_ev_le_advertising_info *ev = ptr;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003600
Andre Guedes3c9e9192012-01-10 18:20:50 -03003601 rssi = ev->data[ev->length];
3602 mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003603 NULL, rssi, 0, 1, ev->data, ev->length);
Andre Guedes3c9e9192012-01-10 18:20:50 -03003604
Andre Guedese95beb42011-09-26 20:48:35 -03003605 ptr += sizeof(*ev) + ev->length + 1;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003606 }
Andre Guedes9aa04c92011-05-26 16:23:51 -03003607}
3608
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003609static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003610{
3611 struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3612 struct hci_cp_le_ltk_reply cp;
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003613 struct hci_cp_le_ltk_neg_reply neg;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003614 struct hci_conn *conn;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003615 struct smp_ltk *ltk;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003616
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003617 BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003618
3619 hci_dev_lock(hdev);
3620
3621 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003622 if (conn == NULL)
3623 goto not_found;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003624
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003625 ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3626 if (ltk == NULL)
3627 goto not_found;
3628
3629 memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003630 cp.handle = cpu_to_le16(conn->handle);
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003631
3632 if (ltk->authenticated)
3633 conn->sec_level = BT_SECURITY_HIGH;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003634
3635 hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3636
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003637 if (ltk->type & HCI_SMP_STK) {
3638 list_del(&ltk->list);
3639 kfree(ltk);
3640 }
3641
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003642 hci_dev_unlock(hdev);
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003643
3644 return;
3645
3646not_found:
3647 neg.handle = ev->handle;
3648 hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3649 hci_dev_unlock(hdev);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003650}
3651
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003652static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
Ville Tervofcd89c02011-02-10 22:38:47 -03003653{
3654 struct hci_ev_le_meta *le_ev = (void *) skb->data;
3655
3656 skb_pull(skb, sizeof(*le_ev));
3657
3658 switch (le_ev->subevent) {
3659 case HCI_EV_LE_CONN_COMPLETE:
3660 hci_le_conn_complete_evt(hdev, skb);
3661 break;
3662
Andre Guedes9aa04c92011-05-26 16:23:51 -03003663 case HCI_EV_LE_ADVERTISING_REPORT:
3664 hci_le_adv_report_evt(hdev, skb);
3665 break;
3666
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003667 case HCI_EV_LE_LTK_REQ:
3668 hci_le_ltk_request_evt(hdev, skb);
3669 break;
3670
Ville Tervofcd89c02011-02-10 22:38:47 -03003671 default:
3672 break;
3673 }
3674}
3675
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +03003676static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
3677{
3678 struct hci_ev_channel_selected *ev = (void *) skb->data;
3679 struct hci_conn *hcon;
3680
3681 BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
3682
3683 skb_pull(skb, sizeof(*ev));
3684
3685 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3686 if (!hcon)
3687 return;
3688
3689 amp_read_loc_assoc_final_data(hdev, hcon);
3690}
3691
Linus Torvalds1da177e2005-04-16 15:20:36 -07003692void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
3693{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003694 struct hci_event_hdr *hdr = (void *) skb->data;
3695 __u8 event = hdr->evt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003696
3697 skb_pull(skb, HCI_EVENT_HDR_SIZE);
3698
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003699 switch (event) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003700 case HCI_EV_INQUIRY_COMPLETE:
3701 hci_inquiry_complete_evt(hdev, skb);
3702 break;
3703
3704 case HCI_EV_INQUIRY_RESULT:
3705 hci_inquiry_result_evt(hdev, skb);
3706 break;
3707
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003708 case HCI_EV_CONN_COMPLETE:
3709 hci_conn_complete_evt(hdev, skb);
Marcel Holtmann21d9e302005-09-13 01:32:25 +02003710 break;
3711
Linus Torvalds1da177e2005-04-16 15:20:36 -07003712 case HCI_EV_CONN_REQUEST:
3713 hci_conn_request_evt(hdev, skb);
3714 break;
3715
Linus Torvalds1da177e2005-04-16 15:20:36 -07003716 case HCI_EV_DISCONN_COMPLETE:
3717 hci_disconn_complete_evt(hdev, skb);
3718 break;
3719
Linus Torvalds1da177e2005-04-16 15:20:36 -07003720 case HCI_EV_AUTH_COMPLETE:
3721 hci_auth_complete_evt(hdev, skb);
3722 break;
3723
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003724 case HCI_EV_REMOTE_NAME:
3725 hci_remote_name_evt(hdev, skb);
3726 break;
3727
Linus Torvalds1da177e2005-04-16 15:20:36 -07003728 case HCI_EV_ENCRYPT_CHANGE:
3729 hci_encrypt_change_evt(hdev, skb);
3730 break;
3731
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003732 case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3733 hci_change_link_key_complete_evt(hdev, skb);
3734 break;
3735
3736 case HCI_EV_REMOTE_FEATURES:
3737 hci_remote_features_evt(hdev, skb);
3738 break;
3739
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003740 case HCI_EV_CMD_COMPLETE:
3741 hci_cmd_complete_evt(hdev, skb);
3742 break;
3743
3744 case HCI_EV_CMD_STATUS:
3745 hci_cmd_status_evt(hdev, skb);
3746 break;
3747
3748 case HCI_EV_ROLE_CHANGE:
3749 hci_role_change_evt(hdev, skb);
3750 break;
3751
3752 case HCI_EV_NUM_COMP_PKTS:
3753 hci_num_comp_pkts_evt(hdev, skb);
3754 break;
3755
3756 case HCI_EV_MODE_CHANGE:
3757 hci_mode_change_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003758 break;
3759
3760 case HCI_EV_PIN_CODE_REQ:
3761 hci_pin_code_request_evt(hdev, skb);
3762 break;
3763
3764 case HCI_EV_LINK_KEY_REQ:
3765 hci_link_key_request_evt(hdev, skb);
3766 break;
3767
3768 case HCI_EV_LINK_KEY_NOTIFY:
3769 hci_link_key_notify_evt(hdev, skb);
3770 break;
3771
3772 case HCI_EV_CLOCK_OFFSET:
3773 hci_clock_offset_evt(hdev, skb);
3774 break;
3775
Marcel Holtmanna8746412008-07-14 20:13:46 +02003776 case HCI_EV_PKT_TYPE_CHANGE:
3777 hci_pkt_type_change_evt(hdev, skb);
3778 break;
3779
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003780 case HCI_EV_PSCAN_REP_MODE:
3781 hci_pscan_rep_mode_evt(hdev, skb);
3782 break;
3783
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003784 case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3785 hci_inquiry_result_with_rssi_evt(hdev, skb);
3786 break;
3787
3788 case HCI_EV_REMOTE_EXT_FEATURES:
3789 hci_remote_ext_features_evt(hdev, skb);
3790 break;
3791
3792 case HCI_EV_SYNC_CONN_COMPLETE:
3793 hci_sync_conn_complete_evt(hdev, skb);
3794 break;
3795
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003796 case HCI_EV_EXTENDED_INQUIRY_RESULT:
3797 hci_extended_inquiry_result_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003798 break;
3799
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003800 case HCI_EV_KEY_REFRESH_COMPLETE:
3801 hci_key_refresh_complete_evt(hdev, skb);
3802 break;
3803
Marcel Holtmann04936842008-07-14 20:13:48 +02003804 case HCI_EV_IO_CAPA_REQUEST:
3805 hci_io_capa_request_evt(hdev, skb);
3806 break;
3807
Johan Hedberg03b555e2011-01-04 15:40:05 +02003808 case HCI_EV_IO_CAPA_REPLY:
3809 hci_io_capa_reply_evt(hdev, skb);
3810 break;
3811
Johan Hedberga5c29682011-02-19 12:05:57 -03003812 case HCI_EV_USER_CONFIRM_REQUEST:
3813 hci_user_confirm_request_evt(hdev, skb);
3814 break;
3815
Brian Gix1143d452011-11-23 08:28:34 -08003816 case HCI_EV_USER_PASSKEY_REQUEST:
3817 hci_user_passkey_request_evt(hdev, skb);
3818 break;
3819
Johan Hedberg92a25252012-09-06 18:39:26 +03003820 case HCI_EV_USER_PASSKEY_NOTIFY:
3821 hci_user_passkey_notify_evt(hdev, skb);
3822 break;
3823
3824 case HCI_EV_KEYPRESS_NOTIFY:
3825 hci_keypress_notify_evt(hdev, skb);
3826 break;
3827
Marcel Holtmann04936842008-07-14 20:13:48 +02003828 case HCI_EV_SIMPLE_PAIR_COMPLETE:
3829 hci_simple_pair_complete_evt(hdev, skb);
3830 break;
3831
Marcel Holtmann41a96212008-07-14 20:13:48 +02003832 case HCI_EV_REMOTE_HOST_FEATURES:
3833 hci_remote_host_features_evt(hdev, skb);
3834 break;
3835
Ville Tervofcd89c02011-02-10 22:38:47 -03003836 case HCI_EV_LE_META:
3837 hci_le_meta_evt(hdev, skb);
3838 break;
3839
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +03003840 case HCI_EV_CHANNEL_SELECTED:
3841 hci_chan_selected_evt(hdev, skb);
3842 break;
3843
Szymon Janc2763eda2011-03-22 13:12:22 +01003844 case HCI_EV_REMOTE_OOB_DATA_REQUEST:
3845 hci_remote_oob_data_request_evt(hdev, skb);
3846 break;
3847
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03003848 case HCI_EV_PHY_LINK_COMPLETE:
3849 hci_phy_link_complete_evt(hdev, skb);
3850 break;
3851
Andrei Emeltchenko27695fb2012-10-25 15:20:45 +03003852 case HCI_EV_LOGICAL_LINK_COMPLETE:
3853 hci_loglink_complete_evt(hdev, skb);
3854 break;
3855
Andrei Emeltchenko606e2a12012-10-31 15:46:31 +02003856 case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE:
3857 hci_disconn_loglink_complete_evt(hdev, skb);
3858 break;
3859
Andrei Emeltchenko9eef6b32012-10-31 15:46:32 +02003860 case HCI_EV_DISCONN_PHY_LINK_COMPLETE:
3861 hci_disconn_phylink_complete_evt(hdev, skb);
3862 break;
3863
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02003864 case HCI_EV_NUM_COMP_BLOCKS:
3865 hci_num_comp_blocks_evt(hdev, skb);
3866 break;
3867
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003868 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003869 BT_DBG("%s event 0x%2.2x", hdev->name, event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003870 break;
3871 }
3872
3873 kfree_skb(skb);
3874 hdev->stat.evt_rx++;
3875}