Bluetooth: mgmt: Refactor hci_dev lookup for commands
[deliverable/linux.git] / net / bluetooth / mgmt.c
CommitLineData
0381101f
JH
1/*
2 BlueZ - Bluetooth protocol stack for Linux
ea585ab5 3
0381101f 4 Copyright (C) 2010 Nokia Corporation
ea585ab5 5 Copyright (C) 2011-2012 Intel Corporation
0381101f
JH
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
15 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
18 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
20 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
22 SOFTWARE IS DISCLAIMED.
23*/
24
25/* Bluetooth HCI Management interface */
26
ca69b795 27#include <linux/kernel.h>
72359753 28#include <linux/uaccess.h>
3a9a231d 29#include <linux/module.h>
0381101f
JH
30#include <asm/unaligned.h>
31
32#include <net/bluetooth/bluetooth.h>
33#include <net/bluetooth/hci_core.h>
34#include <net/bluetooth/mgmt.h>
5fe57d9e 35#include <net/bluetooth/smp.h>
0381101f 36
d7b7e796
MH
37bool enable_hs;
38bool enable_le;
39
2da9c55c
JH
40#define MGMT_VERSION 1
41#define MGMT_REVISION 0
02d98129 42
e70bb2e8
JH
43static const u16 mgmt_commands[] = {
44 MGMT_OP_READ_INDEX_LIST,
45 MGMT_OP_READ_INFO,
46 MGMT_OP_SET_POWERED,
47 MGMT_OP_SET_DISCOVERABLE,
48 MGMT_OP_SET_CONNECTABLE,
49 MGMT_OP_SET_FAST_CONNECTABLE,
50 MGMT_OP_SET_PAIRABLE,
51 MGMT_OP_SET_LINK_SECURITY,
52 MGMT_OP_SET_SSP,
53 MGMT_OP_SET_HS,
54 MGMT_OP_SET_LE,
55 MGMT_OP_SET_DEV_CLASS,
56 MGMT_OP_SET_LOCAL_NAME,
57 MGMT_OP_ADD_UUID,
58 MGMT_OP_REMOVE_UUID,
59 MGMT_OP_LOAD_LINK_KEYS,
60 MGMT_OP_LOAD_LONG_TERM_KEYS,
61 MGMT_OP_DISCONNECT,
62 MGMT_OP_GET_CONNECTIONS,
63 MGMT_OP_PIN_CODE_REPLY,
64 MGMT_OP_PIN_CODE_NEG_REPLY,
65 MGMT_OP_SET_IO_CAPABILITY,
66 MGMT_OP_PAIR_DEVICE,
67 MGMT_OP_CANCEL_PAIR_DEVICE,
68 MGMT_OP_UNPAIR_DEVICE,
69 MGMT_OP_USER_CONFIRM_REPLY,
70 MGMT_OP_USER_CONFIRM_NEG_REPLY,
71 MGMT_OP_USER_PASSKEY_REPLY,
72 MGMT_OP_USER_PASSKEY_NEG_REPLY,
73 MGMT_OP_READ_LOCAL_OOB_DATA,
74 MGMT_OP_ADD_REMOTE_OOB_DATA,
75 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
76 MGMT_OP_START_DISCOVERY,
77 MGMT_OP_STOP_DISCOVERY,
78 MGMT_OP_CONFIRM_NAME,
79 MGMT_OP_BLOCK_DEVICE,
80 MGMT_OP_UNBLOCK_DEVICE,
81};
82
83static const u16 mgmt_events[] = {
84 MGMT_EV_CONTROLLER_ERROR,
85 MGMT_EV_INDEX_ADDED,
86 MGMT_EV_INDEX_REMOVED,
87 MGMT_EV_NEW_SETTINGS,
88 MGMT_EV_CLASS_OF_DEV_CHANGED,
89 MGMT_EV_LOCAL_NAME_CHANGED,
90 MGMT_EV_NEW_LINK_KEY,
91 MGMT_EV_NEW_LONG_TERM_KEY,
92 MGMT_EV_DEVICE_CONNECTED,
93 MGMT_EV_DEVICE_DISCONNECTED,
94 MGMT_EV_CONNECT_FAILED,
95 MGMT_EV_PIN_CODE_REQUEST,
96 MGMT_EV_USER_CONFIRM_REQUEST,
97 MGMT_EV_USER_PASSKEY_REQUEST,
98 MGMT_EV_AUTH_FAILED,
99 MGMT_EV_DEVICE_FOUND,
100 MGMT_EV_DISCOVERING,
101 MGMT_EV_DEVICE_BLOCKED,
102 MGMT_EV_DEVICE_UNBLOCKED,
103 MGMT_EV_DEVICE_UNPAIRED,
104};
105
3fd24153
AG
106/*
107 * These LE scan and inquiry parameters were chosen according to LE General
108 * Discovery Procedure specification.
109 */
110#define LE_SCAN_TYPE 0x01
111#define LE_SCAN_WIN 0x12
112#define LE_SCAN_INT 0x12
113#define LE_SCAN_TIMEOUT_LE_ONLY 10240 /* TGAP(gen_disc_scan_min) */
5e0452c0 114#define LE_SCAN_TIMEOUT_BREDR_LE 5120 /* TGAP(100)/2 */
3fd24153 115
e8777525 116#define INQUIRY_LEN_BREDR 0x08 /* TGAP(100) */
5e0452c0 117#define INQUIRY_LEN_BREDR_LE 0x04 /* TGAP(100)/2 */
2519a1fc 118
7d78525d
JH
119#define SERVICE_CACHE_TIMEOUT (5 * 1000)
120
4b34ee78
JH
121#define hdev_is_powered(hdev) (test_bit(HCI_UP, &hdev->flags) && \
122 !test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
123
eec8d2bc
JH
124struct pending_cmd {
125 struct list_head list;
fc2f4b13 126 u16 opcode;
eec8d2bc 127 int index;
c68fb7ff 128 void *param;
eec8d2bc 129 struct sock *sk;
e9a416b5 130 void *user_data;
eec8d2bc
JH
131};
132
ca69b795
JH
133/* HCI to MGMT error code conversion table */
134static u8 mgmt_status_table[] = {
135 MGMT_STATUS_SUCCESS,
136 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
137 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
138 MGMT_STATUS_FAILED, /* Hardware Failure */
139 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
140 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
141 MGMT_STATUS_NOT_PAIRED, /* PIN or Key Missing */
142 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
143 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
144 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
145 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
146 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
147 MGMT_STATUS_BUSY, /* Command Disallowed */
148 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
149 MGMT_STATUS_REJECTED, /* Rejected Security */
150 MGMT_STATUS_REJECTED, /* Rejected Personal */
151 MGMT_STATUS_TIMEOUT, /* Host Timeout */
152 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
153 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
154 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
155 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
156 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
157 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
158 MGMT_STATUS_BUSY, /* Repeated Attempts */
159 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
160 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
161 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
162 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
163 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
164 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
165 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
166 MGMT_STATUS_FAILED, /* Unspecified Error */
167 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
168 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
169 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
170 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
171 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
172 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
173 MGMT_STATUS_FAILED, /* Unit Link Key Used */
174 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
175 MGMT_STATUS_TIMEOUT, /* Instant Passed */
176 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
177 MGMT_STATUS_FAILED, /* Transaction Collision */
178 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
179 MGMT_STATUS_REJECTED, /* QoS Rejected */
180 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
181 MGMT_STATUS_REJECTED, /* Insufficient Security */
182 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
183 MGMT_STATUS_BUSY, /* Role Switch Pending */
184 MGMT_STATUS_FAILED, /* Slot Violation */
185 MGMT_STATUS_FAILED, /* Role Switch Failed */
186 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
187 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
188 MGMT_STATUS_BUSY, /* Host Busy Pairing */
189 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
190 MGMT_STATUS_BUSY, /* Controller Busy */
191 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
192 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
193 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
194 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
195 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
196};
197
198static u8 mgmt_status(u8 hci_status)
199{
200 if (hci_status < ARRAY_SIZE(mgmt_status_table))
201 return mgmt_status_table[hci_status];
202
203 return MGMT_STATUS_FAILED;
204}
205
4e51eae9 206static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
f7b64e69
JH
207{
208 struct sk_buff *skb;
209 struct mgmt_hdr *hdr;
210 struct mgmt_ev_cmd_status *ev;
56b7d137 211 int err;
f7b64e69 212
34eb525c 213 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
f7b64e69
JH
214
215 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_ATOMIC);
216 if (!skb)
217 return -ENOMEM;
218
219 hdr = (void *) skb_put(skb, sizeof(*hdr));
220
221 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
4e51eae9 222 hdr->index = cpu_to_le16(index);
f7b64e69
JH
223 hdr->len = cpu_to_le16(sizeof(*ev));
224
225 ev = (void *) skb_put(skb, sizeof(*ev));
226 ev->status = status;
227 put_unaligned_le16(cmd, &ev->opcode);
228
56b7d137
GP
229 err = sock_queue_rcv_skb(sk, skb);
230 if (err < 0)
f7b64e69
JH
231 kfree_skb(skb);
232
56b7d137 233 return err;
f7b64e69
JH
234}
235
aee9b218
JH
236static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
237 void *rp, size_t rp_len)
02d98129
JH
238{
239 struct sk_buff *skb;
240 struct mgmt_hdr *hdr;
241 struct mgmt_ev_cmd_complete *ev;
56b7d137 242 int err;
02d98129
JH
243
244 BT_DBG("sock %p", sk);
245
a38528f1 246 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_ATOMIC);
02d98129
JH
247 if (!skb)
248 return -ENOMEM;
249
250 hdr = (void *) skb_put(skb, sizeof(*hdr));
02d98129 251
a38528f1 252 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
4e51eae9 253 hdr->index = cpu_to_le16(index);
a38528f1 254 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
02d98129 255
a38528f1
JH
256 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
257 put_unaligned_le16(cmd, &ev->opcode);
aee9b218 258 ev->status = status;
8020c16a
SJ
259
260 if (rp)
261 memcpy(ev->data, rp, rp_len);
02d98129 262
56b7d137
GP
263 err = sock_queue_rcv_skb(sk, skb);
264 if (err < 0)
02d98129
JH
265 kfree_skb(skb);
266
e5f0e151 267 return err;
02d98129
JH
268}
269
a38528f1
JH
270static int read_version(struct sock *sk)
271{
272 struct mgmt_rp_read_version rp;
273
274 BT_DBG("sock %p", sk);
275
276 rp.version = MGMT_VERSION;
277 put_unaligned_le16(MGMT_REVISION, &rp.revision);
278
aee9b218 279 return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp,
4e51eae9 280 sizeof(rp));
a38528f1
JH
281}
282
e70bb2e8
JH
283static int read_commands(struct sock *sk)
284{
285 struct mgmt_rp_read_commands *rp;
286 u16 num_commands = ARRAY_SIZE(mgmt_commands);
287 u16 num_events = ARRAY_SIZE(mgmt_events);
288 u16 *opcode;
289 size_t rp_size;
290 int i, err;
291
292 BT_DBG("sock %p", sk);
293
294 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
295
296 rp = kmalloc(rp_size, GFP_KERNEL);
297 if (!rp)
298 return -ENOMEM;
299
300 put_unaligned_le16(num_commands, &rp->num_commands);
301 put_unaligned_le16(num_events, &rp->num_events);
302
303 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
304 put_unaligned_le16(mgmt_commands[i], opcode);
305
306 for (i = 0; i < num_events; i++, opcode++)
307 put_unaligned_le16(mgmt_events[i], opcode);
308
aee9b218 309 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0, rp,
e70bb2e8
JH
310 rp_size);
311 kfree(rp);
312
313 return err;
314}
315
faba42eb
JH
316static int read_index_list(struct sock *sk)
317{
faba42eb
JH
318 struct mgmt_rp_read_index_list *rp;
319 struct list_head *p;
8035ded4 320 struct hci_dev *d;
a38528f1 321 size_t rp_len;
faba42eb 322 u16 count;
a38528f1 323 int i, err;
faba42eb
JH
324
325 BT_DBG("sock %p", sk);
326
327 read_lock(&hci_dev_list_lock);
328
329 count = 0;
330 list_for_each(p, &hci_dev_list) {
331 count++;
332 }
333
a38528f1
JH
334 rp_len = sizeof(*rp) + (2 * count);
335 rp = kmalloc(rp_len, GFP_ATOMIC);
336 if (!rp) {
b2c60d42 337 read_unlock(&hci_dev_list_lock);
faba42eb 338 return -ENOMEM;
b2c60d42 339 }
faba42eb 340
faba42eb
JH
341 put_unaligned_le16(count, &rp->num_controllers);
342
343 i = 0;
8035ded4 344 list_for_each_entry(d, &hci_dev_list, list) {
a8b2d5c2 345 if (test_bit(HCI_SETUP, &d->dev_flags))
ab81cbf9
JH
346 continue;
347
faba42eb
JH
348 put_unaligned_le16(d->id, &rp->index[i++]);
349 BT_DBG("Added hci%u", d->id);
350 }
351
352 read_unlock(&hci_dev_list_lock);
353
aee9b218 354 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
4e51eae9 355 rp_len);
faba42eb 356
a38528f1
JH
357 kfree(rp);
358
359 return err;
faba42eb
JH
360}
361
69ab39ea
JH
362static u32 get_supported_settings(struct hci_dev *hdev)
363{
364 u32 settings = 0;
365
366 settings |= MGMT_SETTING_POWERED;
367 settings |= MGMT_SETTING_CONNECTABLE;
368 settings |= MGMT_SETTING_FAST_CONNECTABLE;
369 settings |= MGMT_SETTING_DISCOVERABLE;
370 settings |= MGMT_SETTING_PAIRABLE;
371
372 if (hdev->features[6] & LMP_SIMPLE_PAIR)
373 settings |= MGMT_SETTING_SSP;
374
375 if (!(hdev->features[4] & LMP_NO_BREDR)) {
376 settings |= MGMT_SETTING_BREDR;
377 settings |= MGMT_SETTING_LINK_SECURITY;
378 }
379
d7b7e796
MH
380 if (enable_hs)
381 settings |= MGMT_SETTING_HS;
382
383 if (enable_le) {
384 if (hdev->features[4] & LMP_LE)
385 settings |= MGMT_SETTING_LE;
386 }
69ab39ea
JH
387
388 return settings;
389}
390
391static u32 get_current_settings(struct hci_dev *hdev)
392{
393 u32 settings = 0;
394
f1f0eb02 395 if (hdev_is_powered(hdev))
f0d4b78a
MH
396 settings |= MGMT_SETTING_POWERED;
397
5e5282bb 398 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
69ab39ea
JH
399 settings |= MGMT_SETTING_CONNECTABLE;
400
5e5282bb 401 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
69ab39ea
JH
402 settings |= MGMT_SETTING_DISCOVERABLE;
403
a8b2d5c2 404 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags))
69ab39ea
JH
405 settings |= MGMT_SETTING_PAIRABLE;
406
407 if (!(hdev->features[4] & LMP_NO_BREDR))
408 settings |= MGMT_SETTING_BREDR;
409
06199cf8 410 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
69ab39ea
JH
411 settings |= MGMT_SETTING_LE;
412
47990ea0 413 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
69ab39ea
JH
414 settings |= MGMT_SETTING_LINK_SECURITY;
415
84bde9d6 416 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
69ab39ea
JH
417 settings |= MGMT_SETTING_SSP;
418
6d80dfd0
JH
419 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
420 settings |= MGMT_SETTING_HS;
421
69ab39ea
JH
422 return settings;
423}
424
ef580372
JH
425#define PNP_INFO_SVCLASS_ID 0x1200
426
427static u8 bluetooth_base_uuid[] = {
428 0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
429 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
430};
431
432static u16 get_uuid16(u8 *uuid128)
433{
434 u32 val;
435 int i;
436
437 for (i = 0; i < 12; i++) {
438 if (bluetooth_base_uuid[i] != uuid128[i])
439 return 0;
440 }
441
442 memcpy(&val, &uuid128[12], 4);
443
444 val = le32_to_cpu(val);
445 if (val > 0xffff)
446 return 0;
447
448 return (u16) val;
449}
450
451static void create_eir(struct hci_dev *hdev, u8 *data)
452{
453 u8 *ptr = data;
454 u16 eir_len = 0;
455 u16 uuid16_list[HCI_MAX_EIR_LENGTH / sizeof(u16)];
456 int i, truncated = 0;
457 struct bt_uuid *uuid;
458 size_t name_len;
459
460 name_len = strlen(hdev->dev_name);
461
462 if (name_len > 0) {
463 /* EIR Data type */
464 if (name_len > 48) {
465 name_len = 48;
466 ptr[1] = EIR_NAME_SHORT;
467 } else
468 ptr[1] = EIR_NAME_COMPLETE;
469
470 /* EIR Data length */
471 ptr[0] = name_len + 1;
472
473 memcpy(ptr + 2, hdev->dev_name, name_len);
474
475 eir_len += (name_len + 2);
476 ptr += (name_len + 2);
477 }
478
479 memset(uuid16_list, 0, sizeof(uuid16_list));
480
481 /* Group all UUID16 types */
482 list_for_each_entry(uuid, &hdev->uuids, list) {
483 u16 uuid16;
484
485 uuid16 = get_uuid16(uuid->uuid);
486 if (uuid16 == 0)
487 return;
488
489 if (uuid16 < 0x1100)
490 continue;
491
492 if (uuid16 == PNP_INFO_SVCLASS_ID)
493 continue;
494
495 /* Stop if not enough space to put next UUID */
496 if (eir_len + 2 + sizeof(u16) > HCI_MAX_EIR_LENGTH) {
497 truncated = 1;
498 break;
499 }
500
501 /* Check for duplicates */
502 for (i = 0; uuid16_list[i] != 0; i++)
503 if (uuid16_list[i] == uuid16)
504 break;
505
506 if (uuid16_list[i] == 0) {
507 uuid16_list[i] = uuid16;
508 eir_len += sizeof(u16);
509 }
510 }
511
512 if (uuid16_list[0] != 0) {
513 u8 *length = ptr;
514
515 /* EIR Data type */
516 ptr[1] = truncated ? EIR_UUID16_SOME : EIR_UUID16_ALL;
517
518 ptr += 2;
519 eir_len += 2;
520
521 for (i = 0; uuid16_list[i] != 0; i++) {
522 *ptr++ = (uuid16_list[i] & 0x00ff);
523 *ptr++ = (uuid16_list[i] & 0xff00) >> 8;
524 }
525
526 /* EIR Data length */
527 *length = (i * sizeof(u16)) + 1;
528 }
529}
530
531static int update_eir(struct hci_dev *hdev)
532{
533 struct hci_cp_write_eir cp;
534
504c8dcd 535 if (!hdev_is_powered(hdev))
7770c4aa
JH
536 return 0;
537
ef580372
JH
538 if (!(hdev->features[6] & LMP_EXT_INQ))
539 return 0;
540
84bde9d6 541 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
ef580372
JH
542 return 0;
543
a8b2d5c2 544 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
ef580372
JH
545 return 0;
546
547 memset(&cp, 0, sizeof(cp));
548
549 create_eir(hdev, cp.data);
550
551 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
552 return 0;
553
554 memcpy(hdev->eir, cp.data, sizeof(cp.data));
555
556 return hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
557}
558
559static u8 get_service_classes(struct hci_dev *hdev)
560{
561 struct bt_uuid *uuid;
562 u8 val = 0;
563
564 list_for_each_entry(uuid, &hdev->uuids, list)
565 val |= uuid->svc_hint;
566
567 return val;
568}
569
570static int update_class(struct hci_dev *hdev)
571{
572 u8 cod[3];
c95f0ba7 573 int err;
ef580372
JH
574
575 BT_DBG("%s", hdev->name);
576
504c8dcd 577 if (!hdev_is_powered(hdev))
7770c4aa
JH
578 return 0;
579
a8b2d5c2 580 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
ef580372
JH
581 return 0;
582
583 cod[0] = hdev->minor_class;
584 cod[1] = hdev->major_class;
585 cod[2] = get_service_classes(hdev);
586
587 if (memcmp(cod, hdev->dev_class, 3) == 0)
588 return 0;
589
c95f0ba7
JH
590 err = hci_send_cmd(hdev, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
591 if (err == 0)
592 set_bit(HCI_PENDING_CLASS, &hdev->dev_flags);
593
594 return err;
ef580372
JH
595}
596
7d78525d
JH
597static void service_cache_off(struct work_struct *work)
598{
599 struct hci_dev *hdev = container_of(work, struct hci_dev,
600 service_cache.work);
601
a8b2d5c2 602 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
7d78525d
JH
603 return;
604
605 hci_dev_lock(hdev);
606
607 update_eir(hdev);
608 update_class(hdev);
609
610 hci_dev_unlock(hdev);
611}
612
613static void mgmt_init_hdev(struct hci_dev *hdev)
614{
0cbf4ed6 615 if (!test_and_set_bit(HCI_MGMT, &hdev->dev_flags)) {
7d78525d
JH
616 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
617
0cbf4ed6
JH
618 /* Non-mgmt controlled devices get this bit set
619 * implicitly so that pairing works for them, however
620 * for mgmt we require user-space to explicitly enable
621 * it
622 */
623 clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
624 }
7d78525d
JH
625}
626
bdb6d971 627static int read_controller_info(struct sock *sk, struct hci_dev *hdev)
0381101f 628{
a38528f1 629 struct mgmt_rp_read_info rp;
f7b64e69 630
bdb6d971 631 BT_DBG("sock %p %s", sk, hdev->name);
f7b64e69 632
09fd0de5 633 hci_dev_lock(hdev);
f7b64e69 634
7d78525d
JH
635 if (test_and_clear_bit(HCI_PI_MGMT_INIT, &hci_pi(sk)->flags))
636 mgmt_init_hdev(hdev);
ebc99feb 637
dc4fe30b
JH
638 memset(&rp, 0, sizeof(rp));
639
69ab39ea 640 bacpy(&rp.bdaddr, &hdev->bdaddr);
f7b64e69 641
69ab39ea 642 rp.version = hdev->hci_ver;
f7b64e69 643
69ab39ea
JH
644 put_unaligned_le16(hdev->manufacturer, &rp.manufacturer);
645
646 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
647 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
f7b64e69 648
a38528f1 649 memcpy(rp.dev_class, hdev->dev_class, 3);
f7b64e69 650
dc4fe30b 651 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
27fcc362 652 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
dc4fe30b 653
09fd0de5 654 hci_dev_unlock(hdev);
0381101f 655
bdb6d971
JH
656 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
657 sizeof(rp));
0381101f
JH
658}
659
eec8d2bc
JH
660static void mgmt_pending_free(struct pending_cmd *cmd)
661{
662 sock_put(cmd->sk);
c68fb7ff 663 kfree(cmd->param);
eec8d2bc
JH
664 kfree(cmd);
665}
666
366a0336 667static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
2e58ef3e
JH
668 struct hci_dev *hdev,
669 void *data, u16 len)
eec8d2bc
JH
670{
671 struct pending_cmd *cmd;
672
673 cmd = kmalloc(sizeof(*cmd), GFP_ATOMIC);
674 if (!cmd)
366a0336 675 return NULL;
eec8d2bc
JH
676
677 cmd->opcode = opcode;
2e58ef3e 678 cmd->index = hdev->id;
eec8d2bc 679
c68fb7ff
SJ
680 cmd->param = kmalloc(len, GFP_ATOMIC);
681 if (!cmd->param) {
eec8d2bc 682 kfree(cmd);
366a0336 683 return NULL;
eec8d2bc
JH
684 }
685
8fce6357
SJ
686 if (data)
687 memcpy(cmd->param, data, len);
eec8d2bc
JH
688
689 cmd->sk = sk;
690 sock_hold(sk);
691
2e58ef3e 692 list_add(&cmd->list, &hdev->mgmt_pending);
eec8d2bc 693
366a0336 694 return cmd;
eec8d2bc
JH
695}
696
744cf19e 697static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
eec8d2bc
JH
698 void (*cb)(struct pending_cmd *cmd, void *data),
699 void *data)
700{
701 struct list_head *p, *n;
702
2e58ef3e 703 list_for_each_safe(p, n, &hdev->mgmt_pending) {
eec8d2bc
JH
704 struct pending_cmd *cmd;
705
706 cmd = list_entry(p, struct pending_cmd, list);
707
b24752fe 708 if (opcode > 0 && cmd->opcode != opcode)
eec8d2bc
JH
709 continue;
710
eec8d2bc
JH
711 cb(cmd, data);
712 }
713}
714
2e58ef3e 715static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
eec8d2bc 716{
8035ded4 717 struct pending_cmd *cmd;
eec8d2bc 718
2e58ef3e 719 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2aeabcbe
JH
720 if (cmd->opcode == opcode)
721 return cmd;
eec8d2bc
JH
722 }
723
724 return NULL;
725}
726
a664b5bc 727static void mgmt_pending_remove(struct pending_cmd *cmd)
73f22f62 728{
73f22f62
JH
729 list_del(&cmd->list);
730 mgmt_pending_free(cmd);
731}
732
69ab39ea 733static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
8680570b 734{
69ab39ea 735 __le32 settings = cpu_to_le32(get_current_settings(hdev));
8680570b 736
aee9b218
JH
737 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
738 sizeof(settings));
8680570b
JH
739}
740
bdb6d971
JH
741static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
742 u16 len)
eec8d2bc 743{
650f726d 744 struct mgmt_mode *cp = data;
366a0336 745 struct pending_cmd *cmd;
4b34ee78 746 int err;
eec8d2bc 747
bdb6d971 748 BT_DBG("request for %s", hdev->name);
eec8d2bc 749
bdce7baf 750 if (len != sizeof(*cp))
bdb6d971 751 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
ca69b795 752 MGMT_STATUS_INVALID_PARAMS);
eec8d2bc 753
09fd0de5 754 hci_dev_lock(hdev);
eec8d2bc 755
f0d4b78a
MH
756 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
757 cancel_delayed_work(&hdev->power_off);
758
759 if (cp->val) {
760 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
761 mgmt_powered(hdev, 1);
762 goto failed;
763 }
764 }
765
4b34ee78 766 if (!!cp->val == hdev_is_powered(hdev)) {
69ab39ea 767 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
eec8d2bc
JH
768 goto failed;
769 }
770
2e58ef3e 771 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
bdb6d971 772 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
ca69b795 773 MGMT_STATUS_BUSY);
eec8d2bc
JH
774 goto failed;
775 }
776
2e58ef3e 777 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
366a0336
JH
778 if (!cmd) {
779 err = -ENOMEM;
eec8d2bc 780 goto failed;
366a0336 781 }
eec8d2bc 782
72a734ec 783 if (cp->val)
7f971041 784 schedule_work(&hdev->power_on);
eec8d2bc 785 else
80b7ab33 786 schedule_work(&hdev->power_off.work);
eec8d2bc 787
366a0336 788 err = 0;
eec8d2bc
JH
789
790failed:
09fd0de5 791 hci_dev_unlock(hdev);
366a0336 792 return err;
eec8d2bc
JH
793}
794
beadb2bd
JH
795static int mgmt_event(u16 event, struct hci_dev *hdev, void *data,
796 u16 data_len, struct sock *skip_sk)
797{
798 struct sk_buff *skb;
799 struct mgmt_hdr *hdr;
800
801 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_ATOMIC);
802 if (!skb)
803 return -ENOMEM;
804
805 hdr = (void *) skb_put(skb, sizeof(*hdr));
806 hdr->opcode = cpu_to_le16(event);
807 if (hdev)
808 hdr->index = cpu_to_le16(hdev->id);
809 else
810 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
811 hdr->len = cpu_to_le16(data_len);
812
813 if (data)
814 memcpy(skb_put(skb, data_len), data, data_len);
815
97e0bdeb
MH
816 /* Time stamp */
817 __net_timestamp(skb);
818
beadb2bd
JH
819 hci_send_to_control(skb, skip_sk);
820 kfree_skb(skb);
821
822 return 0;
823}
824
825static int new_settings(struct hci_dev *hdev, struct sock *skip)
826{
827 __le32 ev;
828
829 ev = cpu_to_le32(get_current_settings(hdev));
830
831 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
832}
833
bdb6d971
JH
834static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
835 u16 len)
73f22f62 836{
650f726d 837 struct mgmt_cp_set_discoverable *cp = data;
366a0336 838 struct pending_cmd *cmd;
5e5282bb 839 u16 timeout;
73f22f62
JH
840 u8 scan;
841 int err;
842
bdb6d971 843 BT_DBG("request for %s", hdev->name);
73f22f62 844
bdce7baf 845 if (len != sizeof(*cp))
bdb6d971 846 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
ca69b795 847 MGMT_STATUS_INVALID_PARAMS);
bdce7baf 848
24c54a90
MH
849 timeout = get_unaligned_le16(&cp->timeout);
850 if (!cp->val && timeout > 0)
bdb6d971 851 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
ca69b795 852 MGMT_STATUS_INVALID_PARAMS);
73f22f62 853
09fd0de5 854 hci_dev_lock(hdev);
73f22f62 855
5e5282bb 856 if (!hdev_is_powered(hdev) && timeout > 0) {
bdb6d971 857 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
ca69b795 858 MGMT_STATUS_NOT_POWERED);
73f22f62
JH
859 goto failed;
860 }
861
2e58ef3e
JH
862 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
863 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
bdb6d971 864 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
ca69b795 865 MGMT_STATUS_BUSY);
73f22f62
JH
866 goto failed;
867 }
868
5e5282bb 869 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
bdb6d971 870 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
5e5282bb
JH
871 MGMT_STATUS_REJECTED);
872 goto failed;
873 }
874
875 if (!hdev_is_powered(hdev)) {
0224d2fa
JH
876 bool changed = false;
877
878 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
879 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
880 changed = true;
881 }
882
5e5282bb 883 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
0224d2fa
JH
884 if (err < 0)
885 goto failed;
886
887 if (changed)
888 err = new_settings(hdev, sk);
889
5e5282bb
JH
890 goto failed;
891 }
892
893 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
955638ec
MH
894 if (hdev->discov_timeout > 0) {
895 cancel_delayed_work(&hdev->discov_off);
896 hdev->discov_timeout = 0;
897 }
898
899 if (cp->val && timeout > 0) {
900 hdev->discov_timeout = timeout;
901 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
902 msecs_to_jiffies(hdev->discov_timeout * 1000));
903 }
904
69ab39ea 905 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
73f22f62
JH
906 goto failed;
907 }
908
2e58ef3e 909 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
366a0336
JH
910 if (!cmd) {
911 err = -ENOMEM;
73f22f62 912 goto failed;
366a0336 913 }
73f22f62
JH
914
915 scan = SCAN_PAGE;
916
72a734ec 917 if (cp->val)
73f22f62 918 scan |= SCAN_INQUIRY;
16ab91ab 919 else
e0f9309f 920 cancel_delayed_work(&hdev->discov_off);
73f22f62
JH
921
922 err = hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
923 if (err < 0)
a664b5bc 924 mgmt_pending_remove(cmd);
73f22f62 925
16ab91ab 926 if (cp->val)
5e5282bb 927 hdev->discov_timeout = timeout;
16ab91ab 928
73f22f62 929failed:
09fd0de5 930 hci_dev_unlock(hdev);
73f22f62
JH
931 return err;
932}
933
bdb6d971
JH
934static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
935 u16 len)
9fbcbb45 936{
650f726d 937 struct mgmt_mode *cp = data;
366a0336 938 struct pending_cmd *cmd;
9fbcbb45
JH
939 u8 scan;
940 int err;
941
bdb6d971 942 BT_DBG("request for %s", hdev->name);
9fbcbb45 943
bdce7baf 944 if (len != sizeof(*cp))
bdb6d971 945 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
ca69b795 946 MGMT_STATUS_INVALID_PARAMS);
9fbcbb45 947
09fd0de5 948 hci_dev_lock(hdev);
9fbcbb45 949
4b34ee78 950 if (!hdev_is_powered(hdev)) {
0224d2fa
JH
951 bool changed = false;
952
953 if (!!cp->val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
954 changed = true;
955
6bf0e469 956 if (cp->val) {
5e5282bb 957 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
6bf0e469 958 } else {
5e5282bb
JH
959 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
960 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
961 }
0224d2fa 962
5e5282bb 963 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
0224d2fa
JH
964 if (err < 0)
965 goto failed;
966
967 if (changed)
968 err = new_settings(hdev, sk);
969
9fbcbb45
JH
970 goto failed;
971 }
972
2e58ef3e
JH
973 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
974 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
bdb6d971 975 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
ca69b795 976 MGMT_STATUS_BUSY);
9fbcbb45
JH
977 goto failed;
978 }
979
5e5282bb 980 if (!!cp->val == test_bit(HCI_PSCAN, &hdev->flags)) {
69ab39ea 981 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
9fbcbb45
JH
982 goto failed;
983 }
984
2e58ef3e 985 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
366a0336
JH
986 if (!cmd) {
987 err = -ENOMEM;
9fbcbb45 988 goto failed;
366a0336 989 }
9fbcbb45 990
6bf0e469 991 if (cp->val) {
9fbcbb45 992 scan = SCAN_PAGE;
6bf0e469 993 } else {
9fbcbb45
JH
994 scan = 0;
995
df2c6c5e
JH
996 if (test_bit(HCI_ISCAN, &hdev->flags) &&
997 hdev->discov_timeout > 0)
998 cancel_delayed_work(&hdev->discov_off);
999 }
1000
9fbcbb45
JH
1001 err = hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1002 if (err < 0)
a664b5bc 1003 mgmt_pending_remove(cmd);
9fbcbb45
JH
1004
1005failed:
09fd0de5 1006 hci_dev_unlock(hdev);
9fbcbb45
JH
1007 return err;
1008}
1009
bdb6d971
JH
1010static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data,
1011 u16 len)
c542a06c 1012{
650f726d 1013 struct mgmt_mode *cp = data;
c542a06c
JH
1014 int err;
1015
bdb6d971 1016 BT_DBG("request for %s", hdev->name);
c542a06c 1017
bdce7baf 1018 if (len != sizeof(*cp))
bdb6d971 1019 return cmd_status(sk, hdev->id, MGMT_OP_SET_PAIRABLE,
ca69b795 1020 MGMT_STATUS_INVALID_PARAMS);
c542a06c 1021
09fd0de5 1022 hci_dev_lock(hdev);
c542a06c
JH
1023
1024 if (cp->val)
a8b2d5c2 1025 set_bit(HCI_PAIRABLE, &hdev->dev_flags);
c542a06c 1026 else
a8b2d5c2 1027 clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
c542a06c 1028
69ab39ea 1029 err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev);
c542a06c
JH
1030 if (err < 0)
1031 goto failed;
1032
beadb2bd 1033 err = new_settings(hdev, sk);
c542a06c
JH
1034
1035failed:
09fd0de5 1036 hci_dev_unlock(hdev);
c542a06c
JH
1037 return err;
1038}
1039
bdb6d971
JH
1040static int set_link_security(struct sock *sk, struct hci_dev *hdev,
1041 void *data, u16 len)
33ef95ed
JH
1042{
1043 struct mgmt_mode *cp = data;
1044 struct pending_cmd *cmd;
816a11d5 1045 u8 val;
33ef95ed
JH
1046 int err;
1047
bdb6d971 1048 BT_DBG("request for %s", hdev->name);
33ef95ed
JH
1049
1050 if (len != sizeof(*cp))
bdb6d971 1051 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
33ef95ed
JH
1052 MGMT_STATUS_INVALID_PARAMS);
1053
1054 hci_dev_lock(hdev);
1055
4b34ee78 1056 if (!hdev_is_powered(hdev)) {
47990ea0
JH
1057 bool changed = false;
1058
1059 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
1060 &hdev->dev_flags)) {
1061 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
1062 changed = true;
1063 }
1064
1065 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1066 if (err < 0)
1067 goto failed;
1068
1069 if (changed)
1070 err = new_settings(hdev, sk);
1071
33ef95ed
JH
1072 goto failed;
1073 }
1074
1075 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
bdb6d971 1076 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
33ef95ed
JH
1077 MGMT_STATUS_BUSY);
1078 goto failed;
1079 }
1080
1081 val = !!cp->val;
1082
1083 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
1084 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1085 goto failed;
1086 }
1087
1088 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
1089 if (!cmd) {
1090 err = -ENOMEM;
1091 goto failed;
1092 }
1093
1094 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
1095 if (err < 0) {
1096 mgmt_pending_remove(cmd);
1097 goto failed;
1098 }
1099
1100failed:
1101 hci_dev_unlock(hdev);
33ef95ed
JH
1102 return err;
1103}
1104
bdb6d971 1105static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
ed2c4ee3
JH
1106{
1107 struct mgmt_mode *cp = data;
1108 struct pending_cmd *cmd;
816a11d5 1109 u8 val;
ed2c4ee3
JH
1110 int err;
1111
bdb6d971 1112 BT_DBG("request for %s", hdev->name);
ed2c4ee3
JH
1113
1114 if (len != sizeof(*cp))
bdb6d971 1115 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
ed2c4ee3
JH
1116 MGMT_STATUS_INVALID_PARAMS);
1117
1118 hci_dev_lock(hdev);
1119
6c8f12c1 1120 if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) {
bdb6d971 1121 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
6c8f12c1
JH
1122 MGMT_STATUS_NOT_SUPPORTED);
1123 goto failed;
1124 }
1125
c0ecddc2
JH
1126 val = !!cp->val;
1127
4b34ee78 1128 if (!hdev_is_powered(hdev)) {
c0ecddc2
JH
1129 bool changed = false;
1130
1131 if (val != test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
1132 change_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
1133 changed = true;
1134 }
1135
1136 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1137 if (err < 0)
1138 goto failed;
1139
1140 if (changed)
1141 err = new_settings(hdev, sk);
1142
ed2c4ee3
JH
1143 goto failed;
1144 }
1145
1146 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev)) {
bdb6d971
JH
1147 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1148 MGMT_STATUS_BUSY);
ed2c4ee3
JH
1149 goto failed;
1150 }
1151
ed2c4ee3
JH
1152 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) == val) {
1153 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1154 goto failed;
1155 }
1156
1157 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
1158 if (!cmd) {
1159 err = -ENOMEM;
1160 goto failed;
1161 }
1162
1163 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, sizeof(val), &val);
1164 if (err < 0) {
1165 mgmt_pending_remove(cmd);
1166 goto failed;
1167 }
1168
1169failed:
1170 hci_dev_unlock(hdev);
ed2c4ee3
JH
1171 return err;
1172}
1173
bdb6d971 1174static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
6d80dfd0
JH
1175{
1176 struct mgmt_mode *cp = data;
6d80dfd0 1177
bdb6d971 1178 BT_DBG("request for %s", hdev->name);
6d80dfd0
JH
1179
1180 if (len != sizeof(*cp))
bdb6d971 1181 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
6d80dfd0
JH
1182 MGMT_STATUS_INVALID_PARAMS);
1183
bdb6d971
JH
1184 if (!enable_hs)
1185 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1186 MGMT_STATUS_NOT_SUPPORTED);
6d80dfd0
JH
1187
1188 if (cp->val)
1189 set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
1190 else
1191 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
1192
bdb6d971 1193 return send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
6d80dfd0
JH
1194}
1195
bdb6d971 1196static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
06199cf8
JH
1197{
1198 struct mgmt_mode *cp = data;
1199 struct hci_cp_write_le_host_supported hci_cp;
1200 struct pending_cmd *cmd;
06199cf8 1201 int err;
0b60eba1 1202 u8 val, enabled;
06199cf8 1203
bdb6d971 1204 BT_DBG("request for %s", hdev->name);
06199cf8
JH
1205
1206 if (len != sizeof(*cp))
bdb6d971 1207 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
06199cf8
JH
1208 MGMT_STATUS_INVALID_PARAMS);
1209
1de028ce
JH
1210 hci_dev_lock(hdev);
1211
06199cf8 1212 if (!enable_le || !(hdev->features[4] & LMP_LE)) {
bdb6d971 1213 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
06199cf8 1214 MGMT_STATUS_NOT_SUPPORTED);
1de028ce 1215 goto unlock;
06199cf8
JH
1216 }
1217
1218 val = !!cp->val;
0b60eba1 1219 enabled = !!(hdev->host_features[0] & LMP_HOST_LE);
06199cf8 1220
0b60eba1 1221 if (!hdev_is_powered(hdev) || val == enabled) {
06199cf8
JH
1222 bool changed = false;
1223
1224 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
1225 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
1226 changed = true;
1227 }
1228
1229 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
1230 if (err < 0)
1de028ce 1231 goto unlock;
06199cf8
JH
1232
1233 if (changed)
1234 err = new_settings(hdev, sk);
1235
1de028ce 1236 goto unlock;
06199cf8
JH
1237 }
1238
1239 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
bdb6d971
JH
1240 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
1241 MGMT_STATUS_BUSY);
1de028ce 1242 goto unlock;
06199cf8
JH
1243 }
1244
1245 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
1246 if (!cmd) {
1247 err = -ENOMEM;
1de028ce 1248 goto unlock;
06199cf8
JH
1249 }
1250
1251 memset(&hci_cp, 0, sizeof(hci_cp));
1252
1253 if (val) {
1254 hci_cp.le = val;
1255 hci_cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
1256 }
1257
1258 err = hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED,
1259 sizeof(hci_cp), &hci_cp);
1260 if (err < 0) {
1261 mgmt_pending_remove(cmd);
1de028ce 1262 goto unlock;
06199cf8
JH
1263 }
1264
1de028ce
JH
1265unlock:
1266 hci_dev_unlock(hdev);
06199cf8
JH
1267 return err;
1268}
1269
bdb6d971 1270static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
2aeb9a1a 1271{
650f726d 1272 struct mgmt_cp_add_uuid *cp = data;
90e70454 1273 struct pending_cmd *cmd;
2aeb9a1a 1274 struct bt_uuid *uuid;
2aeb9a1a
JH
1275 int err;
1276
bdb6d971 1277 BT_DBG("request for %s", hdev->name);
2aeb9a1a 1278
bdce7baf 1279 if (len != sizeof(*cp))
bdb6d971 1280 return cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
ca69b795 1281 MGMT_STATUS_INVALID_PARAMS);
2aeb9a1a 1282
09fd0de5 1283 hci_dev_lock(hdev);
2aeb9a1a 1284
c95f0ba7 1285 if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) {
bdb6d971 1286 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
c95f0ba7
JH
1287 MGMT_STATUS_BUSY);
1288 goto failed;
1289 }
1290
2aeb9a1a
JH
1291 uuid = kmalloc(sizeof(*uuid), GFP_ATOMIC);
1292 if (!uuid) {
1293 err = -ENOMEM;
1294 goto failed;
1295 }
1296
1297 memcpy(uuid->uuid, cp->uuid, 16);
1aff6f09 1298 uuid->svc_hint = cp->svc_hint;
2aeb9a1a
JH
1299
1300 list_add(&uuid->list, &hdev->uuids);
1301
1aff6f09
JH
1302 err = update_class(hdev);
1303 if (err < 0)
1304 goto failed;
1305
80a1e1db
JH
1306 err = update_eir(hdev);
1307 if (err < 0)
1308 goto failed;
1309
90e70454 1310 if (!test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) {
bdb6d971 1311 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
90e70454
JH
1312 hdev->dev_class, 3);
1313 goto failed;
1314 }
1315
1316 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
1317 if (!cmd) {
1318 err = -ENOMEM;
1319 goto failed;
1320 }
2aeb9a1a
JH
1321
1322failed:
09fd0de5 1323 hci_dev_unlock(hdev);
2aeb9a1a
JH
1324 return err;
1325}
1326
24b78d0f
JH
1327static bool enable_service_cache(struct hci_dev *hdev)
1328{
1329 if (!hdev_is_powered(hdev))
1330 return false;
1331
1332 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
1333 schedule_delayed_work(&hdev->service_cache,
1334 msecs_to_jiffies(SERVICE_CACHE_TIMEOUT));
1335 return true;
1336 }
1337
1338 return false;
1339}
1340
bdb6d971
JH
1341static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
1342 u16 len)
2aeb9a1a 1343{
650f726d 1344 struct mgmt_cp_remove_uuid *cp = data;
90e70454 1345 struct pending_cmd *cmd;
2aeb9a1a 1346 struct list_head *p, *n;
2aeb9a1a 1347 u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2aeb9a1a
JH
1348 int err, found;
1349
bdb6d971 1350 BT_DBG("request for %s", hdev->name);
2aeb9a1a 1351
bdce7baf 1352 if (len != sizeof(*cp))
bdb6d971 1353 return cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
ca69b795 1354 MGMT_STATUS_INVALID_PARAMS);
2aeb9a1a 1355
09fd0de5 1356 hci_dev_lock(hdev);
2aeb9a1a 1357
c95f0ba7 1358 if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) {
bdb6d971 1359 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
c95f0ba7
JH
1360 MGMT_STATUS_BUSY);
1361 goto unlock;
1362 }
1363
2aeb9a1a
JH
1364 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
1365 err = hci_uuids_clear(hdev);
4004b6d9 1366
24b78d0f 1367 if (enable_service_cache(hdev)) {
bdb6d971
JH
1368 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
1369 0, hdev->dev_class, 3);
24b78d0f
JH
1370 goto unlock;
1371 }
4004b6d9 1372
9246a869 1373 goto update_class;
2aeb9a1a
JH
1374 }
1375
1376 found = 0;
1377
1378 list_for_each_safe(p, n, &hdev->uuids) {
1379 struct bt_uuid *match = list_entry(p, struct bt_uuid, list);
1380
1381 if (memcmp(match->uuid, cp->uuid, 16) != 0)
1382 continue;
1383
1384 list_del(&match->list);
1385 found++;
1386 }
1387
1388 if (found == 0) {
bdb6d971 1389 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
ca69b795 1390 MGMT_STATUS_INVALID_PARAMS);
2aeb9a1a
JH
1391 goto unlock;
1392 }
1393
9246a869 1394update_class:
1aff6f09
JH
1395 err = update_class(hdev);
1396 if (err < 0)
1397 goto unlock;
1398
80a1e1db
JH
1399 err = update_eir(hdev);
1400 if (err < 0)
1401 goto unlock;
1402
90e70454 1403 if (!test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) {
bdb6d971 1404 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
9997a533 1405 hdev->dev_class, 3);
90e70454
JH
1406 goto unlock;
1407 }
1408
1409 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
1410 if (!cmd) {
1411 err = -ENOMEM;
1412 goto unlock;
1413 }
2aeb9a1a
JH
1414
1415unlock:
09fd0de5 1416 hci_dev_unlock(hdev);
2aeb9a1a
JH
1417 return err;
1418}
1419
bdb6d971
JH
1420static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
1421 u16 len)
1aff6f09 1422{
650f726d 1423 struct mgmt_cp_set_dev_class *cp = data;
90e70454 1424 struct pending_cmd *cmd;
1aff6f09
JH
1425 int err;
1426
bdb6d971 1427 BT_DBG("request for %s", hdev->name);
1aff6f09 1428
bdce7baf 1429 if (len != sizeof(*cp))
bdb6d971 1430 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
ca69b795 1431 MGMT_STATUS_INVALID_PARAMS);
1aff6f09 1432
09fd0de5 1433 hci_dev_lock(hdev);
1aff6f09 1434
c95f0ba7 1435 if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) {
bdb6d971 1436 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
c95f0ba7
JH
1437 MGMT_STATUS_BUSY);
1438 goto unlock;
1439 }
1440
932f5ff5
JH
1441 hdev->major_class = cp->major;
1442 hdev->minor_class = cp->minor;
1443
b5235a65 1444 if (!hdev_is_powered(hdev)) {
bdb6d971 1445 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
932f5ff5 1446 hdev->dev_class, 3);
b5235a65
JH
1447 goto unlock;
1448 }
1449
a8b2d5c2 1450 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
7d78525d
JH
1451 hci_dev_unlock(hdev);
1452 cancel_delayed_work_sync(&hdev->service_cache);
1453 hci_dev_lock(hdev);
14c0b608 1454 update_eir(hdev);
7d78525d 1455 }
14c0b608 1456
1aff6f09 1457 err = update_class(hdev);
90e70454
JH
1458 if (err < 0)
1459 goto unlock;
1aff6f09 1460
90e70454 1461 if (!test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) {
bdb6d971 1462 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
8ec37034 1463 hdev->dev_class, 3);
90e70454
JH
1464 goto unlock;
1465 }
1466
1467 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
1468 if (!cmd) {
1469 err = -ENOMEM;
1470 goto unlock;
1471 }
1aff6f09 1472
b5235a65 1473unlock:
09fd0de5 1474 hci_dev_unlock(hdev);
1aff6f09
JH
1475 return err;
1476}
1477
bdb6d971
JH
1478static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
1479 u16 len)
55ed8ca1 1480{
650f726d 1481 struct mgmt_cp_load_link_keys *cp = data;
4e51eae9 1482 u16 key_count, expected_len;
a492cd52 1483 int i;
55ed8ca1 1484
bdce7baf 1485 if (len < sizeof(*cp))
bdb6d971 1486 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
ca69b795 1487 MGMT_STATUS_INVALID_PARAMS);
bdce7baf 1488
55ed8ca1
JH
1489 key_count = get_unaligned_le16(&cp->key_count);
1490
86742e1e
JH
1491 expected_len = sizeof(*cp) + key_count *
1492 sizeof(struct mgmt_link_key_info);
a492cd52 1493 if (expected_len != len) {
86742e1e 1494 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
a492cd52 1495 len, expected_len);
bdb6d971 1496 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
ca69b795 1497 MGMT_STATUS_INVALID_PARAMS);
55ed8ca1
JH
1498 }
1499
bdb6d971 1500 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
55ed8ca1
JH
1501 key_count);
1502
09fd0de5 1503 hci_dev_lock(hdev);
55ed8ca1
JH
1504
1505 hci_link_keys_clear(hdev);
1506
a8b2d5c2 1507 set_bit(HCI_LINK_KEYS, &hdev->dev_flags);
55ed8ca1
JH
1508
1509 if (cp->debug_keys)
a8b2d5c2 1510 set_bit(HCI_DEBUG_KEYS, &hdev->dev_flags);
55ed8ca1 1511 else
a8b2d5c2 1512 clear_bit(HCI_DEBUG_KEYS, &hdev->dev_flags);
55ed8ca1 1513
a492cd52 1514 for (i = 0; i < key_count; i++) {
86742e1e 1515 struct mgmt_link_key_info *key = &cp->keys[i];
55ed8ca1 1516
d753fdc4
JH
1517 hci_add_link_key(hdev, NULL, 0, &key->addr.bdaddr, key->val,
1518 key->type, key->pin_len);
55ed8ca1
JH
1519 }
1520
bdb6d971 1521 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
0e5f875a 1522
09fd0de5 1523 hci_dev_unlock(hdev);
55ed8ca1 1524
a492cd52 1525 return 0;
55ed8ca1
JH
1526}
1527
b1078ad0
JH
1528static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
1529 u8 addr_type, struct sock *skip_sk)
1530{
1531 struct mgmt_ev_device_unpaired ev;
1532
1533 bacpy(&ev.addr.bdaddr, bdaddr);
1534 ev.addr.type = addr_type;
1535
1536 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
1537 skip_sk);
1538}
1539
bdb6d971
JH
1540static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
1541 u16 len)
55ed8ca1 1542{
124f6e35
JH
1543 struct mgmt_cp_unpair_device *cp = data;
1544 struct mgmt_rp_unpair_device rp;
a8a1d19e
JH
1545 struct hci_cp_disconnect dc;
1546 struct pending_cmd *cmd;
55ed8ca1 1547 struct hci_conn *conn;
55ed8ca1
JH
1548 int err;
1549
bdce7baf 1550 if (len != sizeof(*cp))
bdb6d971 1551 return cmd_status(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
ca69b795 1552 MGMT_STATUS_INVALID_PARAMS);
55ed8ca1 1553
09fd0de5 1554 hci_dev_lock(hdev);
55ed8ca1 1555
a8a1d19e 1556 memset(&rp, 0, sizeof(rp));
124f6e35
JH
1557 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
1558 rp.addr.type = cp->addr.type;
a8a1d19e 1559
86a8cfc6 1560 if (!hdev_is_powered(hdev)) {
bdb6d971 1561 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
86a8cfc6
JH
1562 MGMT_STATUS_NOT_POWERED,
1563 &rp, sizeof(rp));
1564 goto unlock;
1565 }
1566
124f6e35
JH
1567 if (cp->addr.type == MGMT_ADDR_BREDR)
1568 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
1569 else
1570 err = hci_remove_ltk(hdev, &cp->addr.bdaddr);
b0dbfb46 1571
55ed8ca1 1572 if (err < 0) {
bdb6d971 1573 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
86a8cfc6
JH
1574 MGMT_STATUS_NOT_PAIRED,
1575 &rp, sizeof(rp));
55ed8ca1
JH
1576 goto unlock;
1577 }
1578
86a8cfc6
JH
1579 if (cp->disconnect) {
1580 if (cp->addr.type == MGMT_ADDR_BREDR)
1581 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
124f6e35 1582 &cp->addr.bdaddr);
86a8cfc6
JH
1583 else
1584 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
124f6e35 1585 &cp->addr.bdaddr);
86a8cfc6
JH
1586 } else {
1587 conn = NULL;
1588 }
124f6e35 1589
a8a1d19e 1590 if (!conn) {
bdb6d971 1591 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
aee9b218 1592 &rp, sizeof(rp));
b1078ad0 1593 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
a8a1d19e
JH
1594 goto unlock;
1595 }
55ed8ca1 1596
124f6e35
JH
1597 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
1598 sizeof(*cp));
a8a1d19e
JH
1599 if (!cmd) {
1600 err = -ENOMEM;
1601 goto unlock;
55ed8ca1
JH
1602 }
1603
a8a1d19e
JH
1604 put_unaligned_le16(conn->handle, &dc.handle);
1605 dc.reason = 0x13; /* Remote User Terminated Connection */
1606 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1607 if (err < 0)
1608 mgmt_pending_remove(cmd);
1609
55ed8ca1 1610unlock:
09fd0de5 1611 hci_dev_unlock(hdev);
55ed8ca1
JH
1612 return err;
1613}
1614
bdb6d971
JH
1615static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
1616 u16 len)
8962ee74 1617{
650f726d 1618 struct mgmt_cp_disconnect *cp = data;
8962ee74 1619 struct hci_cp_disconnect dc;
366a0336 1620 struct pending_cmd *cmd;
8962ee74 1621 struct hci_conn *conn;
8962ee74
JH
1622 int err;
1623
1624 BT_DBG("");
1625
bdce7baf 1626 if (len != sizeof(*cp))
bdb6d971 1627 return cmd_status(sk, hdev->id, MGMT_OP_DISCONNECT,
ca69b795 1628 MGMT_STATUS_INVALID_PARAMS);
8962ee74 1629
09fd0de5 1630 hci_dev_lock(hdev);
8962ee74
JH
1631
1632 if (!test_bit(HCI_UP, &hdev->flags)) {
bdb6d971 1633 err = cmd_status(sk, hdev->id, MGMT_OP_DISCONNECT,
ca69b795 1634 MGMT_STATUS_NOT_POWERED);
8962ee74
JH
1635 goto failed;
1636 }
1637
2e58ef3e 1638 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
bdb6d971 1639 err = cmd_status(sk, hdev->id, MGMT_OP_DISCONNECT,
ca69b795 1640 MGMT_STATUS_BUSY);
8962ee74
JH
1641 goto failed;
1642 }
1643
88c3df13
JH
1644 if (cp->addr.type == MGMT_ADDR_BREDR)
1645 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
1646 else
1647 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
365227e5 1648
8962ee74 1649 if (!conn) {
bdb6d971 1650 err = cmd_status(sk, hdev->id, MGMT_OP_DISCONNECT,
ca69b795 1651 MGMT_STATUS_NOT_CONNECTED);
8962ee74
JH
1652 goto failed;
1653 }
1654
2e58ef3e 1655 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
366a0336
JH
1656 if (!cmd) {
1657 err = -ENOMEM;
8962ee74 1658 goto failed;
366a0336 1659 }
8962ee74
JH
1660
1661 put_unaligned_le16(conn->handle, &dc.handle);
1662 dc.reason = 0x13; /* Remote User Terminated Connection */
1663
1664 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1665 if (err < 0)
a664b5bc 1666 mgmt_pending_remove(cmd);
8962ee74
JH
1667
1668failed:
09fd0de5 1669 hci_dev_unlock(hdev);
8962ee74
JH
1670 return err;
1671}
1672
48264f06 1673static u8 link_to_mgmt(u8 link_type, u8 addr_type)
4c659c39
JH
1674{
1675 switch (link_type) {
1676 case LE_LINK:
48264f06
JH
1677 switch (addr_type) {
1678 case ADDR_LE_DEV_PUBLIC:
1679 return MGMT_ADDR_LE_PUBLIC;
1680 case ADDR_LE_DEV_RANDOM:
1681 return MGMT_ADDR_LE_RANDOM;
1682 default:
1683 return MGMT_ADDR_INVALID;
1684 }
4c659c39
JH
1685 case ACL_LINK:
1686 return MGMT_ADDR_BREDR;
1687 default:
1688 return MGMT_ADDR_INVALID;
1689 }
1690}
1691
bdb6d971 1692static int get_connections(struct sock *sk, struct hci_dev *hdev)
2784eb41 1693{
2784eb41 1694 struct mgmt_rp_get_connections *rp;
8035ded4 1695 struct hci_conn *c;
a38528f1 1696 size_t rp_len;
60fc5fb6
JH
1697 int err;
1698 u16 i;
2784eb41
JH
1699
1700 BT_DBG("");
1701
09fd0de5 1702 hci_dev_lock(hdev);
2784eb41 1703
5f97c1df 1704 if (!hdev_is_powered(hdev)) {
bdb6d971 1705 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
5f97c1df
JH
1706 MGMT_STATUS_NOT_POWERED);
1707 goto unlock;
1708 }
1709
60fc5fb6 1710 i = 0;
b644ba33
JH
1711 list_for_each_entry(c, &hdev->conn_hash.list, list) {
1712 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
60fc5fb6 1713 i++;
2784eb41
JH
1714 }
1715
60fc5fb6 1716 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
a38528f1
JH
1717 rp = kmalloc(rp_len, GFP_ATOMIC);
1718 if (!rp) {
2784eb41
JH
1719 err = -ENOMEM;
1720 goto unlock;
1721 }
1722
2784eb41 1723 i = 0;
4c659c39 1724 list_for_each_entry(c, &hdev->conn_hash.list, list) {
b644ba33
JH
1725 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
1726 continue;
4c659c39 1727 bacpy(&rp->addr[i].bdaddr, &c->dst);
48264f06 1728 rp->addr[i].type = link_to_mgmt(c->type, c->dst_type);
4c659c39
JH
1729 if (rp->addr[i].type == MGMT_ADDR_INVALID)
1730 continue;
1731 i++;
1732 }
1733
60fc5fb6
JH
1734 put_unaligned_le16(i, &rp->conn_count);
1735
4c659c39
JH
1736 /* Recalculate length in case of filtered SCO connections, etc */
1737 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
2784eb41 1738
bdb6d971
JH
1739 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
1740 rp_len);
2784eb41 1741
a38528f1 1742 kfree(rp);
5f97c1df
JH
1743
1744unlock:
09fd0de5 1745 hci_dev_unlock(hdev);
2784eb41
JH
1746 return err;
1747}
1748
bdb6d971
JH
1749static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
1750 struct mgmt_cp_pin_code_neg_reply *cp)
96d97a67
WR
1751{
1752 struct pending_cmd *cmd;
1753 int err;
1754
2e58ef3e 1755 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
96d97a67
WR
1756 sizeof(*cp));
1757 if (!cmd)
1758 return -ENOMEM;
1759
d8457698
JH
1760 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
1761 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
96d97a67
WR
1762 if (err < 0)
1763 mgmt_pending_remove(cmd);
1764
1765 return err;
1766}
1767
bdb6d971
JH
1768static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
1769 u16 len)
980e1a53 1770{
96d97a67 1771 struct hci_conn *conn;
650f726d 1772 struct mgmt_cp_pin_code_reply *cp = data;
980e1a53 1773 struct hci_cp_pin_code_reply reply;
366a0336 1774 struct pending_cmd *cmd;
980e1a53
JH
1775 int err;
1776
1777 BT_DBG("");
1778
bdce7baf 1779 if (len != sizeof(*cp))
bdb6d971 1780 return cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
ca69b795 1781 MGMT_STATUS_INVALID_PARAMS);
980e1a53 1782
09fd0de5 1783 hci_dev_lock(hdev);
980e1a53 1784
4b34ee78 1785 if (!hdev_is_powered(hdev)) {
bdb6d971 1786 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
ca69b795 1787 MGMT_STATUS_NOT_POWERED);
980e1a53
JH
1788 goto failed;
1789 }
1790
d8457698 1791 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
96d97a67 1792 if (!conn) {
bdb6d971 1793 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
ca69b795 1794 MGMT_STATUS_NOT_CONNECTED);
96d97a67
WR
1795 goto failed;
1796 }
1797
1798 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
d8457698
JH
1799 struct mgmt_cp_pin_code_neg_reply ncp;
1800
1801 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
96d97a67
WR
1802
1803 BT_ERR("PIN code is not 16 bytes long");
1804
bdb6d971 1805 err = send_pin_code_neg_reply(sk, hdev, &ncp);
96d97a67 1806 if (err >= 0)
bdb6d971 1807 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
ca69b795 1808 MGMT_STATUS_INVALID_PARAMS);
96d97a67
WR
1809
1810 goto failed;
1811 }
1812
00abfe44 1813 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
366a0336
JH
1814 if (!cmd) {
1815 err = -ENOMEM;
980e1a53 1816 goto failed;
366a0336 1817 }
980e1a53 1818
d8457698 1819 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
980e1a53 1820 reply.pin_len = cp->pin_len;
24718ca5 1821 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
980e1a53
JH
1822
1823 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
1824 if (err < 0)
a664b5bc 1825 mgmt_pending_remove(cmd);
980e1a53
JH
1826
1827failed:
09fd0de5 1828 hci_dev_unlock(hdev);
980e1a53
JH
1829 return err;
1830}
1831
bdb6d971
JH
1832static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
1833 void *data, u16 len)
980e1a53 1834{
650f726d 1835 struct mgmt_cp_pin_code_neg_reply *cp = data;
980e1a53
JH
1836 int err;
1837
1838 BT_DBG("");
1839
bdce7baf 1840 if (len != sizeof(*cp))
bdb6d971 1841 return cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
ca69b795 1842 MGMT_STATUS_INVALID_PARAMS);
980e1a53 1843
09fd0de5 1844 hci_dev_lock(hdev);
980e1a53 1845
4b34ee78 1846 if (!hdev_is_powered(hdev)) {
bdb6d971 1847 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
ca69b795 1848 MGMT_STATUS_NOT_POWERED);
980e1a53
JH
1849 goto failed;
1850 }
1851
bdb6d971 1852 err = send_pin_code_neg_reply(sk, hdev, cp);
980e1a53
JH
1853
1854failed:
09fd0de5 1855 hci_dev_unlock(hdev);
980e1a53
JH
1856 return err;
1857}
1858
bdb6d971
JH
1859static int set_io_capability(struct sock *sk, struct hci_dev *hdev,
1860 void *data, u16 len)
17fa4b9d 1861{
650f726d 1862 struct mgmt_cp_set_io_capability *cp = data;
17fa4b9d
JH
1863
1864 BT_DBG("");
1865
bdce7baf 1866 if (len != sizeof(*cp))
bdb6d971 1867 return cmd_status(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
ca69b795 1868 MGMT_STATUS_INVALID_PARAMS);
17fa4b9d 1869
09fd0de5 1870 hci_dev_lock(hdev);
17fa4b9d
JH
1871
1872 hdev->io_capability = cp->io_capability;
1873
1874 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
b8534e0f 1875 hdev->io_capability);
17fa4b9d 1876
09fd0de5 1877 hci_dev_unlock(hdev);
17fa4b9d 1878
bdb6d971
JH
1879 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0,
1880 NULL, 0);
17fa4b9d
JH
1881}
1882
e9a416b5
JH
1883static inline struct pending_cmd *find_pairing(struct hci_conn *conn)
1884{
1885 struct hci_dev *hdev = conn->hdev;
8035ded4 1886 struct pending_cmd *cmd;
e9a416b5 1887
2e58ef3e 1888 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
e9a416b5
JH
1889 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
1890 continue;
1891
e9a416b5
JH
1892 if (cmd->user_data != conn)
1893 continue;
1894
1895 return cmd;
1896 }
1897
1898 return NULL;
1899}
1900
1901static void pairing_complete(struct pending_cmd *cmd, u8 status)
1902{
1903 struct mgmt_rp_pair_device rp;
1904 struct hci_conn *conn = cmd->user_data;
1905
ba4e564f
JH
1906 bacpy(&rp.addr.bdaddr, &conn->dst);
1907 rp.addr.type = link_to_mgmt(conn->type, conn->dst_type);
e9a416b5 1908
aee9b218
JH
1909 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
1910 &rp, sizeof(rp));
e9a416b5
JH
1911
1912 /* So we don't get further callbacks for this connection */
1913 conn->connect_cfm_cb = NULL;
1914 conn->security_cfm_cb = NULL;
1915 conn->disconn_cfm_cb = NULL;
1916
1917 hci_conn_put(conn);
1918
a664b5bc 1919 mgmt_pending_remove(cmd);
e9a416b5
JH
1920}
1921
1922static void pairing_complete_cb(struct hci_conn *conn, u8 status)
1923{
1924 struct pending_cmd *cmd;
1925
1926 BT_DBG("status %u", status);
1927
1928 cmd = find_pairing(conn);
56e5cb86 1929 if (!cmd)
e9a416b5 1930 BT_DBG("Unable to find a pending command");
56e5cb86 1931 else
e211326c 1932 pairing_complete(cmd, mgmt_status(status));
e9a416b5
JH
1933}
1934
bdb6d971
JH
1935static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
1936 u16 len)
e9a416b5 1937{
650f726d 1938 struct mgmt_cp_pair_device *cp = data;
1425acb7 1939 struct mgmt_rp_pair_device rp;
e9a416b5
JH
1940 struct pending_cmd *cmd;
1941 u8 sec_level, auth_type;
1942 struct hci_conn *conn;
e9a416b5
JH
1943 int err;
1944
1945 BT_DBG("");
1946
bdce7baf 1947 if (len != sizeof(*cp))
bdb6d971 1948 return cmd_status(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
ca69b795 1949 MGMT_STATUS_INVALID_PARAMS);
e9a416b5 1950
09fd0de5 1951 hci_dev_lock(hdev);
e9a416b5 1952
5f97c1df 1953 if (!hdev_is_powered(hdev)) {
bdb6d971 1954 err = cmd_status(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
5f97c1df
JH
1955 MGMT_STATUS_NOT_POWERED);
1956 goto unlock;
1957 }
1958
c908df36
VCG
1959 sec_level = BT_SECURITY_MEDIUM;
1960 if (cp->io_cap == 0x03)
e9a416b5 1961 auth_type = HCI_AT_DEDICATED_BONDING;
c908df36 1962 else
e9a416b5 1963 auth_type = HCI_AT_DEDICATED_BONDING_MITM;
e9a416b5 1964
ba4e564f
JH
1965 if (cp->addr.type == MGMT_ADDR_BREDR)
1966 conn = hci_connect(hdev, ACL_LINK, &cp->addr.bdaddr, sec_level,
7a512d01
VCG
1967 auth_type);
1968 else
ba4e564f 1969 conn = hci_connect(hdev, LE_LINK, &cp->addr.bdaddr, sec_level,
7a512d01
VCG
1970 auth_type);
1971
1425acb7
JH
1972 memset(&rp, 0, sizeof(rp));
1973 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
1974 rp.addr.type = cp->addr.type;
1975
30e76272 1976 if (IS_ERR(conn)) {
bdb6d971 1977 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
e211326c
JH
1978 MGMT_STATUS_CONNECT_FAILED,
1979 &rp, sizeof(rp));
e9a416b5
JH
1980 goto unlock;
1981 }
1982
1983 if (conn->connect_cfm_cb) {
1984 hci_conn_put(conn);
bdb6d971 1985 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
e211326c 1986 MGMT_STATUS_BUSY, &rp, sizeof(rp));
e9a416b5
JH
1987 goto unlock;
1988 }
1989
2e58ef3e 1990 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
e9a416b5
JH
1991 if (!cmd) {
1992 err = -ENOMEM;
1993 hci_conn_put(conn);
1994 goto unlock;
1995 }
1996
7a512d01 1997 /* For LE, just connecting isn't a proof that the pairing finished */
ba4e564f 1998 if (cp->addr.type == MGMT_ADDR_BREDR)
7a512d01
VCG
1999 conn->connect_cfm_cb = pairing_complete_cb;
2000
e9a416b5
JH
2001 conn->security_cfm_cb = pairing_complete_cb;
2002 conn->disconn_cfm_cb = pairing_complete_cb;
2003 conn->io_capability = cp->io_cap;
2004 cmd->user_data = conn;
2005
2006 if (conn->state == BT_CONNECTED &&
2007 hci_conn_security(conn, sec_level, auth_type))
2008 pairing_complete(cmd, 0);
2009
2010 err = 0;
2011
2012unlock:
09fd0de5 2013 hci_dev_unlock(hdev);
e9a416b5
JH
2014 return err;
2015}
2016
bdb6d971 2017static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev,
28424707
JH
2018 unsigned char *data, u16 len)
2019{
2020 struct mgmt_addr_info *addr = (void *) data;
28424707
JH
2021 struct pending_cmd *cmd;
2022 struct hci_conn *conn;
2023 int err;
2024
2025 BT_DBG("");
2026
2027 if (len != sizeof(*addr))
bdb6d971 2028 return cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
28424707
JH
2029 MGMT_STATUS_INVALID_PARAMS);
2030
2031 hci_dev_lock(hdev);
2032
5f97c1df 2033 if (!hdev_is_powered(hdev)) {
bdb6d971 2034 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
5f97c1df
JH
2035 MGMT_STATUS_NOT_POWERED);
2036 goto unlock;
2037 }
2038
28424707
JH
2039 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
2040 if (!cmd) {
bdb6d971 2041 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
28424707
JH
2042 MGMT_STATUS_INVALID_PARAMS);
2043 goto unlock;
2044 }
2045
2046 conn = cmd->user_data;
2047
2048 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
bdb6d971 2049 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
28424707
JH
2050 MGMT_STATUS_INVALID_PARAMS);
2051 goto unlock;
2052 }
2053
2054 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
2055
bdb6d971
JH
2056 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
2057 addr, sizeof(*addr));
28424707
JH
2058unlock:
2059 hci_dev_unlock(hdev);
28424707
JH
2060 return err;
2061}
2062
bdb6d971
JH
2063static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
2064 bdaddr_t *bdaddr, u8 type, u16 mgmt_op,
2065 u16 hci_op, __le32 passkey)
a5c29683 2066{
a5c29683 2067 struct pending_cmd *cmd;
0df4c185 2068 struct hci_conn *conn;
a5c29683
JH
2069 int err;
2070
09fd0de5 2071 hci_dev_lock(hdev);
08ba5382 2072
4b34ee78 2073 if (!hdev_is_powered(hdev)) {
bdb6d971
JH
2074 err = cmd_status(sk, hdev->id, mgmt_op,
2075 MGMT_STATUS_NOT_POWERED);
0df4c185 2076 goto done;
a5c29683
JH
2077 }
2078
272d90df
JH
2079 if (type == MGMT_ADDR_BREDR)
2080 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, bdaddr);
2081 else
47c15e2b 2082 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, bdaddr);
272d90df
JH
2083
2084 if (!conn) {
bdb6d971 2085 err = cmd_status(sk, hdev->id, mgmt_op,
47c15e2b 2086 MGMT_STATUS_NOT_CONNECTED);
272d90df
JH
2087 goto done;
2088 }
47c15e2b 2089
272d90df 2090 if (type == MGMT_ADDR_LE_PUBLIC || type == MGMT_ADDR_LE_RANDOM) {
47c15e2b 2091 /* Continue with pairing via SMP */
5fe57d9e
BG
2092 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
2093
2094 if (!err)
bdb6d971 2095 err = cmd_status(sk, hdev->id, mgmt_op,
5fe57d9e
BG
2096 MGMT_STATUS_SUCCESS);
2097 else
bdb6d971 2098 err = cmd_status(sk, hdev->id, mgmt_op,
5fe57d9e 2099 MGMT_STATUS_FAILED);
47c15e2b 2100
47c15e2b
BG
2101 goto done;
2102 }
2103
0df4c185 2104 cmd = mgmt_pending_add(sk, mgmt_op, hdev, bdaddr, sizeof(*bdaddr));
a5c29683
JH
2105 if (!cmd) {
2106 err = -ENOMEM;
0df4c185 2107 goto done;
a5c29683
JH
2108 }
2109
0df4c185 2110 /* Continue with pairing via HCI */
604086b7
BG
2111 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
2112 struct hci_cp_user_passkey_reply cp;
2113
2114 bacpy(&cp.bdaddr, bdaddr);
2115 cp.passkey = passkey;
2116 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
2117 } else
2118 err = hci_send_cmd(hdev, hci_op, sizeof(*bdaddr), bdaddr);
2119
a664b5bc
JH
2120 if (err < 0)
2121 mgmt_pending_remove(cmd);
a5c29683 2122
0df4c185 2123done:
09fd0de5 2124 hci_dev_unlock(hdev);
a5c29683
JH
2125 return err;
2126}
2127
bdb6d971
JH
2128static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev,
2129 void *data, u16 len)
0df4c185 2130{
650f726d 2131 struct mgmt_cp_user_confirm_reply *cp = data;
0df4c185
BG
2132
2133 BT_DBG("");
2134
2135 if (len != sizeof(*cp))
bdb6d971 2136 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
0df4c185
BG
2137 MGMT_STATUS_INVALID_PARAMS);
2138
bdb6d971 2139 return user_pairing_resp(sk, hdev, &cp->addr.bdaddr, cp->addr.type,
272d90df
JH
2140 MGMT_OP_USER_CONFIRM_REPLY,
2141 HCI_OP_USER_CONFIRM_REPLY, 0);
0df4c185
BG
2142}
2143
bdb6d971
JH
2144static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
2145 void *data, u16 len)
0df4c185 2146{
c9c2659f 2147 struct mgmt_cp_user_confirm_neg_reply *cp = data;
0df4c185
BG
2148
2149 BT_DBG("");
2150
2151 if (len != sizeof(*cp))
bdb6d971 2152 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_NEG_REPLY,
0df4c185
BG
2153 MGMT_STATUS_INVALID_PARAMS);
2154
bdb6d971 2155 return user_pairing_resp(sk, hdev, &cp->addr.bdaddr, cp->addr.type,
272d90df
JH
2156 MGMT_OP_USER_CONFIRM_NEG_REPLY,
2157 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
0df4c185
BG
2158}
2159
bdb6d971
JH
2160static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev,
2161 void *data, u16 len)
604086b7 2162{
650f726d 2163 struct mgmt_cp_user_passkey_reply *cp = data;
604086b7
BG
2164
2165 BT_DBG("");
2166
2167 if (len != sizeof(*cp))
bdb6d971 2168 return cmd_status(sk, hdev->id, MGMT_OP_USER_PASSKEY_REPLY,
604086b7
BG
2169 EINVAL);
2170
bdb6d971 2171 return user_pairing_resp(sk, hdev, &cp->addr.bdaddr, cp->addr.type,
272d90df
JH
2172 MGMT_OP_USER_PASSKEY_REPLY,
2173 HCI_OP_USER_PASSKEY_REPLY,
2174 cp->passkey);
604086b7
BG
2175}
2176
bdb6d971
JH
2177static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
2178 void *data, u16 len)
604086b7 2179{
650f726d 2180 struct mgmt_cp_user_passkey_neg_reply *cp = data;
604086b7
BG
2181
2182 BT_DBG("");
2183
2184 if (len != sizeof(*cp))
bdb6d971
JH
2185 return cmd_status(sk, hdev->id, MGMT_OP_USER_PASSKEY_NEG_REPLY,
2186 EINVAL);
604086b7 2187
bdb6d971 2188 return user_pairing_resp(sk, hdev, &cp->addr.bdaddr, cp->addr.type,
272d90df
JH
2189 MGMT_OP_USER_PASSKEY_NEG_REPLY,
2190 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
604086b7
BG
2191}
2192
bdb6d971 2193static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
b312b161
JH
2194 u16 len)
2195{
650f726d 2196 struct mgmt_cp_set_local_name *mgmt_cp = data;
b312b161 2197 struct hci_cp_write_local_name hci_cp;
b312b161
JH
2198 struct pending_cmd *cmd;
2199 int err;
2200
2201 BT_DBG("");
2202
2203 if (len != sizeof(*mgmt_cp))
bdb6d971 2204 return cmd_status(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
ca69b795 2205 MGMT_STATUS_INVALID_PARAMS);
b312b161 2206
09fd0de5 2207 hci_dev_lock(hdev);
b312b161 2208
28cc7bde
JH
2209 memcpy(hdev->short_name, mgmt_cp->short_name,
2210 sizeof(hdev->short_name));
2211
b5235a65 2212 if (!hdev_is_powered(hdev)) {
28cc7bde
JH
2213 memcpy(hdev->dev_name, mgmt_cp->name, sizeof(hdev->dev_name));
2214
2215 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
2216 data, len);
2217 if (err < 0)
2218 goto failed;
2219
2220 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
2221 sk);
2222
b5235a65
JH
2223 goto failed;
2224 }
2225
28cc7bde 2226 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
b312b161
JH
2227 if (!cmd) {
2228 err = -ENOMEM;
2229 goto failed;
2230 }
2231
2232 memcpy(hci_cp.name, mgmt_cp->name, sizeof(hci_cp.name));
2233 err = hci_send_cmd(hdev, HCI_OP_WRITE_LOCAL_NAME, sizeof(hci_cp),
2234 &hci_cp);
2235 if (err < 0)
2236 mgmt_pending_remove(cmd);
2237
2238failed:
09fd0de5 2239 hci_dev_unlock(hdev);
b312b161
JH
2240 return err;
2241}
2242
bdb6d971 2243static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev)
c35938b2 2244{
c35938b2
SJ
2245 struct pending_cmd *cmd;
2246 int err;
2247
bdb6d971 2248 BT_DBG("%s", hdev->name);
c35938b2 2249
09fd0de5 2250 hci_dev_lock(hdev);
c35938b2 2251
4b34ee78 2252 if (!hdev_is_powered(hdev)) {
bdb6d971 2253 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
ca69b795 2254 MGMT_STATUS_NOT_POWERED);
c35938b2
SJ
2255 goto unlock;
2256 }
2257
2258 if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) {
bdb6d971 2259 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
ca69b795 2260 MGMT_STATUS_NOT_SUPPORTED);
c35938b2
SJ
2261 goto unlock;
2262 }
2263
2e58ef3e 2264 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
bdb6d971 2265 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
ca69b795 2266 MGMT_STATUS_BUSY);
c35938b2
SJ
2267 goto unlock;
2268 }
2269
2e58ef3e 2270 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
c35938b2
SJ
2271 if (!cmd) {
2272 err = -ENOMEM;
2273 goto unlock;
2274 }
2275
2276 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
2277 if (err < 0)
2278 mgmt_pending_remove(cmd);
2279
2280unlock:
09fd0de5 2281 hci_dev_unlock(hdev);
c35938b2
SJ
2282 return err;
2283}
2284
bdb6d971
JH
2285static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
2286 void *data, u16 len)
2763eda6 2287{
650f726d 2288 struct mgmt_cp_add_remote_oob_data *cp = data;
bf1e3541 2289 u8 status;
2763eda6
SJ
2290 int err;
2291
bdb6d971 2292 BT_DBG("%s ", hdev->name);
2763eda6
SJ
2293
2294 if (len != sizeof(*cp))
bdb6d971 2295 return cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
ca69b795 2296 MGMT_STATUS_INVALID_PARAMS);
2763eda6 2297
09fd0de5 2298 hci_dev_lock(hdev);
2763eda6 2299
5f97c1df 2300 if (!hdev_is_powered(hdev)) {
bdb6d971 2301 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
5f97c1df
JH
2302 MGMT_STATUS_NOT_POWERED,
2303 &cp->addr, sizeof(cp->addr));
2304 goto unlock;
2305 }
2306
664ce4cc 2307 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr, cp->hash,
2763eda6
SJ
2308 cp->randomizer);
2309 if (err < 0)
bf1e3541 2310 status = MGMT_STATUS_FAILED;
2763eda6 2311 else
bf1e3541
JH
2312 status = 0;
2313
bdb6d971 2314 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA, status,
bf1e3541 2315 &cp->addr, sizeof(cp->addr));
2763eda6 2316
5f97c1df 2317unlock:
09fd0de5 2318 hci_dev_unlock(hdev);
2763eda6
SJ
2319 return err;
2320}
2321
bdb6d971 2322static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
650f726d 2323 void *data, u16 len)
2763eda6 2324{
650f726d 2325 struct mgmt_cp_remove_remote_oob_data *cp = data;
bf1e3541 2326 u8 status;
2763eda6
SJ
2327 int err;
2328
bdb6d971 2329 BT_DBG("%s", hdev->name);
2763eda6
SJ
2330
2331 if (len != sizeof(*cp))
bdb6d971 2332 return cmd_status(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
ca69b795 2333 MGMT_STATUS_INVALID_PARAMS);
2763eda6 2334
09fd0de5 2335 hci_dev_lock(hdev);
2763eda6 2336
5f97c1df 2337 if (!hdev_is_powered(hdev)) {
bdb6d971
JH
2338 err = cmd_complete(sk, hdev->id,
2339 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
2340 MGMT_STATUS_NOT_POWERED,
2341 &cp->addr, sizeof(cp->addr));
5f97c1df
JH
2342 goto unlock;
2343 }
2344
664ce4cc 2345 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
2763eda6 2346 if (err < 0)
bf1e3541 2347 status = MGMT_STATUS_INVALID_PARAMS;
2763eda6 2348 else
bf1e3541
JH
2349 status = 0;
2350
bdb6d971
JH
2351 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
2352 status, &cp->addr, sizeof(cp->addr));
2763eda6 2353
5f97c1df 2354unlock:
09fd0de5 2355 hci_dev_unlock(hdev);
2763eda6
SJ
2356 return err;
2357}
2358
5e0452c0
AG
2359int mgmt_interleaved_discovery(struct hci_dev *hdev)
2360{
2361 int err;
2362
2363 BT_DBG("%s", hdev->name);
2364
2365 hci_dev_lock(hdev);
2366
2367 err = hci_do_inquiry(hdev, INQUIRY_LEN_BREDR_LE);
2368 if (err < 0)
2369 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
2370
2371 hci_dev_unlock(hdev);
2372
2373 return err;
2374}
2375
bdb6d971 2376static int start_discovery(struct sock *sk, struct hci_dev *hdev,
650f726d 2377 void *data, u16 len)
14a53664 2378{
650f726d 2379 struct mgmt_cp_start_discovery *cp = data;
14a53664 2380 struct pending_cmd *cmd;
14a53664
JH
2381 int err;
2382
bdb6d971 2383 BT_DBG("%s", hdev->name);
14a53664 2384
450dfdaf 2385 if (len != sizeof(*cp))
bdb6d971 2386 return cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
ca69b795 2387 MGMT_STATUS_INVALID_PARAMS);
14a53664 2388
09fd0de5 2389 hci_dev_lock(hdev);
14a53664 2390
4b34ee78 2391 if (!hdev_is_powered(hdev)) {
bdb6d971 2392 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
ca69b795 2393 MGMT_STATUS_NOT_POWERED);
bd2d1334
JH
2394 goto failed;
2395 }
2396
ff9ef578 2397 if (hdev->discovery.state != DISCOVERY_STOPPED) {
bdb6d971
JH
2398 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
2399 MGMT_STATUS_BUSY);
ff9ef578
JH
2400 goto failed;
2401 }
2402
2e58ef3e 2403 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
14a53664
JH
2404 if (!cmd) {
2405 err = -ENOMEM;
2406 goto failed;
2407 }
2408
4aab14e5
AG
2409 hdev->discovery.type = cp->type;
2410
2411 switch (hdev->discovery.type) {
f39799f5 2412 case DISCOV_TYPE_BREDR:
8b90129c
AG
2413 if (lmp_bredr_capable(hdev))
2414 err = hci_do_inquiry(hdev, INQUIRY_LEN_BREDR);
2415 else
2416 err = -ENOTSUPP;
f39799f5
AG
2417 break;
2418
2419 case DISCOV_TYPE_LE:
8b90129c
AG
2420 if (lmp_host_le_capable(hdev))
2421 err = hci_le_scan(hdev, LE_SCAN_TYPE, LE_SCAN_INT,
3fd24153 2422 LE_SCAN_WIN, LE_SCAN_TIMEOUT_LE_ONLY);
8b90129c
AG
2423 else
2424 err = -ENOTSUPP;
f39799f5
AG
2425 break;
2426
5e0452c0 2427 case DISCOV_TYPE_INTERLEAVED:
426c189a
AG
2428 if (lmp_host_le_capable(hdev) && lmp_bredr_capable(hdev))
2429 err = hci_le_scan(hdev, LE_SCAN_TYPE, LE_SCAN_INT,
2430 LE_SCAN_WIN, LE_SCAN_TIMEOUT_BREDR_LE);
2431 else
2432 err = -ENOTSUPP;
5e0452c0
AG
2433 break;
2434
f39799f5 2435 default:
3fd24153 2436 err = -EINVAL;
f39799f5 2437 }
3fd24153 2438
14a53664
JH
2439 if (err < 0)
2440 mgmt_pending_remove(cmd);
ff9ef578
JH
2441 else
2442 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
14a53664
JH
2443
2444failed:
09fd0de5 2445 hci_dev_unlock(hdev);
14a53664
JH
2446 return err;
2447}
2448
bdb6d971
JH
2449static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
2450 u16 len)
14a53664 2451{
d930650b 2452 struct mgmt_cp_stop_discovery *mgmt_cp = data;
14a53664 2453 struct pending_cmd *cmd;
30dc78e1
JH
2454 struct hci_cp_remote_name_req_cancel cp;
2455 struct inquiry_entry *e;
14a53664
JH
2456 int err;
2457
bdb6d971 2458 BT_DBG("%s", hdev->name);
14a53664 2459
d930650b 2460 if (len != sizeof(*mgmt_cp))
bdb6d971 2461 return cmd_status(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
ca69b795 2462 MGMT_STATUS_INVALID_PARAMS);
14a53664 2463
09fd0de5 2464 hci_dev_lock(hdev);
14a53664 2465
30dc78e1 2466 if (!hci_discovery_active(hdev)) {
bdb6d971 2467 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
d930650b
JH
2468 MGMT_STATUS_REJECTED,
2469 &mgmt_cp->type, sizeof(mgmt_cp->type));
2470 goto unlock;
2471 }
2472
2473 if (hdev->discovery.type != mgmt_cp->type) {
bdb6d971 2474 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
d930650b
JH
2475 MGMT_STATUS_INVALID_PARAMS,
2476 &mgmt_cp->type, sizeof(mgmt_cp->type));
30dc78e1 2477 goto unlock;
ff9ef578
JH
2478 }
2479
2e58ef3e 2480 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
14a53664
JH
2481 if (!cmd) {
2482 err = -ENOMEM;
30dc78e1
JH
2483 goto unlock;
2484 }
2485
343f935b 2486 if (hdev->discovery.state == DISCOVERY_FINDING) {
30dc78e1
JH
2487 err = hci_cancel_inquiry(hdev);
2488 if (err < 0)
2489 mgmt_pending_remove(cmd);
2490 else
2491 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
2492 goto unlock;
2493 }
2494
2495 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_PENDING);
2496 if (!e) {
2497 mgmt_pending_remove(cmd);
bdb6d971 2498 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
d930650b 2499 &mgmt_cp->type, sizeof(mgmt_cp->type));
30dc78e1
JH
2500 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
2501 goto unlock;
14a53664
JH
2502 }
2503
30dc78e1
JH
2504 bacpy(&cp.bdaddr, &e->data.bdaddr);
2505 err = hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ_CANCEL,
2506 sizeof(cp), &cp);
14a53664
JH
2507 if (err < 0)
2508 mgmt_pending_remove(cmd);
ff9ef578
JH
2509 else
2510 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
14a53664 2511
30dc78e1 2512unlock:
09fd0de5 2513 hci_dev_unlock(hdev);
14a53664
JH
2514 return err;
2515}
2516
bdb6d971
JH
2517static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
2518 u16 len)
561aafbc 2519{
650f726d 2520 struct mgmt_cp_confirm_name *cp = data;
561aafbc 2521 struct inquiry_entry *e;
561aafbc
JH
2522 int err;
2523
bdb6d971 2524 BT_DBG("%s", hdev->name);
561aafbc
JH
2525
2526 if (len != sizeof(*cp))
bdb6d971
JH
2527 return cmd_status(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
2528 MGMT_STATUS_INVALID_PARAMS);
561aafbc
JH
2529
2530 hci_dev_lock(hdev);
2531
30dc78e1 2532 if (!hci_discovery_active(hdev)) {
bdb6d971 2533 err = cmd_status(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
30dc78e1
JH
2534 MGMT_STATUS_FAILED);
2535 goto failed;
2536 }
2537
a198e7b1 2538 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
561aafbc 2539 if (!e) {
bdb6d971
JH
2540 err = cmd_status(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
2541 MGMT_STATUS_INVALID_PARAMS);
561aafbc
JH
2542 goto failed;
2543 }
2544
2545 if (cp->name_known) {
2546 e->name_state = NAME_KNOWN;
2547 list_del(&e->list);
2548 } else {
2549 e->name_state = NAME_NEEDED;
a3d4e20a 2550 hci_inquiry_cache_update_resolve(hdev, e);
561aafbc
JH
2551 }
2552
2553 err = 0;
2554
2555failed:
2556 hci_dev_unlock(hdev);
561aafbc
JH
2557 return err;
2558}
2559
bdb6d971
JH
2560static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
2561 u16 len)
7fbec224 2562{
650f726d 2563 struct mgmt_cp_block_device *cp = data;
f0eeea8b 2564 u8 status;
7fbec224
AJ
2565 int err;
2566
bdb6d971 2567 BT_DBG("%s", hdev->name);
7fbec224 2568
7fbec224 2569 if (len != sizeof(*cp))
bdb6d971 2570 return cmd_status(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
ca69b795 2571 MGMT_STATUS_INVALID_PARAMS);
7fbec224 2572
09fd0de5 2573 hci_dev_lock(hdev);
5e762444 2574
88c1fe4b 2575 err = hci_blacklist_add(hdev, &cp->addr.bdaddr, cp->addr.type);
7fbec224 2576 if (err < 0)
f0eeea8b 2577 status = MGMT_STATUS_FAILED;
7fbec224 2578 else
f0eeea8b
JH
2579 status = 0;
2580
bdb6d971 2581 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
f0eeea8b 2582 &cp->addr, sizeof(cp->addr));
5e762444 2583
09fd0de5 2584 hci_dev_unlock(hdev);
7fbec224
AJ
2585
2586 return err;
2587}
2588
bdb6d971
JH
2589static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
2590 u16 len)
7fbec224 2591{
650f726d 2592 struct mgmt_cp_unblock_device *cp = data;
f0eeea8b 2593 u8 status;
7fbec224
AJ
2594 int err;
2595
bdb6d971 2596 BT_DBG("%s", hdev->name);
7fbec224 2597
7fbec224 2598 if (len != sizeof(*cp))
bdb6d971 2599 return cmd_status(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
ca69b795 2600 MGMT_STATUS_INVALID_PARAMS);
7fbec224 2601
09fd0de5 2602 hci_dev_lock(hdev);
5e762444 2603
88c1fe4b 2604 err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type);
7fbec224 2605 if (err < 0)
f0eeea8b 2606 status = MGMT_STATUS_INVALID_PARAMS;
7fbec224 2607 else
f0eeea8b
JH
2608 status = 0;
2609
bdb6d971 2610 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
f0eeea8b 2611 &cp->addr, sizeof(cp->addr));
5e762444 2612
09fd0de5 2613 hci_dev_unlock(hdev);
7fbec224
AJ
2614
2615 return err;
2616}
2617
bdb6d971
JH
2618static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
2619 void *data, u16 len)
f6422ec6 2620{
650f726d 2621 struct mgmt_mode *cp = data;
f6422ec6
AJ
2622 struct hci_cp_write_page_scan_activity acp;
2623 u8 type;
2624 int err;
2625
bdb6d971 2626 BT_DBG("%s", hdev->name);
f6422ec6
AJ
2627
2628 if (len != sizeof(*cp))
bdb6d971 2629 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
ca69b795 2630 MGMT_STATUS_INVALID_PARAMS);
f6422ec6 2631
5400c044 2632 if (!hdev_is_powered(hdev))
bdb6d971 2633 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
5400c044
JH
2634 MGMT_STATUS_NOT_POWERED);
2635
2636 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
bdb6d971
JH
2637 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
2638 MGMT_STATUS_REJECTED);
f6422ec6
AJ
2639
2640 hci_dev_lock(hdev);
2641
f7c6869c 2642 if (cp->val) {
f6422ec6
AJ
2643 type = PAGE_SCAN_TYPE_INTERLACED;
2644 acp.interval = 0x0024; /* 22.5 msec page scan interval */
2645 } else {
2646 type = PAGE_SCAN_TYPE_STANDARD; /* default */
2647 acp.interval = 0x0800; /* default 1.28 sec page scan */
2648 }
2649
2650 acp.window = 0x0012; /* default 11.25 msec page scan window */
2651
2652 err = hci_send_cmd(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
2653 sizeof(acp), &acp);
2654 if (err < 0) {
bdb6d971
JH
2655 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
2656 MGMT_STATUS_FAILED);
f6422ec6
AJ
2657 goto done;
2658 }
2659
2660 err = hci_send_cmd(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
2661 if (err < 0) {
bdb6d971
JH
2662 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
2663 MGMT_STATUS_FAILED);
f6422ec6
AJ
2664 goto done;
2665 }
2666
bdb6d971 2667 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, 0,
aee9b218 2668 NULL, 0);
f6422ec6
AJ
2669done:
2670 hci_dev_unlock(hdev);
f6422ec6
AJ
2671 return err;
2672}
2673
bdb6d971 2674static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
346af67b
VCG
2675 void *cp_data, u16 len)
2676{
346af67b
VCG
2677 struct mgmt_cp_load_long_term_keys *cp = cp_data;
2678 u16 key_count, expected_len;
2679 int i;
2680
2681 if (len < sizeof(*cp))
bdb6d971 2682 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
346af67b
VCG
2683 EINVAL);
2684
2685 key_count = get_unaligned_le16(&cp->key_count);
2686
2687 expected_len = sizeof(*cp) + key_count *
2688 sizeof(struct mgmt_ltk_info);
2689 if (expected_len != len) {
2690 BT_ERR("load_keys: expected %u bytes, got %u bytes",
2691 len, expected_len);
bdb6d971 2692 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
346af67b
VCG
2693 EINVAL);
2694 }
2695
bdb6d971 2696 BT_DBG("%s key_count %u", hdev->name, key_count);
346af67b
VCG
2697
2698 hci_dev_lock(hdev);
2699
2700 hci_smp_ltks_clear(hdev);
2701
2702 for (i = 0; i < key_count; i++) {
2703 struct mgmt_ltk_info *key = &cp->keys[i];
2704 u8 type;
2705
2706 if (key->master)
2707 type = HCI_SMP_LTK;
2708 else
2709 type = HCI_SMP_LTK_SLAVE;
2710
2711 hci_add_ltk(hdev, &key->addr.bdaddr, key->addr.type,
2712 type, 0, key->authenticated, key->val,
2713 key->enc_size, key->ediv, key->rand);
2714 }
2715
2716 hci_dev_unlock(hdev);
346af67b
VCG
2717
2718 return 0;
2719}
2720
0381101f
JH
2721int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
2722{
650f726d
VCG
2723 void *buf;
2724 u8 *cp;
0381101f 2725 struct mgmt_hdr *hdr;
4e51eae9 2726 u16 opcode, index, len;
bdb6d971 2727 struct hci_dev *hdev = NULL;
0381101f
JH
2728 int err;
2729
2730 BT_DBG("got %zu bytes", msglen);
2731
2732 if (msglen < sizeof(*hdr))
2733 return -EINVAL;
2734
e63a15ec 2735 buf = kmalloc(msglen, GFP_KERNEL);
0381101f
JH
2736 if (!buf)
2737 return -ENOMEM;
2738
2739 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
2740 err = -EFAULT;
2741 goto done;
2742 }
2743
650f726d 2744 hdr = buf;
0381101f 2745 opcode = get_unaligned_le16(&hdr->opcode);
4e51eae9 2746 index = get_unaligned_le16(&hdr->index);
0381101f
JH
2747 len = get_unaligned_le16(&hdr->len);
2748
2749 if (len != msglen - sizeof(*hdr)) {
2750 err = -EINVAL;
2751 goto done;
2752 }
2753
bdb6d971
JH
2754 if (opcode < MGMT_OP_READ_INFO) {
2755 if (index != MGMT_INDEX_NONE) {
2756 err = cmd_status(sk, index, opcode,
2757 MGMT_STATUS_INVALID_PARAMS);
2758 goto done;
2759 }
2760 } else {
2761 hdev = hci_dev_get(index);
2762 if (!hdev) {
2763 err = cmd_status(sk, index, opcode,
2764 MGMT_STATUS_INVALID_PARAMS);
2765 goto done;
2766 }
2767 }
2768
650f726d
VCG
2769 cp = buf + sizeof(*hdr);
2770
0381101f 2771 switch (opcode) {
02d98129
JH
2772 case MGMT_OP_READ_VERSION:
2773 err = read_version(sk);
2774 break;
e70bb2e8
JH
2775 case MGMT_OP_READ_COMMANDS:
2776 err = read_commands(sk);
2777 break;
faba42eb
JH
2778 case MGMT_OP_READ_INDEX_LIST:
2779 err = read_index_list(sk);
2780 break;
f7b64e69 2781 case MGMT_OP_READ_INFO:
bdb6d971 2782 err = read_controller_info(sk, hdev);
f7b64e69 2783 break;
eec8d2bc 2784 case MGMT_OP_SET_POWERED:
bdb6d971 2785 err = set_powered(sk, hdev, cp, len);
eec8d2bc 2786 break;
73f22f62 2787 case MGMT_OP_SET_DISCOVERABLE:
bdb6d971 2788 err = set_discoverable(sk, hdev, cp, len);
73f22f62 2789 break;
9fbcbb45 2790 case MGMT_OP_SET_CONNECTABLE:
bdb6d971 2791 err = set_connectable(sk, hdev, cp, len);
9fbcbb45 2792 break;
f7c6869c 2793 case MGMT_OP_SET_FAST_CONNECTABLE:
bdb6d971 2794 err = set_fast_connectable(sk, hdev, cp, len);
f7c6869c 2795 break;
c542a06c 2796 case MGMT_OP_SET_PAIRABLE:
bdb6d971 2797 err = set_pairable(sk, hdev, cp, len);
c542a06c 2798 break;
33ef95ed 2799 case MGMT_OP_SET_LINK_SECURITY:
bdb6d971 2800 err = set_link_security(sk, hdev, cp, len);
33ef95ed 2801 break;
ed2c4ee3 2802 case MGMT_OP_SET_SSP:
bdb6d971 2803 err = set_ssp(sk, hdev, cp, len);
ed2c4ee3 2804 break;
6d80dfd0 2805 case MGMT_OP_SET_HS:
bdb6d971 2806 err = set_hs(sk, hdev, cp, len);
6d80dfd0 2807 break;
06199cf8 2808 case MGMT_OP_SET_LE:
bdb6d971 2809 err = set_le(sk, hdev, cp, len);
06199cf8 2810 break;
2aeb9a1a 2811 case MGMT_OP_ADD_UUID:
bdb6d971 2812 err = add_uuid(sk, hdev, cp, len);
2aeb9a1a
JH
2813 break;
2814 case MGMT_OP_REMOVE_UUID:
bdb6d971 2815 err = remove_uuid(sk, hdev, cp, len);
2aeb9a1a 2816 break;
1aff6f09 2817 case MGMT_OP_SET_DEV_CLASS:
bdb6d971 2818 err = set_dev_class(sk, hdev, cp, len);
1aff6f09 2819 break;
86742e1e 2820 case MGMT_OP_LOAD_LINK_KEYS:
bdb6d971 2821 err = load_link_keys(sk, hdev, cp, len);
55ed8ca1 2822 break;
8962ee74 2823 case MGMT_OP_DISCONNECT:
bdb6d971 2824 err = disconnect(sk, hdev, cp, len);
8962ee74 2825 break;
2784eb41 2826 case MGMT_OP_GET_CONNECTIONS:
bdb6d971 2827 err = get_connections(sk, hdev);
2784eb41 2828 break;
980e1a53 2829 case MGMT_OP_PIN_CODE_REPLY:
bdb6d971 2830 err = pin_code_reply(sk, hdev, cp, len);
980e1a53
JH
2831 break;
2832 case MGMT_OP_PIN_CODE_NEG_REPLY:
bdb6d971 2833 err = pin_code_neg_reply(sk, hdev, cp, len);
980e1a53 2834 break;
17fa4b9d 2835 case MGMT_OP_SET_IO_CAPABILITY:
bdb6d971 2836 err = set_io_capability(sk, hdev, cp, len);
17fa4b9d 2837 break;
e9a416b5 2838 case MGMT_OP_PAIR_DEVICE:
bdb6d971 2839 err = pair_device(sk, hdev, cp, len);
e9a416b5 2840 break;
28424707 2841 case MGMT_OP_CANCEL_PAIR_DEVICE:
bdb6d971 2842 err = cancel_pair_device(sk, hdev, buf + sizeof(*hdr), len);
28424707 2843 break;
124f6e35 2844 case MGMT_OP_UNPAIR_DEVICE:
bdb6d971 2845 err = unpair_device(sk, hdev, cp, len);
124f6e35 2846 break;
a5c29683 2847 case MGMT_OP_USER_CONFIRM_REPLY:
bdb6d971 2848 err = user_confirm_reply(sk, hdev, cp, len);
a5c29683
JH
2849 break;
2850 case MGMT_OP_USER_CONFIRM_NEG_REPLY:
bdb6d971 2851 err = user_confirm_neg_reply(sk, hdev, cp, len);
a5c29683 2852 break;
604086b7 2853 case MGMT_OP_USER_PASSKEY_REPLY:
bdb6d971 2854 err = user_passkey_reply(sk, hdev, cp, len);
604086b7
BG
2855 break;
2856 case MGMT_OP_USER_PASSKEY_NEG_REPLY:
bdb6d971 2857 err = user_passkey_neg_reply(sk, hdev, cp, len);
a5c29683 2858 break;
b312b161 2859 case MGMT_OP_SET_LOCAL_NAME:
bdb6d971 2860 err = set_local_name(sk, hdev, cp, len);
b312b161 2861 break;
c35938b2 2862 case MGMT_OP_READ_LOCAL_OOB_DATA:
bdb6d971 2863 err = read_local_oob_data(sk, hdev);
c35938b2 2864 break;
2763eda6 2865 case MGMT_OP_ADD_REMOTE_OOB_DATA:
bdb6d971 2866 err = add_remote_oob_data(sk, hdev, cp, len);
2763eda6
SJ
2867 break;
2868 case MGMT_OP_REMOVE_REMOTE_OOB_DATA:
bdb6d971 2869 err = remove_remote_oob_data(sk, hdev, cp, len);
2763eda6 2870 break;
14a53664 2871 case MGMT_OP_START_DISCOVERY:
bdb6d971 2872 err = start_discovery(sk, hdev, cp, len);
14a53664
JH
2873 break;
2874 case MGMT_OP_STOP_DISCOVERY:
bdb6d971 2875 err = stop_discovery(sk, hdev, cp, len);
14a53664 2876 break;
561aafbc 2877 case MGMT_OP_CONFIRM_NAME:
bdb6d971 2878 err = confirm_name(sk, hdev, cp, len);
561aafbc 2879 break;
7fbec224 2880 case MGMT_OP_BLOCK_DEVICE:
bdb6d971 2881 err = block_device(sk, hdev, cp, len);
7fbec224
AJ
2882 break;
2883 case MGMT_OP_UNBLOCK_DEVICE:
bdb6d971 2884 err = unblock_device(sk, hdev, cp, len);
7fbec224 2885 break;
346af67b 2886 case MGMT_OP_LOAD_LONG_TERM_KEYS:
bdb6d971 2887 err = load_long_term_keys(sk, hdev, cp, len);
346af67b 2888 break;
0381101f
JH
2889 default:
2890 BT_DBG("Unknown op %u", opcode);
ca69b795
JH
2891 err = cmd_status(sk, index, opcode,
2892 MGMT_STATUS_UNKNOWN_COMMAND);
0381101f
JH
2893 break;
2894 }
2895
e41d8b4e
JH
2896 if (err < 0)
2897 goto done;
2898
0381101f
JH
2899 err = msglen;
2900
2901done:
bdb6d971
JH
2902 if (hdev)
2903 hci_dev_put(hdev);
2904
0381101f
JH
2905 kfree(buf);
2906 return err;
2907}
c71e97bf 2908
b24752fe
JH
2909static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
2910{
2911 u8 *status = data;
2912
2913 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
2914 mgmt_pending_remove(cmd);
2915}
2916
744cf19e 2917int mgmt_index_added(struct hci_dev *hdev)
c71e97bf 2918{
744cf19e 2919 return mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
c71e97bf
JH
2920}
2921
744cf19e 2922int mgmt_index_removed(struct hci_dev *hdev)
c71e97bf 2923{
b24752fe
JH
2924 u8 status = ENODEV;
2925
744cf19e 2926 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
b24752fe 2927
744cf19e 2928 return mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
eec8d2bc
JH
2929}
2930
73f22f62 2931struct cmd_lookup {
eec8d2bc 2932 struct sock *sk;
69ab39ea 2933 struct hci_dev *hdev;
90e70454 2934 u8 mgmt_status;
eec8d2bc
JH
2935};
2936
69ab39ea 2937static void settings_rsp(struct pending_cmd *cmd, void *data)
eec8d2bc 2938{
73f22f62 2939 struct cmd_lookup *match = data;
eec8d2bc 2940
69ab39ea 2941 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
eec8d2bc
JH
2942
2943 list_del(&cmd->list);
2944
2945 if (match->sk == NULL) {
2946 match->sk = cmd->sk;
2947 sock_hold(match->sk);
2948 }
2949
2950 mgmt_pending_free(cmd);
c71e97bf 2951}
5add6af8 2952
744cf19e 2953int mgmt_powered(struct hci_dev *hdev, u8 powered)
5add6af8 2954{
76a7f3a4 2955 struct cmd_lookup match = { NULL, hdev };
7bb895d6 2956 int err;
5add6af8 2957
5e5282bb
JH
2958 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
2959 return 0;
2960
69ab39ea 2961 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5add6af8 2962
5e5282bb
JH
2963 if (powered) {
2964 u8 scan = 0;
2965
2966 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
2967 scan |= SCAN_PAGE;
2968 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
2969 scan |= SCAN_INQUIRY;
2970
2971 if (scan)
2972 hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
504c8dcd
JH
2973
2974 update_class(hdev);
2975 update_eir(hdev);
5e5282bb 2976 } else {
b24752fe 2977 u8 status = ENETDOWN;
744cf19e 2978 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
b24752fe
JH
2979 }
2980
beadb2bd 2981 err = new_settings(hdev, match.sk);
eec8d2bc
JH
2982
2983 if (match.sk)
2984 sock_put(match.sk);
2985
7bb895d6 2986 return err;
5add6af8 2987}
73f22f62 2988
744cf19e 2989int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
73f22f62 2990{
76a7f3a4 2991 struct cmd_lookup match = { NULL, hdev };
5e5282bb
JH
2992 bool changed = false;
2993 int err = 0;
73f22f62 2994
5e5282bb
JH
2995 if (discoverable) {
2996 if (!test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
2997 changed = true;
2998 } else {
2999 if (test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
3000 changed = true;
3001 }
73f22f62 3002
ed9b5f2f
JH
3003 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev, settings_rsp,
3004 &match);
3005
beadb2bd
JH
3006 if (changed)
3007 err = new_settings(hdev, match.sk);
5e5282bb 3008
73f22f62
JH
3009 if (match.sk)
3010 sock_put(match.sk);
3011
7bb895d6 3012 return err;
73f22f62 3013}
9fbcbb45 3014
744cf19e 3015int mgmt_connectable(struct hci_dev *hdev, u8 connectable)
9fbcbb45 3016{
76a7f3a4 3017 struct cmd_lookup match = { NULL, hdev };
5e5282bb
JH
3018 bool changed = false;
3019 int err = 0;
9fbcbb45 3020
5e5282bb
JH
3021 if (connectable) {
3022 if (!test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags))
3023 changed = true;
3024 } else {
3025 if (test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags))
3026 changed = true;
3027 }
9fbcbb45 3028
ed9b5f2f
JH
3029 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev, settings_rsp,
3030 &match);
3031
beadb2bd
JH
3032 if (changed)
3033 err = new_settings(hdev, match.sk);
9fbcbb45
JH
3034
3035 if (match.sk)
3036 sock_put(match.sk);
3037
7bb895d6 3038 return err;
9fbcbb45 3039}
55ed8ca1 3040
744cf19e 3041int mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
2d7cee58 3042{
ca69b795
JH
3043 u8 mgmt_err = mgmt_status(status);
3044
2d7cee58 3045 if (scan & SCAN_PAGE)
744cf19e 3046 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
ca69b795 3047 cmd_status_rsp, &mgmt_err);
2d7cee58
JH
3048
3049 if (scan & SCAN_INQUIRY)
744cf19e 3050 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
ca69b795 3051 cmd_status_rsp, &mgmt_err);
2d7cee58
JH
3052
3053 return 0;
3054}
3055
744cf19e
JH
3056int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
3057 u8 persistent)
55ed8ca1 3058{
86742e1e 3059 struct mgmt_ev_new_link_key ev;
55ed8ca1 3060
a492cd52 3061 memset(&ev, 0, sizeof(ev));
55ed8ca1 3062
a492cd52 3063 ev.store_hint = persistent;
d753fdc4
JH
3064 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
3065 ev.key.addr.type = MGMT_ADDR_BREDR;
a492cd52
VCG
3066 ev.key.type = key->type;
3067 memcpy(ev.key.val, key->val, 16);
3068 ev.key.pin_len = key->pin_len;
55ed8ca1 3069
744cf19e 3070 return mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
55ed8ca1 3071}
f7520543 3072
346af67b
VCG
3073int mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent)
3074{
3075 struct mgmt_ev_new_long_term_key ev;
3076
3077 memset(&ev, 0, sizeof(ev));
3078
3079 ev.store_hint = persistent;
3080 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
3081 ev.key.addr.type = key->bdaddr_type;
3082 ev.key.authenticated = key->authenticated;
3083 ev.key.enc_size = key->enc_size;
3084 ev.key.ediv = key->ediv;
3085
3086 if (key->type == HCI_SMP_LTK)
3087 ev.key.master = 1;
3088
3089 memcpy(ev.key.rand, key->rand, sizeof(key->rand));
3090 memcpy(ev.key.val, key->val, sizeof(key->val));
3091
3092 return mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev,
3093 &ev, sizeof(ev), NULL);
3094}
3095
afc747a6 3096int mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
08c79b61
JH
3097 u8 addr_type, u32 flags, u8 *name,
3098 u8 name_len, u8 *dev_class)
f7520543 3099{
b644ba33
JH
3100 char buf[512];
3101 struct mgmt_ev_device_connected *ev = (void *) buf;
3102 u16 eir_len = 0;
f7520543 3103
b644ba33
JH
3104 bacpy(&ev->addr.bdaddr, bdaddr);
3105 ev->addr.type = link_to_mgmt(link_type, addr_type);
f7520543 3106
c95f0ba7 3107 ev->flags = __cpu_to_le32(flags);
08c79b61 3108
b644ba33
JH
3109 if (name_len > 0)
3110 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
3111 name, name_len);
3112
3113 if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
3114 eir_len = eir_append_data(&ev->eir[eir_len], eir_len,
3115 EIR_CLASS_OF_DEV, dev_class, 3);
3116
3117 put_unaligned_le16(eir_len, &ev->eir_len);
3118
3119 return mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
3120 sizeof(*ev) + eir_len, NULL);
f7520543
JH
3121}
3122
8962ee74
JH
3123static void disconnect_rsp(struct pending_cmd *cmd, void *data)
3124{
c68fb7ff 3125 struct mgmt_cp_disconnect *cp = cmd->param;
8962ee74 3126 struct sock **sk = data;
a38528f1 3127 struct mgmt_rp_disconnect rp;
8962ee74 3128
88c3df13
JH
3129 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3130 rp.addr.type = cp->addr.type;
8962ee74 3131
aee9b218
JH
3132 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
3133 sizeof(rp));
8962ee74
JH
3134
3135 *sk = cmd->sk;
3136 sock_hold(*sk);
3137
a664b5bc 3138 mgmt_pending_remove(cmd);
8962ee74
JH
3139}
3140
124f6e35 3141static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
a8a1d19e 3142{
b1078ad0 3143 struct hci_dev *hdev = data;
124f6e35
JH
3144 struct mgmt_cp_unpair_device *cp = cmd->param;
3145 struct mgmt_rp_unpair_device rp;
a8a1d19e
JH
3146
3147 memset(&rp, 0, sizeof(rp));
124f6e35
JH
3148 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3149 rp.addr.type = cp->addr.type;
a8a1d19e 3150
b1078ad0
JH
3151 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
3152
aee9b218 3153 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
a8a1d19e
JH
3154
3155 mgmt_pending_remove(cmd);
3156}
3157
afc747a6
JH
3158int mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
3159 u8 link_type, u8 addr_type)
f7520543 3160{
4c659c39 3161 struct mgmt_addr_info ev;
8962ee74
JH
3162 struct sock *sk = NULL;
3163 int err;
3164
744cf19e 3165 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
f7520543 3166
f7520543 3167 bacpy(&ev.bdaddr, bdaddr);
48264f06 3168 ev.type = link_to_mgmt(link_type, addr_type);
f7520543 3169
afc747a6
JH
3170 err = mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev),
3171 sk);
8962ee74
JH
3172
3173 if (sk)
3174 sock_put(sk);
3175
124f6e35 3176 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
b1078ad0 3177 hdev);
a8a1d19e 3178
8962ee74
JH
3179 return err;
3180}
3181
88c3df13
JH
3182int mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
3183 u8 link_type, u8 addr_type, u8 status)
8962ee74 3184{
88c3df13 3185 struct mgmt_rp_disconnect rp;
8962ee74
JH
3186 struct pending_cmd *cmd;
3187 int err;
3188
2e58ef3e 3189 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
8962ee74
JH
3190 if (!cmd)
3191 return -ENOENT;
3192
88c3df13
JH
3193 bacpy(&rp.addr.bdaddr, bdaddr);
3194 rp.addr.type = link_to_mgmt(link_type, addr_type);
37d9ef76 3195
88c3df13 3196 err = cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
aee9b218 3197 mgmt_status(status), &rp, sizeof(rp));
8962ee74 3198
a664b5bc 3199 mgmt_pending_remove(cmd);
8962ee74 3200
b1078ad0
JH
3201 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
3202 hdev);
8962ee74 3203 return err;
f7520543 3204}
17d5c04c 3205
48264f06
JH
3206int mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
3207 u8 addr_type, u8 status)
17d5c04c
JH
3208{
3209 struct mgmt_ev_connect_failed ev;
3210
4c659c39 3211 bacpy(&ev.addr.bdaddr, bdaddr);
48264f06 3212 ev.addr.type = link_to_mgmt(link_type, addr_type);
ca69b795 3213 ev.status = mgmt_status(status);
17d5c04c 3214
744cf19e 3215 return mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
17d5c04c 3216}
980e1a53 3217
744cf19e 3218int mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
980e1a53
JH
3219{
3220 struct mgmt_ev_pin_code_request ev;
3221
d8457698
JH
3222 bacpy(&ev.addr.bdaddr, bdaddr);
3223 ev.addr.type = MGMT_ADDR_BREDR;
a770bb5a 3224 ev.secure = secure;
980e1a53 3225
744cf19e 3226 return mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev),
4e51eae9 3227 NULL);
980e1a53
JH
3228}
3229
744cf19e
JH
3230int mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
3231 u8 status)
980e1a53
JH
3232{
3233 struct pending_cmd *cmd;
ac56fb13 3234 struct mgmt_rp_pin_code_reply rp;
980e1a53
JH
3235 int err;
3236
2e58ef3e 3237 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
980e1a53
JH
3238 if (!cmd)
3239 return -ENOENT;
3240
d8457698
JH
3241 bacpy(&rp.addr.bdaddr, bdaddr);
3242 rp.addr.type = MGMT_ADDR_BREDR;
ac56fb13 3243
aee9b218
JH
3244 err = cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3245 mgmt_status(status), &rp, sizeof(rp));
980e1a53 3246
a664b5bc 3247 mgmt_pending_remove(cmd);
980e1a53
JH
3248
3249 return err;
3250}
3251
744cf19e
JH
3252int mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
3253 u8 status)
980e1a53
JH
3254{
3255 struct pending_cmd *cmd;
ac56fb13 3256 struct mgmt_rp_pin_code_reply rp;
980e1a53
JH
3257 int err;
3258
2e58ef3e 3259 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
980e1a53
JH
3260 if (!cmd)
3261 return -ENOENT;
3262
d8457698
JH
3263 bacpy(&rp.addr.bdaddr, bdaddr);
3264 rp.addr.type = MGMT_ADDR_BREDR;
ac56fb13 3265
aee9b218
JH
3266 err = cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
3267 mgmt_status(status), &rp, sizeof(rp));
980e1a53 3268
a664b5bc 3269 mgmt_pending_remove(cmd);
980e1a53
JH
3270
3271 return err;
3272}
a5c29683 3273
744cf19e 3274int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
272d90df
JH
3275 u8 link_type, u8 addr_type, __le32 value,
3276 u8 confirm_hint)
a5c29683
JH
3277{
3278 struct mgmt_ev_user_confirm_request ev;
3279
744cf19e 3280 BT_DBG("%s", hdev->name);
a5c29683 3281
272d90df
JH
3282 bacpy(&ev.addr.bdaddr, bdaddr);
3283 ev.addr.type = link_to_mgmt(link_type, addr_type);
55bc1a37 3284 ev.confirm_hint = confirm_hint;
a5c29683
JH
3285 put_unaligned_le32(value, &ev.value);
3286
744cf19e 3287 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
4e51eae9 3288 NULL);
a5c29683
JH
3289}
3290
272d90df
JH
3291int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
3292 u8 link_type, u8 addr_type)
604086b7
BG
3293{
3294 struct mgmt_ev_user_passkey_request ev;
3295
3296 BT_DBG("%s", hdev->name);
3297
272d90df
JH
3298 bacpy(&ev.addr.bdaddr, bdaddr);
3299 ev.addr.type = link_to_mgmt(link_type, addr_type);
604086b7
BG
3300
3301 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
3302 NULL);
3303}
3304
0df4c185 3305static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
272d90df
JH
3306 u8 link_type, u8 addr_type, u8 status,
3307 u8 opcode)
a5c29683
JH
3308{
3309 struct pending_cmd *cmd;
3310 struct mgmt_rp_user_confirm_reply rp;
3311 int err;
3312
2e58ef3e 3313 cmd = mgmt_pending_find(opcode, hdev);
a5c29683
JH
3314 if (!cmd)
3315 return -ENOENT;
3316
272d90df
JH
3317 bacpy(&rp.addr.bdaddr, bdaddr);
3318 rp.addr.type = link_to_mgmt(link_type, addr_type);
aee9b218
JH
3319 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
3320 &rp, sizeof(rp));
a5c29683 3321
a664b5bc 3322 mgmt_pending_remove(cmd);
a5c29683
JH
3323
3324 return err;
3325}
3326
744cf19e 3327int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
272d90df 3328 u8 link_type, u8 addr_type, u8 status)
a5c29683 3329{
272d90df
JH
3330 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
3331 status, MGMT_OP_USER_CONFIRM_REPLY);
a5c29683
JH
3332}
3333
272d90df
JH
3334int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
3335 u8 link_type, u8 addr_type, u8 status)
a5c29683 3336{
272d90df
JH
3337 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
3338 status, MGMT_OP_USER_CONFIRM_NEG_REPLY);
a5c29683 3339}
2a611692 3340
604086b7 3341int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
272d90df 3342 u8 link_type, u8 addr_type, u8 status)
604086b7 3343{
272d90df
JH
3344 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
3345 status, MGMT_OP_USER_PASSKEY_REPLY);
604086b7
BG
3346}
3347
272d90df
JH
3348int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
3349 u8 link_type, u8 addr_type, u8 status)
604086b7 3350{
272d90df
JH
3351 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
3352 status, MGMT_OP_USER_PASSKEY_NEG_REPLY);
604086b7
BG
3353}
3354
bab73cb6
JH
3355int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
3356 u8 addr_type, u8 status)
2a611692
JH
3357{
3358 struct mgmt_ev_auth_failed ev;
3359
bab73cb6
JH
3360 bacpy(&ev.addr.bdaddr, bdaddr);
3361 ev.addr.type = link_to_mgmt(link_type, addr_type);
ca69b795 3362 ev.status = mgmt_status(status);
2a611692 3363
744cf19e 3364 return mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
2a611692 3365}
b312b161 3366
33ef95ed
JH
3367int mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
3368{
3369 struct cmd_lookup match = { NULL, hdev };
47990ea0
JH
3370 bool changed = false;
3371 int err = 0;
33ef95ed
JH
3372
3373 if (status) {
3374 u8 mgmt_err = mgmt_status(status);
3375 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
3376 cmd_status_rsp, &mgmt_err);
3377 return 0;
3378 }
3379
47990ea0
JH
3380 if (test_bit(HCI_AUTH, &hdev->flags)) {
3381 if (!test_and_set_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
3382 changed = true;
3383 } else {
3384 if (test_and_clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
3385 changed = true;
3386 }
3387
33ef95ed
JH
3388 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
3389 &match);
3390
47990ea0
JH
3391 if (changed)
3392 err = new_settings(hdev, match.sk);
33ef95ed
JH
3393
3394 if (match.sk)
3395 sock_put(match.sk);
3396
3397 return err;
3398}
3399
cacaf52f
JH
3400static int clear_eir(struct hci_dev *hdev)
3401{
3402 struct hci_cp_write_eir cp;
3403
3404 if (!(hdev->features[6] & LMP_EXT_INQ))
3405 return 0;
3406
c80da27e
JH
3407 memset(hdev->eir, 0, sizeof(hdev->eir));
3408
cacaf52f
JH
3409 memset(&cp, 0, sizeof(cp));
3410
3411 return hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
3412}
3413
c0ecddc2 3414int mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
ed2c4ee3
JH
3415{
3416 struct cmd_lookup match = { NULL, hdev };
c0ecddc2
JH
3417 bool changed = false;
3418 int err = 0;
ed2c4ee3
JH
3419
3420 if (status) {
3421 u8 mgmt_err = mgmt_status(status);
c0ecddc2
JH
3422
3423 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
3424 &hdev->dev_flags))
3425 err = new_settings(hdev, NULL);
3426
ed2c4ee3
JH
3427 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev,
3428 cmd_status_rsp, &mgmt_err);
c0ecddc2
JH
3429
3430 return err;
3431 }
3432
3433 if (enable) {
3434 if (!test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
3435 changed = true;
3436 } else {
3437 if (test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
3438 changed = true;
ed2c4ee3
JH
3439 }
3440
3441 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
3442
c0ecddc2
JH
3443 if (changed)
3444 err = new_settings(hdev, match.sk);
ed2c4ee3 3445
5fc6ebb1 3446 if (match.sk)
ed2c4ee3
JH
3447 sock_put(match.sk);
3448
5fc6ebb1
JH
3449 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
3450 update_eir(hdev);
3451 else
3452 clear_eir(hdev);
cacaf52f 3453
ed2c4ee3
JH
3454 return err;
3455}
3456
90e70454
JH
3457static void class_rsp(struct pending_cmd *cmd, void *data)
3458{
3459 struct cmd_lookup *match = data;
3460
3461 cmd_complete(cmd->sk, cmd->index, cmd->opcode, match->mgmt_status,
3462 match->hdev->dev_class, 3);
3463
3464 list_del(&cmd->list);
3465
3466 if (match->sk == NULL) {
3467 match->sk = cmd->sk;
3468 sock_hold(match->sk);
3469 }
3470
3471 mgmt_pending_free(cmd);
3472}
3473
7f9a903c
MH
3474int mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
3475 u8 status)
3476{
90e70454
JH
3477 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
3478 int err = 0;
7f9a903c 3479
c95f0ba7
JH
3480 clear_bit(HCI_PENDING_CLASS, &hdev->dev_flags);
3481
90e70454
JH
3482 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, class_rsp, &match);
3483 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, class_rsp, &match);
3484 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, class_rsp, &match);
3485
3486 if (!status)
3487 err = mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
3488 dev_class, 3, NULL);
3489
3490 if (match.sk)
3491 sock_put(match.sk);
7f9a903c
MH
3492
3493 return err;
3494}
3495
744cf19e 3496int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
b312b161
JH
3497{
3498 struct pending_cmd *cmd;
3499 struct mgmt_cp_set_local_name ev;
28cc7bde
JH
3500 bool changed = false;
3501 int err = 0;
3502
3503 if (memcmp(name, hdev->dev_name, sizeof(hdev->dev_name)) != 0) {
3504 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
3505 changed = true;
3506 }
b312b161
JH
3507
3508 memset(&ev, 0, sizeof(ev));
3509 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
28cc7bde 3510 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
b312b161 3511
2e58ef3e 3512 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
b312b161
JH
3513 if (!cmd)
3514 goto send_event;
3515
7bdaae4a
JH
3516 /* Always assume that either the short or the complete name has
3517 * changed if there was a pending mgmt command */
3518 changed = true;
3519
b312b161 3520 if (status) {
744cf19e 3521 err = cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
ca69b795 3522 mgmt_status(status));
b312b161
JH
3523 goto failed;
3524 }
3525
aee9b218 3526 err = cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0, &ev,
b312b161
JH
3527 sizeof(ev));
3528 if (err < 0)
3529 goto failed;
3530
3531send_event:
28cc7bde
JH
3532 if (changed)
3533 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev,
3534 sizeof(ev), cmd ? cmd->sk : NULL);
3535
f51d5b24 3536 update_eir(hdev);
b312b161
JH
3537
3538failed:
3539 if (cmd)
3540 mgmt_pending_remove(cmd);
3541 return err;
3542}
c35938b2 3543
744cf19e
JH
3544int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash,
3545 u8 *randomizer, u8 status)
c35938b2
SJ
3546{
3547 struct pending_cmd *cmd;
3548 int err;
3549
744cf19e 3550 BT_DBG("%s status %u", hdev->name, status);
c35938b2 3551
2e58ef3e 3552 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
c35938b2
SJ
3553 if (!cmd)
3554 return -ENOENT;
3555
3556 if (status) {
744cf19e 3557 err = cmd_status(cmd->sk, hdev->id,
ca69b795
JH
3558 MGMT_OP_READ_LOCAL_OOB_DATA,
3559 mgmt_status(status));
c35938b2
SJ
3560 } else {
3561 struct mgmt_rp_read_local_oob_data rp;
3562
3563 memcpy(rp.hash, hash, sizeof(rp.hash));
3564 memcpy(rp.randomizer, randomizer, sizeof(rp.randomizer));
3565
744cf19e
JH
3566 err = cmd_complete(cmd->sk, hdev->id,
3567 MGMT_OP_READ_LOCAL_OOB_DATA,
aee9b218 3568 0, &rp, sizeof(rp));
c35938b2
SJ
3569 }
3570
3571 mgmt_pending_remove(cmd);
3572
3573 return err;
3574}
e17acd40 3575
06199cf8
JH
3576int mgmt_le_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
3577{
3578 struct cmd_lookup match = { NULL, hdev };
3579 bool changed = false;
3580 int err = 0;
3581
3582 if (status) {
3583 u8 mgmt_err = mgmt_status(status);
3584
3585 if (enable && test_and_clear_bit(HCI_LE_ENABLED,
3586 &hdev->dev_flags))
3587 err = new_settings(hdev, NULL);
3588
3589 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev,
3590 cmd_status_rsp, &mgmt_err);
3591
3592 return err;
3593 }
3594
3595 if (enable) {
3596 if (!test_and_set_bit(HCI_LE_ENABLED, &hdev->dev_flags))
3597 changed = true;
3598 } else {
3599 if (test_and_clear_bit(HCI_LE_ENABLED, &hdev->dev_flags))
3600 changed = true;
3601 }
3602
3603 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
3604
3605 if (changed)
3606 err = new_settings(hdev, match.sk);
3607
3608 if (match.sk)
3609 sock_put(match.sk);
3610
3611 return err;
3612}
3613
48264f06 3614int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
561aafbc 3615 u8 addr_type, u8 *dev_class, s8 rssi,
388fc8fa 3616 u8 cfm_name, u8 ssp, u8 *eir, u16 eir_len)
e17acd40 3617{
e319d2e7
JH
3618 char buf[512];
3619 struct mgmt_ev_device_found *ev = (void *) buf;
1dc06093 3620 size_t ev_size;
e17acd40 3621
1dc06093
JH
3622 /* Leave 5 bytes for a potential CoD field */
3623 if (sizeof(*ev) + eir_len + 5 > sizeof(buf))
7d262f86
AG
3624 return -EINVAL;
3625
1dc06093
JH
3626 memset(buf, 0, sizeof(buf));
3627
e319d2e7
JH
3628 bacpy(&ev->addr.bdaddr, bdaddr);
3629 ev->addr.type = link_to_mgmt(link_type, addr_type);
3630 ev->rssi = rssi;
9a395a80
JH
3631 if (cfm_name)
3632 ev->flags[0] |= MGMT_DEV_FOUND_CONFIRM_NAME;
388fc8fa
JH
3633 if (!ssp)
3634 ev->flags[0] |= MGMT_DEV_FOUND_LEGACY_PAIRING;
e17acd40 3635
1dc06093 3636 if (eir_len > 0)
e319d2e7 3637 memcpy(ev->eir, eir, eir_len);
e17acd40 3638
1dc06093
JH
3639 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
3640 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
3641 dev_class, 3);
3642
3643 put_unaligned_le16(eir_len, &ev->eir_len);
3644
3645 ev_size = sizeof(*ev) + eir_len;
f8523598 3646
e319d2e7 3647 return mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
e17acd40 3648}
a88a9652 3649
b644ba33
JH
3650int mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
3651 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
a88a9652 3652{
b644ba33
JH
3653 struct mgmt_ev_device_found *ev;
3654 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
3655 u16 eir_len;
a88a9652 3656
b644ba33 3657 ev = (struct mgmt_ev_device_found *) buf;
a88a9652 3658
b644ba33
JH
3659 memset(buf, 0, sizeof(buf));
3660
3661 bacpy(&ev->addr.bdaddr, bdaddr);
3662 ev->addr.type = link_to_mgmt(link_type, addr_type);
3663 ev->rssi = rssi;
3664
3665 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
3666 name_len);
3667
3668 put_unaligned_le16(eir_len, &ev->eir_len);
a88a9652 3669
053c7e0c
JH
3670 return mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev,
3671 sizeof(*ev) + eir_len, NULL);
a88a9652 3672}
314b2381 3673
7a135109 3674int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
164a6e78
JH
3675{
3676 struct pending_cmd *cmd;
f808e166 3677 u8 type;
164a6e78
JH
3678 int err;
3679
203159d4
AG
3680 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3681
2e58ef3e 3682 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
164a6e78
JH
3683 if (!cmd)
3684 return -ENOENT;
3685
f808e166
JH
3686 type = hdev->discovery.type;
3687
3688 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3689 &type, sizeof(type));
164a6e78
JH
3690 mgmt_pending_remove(cmd);
3691
3692 return err;
3693}
3694
e6d465cb
AG
3695int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
3696{
3697 struct pending_cmd *cmd;
3698 int err;
3699
3700 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
3701 if (!cmd)
3702 return -ENOENT;
3703
d930650b
JH
3704 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3705 &hdev->discovery.type,
3706 sizeof(hdev->discovery.type));
164a6e78
JH
3707 mgmt_pending_remove(cmd);
3708
3709 return err;
3710}
3711
744cf19e 3712int mgmt_discovering(struct hci_dev *hdev, u8 discovering)
314b2381 3713{
f963e8e9 3714 struct mgmt_ev_discovering ev;
164a6e78
JH
3715 struct pending_cmd *cmd;
3716
343fb145
AG
3717 BT_DBG("%s discovering %u", hdev->name, discovering);
3718
164a6e78 3719 if (discovering)
2e58ef3e 3720 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
164a6e78 3721 else
2e58ef3e 3722 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
164a6e78
JH
3723
3724 if (cmd != NULL) {
f808e166
JH
3725 u8 type = hdev->discovery.type;
3726
d930650b 3727 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0,
f808e166 3728 &type, sizeof(type));
164a6e78
JH
3729 mgmt_pending_remove(cmd);
3730 }
3731
f963e8e9
JH
3732 memset(&ev, 0, sizeof(ev));
3733 ev.type = hdev->discovery.type;
3734 ev.discovering = discovering;
3735
3736 return mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
314b2381 3737}
5e762444 3738
88c1fe4b 3739int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
5e762444
AJ
3740{
3741 struct pending_cmd *cmd;
3742 struct mgmt_ev_device_blocked ev;
3743
2e58ef3e 3744 cmd = mgmt_pending_find(MGMT_OP_BLOCK_DEVICE, hdev);
5e762444 3745
88c1fe4b
JH
3746 bacpy(&ev.addr.bdaddr, bdaddr);
3747 ev.addr.type = type;
5e762444 3748
744cf19e
JH
3749 return mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &ev, sizeof(ev),
3750 cmd ? cmd->sk : NULL);
5e762444
AJ
3751}
3752
88c1fe4b 3753int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
5e762444
AJ
3754{
3755 struct pending_cmd *cmd;
3756 struct mgmt_ev_device_unblocked ev;
3757
2e58ef3e 3758 cmd = mgmt_pending_find(MGMT_OP_UNBLOCK_DEVICE, hdev);
5e762444 3759
88c1fe4b
JH
3760 bacpy(&ev.addr.bdaddr, bdaddr);
3761 ev.addr.type = type;
5e762444 3762
744cf19e
JH
3763 return mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &ev, sizeof(ev),
3764 cmd ? cmd->sk : NULL);
5e762444 3765}
d7b7e796
MH
3766
3767module_param(enable_hs, bool, 0644);
3768MODULE_PARM_DESC(enable_hs, "Enable High Speed support");
3769
3770module_param(enable_le, bool, 0644);
3771MODULE_PARM_DESC(enable_le, "Enable Low Energy support");
This page took 0.346061 seconds and 5 git commands to generate.