Bluetooth: Update ordering and opcodes of mgmt messages
[deliverable/linux.git] / net / bluetooth / mgmt.c
CommitLineData
0381101f
JH
1/*
2 BlueZ - Bluetooth protocol stack for Linux
3 Copyright (C) 2010 Nokia Corporation
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License version 2 as
7 published by the Free Software Foundation;
8
9 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
10 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
11 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
12 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
13 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
18 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
19 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
20 SOFTWARE IS DISCLAIMED.
21*/
22
23/* Bluetooth HCI Management interface */
24
ca69b795 25#include <linux/kernel.h>
72359753 26#include <linux/uaccess.h>
0381101f
JH
27#include <asm/unaligned.h>
28
29#include <net/bluetooth/bluetooth.h>
30#include <net/bluetooth/hci_core.h>
31#include <net/bluetooth/mgmt.h>
32
02d98129
JH
33#define MGMT_VERSION 0
34#define MGMT_REVISION 1
35
2519a1fc
AG
36#define INQUIRY_LEN_BREDR 0x08 /* TGAP(100) */
37
7d78525d
JH
38#define SERVICE_CACHE_TIMEOUT (5 * 1000)
39
eec8d2bc
JH
40struct pending_cmd {
41 struct list_head list;
fc2f4b13 42 u16 opcode;
eec8d2bc 43 int index;
c68fb7ff 44 void *param;
eec8d2bc 45 struct sock *sk;
e9a416b5 46 void *user_data;
eec8d2bc
JH
47};
48
ca69b795
JH
49/* HCI to MGMT error code conversion table */
50static u8 mgmt_status_table[] = {
51 MGMT_STATUS_SUCCESS,
52 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
53 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
54 MGMT_STATUS_FAILED, /* Hardware Failure */
55 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
56 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
57 MGMT_STATUS_NOT_PAIRED, /* PIN or Key Missing */
58 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
59 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
60 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
61 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
62 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
63 MGMT_STATUS_BUSY, /* Command Disallowed */
64 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
65 MGMT_STATUS_REJECTED, /* Rejected Security */
66 MGMT_STATUS_REJECTED, /* Rejected Personal */
67 MGMT_STATUS_TIMEOUT, /* Host Timeout */
68 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
69 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
70 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
71 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
72 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
73 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
74 MGMT_STATUS_BUSY, /* Repeated Attempts */
75 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
76 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
77 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
78 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
79 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
80 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
81 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
82 MGMT_STATUS_FAILED, /* Unspecified Error */
83 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
84 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
85 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
86 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
87 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
88 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
89 MGMT_STATUS_FAILED, /* Unit Link Key Used */
90 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
91 MGMT_STATUS_TIMEOUT, /* Instant Passed */
92 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
93 MGMT_STATUS_FAILED, /* Transaction Collision */
94 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
95 MGMT_STATUS_REJECTED, /* QoS Rejected */
96 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
97 MGMT_STATUS_REJECTED, /* Insufficient Security */
98 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
99 MGMT_STATUS_BUSY, /* Role Switch Pending */
100 MGMT_STATUS_FAILED, /* Slot Violation */
101 MGMT_STATUS_FAILED, /* Role Switch Failed */
102 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
103 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
104 MGMT_STATUS_BUSY, /* Host Busy Pairing */
105 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
106 MGMT_STATUS_BUSY, /* Controller Busy */
107 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
108 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
109 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
110 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
111 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
112};
113
114static u8 mgmt_status(u8 hci_status)
115{
116 if (hci_status < ARRAY_SIZE(mgmt_status_table))
117 return mgmt_status_table[hci_status];
118
119 return MGMT_STATUS_FAILED;
120}
121
4e51eae9 122static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
f7b64e69
JH
123{
124 struct sk_buff *skb;
125 struct mgmt_hdr *hdr;
126 struct mgmt_ev_cmd_status *ev;
56b7d137 127 int err;
f7b64e69 128
34eb525c 129 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
f7b64e69
JH
130
131 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_ATOMIC);
132 if (!skb)
133 return -ENOMEM;
134
135 hdr = (void *) skb_put(skb, sizeof(*hdr));
136
137 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
4e51eae9 138 hdr->index = cpu_to_le16(index);
f7b64e69
JH
139 hdr->len = cpu_to_le16(sizeof(*ev));
140
141 ev = (void *) skb_put(skb, sizeof(*ev));
142 ev->status = status;
143 put_unaligned_le16(cmd, &ev->opcode);
144
56b7d137
GP
145 err = sock_queue_rcv_skb(sk, skb);
146 if (err < 0)
f7b64e69
JH
147 kfree_skb(skb);
148
56b7d137 149 return err;
f7b64e69
JH
150}
151
4e51eae9
SJ
152static int cmd_complete(struct sock *sk, u16 index, u16 cmd, void *rp,
153 size_t rp_len)
02d98129
JH
154{
155 struct sk_buff *skb;
156 struct mgmt_hdr *hdr;
157 struct mgmt_ev_cmd_complete *ev;
56b7d137 158 int err;
02d98129
JH
159
160 BT_DBG("sock %p", sk);
161
a38528f1 162 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_ATOMIC);
02d98129
JH
163 if (!skb)
164 return -ENOMEM;
165
166 hdr = (void *) skb_put(skb, sizeof(*hdr));
02d98129 167
a38528f1 168 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
4e51eae9 169 hdr->index = cpu_to_le16(index);
a38528f1 170 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
02d98129 171
a38528f1
JH
172 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
173 put_unaligned_le16(cmd, &ev->opcode);
8020c16a
SJ
174
175 if (rp)
176 memcpy(ev->data, rp, rp_len);
02d98129 177
56b7d137
GP
178 err = sock_queue_rcv_skb(sk, skb);
179 if (err < 0)
02d98129
JH
180 kfree_skb(skb);
181
56b7d137 182 return err;;
02d98129
JH
183}
184
a38528f1
JH
185static int read_version(struct sock *sk)
186{
187 struct mgmt_rp_read_version rp;
188
189 BT_DBG("sock %p", sk);
190
191 rp.version = MGMT_VERSION;
192 put_unaligned_le16(MGMT_REVISION, &rp.revision);
193
4e51eae9
SJ
194 return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, &rp,
195 sizeof(rp));
a38528f1
JH
196}
197
faba42eb
JH
198static int read_index_list(struct sock *sk)
199{
faba42eb
JH
200 struct mgmt_rp_read_index_list *rp;
201 struct list_head *p;
8035ded4 202 struct hci_dev *d;
a38528f1 203 size_t rp_len;
faba42eb 204 u16 count;
a38528f1 205 int i, err;
faba42eb
JH
206
207 BT_DBG("sock %p", sk);
208
209 read_lock(&hci_dev_list_lock);
210
211 count = 0;
212 list_for_each(p, &hci_dev_list) {
213 count++;
214 }
215
a38528f1
JH
216 rp_len = sizeof(*rp) + (2 * count);
217 rp = kmalloc(rp_len, GFP_ATOMIC);
218 if (!rp) {
b2c60d42 219 read_unlock(&hci_dev_list_lock);
faba42eb 220 return -ENOMEM;
b2c60d42 221 }
faba42eb 222
faba42eb
JH
223 put_unaligned_le16(count, &rp->num_controllers);
224
225 i = 0;
8035ded4 226 list_for_each_entry(d, &hci_dev_list, list) {
3243553f 227 if (test_and_clear_bit(HCI_AUTO_OFF, &d->flags))
e0f9309f 228 cancel_delayed_work(&d->power_off);
ab81cbf9
JH
229
230 if (test_bit(HCI_SETUP, &d->flags))
231 continue;
232
faba42eb
JH
233 put_unaligned_le16(d->id, &rp->index[i++]);
234 BT_DBG("Added hci%u", d->id);
235 }
236
237 read_unlock(&hci_dev_list_lock);
238
4e51eae9
SJ
239 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, rp,
240 rp_len);
faba42eb 241
a38528f1
JH
242 kfree(rp);
243
244 return err;
faba42eb
JH
245}
246
69ab39ea
JH
247static u32 get_supported_settings(struct hci_dev *hdev)
248{
249 u32 settings = 0;
250
251 settings |= MGMT_SETTING_POWERED;
252 settings |= MGMT_SETTING_CONNECTABLE;
253 settings |= MGMT_SETTING_FAST_CONNECTABLE;
254 settings |= MGMT_SETTING_DISCOVERABLE;
255 settings |= MGMT_SETTING_PAIRABLE;
256
257 if (hdev->features[6] & LMP_SIMPLE_PAIR)
258 settings |= MGMT_SETTING_SSP;
259
260 if (!(hdev->features[4] & LMP_NO_BREDR)) {
261 settings |= MGMT_SETTING_BREDR;
262 settings |= MGMT_SETTING_LINK_SECURITY;
263 }
264
265 if (hdev->features[4] & LMP_LE)
266 settings |= MGMT_SETTING_LE;
267
268 return settings;
269}
270
271static u32 get_current_settings(struct hci_dev *hdev)
272{
273 u32 settings = 0;
274
275 if (test_bit(HCI_UP, &hdev->flags))
276 settings |= MGMT_SETTING_POWERED;
277 else
278 return settings;
279
280 if (test_bit(HCI_PSCAN, &hdev->flags))
281 settings |= MGMT_SETTING_CONNECTABLE;
282
283 if (test_bit(HCI_ISCAN, &hdev->flags))
284 settings |= MGMT_SETTING_DISCOVERABLE;
285
286 if (test_bit(HCI_PAIRABLE, &hdev->flags))
287 settings |= MGMT_SETTING_PAIRABLE;
288
289 if (!(hdev->features[4] & LMP_NO_BREDR))
290 settings |= MGMT_SETTING_BREDR;
291
292 if (hdev->extfeatures[0] & LMP_HOST_LE)
293 settings |= MGMT_SETTING_LE;
294
295 if (test_bit(HCI_AUTH, &hdev->flags))
296 settings |= MGMT_SETTING_LINK_SECURITY;
297
298 if (hdev->ssp_mode > 0)
299 settings |= MGMT_SETTING_SSP;
300
301 return settings;
302}
303
ef580372
JH
304#define EIR_FLAGS 0x01 /* flags */
305#define EIR_UUID16_SOME 0x02 /* 16-bit UUID, more available */
306#define EIR_UUID16_ALL 0x03 /* 16-bit UUID, all listed */
307#define EIR_UUID32_SOME 0x04 /* 32-bit UUID, more available */
308#define EIR_UUID32_ALL 0x05 /* 32-bit UUID, all listed */
309#define EIR_UUID128_SOME 0x06 /* 128-bit UUID, more available */
310#define EIR_UUID128_ALL 0x07 /* 128-bit UUID, all listed */
311#define EIR_NAME_SHORT 0x08 /* shortened local name */
312#define EIR_NAME_COMPLETE 0x09 /* complete local name */
313#define EIR_TX_POWER 0x0A /* transmit power level */
314#define EIR_DEVICE_ID 0x10 /* device ID */
315
316#define PNP_INFO_SVCLASS_ID 0x1200
317
318static u8 bluetooth_base_uuid[] = {
319 0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
320 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
321};
322
323static u16 get_uuid16(u8 *uuid128)
324{
325 u32 val;
326 int i;
327
328 for (i = 0; i < 12; i++) {
329 if (bluetooth_base_uuid[i] != uuid128[i])
330 return 0;
331 }
332
333 memcpy(&val, &uuid128[12], 4);
334
335 val = le32_to_cpu(val);
336 if (val > 0xffff)
337 return 0;
338
339 return (u16) val;
340}
341
342static void create_eir(struct hci_dev *hdev, u8 *data)
343{
344 u8 *ptr = data;
345 u16 eir_len = 0;
346 u16 uuid16_list[HCI_MAX_EIR_LENGTH / sizeof(u16)];
347 int i, truncated = 0;
348 struct bt_uuid *uuid;
349 size_t name_len;
350
351 name_len = strlen(hdev->dev_name);
352
353 if (name_len > 0) {
354 /* EIR Data type */
355 if (name_len > 48) {
356 name_len = 48;
357 ptr[1] = EIR_NAME_SHORT;
358 } else
359 ptr[1] = EIR_NAME_COMPLETE;
360
361 /* EIR Data length */
362 ptr[0] = name_len + 1;
363
364 memcpy(ptr + 2, hdev->dev_name, name_len);
365
366 eir_len += (name_len + 2);
367 ptr += (name_len + 2);
368 }
369
370 memset(uuid16_list, 0, sizeof(uuid16_list));
371
372 /* Group all UUID16 types */
373 list_for_each_entry(uuid, &hdev->uuids, list) {
374 u16 uuid16;
375
376 uuid16 = get_uuid16(uuid->uuid);
377 if (uuid16 == 0)
378 return;
379
380 if (uuid16 < 0x1100)
381 continue;
382
383 if (uuid16 == PNP_INFO_SVCLASS_ID)
384 continue;
385
386 /* Stop if not enough space to put next UUID */
387 if (eir_len + 2 + sizeof(u16) > HCI_MAX_EIR_LENGTH) {
388 truncated = 1;
389 break;
390 }
391
392 /* Check for duplicates */
393 for (i = 0; uuid16_list[i] != 0; i++)
394 if (uuid16_list[i] == uuid16)
395 break;
396
397 if (uuid16_list[i] == 0) {
398 uuid16_list[i] = uuid16;
399 eir_len += sizeof(u16);
400 }
401 }
402
403 if (uuid16_list[0] != 0) {
404 u8 *length = ptr;
405
406 /* EIR Data type */
407 ptr[1] = truncated ? EIR_UUID16_SOME : EIR_UUID16_ALL;
408
409 ptr += 2;
410 eir_len += 2;
411
412 for (i = 0; uuid16_list[i] != 0; i++) {
413 *ptr++ = (uuid16_list[i] & 0x00ff);
414 *ptr++ = (uuid16_list[i] & 0xff00) >> 8;
415 }
416
417 /* EIR Data length */
418 *length = (i * sizeof(u16)) + 1;
419 }
420}
421
422static int update_eir(struct hci_dev *hdev)
423{
424 struct hci_cp_write_eir cp;
425
426 if (!(hdev->features[6] & LMP_EXT_INQ))
427 return 0;
428
429 if (hdev->ssp_mode == 0)
430 return 0;
431
432 if (test_bit(HCI_SERVICE_CACHE, &hdev->flags))
433 return 0;
434
435 memset(&cp, 0, sizeof(cp));
436
437 create_eir(hdev, cp.data);
438
439 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
440 return 0;
441
442 memcpy(hdev->eir, cp.data, sizeof(cp.data));
443
444 return hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
445}
446
447static u8 get_service_classes(struct hci_dev *hdev)
448{
449 struct bt_uuid *uuid;
450 u8 val = 0;
451
452 list_for_each_entry(uuid, &hdev->uuids, list)
453 val |= uuid->svc_hint;
454
455 return val;
456}
457
458static int update_class(struct hci_dev *hdev)
459{
460 u8 cod[3];
461
462 BT_DBG("%s", hdev->name);
463
464 if (test_bit(HCI_SERVICE_CACHE, &hdev->flags))
465 return 0;
466
467 cod[0] = hdev->minor_class;
468 cod[1] = hdev->major_class;
469 cod[2] = get_service_classes(hdev);
470
471 if (memcmp(cod, hdev->dev_class, 3) == 0)
472 return 0;
473
474 return hci_send_cmd(hdev, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
475}
476
7d78525d
JH
477static void service_cache_off(struct work_struct *work)
478{
479 struct hci_dev *hdev = container_of(work, struct hci_dev,
480 service_cache.work);
481
482 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->flags))
483 return;
484
485 hci_dev_lock(hdev);
486
487 update_eir(hdev);
488 update_class(hdev);
489
490 hci_dev_unlock(hdev);
491}
492
493static void mgmt_init_hdev(struct hci_dev *hdev)
494{
495 if (!test_and_set_bit(HCI_MGMT, &hdev->flags))
496 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
497
498 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->flags))
499 schedule_delayed_work(&hdev->service_cache,
500 msecs_to_jiffies(SERVICE_CACHE_TIMEOUT));
501}
502
4e51eae9 503static int read_controller_info(struct sock *sk, u16 index)
0381101f 504{
a38528f1 505 struct mgmt_rp_read_info rp;
f7b64e69 506 struct hci_dev *hdev;
0381101f 507
4e51eae9 508 BT_DBG("sock %p hci%u", sk, index);
f7b64e69 509
4e51eae9 510 hdev = hci_dev_get(index);
a38528f1 511 if (!hdev)
ca69b795
JH
512 return cmd_status(sk, index, MGMT_OP_READ_INFO,
513 MGMT_STATUS_INVALID_PARAMS);
f7b64e69 514
3243553f
JH
515 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->flags))
516 cancel_delayed_work_sync(&hdev->power_off);
ab81cbf9 517
09fd0de5 518 hci_dev_lock(hdev);
f7b64e69 519
7d78525d
JH
520 if (test_and_clear_bit(HCI_PI_MGMT_INIT, &hci_pi(sk)->flags))
521 mgmt_init_hdev(hdev);
ebc99feb 522
dc4fe30b
JH
523 memset(&rp, 0, sizeof(rp));
524
69ab39ea 525 bacpy(&rp.bdaddr, &hdev->bdaddr);
f7b64e69 526
69ab39ea 527 rp.version = hdev->hci_ver;
f7b64e69 528
69ab39ea
JH
529 put_unaligned_le16(hdev->manufacturer, &rp.manufacturer);
530
531 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
532 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
f7b64e69 533
a38528f1 534 memcpy(rp.dev_class, hdev->dev_class, 3);
f7b64e69 535
dc4fe30b
JH
536 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
537
09fd0de5 538 hci_dev_unlock(hdev);
f7b64e69 539 hci_dev_put(hdev);
0381101f 540
4e51eae9 541 return cmd_complete(sk, index, MGMT_OP_READ_INFO, &rp, sizeof(rp));
0381101f
JH
542}
543
eec8d2bc
JH
544static void mgmt_pending_free(struct pending_cmd *cmd)
545{
546 sock_put(cmd->sk);
c68fb7ff 547 kfree(cmd->param);
eec8d2bc
JH
548 kfree(cmd);
549}
550
366a0336 551static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
2e58ef3e
JH
552 struct hci_dev *hdev,
553 void *data, u16 len)
eec8d2bc
JH
554{
555 struct pending_cmd *cmd;
556
557 cmd = kmalloc(sizeof(*cmd), GFP_ATOMIC);
558 if (!cmd)
366a0336 559 return NULL;
eec8d2bc
JH
560
561 cmd->opcode = opcode;
2e58ef3e 562 cmd->index = hdev->id;
eec8d2bc 563
c68fb7ff
SJ
564 cmd->param = kmalloc(len, GFP_ATOMIC);
565 if (!cmd->param) {
eec8d2bc 566 kfree(cmd);
366a0336 567 return NULL;
eec8d2bc
JH
568 }
569
8fce6357
SJ
570 if (data)
571 memcpy(cmd->param, data, len);
eec8d2bc
JH
572
573 cmd->sk = sk;
574 sock_hold(sk);
575
2e58ef3e 576 list_add(&cmd->list, &hdev->mgmt_pending);
eec8d2bc 577
366a0336 578 return cmd;
eec8d2bc
JH
579}
580
744cf19e 581static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
eec8d2bc
JH
582 void (*cb)(struct pending_cmd *cmd, void *data),
583 void *data)
584{
585 struct list_head *p, *n;
586
2e58ef3e 587 list_for_each_safe(p, n, &hdev->mgmt_pending) {
eec8d2bc
JH
588 struct pending_cmd *cmd;
589
590 cmd = list_entry(p, struct pending_cmd, list);
591
b24752fe 592 if (opcode > 0 && cmd->opcode != opcode)
eec8d2bc
JH
593 continue;
594
eec8d2bc
JH
595 cb(cmd, data);
596 }
597}
598
2e58ef3e 599static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
eec8d2bc 600{
8035ded4 601 struct pending_cmd *cmd;
eec8d2bc 602
2e58ef3e 603 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2aeabcbe
JH
604 if (cmd->opcode == opcode)
605 return cmd;
eec8d2bc
JH
606 }
607
608 return NULL;
609}
610
a664b5bc 611static void mgmt_pending_remove(struct pending_cmd *cmd)
73f22f62 612{
73f22f62
JH
613 list_del(&cmd->list);
614 mgmt_pending_free(cmd);
615}
616
69ab39ea 617static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
8680570b 618{
69ab39ea 619 __le32 settings = cpu_to_le32(get_current_settings(hdev));
8680570b 620
69ab39ea 621 return cmd_complete(sk, hdev->id, opcode, &settings, sizeof(settings));
8680570b
JH
622}
623
4e51eae9 624static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len)
eec8d2bc 625{
72a734ec 626 struct mgmt_mode *cp;
eec8d2bc 627 struct hci_dev *hdev;
366a0336 628 struct pending_cmd *cmd;
366a0336 629 int err, up;
eec8d2bc
JH
630
631 cp = (void *) data;
eec8d2bc 632
4e51eae9 633 BT_DBG("request for hci%u", index);
eec8d2bc 634
bdce7baf 635 if (len != sizeof(*cp))
ca69b795
JH
636 return cmd_status(sk, index, MGMT_OP_SET_POWERED,
637 MGMT_STATUS_INVALID_PARAMS);
bdce7baf 638
4e51eae9 639 hdev = hci_dev_get(index);
eec8d2bc 640 if (!hdev)
ca69b795
JH
641 return cmd_status(sk, index, MGMT_OP_SET_POWERED,
642 MGMT_STATUS_INVALID_PARAMS);
eec8d2bc 643
09fd0de5 644 hci_dev_lock(hdev);
eec8d2bc
JH
645
646 up = test_bit(HCI_UP, &hdev->flags);
72a734ec 647 if ((cp->val && up) || (!cp->val && !up)) {
69ab39ea 648 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
eec8d2bc
JH
649 goto failed;
650 }
651
2e58ef3e 652 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
ca69b795
JH
653 err = cmd_status(sk, index, MGMT_OP_SET_POWERED,
654 MGMT_STATUS_BUSY);
eec8d2bc
JH
655 goto failed;
656 }
657
2e58ef3e 658 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
366a0336
JH
659 if (!cmd) {
660 err = -ENOMEM;
eec8d2bc 661 goto failed;
366a0336 662 }
eec8d2bc 663
72a734ec 664 if (cp->val)
7f971041 665 schedule_work(&hdev->power_on);
eec8d2bc 666 else
80b7ab33 667 schedule_work(&hdev->power_off.work);
eec8d2bc 668
366a0336 669 err = 0;
eec8d2bc
JH
670
671failed:
09fd0de5 672 hci_dev_unlock(hdev);
eec8d2bc 673 hci_dev_put(hdev);
366a0336 674 return err;
eec8d2bc
JH
675}
676
4e51eae9
SJ
677static int set_discoverable(struct sock *sk, u16 index, unsigned char *data,
678 u16 len)
73f22f62 679{
16ab91ab 680 struct mgmt_cp_set_discoverable *cp;
73f22f62 681 struct hci_dev *hdev;
366a0336 682 struct pending_cmd *cmd;
73f22f62
JH
683 u8 scan;
684 int err;
685
686 cp = (void *) data;
73f22f62 687
4e51eae9 688 BT_DBG("request for hci%u", index);
73f22f62 689
bdce7baf 690 if (len != sizeof(*cp))
ca69b795
JH
691 return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE,
692 MGMT_STATUS_INVALID_PARAMS);
bdce7baf 693
4e51eae9 694 hdev = hci_dev_get(index);
73f22f62 695 if (!hdev)
ca69b795
JH
696 return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE,
697 MGMT_STATUS_INVALID_PARAMS);
73f22f62 698
09fd0de5 699 hci_dev_lock(hdev);
73f22f62
JH
700
701 if (!test_bit(HCI_UP, &hdev->flags)) {
ca69b795
JH
702 err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE,
703 MGMT_STATUS_NOT_POWERED);
73f22f62
JH
704 goto failed;
705 }
706
2e58ef3e
JH
707 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
708 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
ca69b795
JH
709 err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE,
710 MGMT_STATUS_BUSY);
73f22f62
JH
711 goto failed;
712 }
713
72a734ec 714 if (cp->val == test_bit(HCI_ISCAN, &hdev->flags) &&
73f22f62 715 test_bit(HCI_PSCAN, &hdev->flags)) {
69ab39ea 716 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
73f22f62
JH
717 goto failed;
718 }
719
2e58ef3e 720 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
366a0336
JH
721 if (!cmd) {
722 err = -ENOMEM;
73f22f62 723 goto failed;
366a0336 724 }
73f22f62
JH
725
726 scan = SCAN_PAGE;
727
72a734ec 728 if (cp->val)
73f22f62 729 scan |= SCAN_INQUIRY;
16ab91ab 730 else
e0f9309f 731 cancel_delayed_work(&hdev->discov_off);
73f22f62
JH
732
733 err = hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
734 if (err < 0)
a664b5bc 735 mgmt_pending_remove(cmd);
73f22f62 736
16ab91ab
JH
737 if (cp->val)
738 hdev->discov_timeout = get_unaligned_le16(&cp->timeout);
739
73f22f62 740failed:
09fd0de5 741 hci_dev_unlock(hdev);
73f22f62
JH
742 hci_dev_put(hdev);
743
744 return err;
745}
746
4e51eae9
SJ
747static int set_connectable(struct sock *sk, u16 index, unsigned char *data,
748 u16 len)
9fbcbb45 749{
72a734ec 750 struct mgmt_mode *cp;
9fbcbb45 751 struct hci_dev *hdev;
366a0336 752 struct pending_cmd *cmd;
9fbcbb45
JH
753 u8 scan;
754 int err;
755
756 cp = (void *) data;
9fbcbb45 757
4e51eae9 758 BT_DBG("request for hci%u", index);
9fbcbb45 759
bdce7baf 760 if (len != sizeof(*cp))
ca69b795
JH
761 return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE,
762 MGMT_STATUS_INVALID_PARAMS);
bdce7baf 763
4e51eae9 764 hdev = hci_dev_get(index);
9fbcbb45 765 if (!hdev)
ca69b795
JH
766 return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE,
767 MGMT_STATUS_INVALID_PARAMS);
9fbcbb45 768
09fd0de5 769 hci_dev_lock(hdev);
9fbcbb45
JH
770
771 if (!test_bit(HCI_UP, &hdev->flags)) {
ca69b795
JH
772 err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE,
773 MGMT_STATUS_NOT_POWERED);
9fbcbb45
JH
774 goto failed;
775 }
776
2e58ef3e
JH
777 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
778 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
ca69b795
JH
779 err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE,
780 MGMT_STATUS_BUSY);
9fbcbb45
JH
781 goto failed;
782 }
783
72a734ec 784 if (cp->val == test_bit(HCI_PSCAN, &hdev->flags)) {
69ab39ea 785 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
9fbcbb45
JH
786 goto failed;
787 }
788
2e58ef3e 789 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
366a0336
JH
790 if (!cmd) {
791 err = -ENOMEM;
9fbcbb45 792 goto failed;
366a0336 793 }
9fbcbb45 794
72a734ec 795 if (cp->val)
9fbcbb45
JH
796 scan = SCAN_PAGE;
797 else
798 scan = 0;
799
800 err = hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
801 if (err < 0)
a664b5bc 802 mgmt_pending_remove(cmd);
9fbcbb45
JH
803
804failed:
09fd0de5 805 hci_dev_unlock(hdev);
9fbcbb45
JH
806 hci_dev_put(hdev);
807
808 return err;
809}
810
744cf19e
JH
811static int mgmt_event(u16 event, struct hci_dev *hdev, void *data,
812 u16 data_len, struct sock *skip_sk)
c542a06c
JH
813{
814 struct sk_buff *skb;
815 struct mgmt_hdr *hdr;
816
817 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_ATOMIC);
818 if (!skb)
819 return -ENOMEM;
820
821 bt_cb(skb)->channel = HCI_CHANNEL_CONTROL;
822
823 hdr = (void *) skb_put(skb, sizeof(*hdr));
824 hdr->opcode = cpu_to_le16(event);
744cf19e
JH
825 if (hdev)
826 hdr->index = cpu_to_le16(hdev->id);
827 else
828 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
c542a06c
JH
829 hdr->len = cpu_to_le16(data_len);
830
4e51eae9
SJ
831 if (data)
832 memcpy(skb_put(skb, data_len), data, data_len);
c542a06c
JH
833
834 hci_send_to_sock(NULL, skb, skip_sk);
835 kfree_skb(skb);
836
837 return 0;
838}
839
4e51eae9
SJ
840static int set_pairable(struct sock *sk, u16 index, unsigned char *data,
841 u16 len)
c542a06c 842{
69ab39ea 843 struct mgmt_mode *cp;
c542a06c 844 struct hci_dev *hdev;
69ab39ea 845 __le32 ev;
c542a06c
JH
846 int err;
847
848 cp = (void *) data;
c542a06c 849
4e51eae9 850 BT_DBG("request for hci%u", index);
c542a06c 851
bdce7baf 852 if (len != sizeof(*cp))
ca69b795
JH
853 return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE,
854 MGMT_STATUS_INVALID_PARAMS);
bdce7baf 855
4e51eae9 856 hdev = hci_dev_get(index);
c542a06c 857 if (!hdev)
ca69b795
JH
858 return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE,
859 MGMT_STATUS_INVALID_PARAMS);
c542a06c 860
09fd0de5 861 hci_dev_lock(hdev);
c542a06c
JH
862
863 if (cp->val)
864 set_bit(HCI_PAIRABLE, &hdev->flags);
865 else
866 clear_bit(HCI_PAIRABLE, &hdev->flags);
867
69ab39ea 868 err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev);
c542a06c
JH
869 if (err < 0)
870 goto failed;
871
69ab39ea 872 ev = cpu_to_le32(get_current_settings(hdev));
c542a06c 873
69ab39ea 874 err = mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), sk);
c542a06c
JH
875
876failed:
09fd0de5 877 hci_dev_unlock(hdev);
c542a06c
JH
878 hci_dev_put(hdev);
879
880 return err;
881}
882
4e51eae9 883static int add_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len)
2aeb9a1a
JH
884{
885 struct mgmt_cp_add_uuid *cp;
886 struct hci_dev *hdev;
887 struct bt_uuid *uuid;
2aeb9a1a
JH
888 int err;
889
890 cp = (void *) data;
2aeb9a1a 891
4e51eae9 892 BT_DBG("request for hci%u", index);
2aeb9a1a 893
bdce7baf 894 if (len != sizeof(*cp))
ca69b795
JH
895 return cmd_status(sk, index, MGMT_OP_ADD_UUID,
896 MGMT_STATUS_INVALID_PARAMS);
bdce7baf 897
4e51eae9 898 hdev = hci_dev_get(index);
2aeb9a1a 899 if (!hdev)
ca69b795
JH
900 return cmd_status(sk, index, MGMT_OP_ADD_UUID,
901 MGMT_STATUS_INVALID_PARAMS);
2aeb9a1a 902
09fd0de5 903 hci_dev_lock(hdev);
2aeb9a1a
JH
904
905 uuid = kmalloc(sizeof(*uuid), GFP_ATOMIC);
906 if (!uuid) {
907 err = -ENOMEM;
908 goto failed;
909 }
910
911 memcpy(uuid->uuid, cp->uuid, 16);
1aff6f09 912 uuid->svc_hint = cp->svc_hint;
2aeb9a1a
JH
913
914 list_add(&uuid->list, &hdev->uuids);
915
1aff6f09
JH
916 err = update_class(hdev);
917 if (err < 0)
918 goto failed;
919
80a1e1db
JH
920 err = update_eir(hdev);
921 if (err < 0)
922 goto failed;
923
4e51eae9 924 err = cmd_complete(sk, index, MGMT_OP_ADD_UUID, NULL, 0);
2aeb9a1a
JH
925
926failed:
09fd0de5 927 hci_dev_unlock(hdev);
2aeb9a1a
JH
928 hci_dev_put(hdev);
929
930 return err;
931}
932
4e51eae9 933static int remove_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len)
2aeb9a1a
JH
934{
935 struct list_head *p, *n;
779cb850 936 struct mgmt_cp_remove_uuid *cp;
2aeb9a1a
JH
937 struct hci_dev *hdev;
938 u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2aeb9a1a
JH
939 int err, found;
940
941 cp = (void *) data;
2aeb9a1a 942
4e51eae9 943 BT_DBG("request for hci%u", index);
2aeb9a1a 944
bdce7baf 945 if (len != sizeof(*cp))
ca69b795
JH
946 return cmd_status(sk, index, MGMT_OP_REMOVE_UUID,
947 MGMT_STATUS_INVALID_PARAMS);
bdce7baf 948
4e51eae9 949 hdev = hci_dev_get(index);
2aeb9a1a 950 if (!hdev)
ca69b795
JH
951 return cmd_status(sk, index, MGMT_OP_REMOVE_UUID,
952 MGMT_STATUS_INVALID_PARAMS);
2aeb9a1a 953
09fd0de5 954 hci_dev_lock(hdev);
2aeb9a1a
JH
955
956 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
957 err = hci_uuids_clear(hdev);
958 goto unlock;
959 }
960
961 found = 0;
962
963 list_for_each_safe(p, n, &hdev->uuids) {
964 struct bt_uuid *match = list_entry(p, struct bt_uuid, list);
965
966 if (memcmp(match->uuid, cp->uuid, 16) != 0)
967 continue;
968
969 list_del(&match->list);
970 found++;
971 }
972
973 if (found == 0) {
ca69b795
JH
974 err = cmd_status(sk, index, MGMT_OP_REMOVE_UUID,
975 MGMT_STATUS_INVALID_PARAMS);
2aeb9a1a
JH
976 goto unlock;
977 }
978
1aff6f09
JH
979 err = update_class(hdev);
980 if (err < 0)
981 goto unlock;
982
80a1e1db
JH
983 err = update_eir(hdev);
984 if (err < 0)
985 goto unlock;
986
4e51eae9 987 err = cmd_complete(sk, index, MGMT_OP_REMOVE_UUID, NULL, 0);
2aeb9a1a
JH
988
989unlock:
09fd0de5 990 hci_dev_unlock(hdev);
2aeb9a1a
JH
991 hci_dev_put(hdev);
992
993 return err;
994}
995
4e51eae9
SJ
996static int set_dev_class(struct sock *sk, u16 index, unsigned char *data,
997 u16 len)
1aff6f09
JH
998{
999 struct hci_dev *hdev;
1000 struct mgmt_cp_set_dev_class *cp;
1aff6f09
JH
1001 int err;
1002
1003 cp = (void *) data;
1aff6f09 1004
4e51eae9 1005 BT_DBG("request for hci%u", index);
1aff6f09 1006
bdce7baf 1007 if (len != sizeof(*cp))
ca69b795
JH
1008 return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS,
1009 MGMT_STATUS_INVALID_PARAMS);
bdce7baf 1010
4e51eae9 1011 hdev = hci_dev_get(index);
1aff6f09 1012 if (!hdev)
ca69b795
JH
1013 return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS,
1014 MGMT_STATUS_INVALID_PARAMS);
1aff6f09 1015
09fd0de5 1016 hci_dev_lock(hdev);
1aff6f09
JH
1017
1018 hdev->major_class = cp->major;
1019 hdev->minor_class = cp->minor;
1020
7d78525d
JH
1021 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->flags)) {
1022 hci_dev_unlock(hdev);
1023 cancel_delayed_work_sync(&hdev->service_cache);
1024 hci_dev_lock(hdev);
14c0b608 1025 update_eir(hdev);
7d78525d 1026 }
14c0b608 1027
1aff6f09
JH
1028 err = update_class(hdev);
1029
1030 if (err == 0)
4e51eae9 1031 err = cmd_complete(sk, index, MGMT_OP_SET_DEV_CLASS, NULL, 0);
1aff6f09 1032
09fd0de5 1033 hci_dev_unlock(hdev);
1aff6f09
JH
1034 hci_dev_put(hdev);
1035
1036 return err;
1037}
1038
86742e1e
JH
1039static int load_link_keys(struct sock *sk, u16 index, unsigned char *data,
1040 u16 len)
55ed8ca1
JH
1041{
1042 struct hci_dev *hdev;
86742e1e 1043 struct mgmt_cp_load_link_keys *cp;
4e51eae9 1044 u16 key_count, expected_len;
a492cd52 1045 int i;
55ed8ca1
JH
1046
1047 cp = (void *) data;
bdce7baf
SJ
1048
1049 if (len < sizeof(*cp))
ca69b795
JH
1050 return cmd_status(sk, index, MGMT_OP_LOAD_LINK_KEYS,
1051 MGMT_STATUS_INVALID_PARAMS);
bdce7baf 1052
55ed8ca1
JH
1053 key_count = get_unaligned_le16(&cp->key_count);
1054
86742e1e
JH
1055 expected_len = sizeof(*cp) + key_count *
1056 sizeof(struct mgmt_link_key_info);
a492cd52 1057 if (expected_len != len) {
86742e1e 1058 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
a492cd52 1059 len, expected_len);
ca69b795
JH
1060 return cmd_status(sk, index, MGMT_OP_LOAD_LINK_KEYS,
1061 MGMT_STATUS_INVALID_PARAMS);
55ed8ca1
JH
1062 }
1063
4e51eae9 1064 hdev = hci_dev_get(index);
55ed8ca1 1065 if (!hdev)
ca69b795
JH
1066 return cmd_status(sk, index, MGMT_OP_LOAD_LINK_KEYS,
1067 MGMT_STATUS_INVALID_PARAMS);
55ed8ca1 1068
4e51eae9 1069 BT_DBG("hci%u debug_keys %u key_count %u", index, cp->debug_keys,
55ed8ca1
JH
1070 key_count);
1071
09fd0de5 1072 hci_dev_lock(hdev);
55ed8ca1
JH
1073
1074 hci_link_keys_clear(hdev);
1075
1076 set_bit(HCI_LINK_KEYS, &hdev->flags);
1077
1078 if (cp->debug_keys)
1079 set_bit(HCI_DEBUG_KEYS, &hdev->flags);
1080 else
1081 clear_bit(HCI_DEBUG_KEYS, &hdev->flags);
1082
a492cd52 1083 for (i = 0; i < key_count; i++) {
86742e1e 1084 struct mgmt_link_key_info *key = &cp->keys[i];
55ed8ca1 1085
d25e28ab 1086 hci_add_link_key(hdev, NULL, 0, &key->bdaddr, key->val, key->type,
55ed8ca1
JH
1087 key->pin_len);
1088 }
1089
0e5f875a
JH
1090 cmd_complete(sk, index, MGMT_OP_LOAD_LINK_KEYS, NULL, 0);
1091
09fd0de5 1092 hci_dev_unlock(hdev);
55ed8ca1
JH
1093 hci_dev_put(hdev);
1094
a492cd52 1095 return 0;
55ed8ca1
JH
1096}
1097
86742e1e
JH
1098static int remove_keys(struct sock *sk, u16 index, unsigned char *data,
1099 u16 len)
55ed8ca1
JH
1100{
1101 struct hci_dev *hdev;
86742e1e 1102 struct mgmt_cp_remove_keys *cp;
a8a1d19e
JH
1103 struct mgmt_rp_remove_keys rp;
1104 struct hci_cp_disconnect dc;
1105 struct pending_cmd *cmd;
55ed8ca1 1106 struct hci_conn *conn;
55ed8ca1
JH
1107 int err;
1108
1109 cp = (void *) data;
55ed8ca1 1110
bdce7baf 1111 if (len != sizeof(*cp))
ca69b795
JH
1112 return cmd_status(sk, index, MGMT_OP_REMOVE_KEYS,
1113 MGMT_STATUS_INVALID_PARAMS);
bdce7baf 1114
4e51eae9 1115 hdev = hci_dev_get(index);
55ed8ca1 1116 if (!hdev)
ca69b795
JH
1117 return cmd_status(sk, index, MGMT_OP_REMOVE_KEYS,
1118 MGMT_STATUS_INVALID_PARAMS);
55ed8ca1 1119
09fd0de5 1120 hci_dev_lock(hdev);
55ed8ca1 1121
a8a1d19e
JH
1122 memset(&rp, 0, sizeof(rp));
1123 bacpy(&rp.bdaddr, &cp->bdaddr);
ca69b795 1124 rp.status = MGMT_STATUS_FAILED;
a8a1d19e 1125
55ed8ca1 1126 err = hci_remove_link_key(hdev, &cp->bdaddr);
ca69b795
JH
1127 if (err < 0) {
1128 rp.status = MGMT_STATUS_NOT_PAIRED;
55ed8ca1 1129 goto unlock;
ca69b795 1130 }
55ed8ca1 1131
a8a1d19e
JH
1132 if (!test_bit(HCI_UP, &hdev->flags) || !cp->disconnect) {
1133 err = cmd_complete(sk, index, MGMT_OP_REMOVE_KEYS, &rp,
1134 sizeof(rp));
55ed8ca1 1135 goto unlock;
a8a1d19e 1136 }
55ed8ca1
JH
1137
1138 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
a8a1d19e
JH
1139 if (!conn) {
1140 err = cmd_complete(sk, index, MGMT_OP_REMOVE_KEYS, &rp,
1141 sizeof(rp));
1142 goto unlock;
1143 }
55ed8ca1 1144
a8a1d19e
JH
1145 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_KEYS, hdev, cp, sizeof(*cp));
1146 if (!cmd) {
1147 err = -ENOMEM;
1148 goto unlock;
55ed8ca1
JH
1149 }
1150
a8a1d19e
JH
1151 put_unaligned_le16(conn->handle, &dc.handle);
1152 dc.reason = 0x13; /* Remote User Terminated Connection */
1153 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1154 if (err < 0)
1155 mgmt_pending_remove(cmd);
1156
55ed8ca1 1157unlock:
ca69b795 1158 if (err < 0)
a8a1d19e
JH
1159 err = cmd_complete(sk, index, MGMT_OP_REMOVE_KEYS, &rp,
1160 sizeof(rp));
09fd0de5 1161 hci_dev_unlock(hdev);
55ed8ca1
JH
1162 hci_dev_put(hdev);
1163
1164 return err;
1165}
1166
4e51eae9 1167static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len)
8962ee74
JH
1168{
1169 struct hci_dev *hdev;
1170 struct mgmt_cp_disconnect *cp;
1171 struct hci_cp_disconnect dc;
366a0336 1172 struct pending_cmd *cmd;
8962ee74 1173 struct hci_conn *conn;
8962ee74
JH
1174 int err;
1175
1176 BT_DBG("");
1177
1178 cp = (void *) data;
8962ee74 1179
bdce7baf 1180 if (len != sizeof(*cp))
ca69b795
JH
1181 return cmd_status(sk, index, MGMT_OP_DISCONNECT,
1182 MGMT_STATUS_INVALID_PARAMS);
bdce7baf 1183
4e51eae9 1184 hdev = hci_dev_get(index);
8962ee74 1185 if (!hdev)
ca69b795
JH
1186 return cmd_status(sk, index, MGMT_OP_DISCONNECT,
1187 MGMT_STATUS_INVALID_PARAMS);
8962ee74 1188
09fd0de5 1189 hci_dev_lock(hdev);
8962ee74
JH
1190
1191 if (!test_bit(HCI_UP, &hdev->flags)) {
ca69b795
JH
1192 err = cmd_status(sk, index, MGMT_OP_DISCONNECT,
1193 MGMT_STATUS_NOT_POWERED);
8962ee74
JH
1194 goto failed;
1195 }
1196
2e58ef3e 1197 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
ca69b795
JH
1198 err = cmd_status(sk, index, MGMT_OP_DISCONNECT,
1199 MGMT_STATUS_BUSY);
8962ee74
JH
1200 goto failed;
1201 }
1202
1203 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
365227e5
VCG
1204 if (!conn)
1205 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->bdaddr);
1206
8962ee74 1207 if (!conn) {
ca69b795
JH
1208 err = cmd_status(sk, index, MGMT_OP_DISCONNECT,
1209 MGMT_STATUS_NOT_CONNECTED);
8962ee74
JH
1210 goto failed;
1211 }
1212
2e58ef3e 1213 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
366a0336
JH
1214 if (!cmd) {
1215 err = -ENOMEM;
8962ee74 1216 goto failed;
366a0336 1217 }
8962ee74
JH
1218
1219 put_unaligned_le16(conn->handle, &dc.handle);
1220 dc.reason = 0x13; /* Remote User Terminated Connection */
1221
1222 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1223 if (err < 0)
a664b5bc 1224 mgmt_pending_remove(cmd);
8962ee74
JH
1225
1226failed:
09fd0de5 1227 hci_dev_unlock(hdev);
8962ee74
JH
1228 hci_dev_put(hdev);
1229
1230 return err;
1231}
1232
48264f06 1233static u8 link_to_mgmt(u8 link_type, u8 addr_type)
4c659c39
JH
1234{
1235 switch (link_type) {
1236 case LE_LINK:
48264f06
JH
1237 switch (addr_type) {
1238 case ADDR_LE_DEV_PUBLIC:
1239 return MGMT_ADDR_LE_PUBLIC;
1240 case ADDR_LE_DEV_RANDOM:
1241 return MGMT_ADDR_LE_RANDOM;
1242 default:
1243 return MGMT_ADDR_INVALID;
1244 }
4c659c39
JH
1245 case ACL_LINK:
1246 return MGMT_ADDR_BREDR;
1247 default:
1248 return MGMT_ADDR_INVALID;
1249 }
1250}
1251
8ce6284e 1252static int get_connections(struct sock *sk, u16 index)
2784eb41 1253{
2784eb41
JH
1254 struct mgmt_rp_get_connections *rp;
1255 struct hci_dev *hdev;
8035ded4 1256 struct hci_conn *c;
2784eb41 1257 struct list_head *p;
a38528f1 1258 size_t rp_len;
4e51eae9 1259 u16 count;
2784eb41
JH
1260 int i, err;
1261
1262 BT_DBG("");
1263
4e51eae9 1264 hdev = hci_dev_get(index);
2784eb41 1265 if (!hdev)
ca69b795
JH
1266 return cmd_status(sk, index, MGMT_OP_GET_CONNECTIONS,
1267 MGMT_STATUS_INVALID_PARAMS);
2784eb41 1268
09fd0de5 1269 hci_dev_lock(hdev);
2784eb41
JH
1270
1271 count = 0;
1272 list_for_each(p, &hdev->conn_hash.list) {
1273 count++;
1274 }
1275
4c659c39 1276 rp_len = sizeof(*rp) + (count * sizeof(struct mgmt_addr_info));
a38528f1
JH
1277 rp = kmalloc(rp_len, GFP_ATOMIC);
1278 if (!rp) {
2784eb41
JH
1279 err = -ENOMEM;
1280 goto unlock;
1281 }
1282
2784eb41
JH
1283 put_unaligned_le16(count, &rp->conn_count);
1284
2784eb41 1285 i = 0;
4c659c39
JH
1286 list_for_each_entry(c, &hdev->conn_hash.list, list) {
1287 bacpy(&rp->addr[i].bdaddr, &c->dst);
48264f06 1288 rp->addr[i].type = link_to_mgmt(c->type, c->dst_type);
4c659c39
JH
1289 if (rp->addr[i].type == MGMT_ADDR_INVALID)
1290 continue;
1291 i++;
1292 }
1293
1294 /* Recalculate length in case of filtered SCO connections, etc */
1295 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
2784eb41 1296
4e51eae9 1297 err = cmd_complete(sk, index, MGMT_OP_GET_CONNECTIONS, rp, rp_len);
2784eb41
JH
1298
1299unlock:
a38528f1 1300 kfree(rp);
09fd0de5 1301 hci_dev_unlock(hdev);
2784eb41
JH
1302 hci_dev_put(hdev);
1303 return err;
1304}
1305
96d97a67
WR
1306static int send_pin_code_neg_reply(struct sock *sk, u16 index,
1307 struct hci_dev *hdev, struct mgmt_cp_pin_code_neg_reply *cp)
1308{
1309 struct pending_cmd *cmd;
1310 int err;
1311
2e58ef3e 1312 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
96d97a67
WR
1313 sizeof(*cp));
1314 if (!cmd)
1315 return -ENOMEM;
1316
1317 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, sizeof(cp->bdaddr),
1318 &cp->bdaddr);
1319 if (err < 0)
1320 mgmt_pending_remove(cmd);
1321
1322 return err;
1323}
1324
4e51eae9
SJ
1325static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data,
1326 u16 len)
980e1a53
JH
1327{
1328 struct hci_dev *hdev;
96d97a67 1329 struct hci_conn *conn;
980e1a53 1330 struct mgmt_cp_pin_code_reply *cp;
96d97a67 1331 struct mgmt_cp_pin_code_neg_reply ncp;
980e1a53 1332 struct hci_cp_pin_code_reply reply;
366a0336 1333 struct pending_cmd *cmd;
980e1a53
JH
1334 int err;
1335
1336 BT_DBG("");
1337
1338 cp = (void *) data;
980e1a53 1339
bdce7baf 1340 if (len != sizeof(*cp))
ca69b795
JH
1341 return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY,
1342 MGMT_STATUS_INVALID_PARAMS);
bdce7baf 1343
4e51eae9 1344 hdev = hci_dev_get(index);
980e1a53 1345 if (!hdev)
ca69b795
JH
1346 return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY,
1347 MGMT_STATUS_INVALID_PARAMS);
980e1a53 1348
09fd0de5 1349 hci_dev_lock(hdev);
980e1a53
JH
1350
1351 if (!test_bit(HCI_UP, &hdev->flags)) {
ca69b795
JH
1352 err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY,
1353 MGMT_STATUS_NOT_POWERED);
980e1a53
JH
1354 goto failed;
1355 }
1356
96d97a67
WR
1357 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1358 if (!conn) {
ca69b795
JH
1359 err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY,
1360 MGMT_STATUS_NOT_CONNECTED);
96d97a67
WR
1361 goto failed;
1362 }
1363
1364 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
1365 bacpy(&ncp.bdaddr, &cp->bdaddr);
1366
1367 BT_ERR("PIN code is not 16 bytes long");
1368
1369 err = send_pin_code_neg_reply(sk, index, hdev, &ncp);
1370 if (err >= 0)
1371 err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY,
ca69b795 1372 MGMT_STATUS_INVALID_PARAMS);
96d97a67
WR
1373
1374 goto failed;
1375 }
1376
2e58ef3e 1377 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
366a0336
JH
1378 if (!cmd) {
1379 err = -ENOMEM;
980e1a53 1380 goto failed;
366a0336 1381 }
980e1a53
JH
1382
1383 bacpy(&reply.bdaddr, &cp->bdaddr);
1384 reply.pin_len = cp->pin_len;
24718ca5 1385 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
980e1a53
JH
1386
1387 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
1388 if (err < 0)
a664b5bc 1389 mgmt_pending_remove(cmd);
980e1a53
JH
1390
1391failed:
09fd0de5 1392 hci_dev_unlock(hdev);
980e1a53
JH
1393 hci_dev_put(hdev);
1394
1395 return err;
1396}
1397
4e51eae9
SJ
1398static int pin_code_neg_reply(struct sock *sk, u16 index, unsigned char *data,
1399 u16 len)
980e1a53
JH
1400{
1401 struct hci_dev *hdev;
1402 struct mgmt_cp_pin_code_neg_reply *cp;
980e1a53
JH
1403 int err;
1404
1405 BT_DBG("");
1406
1407 cp = (void *) data;
980e1a53 1408
bdce7baf
SJ
1409 if (len != sizeof(*cp))
1410 return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
ca69b795 1411 MGMT_STATUS_INVALID_PARAMS);
bdce7baf 1412
4e51eae9 1413 hdev = hci_dev_get(index);
980e1a53 1414 if (!hdev)
4e51eae9 1415 return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
ca69b795 1416 MGMT_STATUS_INVALID_PARAMS);
980e1a53 1417
09fd0de5 1418 hci_dev_lock(hdev);
980e1a53
JH
1419
1420 if (!test_bit(HCI_UP, &hdev->flags)) {
4e51eae9 1421 err = cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
ca69b795 1422 MGMT_STATUS_NOT_POWERED);
980e1a53
JH
1423 goto failed;
1424 }
1425
96d97a67 1426 err = send_pin_code_neg_reply(sk, index, hdev, cp);
980e1a53
JH
1427
1428failed:
09fd0de5 1429 hci_dev_unlock(hdev);
980e1a53
JH
1430 hci_dev_put(hdev);
1431
1432 return err;
1433}
1434
4e51eae9
SJ
1435static int set_io_capability(struct sock *sk, u16 index, unsigned char *data,
1436 u16 len)
17fa4b9d
JH
1437{
1438 struct hci_dev *hdev;
1439 struct mgmt_cp_set_io_capability *cp;
17fa4b9d
JH
1440
1441 BT_DBG("");
1442
1443 cp = (void *) data;
17fa4b9d 1444
bdce7baf 1445 if (len != sizeof(*cp))
ca69b795
JH
1446 return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY,
1447 MGMT_STATUS_INVALID_PARAMS);
bdce7baf 1448
4e51eae9 1449 hdev = hci_dev_get(index);
17fa4b9d 1450 if (!hdev)
ca69b795
JH
1451 return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY,
1452 MGMT_STATUS_INVALID_PARAMS);
17fa4b9d 1453
09fd0de5 1454 hci_dev_lock(hdev);
17fa4b9d
JH
1455
1456 hdev->io_capability = cp->io_capability;
1457
1458 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
b8534e0f 1459 hdev->io_capability);
17fa4b9d 1460
09fd0de5 1461 hci_dev_unlock(hdev);
17fa4b9d
JH
1462 hci_dev_put(hdev);
1463
4e51eae9 1464 return cmd_complete(sk, index, MGMT_OP_SET_IO_CAPABILITY, NULL, 0);
17fa4b9d
JH
1465}
1466
e9a416b5
JH
1467static inline struct pending_cmd *find_pairing(struct hci_conn *conn)
1468{
1469 struct hci_dev *hdev = conn->hdev;
8035ded4 1470 struct pending_cmd *cmd;
e9a416b5 1471
2e58ef3e 1472 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
e9a416b5
JH
1473 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
1474 continue;
1475
e9a416b5
JH
1476 if (cmd->user_data != conn)
1477 continue;
1478
1479 return cmd;
1480 }
1481
1482 return NULL;
1483}
1484
1485static void pairing_complete(struct pending_cmd *cmd, u8 status)
1486{
1487 struct mgmt_rp_pair_device rp;
1488 struct hci_conn *conn = cmd->user_data;
1489
ba4e564f
JH
1490 bacpy(&rp.addr.bdaddr, &conn->dst);
1491 rp.addr.type = link_to_mgmt(conn->type, conn->dst_type);
e9a416b5
JH
1492 rp.status = status;
1493
4e51eae9 1494 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, &rp, sizeof(rp));
e9a416b5
JH
1495
1496 /* So we don't get further callbacks for this connection */
1497 conn->connect_cfm_cb = NULL;
1498 conn->security_cfm_cb = NULL;
1499 conn->disconn_cfm_cb = NULL;
1500
1501 hci_conn_put(conn);
1502
a664b5bc 1503 mgmt_pending_remove(cmd);
e9a416b5
JH
1504}
1505
1506static void pairing_complete_cb(struct hci_conn *conn, u8 status)
1507{
1508 struct pending_cmd *cmd;
1509
1510 BT_DBG("status %u", status);
1511
1512 cmd = find_pairing(conn);
56e5cb86 1513 if (!cmd)
e9a416b5 1514 BT_DBG("Unable to find a pending command");
56e5cb86
JH
1515 else
1516 pairing_complete(cmd, status);
e9a416b5
JH
1517}
1518
4e51eae9 1519static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len)
e9a416b5
JH
1520{
1521 struct hci_dev *hdev;
1522 struct mgmt_cp_pair_device *cp;
1425acb7 1523 struct mgmt_rp_pair_device rp;
e9a416b5
JH
1524 struct pending_cmd *cmd;
1525 u8 sec_level, auth_type;
1526 struct hci_conn *conn;
e9a416b5
JH
1527 int err;
1528
1529 BT_DBG("");
1530
1531 cp = (void *) data;
e9a416b5 1532
bdce7baf 1533 if (len != sizeof(*cp))
ca69b795
JH
1534 return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE,
1535 MGMT_STATUS_INVALID_PARAMS);
bdce7baf 1536
4e51eae9 1537 hdev = hci_dev_get(index);
e9a416b5 1538 if (!hdev)
ca69b795
JH
1539 return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE,
1540 MGMT_STATUS_INVALID_PARAMS);
e9a416b5 1541
09fd0de5 1542 hci_dev_lock(hdev);
e9a416b5 1543
c908df36
VCG
1544 sec_level = BT_SECURITY_MEDIUM;
1545 if (cp->io_cap == 0x03)
e9a416b5 1546 auth_type = HCI_AT_DEDICATED_BONDING;
c908df36 1547 else
e9a416b5 1548 auth_type = HCI_AT_DEDICATED_BONDING_MITM;
e9a416b5 1549
ba4e564f
JH
1550 if (cp->addr.type == MGMT_ADDR_BREDR)
1551 conn = hci_connect(hdev, ACL_LINK, &cp->addr.bdaddr, sec_level,
7a512d01
VCG
1552 auth_type);
1553 else
ba4e564f 1554 conn = hci_connect(hdev, LE_LINK, &cp->addr.bdaddr, sec_level,
7a512d01
VCG
1555 auth_type);
1556
1425acb7
JH
1557 memset(&rp, 0, sizeof(rp));
1558 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
1559 rp.addr.type = cp->addr.type;
1560
30e76272 1561 if (IS_ERR(conn)) {
1425acb7
JH
1562 rp.status = -PTR_ERR(conn);
1563 err = cmd_complete(sk, index, MGMT_OP_PAIR_DEVICE,
1564 &rp, sizeof(rp));
e9a416b5
JH
1565 goto unlock;
1566 }
1567
1568 if (conn->connect_cfm_cb) {
1569 hci_conn_put(conn);
1425acb7
JH
1570 rp.status = EBUSY;
1571 err = cmd_complete(sk, index, MGMT_OP_PAIR_DEVICE,
1572 &rp, sizeof(rp));
e9a416b5
JH
1573 goto unlock;
1574 }
1575
2e58ef3e 1576 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
e9a416b5
JH
1577 if (!cmd) {
1578 err = -ENOMEM;
1579 hci_conn_put(conn);
1580 goto unlock;
1581 }
1582
7a512d01 1583 /* For LE, just connecting isn't a proof that the pairing finished */
ba4e564f 1584 if (cp->addr.type == MGMT_ADDR_BREDR)
7a512d01
VCG
1585 conn->connect_cfm_cb = pairing_complete_cb;
1586
e9a416b5
JH
1587 conn->security_cfm_cb = pairing_complete_cb;
1588 conn->disconn_cfm_cb = pairing_complete_cb;
1589 conn->io_capability = cp->io_cap;
1590 cmd->user_data = conn;
1591
1592 if (conn->state == BT_CONNECTED &&
1593 hci_conn_security(conn, sec_level, auth_type))
1594 pairing_complete(cmd, 0);
1595
1596 err = 0;
1597
1598unlock:
09fd0de5 1599 hci_dev_unlock(hdev);
e9a416b5
JH
1600 hci_dev_put(hdev);
1601
1602 return err;
1603}
1604
0df4c185
BG
1605static int user_pairing_resp(struct sock *sk, u16 index, bdaddr_t *bdaddr,
1606 u16 mgmt_op, u16 hci_op, __le32 passkey)
a5c29683 1607{
a5c29683
JH
1608 struct pending_cmd *cmd;
1609 struct hci_dev *hdev;
0df4c185 1610 struct hci_conn *conn;
a5c29683
JH
1611 int err;
1612
4e51eae9 1613 hdev = hci_dev_get(index);
a5c29683 1614 if (!hdev)
ca69b795
JH
1615 return cmd_status(sk, index, mgmt_op,
1616 MGMT_STATUS_INVALID_PARAMS);
a5c29683 1617
09fd0de5 1618 hci_dev_lock(hdev);
08ba5382 1619
a5c29683 1620 if (!test_bit(HCI_UP, &hdev->flags)) {
0df4c185
BG
1621 err = cmd_status(sk, index, mgmt_op, MGMT_STATUS_NOT_POWERED);
1622 goto done;
a5c29683
JH
1623 }
1624
47c15e2b
BG
1625 /*
1626 * Check for an existing ACL link, if present pair via
1627 * HCI commands.
1628 *
1629 * If no ACL link is present, check for an LE link and if
1630 * present, pair via the SMP engine.
1631 *
1632 * If neither ACL nor LE links are present, fail with error.
1633 */
1634 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, bdaddr);
1635 if (!conn) {
1636 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, bdaddr);
1637 if (!conn) {
1638 err = cmd_status(sk, index, mgmt_op,
1639 MGMT_STATUS_NOT_CONNECTED);
1640 goto done;
1641 }
1642
1643 /* Continue with pairing via SMP */
1644
1645 err = cmd_status(sk, index, mgmt_op, MGMT_STATUS_SUCCESS);
1646 goto done;
1647 }
1648
0df4c185 1649 cmd = mgmt_pending_add(sk, mgmt_op, hdev, bdaddr, sizeof(*bdaddr));
a5c29683
JH
1650 if (!cmd) {
1651 err = -ENOMEM;
0df4c185 1652 goto done;
a5c29683
JH
1653 }
1654
0df4c185 1655 /* Continue with pairing via HCI */
604086b7
BG
1656 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
1657 struct hci_cp_user_passkey_reply cp;
1658
1659 bacpy(&cp.bdaddr, bdaddr);
1660 cp.passkey = passkey;
1661 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
1662 } else
1663 err = hci_send_cmd(hdev, hci_op, sizeof(*bdaddr), bdaddr);
1664
a664b5bc
JH
1665 if (err < 0)
1666 mgmt_pending_remove(cmd);
a5c29683 1667
0df4c185 1668done:
09fd0de5 1669 hci_dev_unlock(hdev);
a5c29683
JH
1670 hci_dev_put(hdev);
1671
1672 return err;
1673}
1674
0df4c185
BG
1675static int user_confirm_reply(struct sock *sk, u16 index, void *data, u16 len)
1676{
1677 struct mgmt_cp_user_confirm_reply *cp = (void *) data;
1678
1679 BT_DBG("");
1680
1681 if (len != sizeof(*cp))
1682 return cmd_status(sk, index, MGMT_OP_USER_CONFIRM_REPLY,
1683 MGMT_STATUS_INVALID_PARAMS);
1684
1685 return user_pairing_resp(sk, index, &cp->bdaddr,
1686 MGMT_OP_USER_CONFIRM_REPLY,
1687 HCI_OP_USER_CONFIRM_REPLY, 0);
1688}
1689
1690static int user_confirm_neg_reply(struct sock *sk, u16 index, void *data,
1691 u16 len)
1692{
1693 struct mgmt_cp_user_confirm_reply *cp = (void *) data;
1694
1695 BT_DBG("");
1696
1697 if (len != sizeof(*cp))
1698 return cmd_status(sk, index, MGMT_OP_USER_CONFIRM_NEG_REPLY,
1699 MGMT_STATUS_INVALID_PARAMS);
1700
1701 return user_pairing_resp(sk, index, &cp->bdaddr,
1702 MGMT_OP_USER_CONFIRM_NEG_REPLY,
1703 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
1704}
1705
604086b7
BG
1706static int user_passkey_reply(struct sock *sk, u16 index, void *data, u16 len)
1707{
1708 struct mgmt_cp_user_passkey_reply *cp = (void *) data;
1709
1710 BT_DBG("");
1711
1712 if (len != sizeof(*cp))
1713 return cmd_status(sk, index, MGMT_OP_USER_PASSKEY_REPLY,
1714 EINVAL);
1715
1716 return user_pairing_resp(sk, index, &cp->bdaddr,
1717 MGMT_OP_USER_PASSKEY_REPLY,
1718 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
1719}
1720
1721static int user_passkey_neg_reply(struct sock *sk, u16 index, void *data,
1722 u16 len)
1723{
1724 struct mgmt_cp_user_passkey_neg_reply *cp = (void *) data;
1725
1726 BT_DBG("");
1727
1728 if (len != sizeof(*cp))
1729 return cmd_status(sk, index, MGMT_OP_USER_PASSKEY_NEG_REPLY,
1730 EINVAL);
1731
1732 return user_pairing_resp(sk, index, &cp->bdaddr,
1733 MGMT_OP_USER_PASSKEY_NEG_REPLY,
1734 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
1735}
1736
b312b161
JH
1737static int set_local_name(struct sock *sk, u16 index, unsigned char *data,
1738 u16 len)
1739{
1740 struct mgmt_cp_set_local_name *mgmt_cp = (void *) data;
1741 struct hci_cp_write_local_name hci_cp;
1742 struct hci_dev *hdev;
1743 struct pending_cmd *cmd;
1744 int err;
1745
1746 BT_DBG("");
1747
1748 if (len != sizeof(*mgmt_cp))
ca69b795
JH
1749 return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME,
1750 MGMT_STATUS_INVALID_PARAMS);
b312b161
JH
1751
1752 hdev = hci_dev_get(index);
1753 if (!hdev)
ca69b795
JH
1754 return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME,
1755 MGMT_STATUS_INVALID_PARAMS);
b312b161 1756
09fd0de5 1757 hci_dev_lock(hdev);
b312b161 1758
2e58ef3e 1759 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
b312b161
JH
1760 if (!cmd) {
1761 err = -ENOMEM;
1762 goto failed;
1763 }
1764
1765 memcpy(hci_cp.name, mgmt_cp->name, sizeof(hci_cp.name));
1766 err = hci_send_cmd(hdev, HCI_OP_WRITE_LOCAL_NAME, sizeof(hci_cp),
1767 &hci_cp);
1768 if (err < 0)
1769 mgmt_pending_remove(cmd);
1770
1771failed:
09fd0de5 1772 hci_dev_unlock(hdev);
b312b161
JH
1773 hci_dev_put(hdev);
1774
1775 return err;
1776}
1777
c35938b2
SJ
1778static int read_local_oob_data(struct sock *sk, u16 index)
1779{
1780 struct hci_dev *hdev;
1781 struct pending_cmd *cmd;
1782 int err;
1783
1784 BT_DBG("hci%u", index);
1785
1786 hdev = hci_dev_get(index);
1787 if (!hdev)
1788 return cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
ca69b795 1789 MGMT_STATUS_INVALID_PARAMS);
c35938b2 1790
09fd0de5 1791 hci_dev_lock(hdev);
c35938b2
SJ
1792
1793 if (!test_bit(HCI_UP, &hdev->flags)) {
1794 err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
ca69b795 1795 MGMT_STATUS_NOT_POWERED);
c35938b2
SJ
1796 goto unlock;
1797 }
1798
1799 if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) {
1800 err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
ca69b795 1801 MGMT_STATUS_NOT_SUPPORTED);
c35938b2
SJ
1802 goto unlock;
1803 }
1804
2e58ef3e 1805 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
ca69b795
JH
1806 err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
1807 MGMT_STATUS_BUSY);
c35938b2
SJ
1808 goto unlock;
1809 }
1810
2e58ef3e 1811 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
c35938b2
SJ
1812 if (!cmd) {
1813 err = -ENOMEM;
1814 goto unlock;
1815 }
1816
1817 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
1818 if (err < 0)
1819 mgmt_pending_remove(cmd);
1820
1821unlock:
09fd0de5 1822 hci_dev_unlock(hdev);
c35938b2
SJ
1823 hci_dev_put(hdev);
1824
1825 return err;
1826}
1827
2763eda6
SJ
1828static int add_remote_oob_data(struct sock *sk, u16 index, unsigned char *data,
1829 u16 len)
1830{
1831 struct hci_dev *hdev;
1832 struct mgmt_cp_add_remote_oob_data *cp = (void *) data;
1833 int err;
1834
1835 BT_DBG("hci%u ", index);
1836
1837 if (len != sizeof(*cp))
1838 return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA,
ca69b795 1839 MGMT_STATUS_INVALID_PARAMS);
2763eda6
SJ
1840
1841 hdev = hci_dev_get(index);
1842 if (!hdev)
1843 return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA,
ca69b795 1844 MGMT_STATUS_INVALID_PARAMS);
2763eda6 1845
09fd0de5 1846 hci_dev_lock(hdev);
2763eda6
SJ
1847
1848 err = hci_add_remote_oob_data(hdev, &cp->bdaddr, cp->hash,
1849 cp->randomizer);
1850 if (err < 0)
ca69b795
JH
1851 err = cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA,
1852 MGMT_STATUS_FAILED);
2763eda6
SJ
1853 else
1854 err = cmd_complete(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, NULL,
1855 0);
1856
09fd0de5 1857 hci_dev_unlock(hdev);
2763eda6
SJ
1858 hci_dev_put(hdev);
1859
1860 return err;
1861}
1862
1863static int remove_remote_oob_data(struct sock *sk, u16 index,
1864 unsigned char *data, u16 len)
1865{
1866 struct hci_dev *hdev;
1867 struct mgmt_cp_remove_remote_oob_data *cp = (void *) data;
1868 int err;
1869
1870 BT_DBG("hci%u ", index);
1871
1872 if (len != sizeof(*cp))
1873 return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
ca69b795 1874 MGMT_STATUS_INVALID_PARAMS);
2763eda6
SJ
1875
1876 hdev = hci_dev_get(index);
1877 if (!hdev)
1878 return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
ca69b795 1879 MGMT_STATUS_INVALID_PARAMS);
2763eda6 1880
09fd0de5 1881 hci_dev_lock(hdev);
2763eda6
SJ
1882
1883 err = hci_remove_remote_oob_data(hdev, &cp->bdaddr);
1884 if (err < 0)
1885 err = cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
ca69b795 1886 MGMT_STATUS_INVALID_PARAMS);
2763eda6
SJ
1887 else
1888 err = cmd_complete(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
1889 NULL, 0);
1890
09fd0de5 1891 hci_dev_unlock(hdev);
2763eda6
SJ
1892 hci_dev_put(hdev);
1893
1894 return err;
1895}
1896
450dfdaf
JH
1897static int start_discovery(struct sock *sk, u16 index,
1898 unsigned char *data, u16 len)
14a53664 1899{
450dfdaf 1900 struct mgmt_cp_start_discovery *cp = (void *) data;
14a53664
JH
1901 struct pending_cmd *cmd;
1902 struct hci_dev *hdev;
1903 int err;
1904
1905 BT_DBG("hci%u", index);
1906
450dfdaf
JH
1907 if (len != sizeof(*cp))
1908 return cmd_status(sk, index, MGMT_OP_START_DISCOVERY,
1909 MGMT_STATUS_INVALID_PARAMS);
1910
14a53664
JH
1911 hdev = hci_dev_get(index);
1912 if (!hdev)
ca69b795
JH
1913 return cmd_status(sk, index, MGMT_OP_START_DISCOVERY,
1914 MGMT_STATUS_INVALID_PARAMS);
14a53664 1915
09fd0de5 1916 hci_dev_lock(hdev);
14a53664 1917
bd2d1334 1918 if (!test_bit(HCI_UP, &hdev->flags)) {
ca69b795
JH
1919 err = cmd_status(sk, index, MGMT_OP_START_DISCOVERY,
1920 MGMT_STATUS_NOT_POWERED);
bd2d1334
JH
1921 goto failed;
1922 }
1923
2e58ef3e 1924 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
14a53664
JH
1925 if (!cmd) {
1926 err = -ENOMEM;
1927 goto failed;
1928 }
1929
2519a1fc 1930 err = hci_do_inquiry(hdev, INQUIRY_LEN_BREDR);
14a53664
JH
1931 if (err < 0)
1932 mgmt_pending_remove(cmd);
1933
1934failed:
09fd0de5 1935 hci_dev_unlock(hdev);
14a53664
JH
1936 hci_dev_put(hdev);
1937
1938 return err;
1939}
1940
1941static int stop_discovery(struct sock *sk, u16 index)
1942{
1943 struct hci_dev *hdev;
1944 struct pending_cmd *cmd;
1945 int err;
1946
1947 BT_DBG("hci%u", index);
1948
1949 hdev = hci_dev_get(index);
1950 if (!hdev)
ca69b795
JH
1951 return cmd_status(sk, index, MGMT_OP_STOP_DISCOVERY,
1952 MGMT_STATUS_INVALID_PARAMS);
14a53664 1953
09fd0de5 1954 hci_dev_lock(hdev);
14a53664 1955
2e58ef3e 1956 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
14a53664
JH
1957 if (!cmd) {
1958 err = -ENOMEM;
1959 goto failed;
1960 }
1961
023d5049 1962 err = hci_cancel_inquiry(hdev);
14a53664
JH
1963 if (err < 0)
1964 mgmt_pending_remove(cmd);
1965
1966failed:
09fd0de5 1967 hci_dev_unlock(hdev);
14a53664
JH
1968 hci_dev_put(hdev);
1969
1970 return err;
1971}
1972
7fbec224
AJ
1973static int block_device(struct sock *sk, u16 index, unsigned char *data,
1974 u16 len)
1975{
1976 struct hci_dev *hdev;
5e762444 1977 struct mgmt_cp_block_device *cp = (void *) data;
7fbec224
AJ
1978 int err;
1979
1980 BT_DBG("hci%u", index);
1981
7fbec224
AJ
1982 if (len != sizeof(*cp))
1983 return cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE,
ca69b795 1984 MGMT_STATUS_INVALID_PARAMS);
7fbec224
AJ
1985
1986 hdev = hci_dev_get(index);
1987 if (!hdev)
1988 return cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE,
ca69b795 1989 MGMT_STATUS_INVALID_PARAMS);
7fbec224 1990
09fd0de5 1991 hci_dev_lock(hdev);
5e762444 1992
7fbec224 1993 err = hci_blacklist_add(hdev, &cp->bdaddr);
7fbec224 1994 if (err < 0)
ca69b795
JH
1995 err = cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE,
1996 MGMT_STATUS_FAILED);
7fbec224
AJ
1997 else
1998 err = cmd_complete(sk, index, MGMT_OP_BLOCK_DEVICE,
1999 NULL, 0);
5e762444 2000
09fd0de5 2001 hci_dev_unlock(hdev);
7fbec224
AJ
2002 hci_dev_put(hdev);
2003
2004 return err;
2005}
2006
2007static int unblock_device(struct sock *sk, u16 index, unsigned char *data,
2008 u16 len)
2009{
2010 struct hci_dev *hdev;
5e762444 2011 struct mgmt_cp_unblock_device *cp = (void *) data;
7fbec224
AJ
2012 int err;
2013
2014 BT_DBG("hci%u", index);
2015
7fbec224
AJ
2016 if (len != sizeof(*cp))
2017 return cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE,
ca69b795 2018 MGMT_STATUS_INVALID_PARAMS);
7fbec224
AJ
2019
2020 hdev = hci_dev_get(index);
2021 if (!hdev)
2022 return cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE,
ca69b795 2023 MGMT_STATUS_INVALID_PARAMS);
7fbec224 2024
09fd0de5 2025 hci_dev_lock(hdev);
5e762444 2026
7fbec224
AJ
2027 err = hci_blacklist_del(hdev, &cp->bdaddr);
2028
2029 if (err < 0)
ca69b795
JH
2030 err = cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE,
2031 MGMT_STATUS_INVALID_PARAMS);
7fbec224
AJ
2032 else
2033 err = cmd_complete(sk, index, MGMT_OP_UNBLOCK_DEVICE,
2034 NULL, 0);
5e762444 2035
09fd0de5 2036 hci_dev_unlock(hdev);
7fbec224
AJ
2037 hci_dev_put(hdev);
2038
2039 return err;
2040}
2041
f6422ec6
AJ
2042static int set_fast_connectable(struct sock *sk, u16 index,
2043 unsigned char *data, u16 len)
2044{
2045 struct hci_dev *hdev;
f7c6869c 2046 struct mgmt_mode *cp = (void *) data;
f6422ec6
AJ
2047 struct hci_cp_write_page_scan_activity acp;
2048 u8 type;
2049 int err;
2050
2051 BT_DBG("hci%u", index);
2052
2053 if (len != sizeof(*cp))
2054 return cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE,
ca69b795 2055 MGMT_STATUS_INVALID_PARAMS);
f6422ec6
AJ
2056
2057 hdev = hci_dev_get(index);
2058 if (!hdev)
2059 return cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE,
ca69b795 2060 MGMT_STATUS_INVALID_PARAMS);
f6422ec6
AJ
2061
2062 hci_dev_lock(hdev);
2063
f7c6869c 2064 if (cp->val) {
f6422ec6
AJ
2065 type = PAGE_SCAN_TYPE_INTERLACED;
2066 acp.interval = 0x0024; /* 22.5 msec page scan interval */
2067 } else {
2068 type = PAGE_SCAN_TYPE_STANDARD; /* default */
2069 acp.interval = 0x0800; /* default 1.28 sec page scan */
2070 }
2071
2072 acp.window = 0x0012; /* default 11.25 msec page scan window */
2073
2074 err = hci_send_cmd(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
2075 sizeof(acp), &acp);
2076 if (err < 0) {
2077 err = cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE,
ca69b795 2078 MGMT_STATUS_FAILED);
f6422ec6
AJ
2079 goto done;
2080 }
2081
2082 err = hci_send_cmd(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
2083 if (err < 0) {
2084 err = cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE,
ca69b795 2085 MGMT_STATUS_FAILED);
f6422ec6
AJ
2086 goto done;
2087 }
2088
2089 err = cmd_complete(sk, index, MGMT_OP_SET_FAST_CONNECTABLE,
2090 NULL, 0);
2091done:
2092 hci_dev_unlock(hdev);
2093 hci_dev_put(hdev);
2094
2095 return err;
2096}
2097
0381101f
JH
2098int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
2099{
2100 unsigned char *buf;
2101 struct mgmt_hdr *hdr;
4e51eae9 2102 u16 opcode, index, len;
0381101f
JH
2103 int err;
2104
2105 BT_DBG("got %zu bytes", msglen);
2106
2107 if (msglen < sizeof(*hdr))
2108 return -EINVAL;
2109
e63a15ec 2110 buf = kmalloc(msglen, GFP_KERNEL);
0381101f
JH
2111 if (!buf)
2112 return -ENOMEM;
2113
2114 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
2115 err = -EFAULT;
2116 goto done;
2117 }
2118
2119 hdr = (struct mgmt_hdr *) buf;
2120 opcode = get_unaligned_le16(&hdr->opcode);
4e51eae9 2121 index = get_unaligned_le16(&hdr->index);
0381101f
JH
2122 len = get_unaligned_le16(&hdr->len);
2123
2124 if (len != msglen - sizeof(*hdr)) {
2125 err = -EINVAL;
2126 goto done;
2127 }
2128
2129 switch (opcode) {
02d98129
JH
2130 case MGMT_OP_READ_VERSION:
2131 err = read_version(sk);
2132 break;
faba42eb
JH
2133 case MGMT_OP_READ_INDEX_LIST:
2134 err = read_index_list(sk);
2135 break;
f7b64e69 2136 case MGMT_OP_READ_INFO:
4e51eae9 2137 err = read_controller_info(sk, index);
f7b64e69 2138 break;
eec8d2bc 2139 case MGMT_OP_SET_POWERED:
4e51eae9 2140 err = set_powered(sk, index, buf + sizeof(*hdr), len);
eec8d2bc 2141 break;
73f22f62 2142 case MGMT_OP_SET_DISCOVERABLE:
4e51eae9 2143 err = set_discoverable(sk, index, buf + sizeof(*hdr), len);
73f22f62 2144 break;
9fbcbb45 2145 case MGMT_OP_SET_CONNECTABLE:
4e51eae9 2146 err = set_connectable(sk, index, buf + sizeof(*hdr), len);
9fbcbb45 2147 break;
f7c6869c
JH
2148 case MGMT_OP_SET_FAST_CONNECTABLE:
2149 err = set_fast_connectable(sk, index, buf + sizeof(*hdr),
2150 len);
2151 break;
c542a06c 2152 case MGMT_OP_SET_PAIRABLE:
4e51eae9 2153 err = set_pairable(sk, index, buf + sizeof(*hdr), len);
c542a06c 2154 break;
2aeb9a1a 2155 case MGMT_OP_ADD_UUID:
4e51eae9 2156 err = add_uuid(sk, index, buf + sizeof(*hdr), len);
2aeb9a1a
JH
2157 break;
2158 case MGMT_OP_REMOVE_UUID:
4e51eae9 2159 err = remove_uuid(sk, index, buf + sizeof(*hdr), len);
2aeb9a1a 2160 break;
1aff6f09 2161 case MGMT_OP_SET_DEV_CLASS:
4e51eae9 2162 err = set_dev_class(sk, index, buf + sizeof(*hdr), len);
1aff6f09 2163 break;
86742e1e
JH
2164 case MGMT_OP_LOAD_LINK_KEYS:
2165 err = load_link_keys(sk, index, buf + sizeof(*hdr), len);
55ed8ca1 2166 break;
86742e1e
JH
2167 case MGMT_OP_REMOVE_KEYS:
2168 err = remove_keys(sk, index, buf + sizeof(*hdr), len);
55ed8ca1 2169 break;
8962ee74 2170 case MGMT_OP_DISCONNECT:
4e51eae9 2171 err = disconnect(sk, index, buf + sizeof(*hdr), len);
8962ee74 2172 break;
2784eb41 2173 case MGMT_OP_GET_CONNECTIONS:
8ce6284e 2174 err = get_connections(sk, index);
2784eb41 2175 break;
980e1a53 2176 case MGMT_OP_PIN_CODE_REPLY:
4e51eae9 2177 err = pin_code_reply(sk, index, buf + sizeof(*hdr), len);
980e1a53
JH
2178 break;
2179 case MGMT_OP_PIN_CODE_NEG_REPLY:
4e51eae9 2180 err = pin_code_neg_reply(sk, index, buf + sizeof(*hdr), len);
980e1a53 2181 break;
17fa4b9d 2182 case MGMT_OP_SET_IO_CAPABILITY:
4e51eae9 2183 err = set_io_capability(sk, index, buf + sizeof(*hdr), len);
17fa4b9d 2184 break;
e9a416b5 2185 case MGMT_OP_PAIR_DEVICE:
4e51eae9 2186 err = pair_device(sk, index, buf + sizeof(*hdr), len);
e9a416b5 2187 break;
a5c29683 2188 case MGMT_OP_USER_CONFIRM_REPLY:
0df4c185 2189 err = user_confirm_reply(sk, index, buf + sizeof(*hdr), len);
a5c29683
JH
2190 break;
2191 case MGMT_OP_USER_CONFIRM_NEG_REPLY:
0df4c185
BG
2192 err = user_confirm_neg_reply(sk, index, buf + sizeof(*hdr),
2193 len);
a5c29683 2194 break;
604086b7
BG
2195 case MGMT_OP_USER_PASSKEY_REPLY:
2196 err = user_passkey_reply(sk, index, buf + sizeof(*hdr), len);
2197 break;
2198 case MGMT_OP_USER_PASSKEY_NEG_REPLY:
2199 err = user_passkey_neg_reply(sk, index, buf + sizeof(*hdr),
2200 len);
2201 break;
b312b161
JH
2202 case MGMT_OP_SET_LOCAL_NAME:
2203 err = set_local_name(sk, index, buf + sizeof(*hdr), len);
2204 break;
c35938b2
SJ
2205 case MGMT_OP_READ_LOCAL_OOB_DATA:
2206 err = read_local_oob_data(sk, index);
2207 break;
2763eda6
SJ
2208 case MGMT_OP_ADD_REMOTE_OOB_DATA:
2209 err = add_remote_oob_data(sk, index, buf + sizeof(*hdr), len);
2210 break;
2211 case MGMT_OP_REMOVE_REMOTE_OOB_DATA:
2212 err = remove_remote_oob_data(sk, index, buf + sizeof(*hdr),
2213 len);
2214 break;
14a53664 2215 case MGMT_OP_START_DISCOVERY:
450dfdaf 2216 err = start_discovery(sk, index, buf + sizeof(*hdr), len);
14a53664
JH
2217 break;
2218 case MGMT_OP_STOP_DISCOVERY:
2219 err = stop_discovery(sk, index);
2220 break;
7fbec224
AJ
2221 case MGMT_OP_BLOCK_DEVICE:
2222 err = block_device(sk, index, buf + sizeof(*hdr), len);
2223 break;
2224 case MGMT_OP_UNBLOCK_DEVICE:
2225 err = unblock_device(sk, index, buf + sizeof(*hdr), len);
2226 break;
0381101f
JH
2227 default:
2228 BT_DBG("Unknown op %u", opcode);
ca69b795
JH
2229 err = cmd_status(sk, index, opcode,
2230 MGMT_STATUS_UNKNOWN_COMMAND);
0381101f
JH
2231 break;
2232 }
2233
e41d8b4e
JH
2234 if (err < 0)
2235 goto done;
2236
0381101f
JH
2237 err = msglen;
2238
2239done:
2240 kfree(buf);
2241 return err;
2242}
c71e97bf 2243
b24752fe
JH
2244static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
2245{
2246 u8 *status = data;
2247
2248 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
2249 mgmt_pending_remove(cmd);
2250}
2251
744cf19e 2252int mgmt_index_added(struct hci_dev *hdev)
c71e97bf 2253{
744cf19e 2254 return mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
c71e97bf
JH
2255}
2256
744cf19e 2257int mgmt_index_removed(struct hci_dev *hdev)
c71e97bf 2258{
b24752fe
JH
2259 u8 status = ENODEV;
2260
744cf19e 2261 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
b24752fe 2262
744cf19e 2263 return mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
eec8d2bc
JH
2264}
2265
73f22f62 2266struct cmd_lookup {
72a734ec 2267 u8 val;
eec8d2bc 2268 struct sock *sk;
69ab39ea 2269 struct hci_dev *hdev;
eec8d2bc
JH
2270};
2271
69ab39ea 2272static void settings_rsp(struct pending_cmd *cmd, void *data)
eec8d2bc 2273{
73f22f62 2274 struct cmd_lookup *match = data;
eec8d2bc 2275
69ab39ea 2276 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
eec8d2bc
JH
2277
2278 list_del(&cmd->list);
2279
2280 if (match->sk == NULL) {
2281 match->sk = cmd->sk;
2282 sock_hold(match->sk);
2283 }
2284
2285 mgmt_pending_free(cmd);
c71e97bf 2286}
5add6af8 2287
744cf19e 2288int mgmt_powered(struct hci_dev *hdev, u8 powered)
5add6af8 2289{
69ab39ea
JH
2290 struct cmd_lookup match = { powered, NULL, hdev };
2291 __le32 ev;
eec8d2bc 2292 int ret;
5add6af8 2293
69ab39ea 2294 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5add6af8 2295
b24752fe
JH
2296 if (!powered) {
2297 u8 status = ENETDOWN;
744cf19e 2298 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
b24752fe
JH
2299 }
2300
69ab39ea 2301 ev = cpu_to_le32(get_current_settings(hdev));
eec8d2bc 2302
69ab39ea
JH
2303 ret = mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev),
2304 match.sk);
eec8d2bc
JH
2305
2306 if (match.sk)
2307 sock_put(match.sk);
2308
2309 return ret;
5add6af8 2310}
73f22f62 2311
744cf19e 2312int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
73f22f62 2313{
69ab39ea
JH
2314 struct cmd_lookup match = { discoverable, NULL, hdev };
2315 __le32 ev;
73f22f62
JH
2316 int ret;
2317
69ab39ea 2318 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev, settings_rsp, &match);
72a734ec 2319
69ab39ea 2320 ev = cpu_to_le32(get_current_settings(hdev));
73f22f62 2321
69ab39ea 2322 ret = mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev),
4e51eae9 2323 match.sk);
73f22f62
JH
2324 if (match.sk)
2325 sock_put(match.sk);
2326
2327 return ret;
2328}
9fbcbb45 2329
744cf19e 2330int mgmt_connectable(struct hci_dev *hdev, u8 connectable)
9fbcbb45 2331{
69ab39ea
JH
2332 __le32 ev;
2333 struct cmd_lookup match = { connectable, NULL, hdev };
9fbcbb45
JH
2334 int ret;
2335
69ab39ea
JH
2336 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev, settings_rsp,
2337 &match);
9fbcbb45 2338
69ab39ea 2339 ev = cpu_to_le32(get_current_settings(hdev));
9fbcbb45 2340
69ab39ea 2341 ret = mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), match.sk);
9fbcbb45
JH
2342
2343 if (match.sk)
2344 sock_put(match.sk);
2345
2346 return ret;
2347}
55ed8ca1 2348
744cf19e 2349int mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
2d7cee58 2350{
ca69b795
JH
2351 u8 mgmt_err = mgmt_status(status);
2352
2d7cee58 2353 if (scan & SCAN_PAGE)
744cf19e 2354 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
ca69b795 2355 cmd_status_rsp, &mgmt_err);
2d7cee58
JH
2356
2357 if (scan & SCAN_INQUIRY)
744cf19e 2358 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
ca69b795 2359 cmd_status_rsp, &mgmt_err);
2d7cee58
JH
2360
2361 return 0;
2362}
2363
744cf19e
JH
2364int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
2365 u8 persistent)
55ed8ca1 2366{
86742e1e 2367 struct mgmt_ev_new_link_key ev;
55ed8ca1 2368
a492cd52 2369 memset(&ev, 0, sizeof(ev));
55ed8ca1 2370
a492cd52
VCG
2371 ev.store_hint = persistent;
2372 bacpy(&ev.key.bdaddr, &key->bdaddr);
2373 ev.key.type = key->type;
2374 memcpy(ev.key.val, key->val, 16);
2375 ev.key.pin_len = key->pin_len;
55ed8ca1 2376
744cf19e 2377 return mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
55ed8ca1 2378}
f7520543 2379
48264f06
JH
2380int mgmt_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
2381 u8 addr_type)
f7520543 2382{
4c659c39 2383 struct mgmt_addr_info ev;
f7520543 2384
f7520543 2385 bacpy(&ev.bdaddr, bdaddr);
48264f06 2386 ev.type = link_to_mgmt(link_type, addr_type);
f7520543 2387
744cf19e 2388 return mgmt_event(MGMT_EV_CONNECTED, hdev, &ev, sizeof(ev), NULL);
f7520543
JH
2389}
2390
8962ee74
JH
2391static void disconnect_rsp(struct pending_cmd *cmd, void *data)
2392{
c68fb7ff 2393 struct mgmt_cp_disconnect *cp = cmd->param;
8962ee74 2394 struct sock **sk = data;
a38528f1 2395 struct mgmt_rp_disconnect rp;
8962ee74 2396
a38528f1 2397 bacpy(&rp.bdaddr, &cp->bdaddr);
37d9ef76 2398 rp.status = 0;
8962ee74 2399
4e51eae9 2400 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, &rp, sizeof(rp));
8962ee74
JH
2401
2402 *sk = cmd->sk;
2403 sock_hold(*sk);
2404
a664b5bc 2405 mgmt_pending_remove(cmd);
8962ee74
JH
2406}
2407
a8a1d19e
JH
2408static void remove_keys_rsp(struct pending_cmd *cmd, void *data)
2409{
2410 u8 *status = data;
2411 struct mgmt_cp_remove_keys *cp = cmd->param;
2412 struct mgmt_rp_remove_keys rp;
2413
2414 memset(&rp, 0, sizeof(rp));
2415 bacpy(&rp.bdaddr, &cp->bdaddr);
2416 if (status != NULL)
2417 rp.status = *status;
2418
2419 cmd_complete(cmd->sk, cmd->index, MGMT_OP_REMOVE_KEYS, &rp,
2420 sizeof(rp));
2421
2422 mgmt_pending_remove(cmd);
2423}
2424
48264f06
JH
2425int mgmt_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
2426 u8 addr_type)
f7520543 2427{
4c659c39 2428 struct mgmt_addr_info ev;
8962ee74
JH
2429 struct sock *sk = NULL;
2430 int err;
2431
744cf19e 2432 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
f7520543 2433
f7520543 2434 bacpy(&ev.bdaddr, bdaddr);
48264f06 2435 ev.type = link_to_mgmt(link_type, addr_type);
f7520543 2436
744cf19e 2437 err = mgmt_event(MGMT_EV_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
8962ee74
JH
2438
2439 if (sk)
2440 sock_put(sk);
2441
a8a1d19e
JH
2442 mgmt_pending_foreach(MGMT_OP_REMOVE_KEYS, hdev, remove_keys_rsp, NULL);
2443
8962ee74
JH
2444 return err;
2445}
2446
37d9ef76 2447int mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status)
8962ee74
JH
2448{
2449 struct pending_cmd *cmd;
ca69b795 2450 u8 mgmt_err = mgmt_status(status);
8962ee74
JH
2451 int err;
2452
2e58ef3e 2453 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
8962ee74
JH
2454 if (!cmd)
2455 return -ENOENT;
2456
37d9ef76
JH
2457 if (bdaddr) {
2458 struct mgmt_rp_disconnect rp;
2459
2460 bacpy(&rp.bdaddr, bdaddr);
2461 rp.status = status;
2462
2463 err = cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
2464 &rp, sizeof(rp));
2465 } else
2466 err = cmd_status(cmd->sk, hdev->id, MGMT_OP_DISCONNECT,
ca69b795 2467 mgmt_err);
8962ee74 2468
a664b5bc 2469 mgmt_pending_remove(cmd);
8962ee74
JH
2470
2471 return err;
f7520543 2472}
17d5c04c 2473
48264f06
JH
2474int mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
2475 u8 addr_type, u8 status)
17d5c04c
JH
2476{
2477 struct mgmt_ev_connect_failed ev;
2478
4c659c39 2479 bacpy(&ev.addr.bdaddr, bdaddr);
48264f06 2480 ev.addr.type = link_to_mgmt(link_type, addr_type);
ca69b795 2481 ev.status = mgmt_status(status);
17d5c04c 2482
744cf19e 2483 return mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
17d5c04c 2484}
980e1a53 2485
744cf19e 2486int mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
980e1a53
JH
2487{
2488 struct mgmt_ev_pin_code_request ev;
2489
980e1a53 2490 bacpy(&ev.bdaddr, bdaddr);
a770bb5a 2491 ev.secure = secure;
980e1a53 2492
744cf19e 2493 return mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev),
4e51eae9 2494 NULL);
980e1a53
JH
2495}
2496
744cf19e
JH
2497int mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
2498 u8 status)
980e1a53
JH
2499{
2500 struct pending_cmd *cmd;
ac56fb13 2501 struct mgmt_rp_pin_code_reply rp;
980e1a53
JH
2502 int err;
2503
2e58ef3e 2504 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
980e1a53
JH
2505 if (!cmd)
2506 return -ENOENT;
2507
ac56fb13 2508 bacpy(&rp.bdaddr, bdaddr);
ca69b795 2509 rp.status = mgmt_status(status);
ac56fb13 2510
744cf19e 2511 err = cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY, &rp,
4e51eae9 2512 sizeof(rp));
980e1a53 2513
a664b5bc 2514 mgmt_pending_remove(cmd);
980e1a53
JH
2515
2516 return err;
2517}
2518
744cf19e
JH
2519int mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
2520 u8 status)
980e1a53
JH
2521{
2522 struct pending_cmd *cmd;
ac56fb13 2523 struct mgmt_rp_pin_code_reply rp;
980e1a53
JH
2524 int err;
2525
2e58ef3e 2526 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
980e1a53
JH
2527 if (!cmd)
2528 return -ENOENT;
2529
ac56fb13 2530 bacpy(&rp.bdaddr, bdaddr);
ca69b795 2531 rp.status = mgmt_status(status);
ac56fb13 2532
744cf19e 2533 err = cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY, &rp,
4e51eae9 2534 sizeof(rp));
980e1a53 2535
a664b5bc 2536 mgmt_pending_remove(cmd);
980e1a53
JH
2537
2538 return err;
2539}
a5c29683 2540
744cf19e
JH
2541int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
2542 __le32 value, u8 confirm_hint)
a5c29683
JH
2543{
2544 struct mgmt_ev_user_confirm_request ev;
2545
744cf19e 2546 BT_DBG("%s", hdev->name);
a5c29683 2547
a5c29683 2548 bacpy(&ev.bdaddr, bdaddr);
55bc1a37 2549 ev.confirm_hint = confirm_hint;
a5c29683
JH
2550 put_unaligned_le32(value, &ev.value);
2551
744cf19e 2552 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
4e51eae9 2553 NULL);
a5c29683
JH
2554}
2555
604086b7
BG
2556int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr)
2557{
2558 struct mgmt_ev_user_passkey_request ev;
2559
2560 BT_DBG("%s", hdev->name);
2561
2562 bacpy(&ev.bdaddr, bdaddr);
2563
2564 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
2565 NULL);
2566}
2567
0df4c185 2568static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
744cf19e 2569 u8 status, u8 opcode)
a5c29683
JH
2570{
2571 struct pending_cmd *cmd;
2572 struct mgmt_rp_user_confirm_reply rp;
2573 int err;
2574
2e58ef3e 2575 cmd = mgmt_pending_find(opcode, hdev);
a5c29683
JH
2576 if (!cmd)
2577 return -ENOENT;
2578
a5c29683 2579 bacpy(&rp.bdaddr, bdaddr);
ca69b795 2580 rp.status = mgmt_status(status);
744cf19e 2581 err = cmd_complete(cmd->sk, hdev->id, opcode, &rp, sizeof(rp));
a5c29683 2582
a664b5bc 2583 mgmt_pending_remove(cmd);
a5c29683
JH
2584
2585 return err;
2586}
2587
744cf19e
JH
2588int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
2589 u8 status)
a5c29683 2590{
0df4c185 2591 return user_pairing_resp_complete(hdev, bdaddr, status,
a5c29683
JH
2592 MGMT_OP_USER_CONFIRM_REPLY);
2593}
2594
744cf19e
JH
2595int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev,
2596 bdaddr_t *bdaddr, u8 status)
a5c29683 2597{
0df4c185 2598 return user_pairing_resp_complete(hdev, bdaddr, status,
a5c29683
JH
2599 MGMT_OP_USER_CONFIRM_NEG_REPLY);
2600}
2a611692 2601
604086b7
BG
2602int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
2603 u8 status)
2604{
2605 return user_pairing_resp_complete(hdev, bdaddr, status,
2606 MGMT_OP_USER_PASSKEY_REPLY);
2607}
2608
2609int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev,
2610 bdaddr_t *bdaddr, u8 status)
2611{
2612 return user_pairing_resp_complete(hdev, bdaddr, status,
2613 MGMT_OP_USER_PASSKEY_NEG_REPLY);
2614}
2615
744cf19e 2616int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status)
2a611692
JH
2617{
2618 struct mgmt_ev_auth_failed ev;
2619
2a611692 2620 bacpy(&ev.bdaddr, bdaddr);
ca69b795 2621 ev.status = mgmt_status(status);
2a611692 2622
744cf19e 2623 return mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
2a611692 2624}
b312b161 2625
744cf19e 2626int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
b312b161
JH
2627{
2628 struct pending_cmd *cmd;
2629 struct mgmt_cp_set_local_name ev;
2630 int err;
2631
2632 memset(&ev, 0, sizeof(ev));
2633 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
2634
2e58ef3e 2635 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
b312b161
JH
2636 if (!cmd)
2637 goto send_event;
2638
2639 if (status) {
744cf19e 2640 err = cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
ca69b795 2641 mgmt_status(status));
b312b161
JH
2642 goto failed;
2643 }
2644
744cf19e 2645 update_eir(hdev);
80a1e1db 2646
744cf19e 2647 err = cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, &ev,
b312b161
JH
2648 sizeof(ev));
2649 if (err < 0)
2650 goto failed;
2651
2652send_event:
744cf19e 2653 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
b312b161
JH
2654 cmd ? cmd->sk : NULL);
2655
2656failed:
2657 if (cmd)
2658 mgmt_pending_remove(cmd);
2659 return err;
2660}
c35938b2 2661
744cf19e
JH
2662int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash,
2663 u8 *randomizer, u8 status)
c35938b2
SJ
2664{
2665 struct pending_cmd *cmd;
2666 int err;
2667
744cf19e 2668 BT_DBG("%s status %u", hdev->name, status);
c35938b2 2669
2e58ef3e 2670 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
c35938b2
SJ
2671 if (!cmd)
2672 return -ENOENT;
2673
2674 if (status) {
744cf19e 2675 err = cmd_status(cmd->sk, hdev->id,
ca69b795
JH
2676 MGMT_OP_READ_LOCAL_OOB_DATA,
2677 mgmt_status(status));
c35938b2
SJ
2678 } else {
2679 struct mgmt_rp_read_local_oob_data rp;
2680
2681 memcpy(rp.hash, hash, sizeof(rp.hash));
2682 memcpy(rp.randomizer, randomizer, sizeof(rp.randomizer));
2683
744cf19e
JH
2684 err = cmd_complete(cmd->sk, hdev->id,
2685 MGMT_OP_READ_LOCAL_OOB_DATA,
2686 &rp, sizeof(rp));
c35938b2
SJ
2687 }
2688
2689 mgmt_pending_remove(cmd);
2690
2691 return err;
2692}
e17acd40 2693
48264f06
JH
2694int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
2695 u8 addr_type, u8 *dev_class, s8 rssi, u8 *eir)
e17acd40
JH
2696{
2697 struct mgmt_ev_device_found ev;
2698
2699 memset(&ev, 0, sizeof(ev));
2700
4c659c39 2701 bacpy(&ev.addr.bdaddr, bdaddr);
48264f06 2702 ev.addr.type = link_to_mgmt(link_type, addr_type);
e17acd40
JH
2703 ev.rssi = rssi;
2704
2705 if (eir)
2706 memcpy(ev.eir, eir, sizeof(ev.eir));
2707
f8523598
AG
2708 if (dev_class)
2709 memcpy(ev.dev_class, dev_class, sizeof(ev.dev_class));
2710
744cf19e 2711 return mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, &ev, sizeof(ev), NULL);
e17acd40 2712}
a88a9652 2713
744cf19e 2714int mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *name)
a88a9652
JH
2715{
2716 struct mgmt_ev_remote_name ev;
2717
2718 memset(&ev, 0, sizeof(ev));
2719
2720 bacpy(&ev.bdaddr, bdaddr);
2721 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
2722
744cf19e 2723 return mgmt_event(MGMT_EV_REMOTE_NAME, hdev, &ev, sizeof(ev), NULL);
a88a9652 2724}
314b2381 2725
7a135109 2726int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
164a6e78
JH
2727{
2728 struct pending_cmd *cmd;
2729 int err;
2730
2e58ef3e 2731 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
164a6e78
JH
2732 if (!cmd)
2733 return -ENOENT;
2734
ca69b795 2735 err = cmd_status(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status));
164a6e78
JH
2736 mgmt_pending_remove(cmd);
2737
2738 return err;
2739}
2740
e6d465cb
AG
2741int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
2742{
2743 struct pending_cmd *cmd;
2744 int err;
2745
2746 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
2747 if (!cmd)
2748 return -ENOENT;
2749
2750 err = cmd_status(cmd->sk, hdev->id, cmd->opcode, status);
2751 mgmt_pending_remove(cmd);
2752
2753 return err;
2754}
2755
744cf19e 2756int mgmt_discovering(struct hci_dev *hdev, u8 discovering)
314b2381 2757{
164a6e78
JH
2758 struct pending_cmd *cmd;
2759
2760 if (discovering)
2e58ef3e 2761 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
164a6e78 2762 else
2e58ef3e 2763 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
164a6e78
JH
2764
2765 if (cmd != NULL) {
744cf19e 2766 cmd_complete(cmd->sk, hdev->id, cmd->opcode, NULL, 0);
164a6e78
JH
2767 mgmt_pending_remove(cmd);
2768 }
2769
744cf19e 2770 return mgmt_event(MGMT_EV_DISCOVERING, hdev, &discovering,
314b2381
JH
2771 sizeof(discovering), NULL);
2772}
5e762444 2773
744cf19e 2774int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr)
5e762444
AJ
2775{
2776 struct pending_cmd *cmd;
2777 struct mgmt_ev_device_blocked ev;
2778
2e58ef3e 2779 cmd = mgmt_pending_find(MGMT_OP_BLOCK_DEVICE, hdev);
5e762444
AJ
2780
2781 bacpy(&ev.bdaddr, bdaddr);
2782
744cf19e
JH
2783 return mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &ev, sizeof(ev),
2784 cmd ? cmd->sk : NULL);
5e762444
AJ
2785}
2786
744cf19e 2787int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr)
5e762444
AJ
2788{
2789 struct pending_cmd *cmd;
2790 struct mgmt_ev_device_unblocked ev;
2791
2e58ef3e 2792 cmd = mgmt_pending_find(MGMT_OP_UNBLOCK_DEVICE, hdev);
5e762444
AJ
2793
2794 bacpy(&ev.bdaddr, bdaddr);
2795
744cf19e
JH
2796 return mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &ev, sizeof(ev),
2797 cmd ? cmd->sk : NULL);
5e762444 2798}
This page took 0.228993 seconds and 5 git commands to generate.