]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blame - net/bluetooth/mgmt.c
Bluetooth: Make pending_add return a pointer to the added entry
[mirror_ubuntu-zesty-kernel.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
72359753 25#include <linux/uaccess.h>
0381101f
JH
26#include <asm/unaligned.h>
27
28#include <net/bluetooth/bluetooth.h>
29#include <net/bluetooth/hci_core.h>
30#include <net/bluetooth/mgmt.h>
31
02d98129
JH
32#define MGMT_VERSION 0
33#define MGMT_REVISION 1
34
eec8d2bc
JH
35struct pending_cmd {
36 struct list_head list;
37 __u16 opcode;
38 int index;
39 void *cmd;
40 struct sock *sk;
41};
42
43LIST_HEAD(cmd_list);
44
f7b64e69
JH
45static int cmd_status(struct sock *sk, u16 cmd, u8 status)
46{
47 struct sk_buff *skb;
48 struct mgmt_hdr *hdr;
49 struct mgmt_ev_cmd_status *ev;
50
51 BT_DBG("sock %p", sk);
52
53 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_ATOMIC);
54 if (!skb)
55 return -ENOMEM;
56
57 hdr = (void *) skb_put(skb, sizeof(*hdr));
58
59 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
60 hdr->len = cpu_to_le16(sizeof(*ev));
61
62 ev = (void *) skb_put(skb, sizeof(*ev));
63 ev->status = status;
64 put_unaligned_le16(cmd, &ev->opcode);
65
66 if (sock_queue_rcv_skb(sk, skb) < 0)
67 kfree_skb(skb);
68
69 return 0;
70}
71
a38528f1 72static int cmd_complete(struct sock *sk, u16 cmd, void *rp, size_t rp_len)
02d98129
JH
73{
74 struct sk_buff *skb;
75 struct mgmt_hdr *hdr;
76 struct mgmt_ev_cmd_complete *ev;
02d98129
JH
77
78 BT_DBG("sock %p", sk);
79
a38528f1 80 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_ATOMIC);
02d98129
JH
81 if (!skb)
82 return -ENOMEM;
83
84 hdr = (void *) skb_put(skb, sizeof(*hdr));
02d98129 85
a38528f1
JH
86 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
87 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
02d98129 88
a38528f1
JH
89 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
90 put_unaligned_le16(cmd, &ev->opcode);
91 memcpy(ev->data, rp, rp_len);
02d98129
JH
92
93 if (sock_queue_rcv_skb(sk, skb) < 0)
94 kfree_skb(skb);
95
96 return 0;
97}
98
a38528f1
JH
99static int read_version(struct sock *sk)
100{
101 struct mgmt_rp_read_version rp;
102
103 BT_DBG("sock %p", sk);
104
105 rp.version = MGMT_VERSION;
106 put_unaligned_le16(MGMT_REVISION, &rp.revision);
107
108 return cmd_complete(sk, MGMT_OP_READ_VERSION, &rp, sizeof(rp));
109}
110
faba42eb
JH
111static int read_index_list(struct sock *sk)
112{
faba42eb
JH
113 struct mgmt_rp_read_index_list *rp;
114 struct list_head *p;
a38528f1 115 size_t rp_len;
faba42eb 116 u16 count;
a38528f1 117 int i, err;
faba42eb
JH
118
119 BT_DBG("sock %p", sk);
120
121 read_lock(&hci_dev_list_lock);
122
123 count = 0;
124 list_for_each(p, &hci_dev_list) {
125 count++;
126 }
127
a38528f1
JH
128 rp_len = sizeof(*rp) + (2 * count);
129 rp = kmalloc(rp_len, GFP_ATOMIC);
130 if (!rp) {
b2c60d42 131 read_unlock(&hci_dev_list_lock);
faba42eb 132 return -ENOMEM;
b2c60d42 133 }
faba42eb 134
faba42eb
JH
135 put_unaligned_le16(count, &rp->num_controllers);
136
137 i = 0;
138 list_for_each(p, &hci_dev_list) {
139 struct hci_dev *d = list_entry(p, struct hci_dev, list);
ab81cbf9
JH
140
141 hci_del_off_timer(d);
142
ebc99feb
JH
143 set_bit(HCI_MGMT, &d->flags);
144
ab81cbf9
JH
145 if (test_bit(HCI_SETUP, &d->flags))
146 continue;
147
faba42eb
JH
148 put_unaligned_le16(d->id, &rp->index[i++]);
149 BT_DBG("Added hci%u", d->id);
150 }
151
152 read_unlock(&hci_dev_list_lock);
153
a38528f1 154 err = cmd_complete(sk, MGMT_OP_READ_INDEX_LIST, rp, rp_len);
faba42eb 155
a38528f1
JH
156 kfree(rp);
157
158 return err;
faba42eb
JH
159}
160
f7b64e69 161static int read_controller_info(struct sock *sk, unsigned char *data, u16 len)
0381101f 162{
a38528f1
JH
163 struct mgmt_rp_read_info rp;
164 struct mgmt_cp_read_info *cp = (void *) data;
f7b64e69
JH
165 struct hci_dev *hdev;
166 u16 dev_id;
0381101f
JH
167
168 BT_DBG("sock %p", sk);
169
f7b64e69
JH
170 if (len != 2)
171 return cmd_status(sk, MGMT_OP_READ_INFO, EINVAL);
172
f7b64e69
JH
173 dev_id = get_unaligned_le16(&cp->index);
174
175 BT_DBG("request for hci%u", dev_id);
176
177 hdev = hci_dev_get(dev_id);
a38528f1 178 if (!hdev)
f7b64e69 179 return cmd_status(sk, MGMT_OP_READ_INFO, ENODEV);
f7b64e69 180
ab81cbf9
JH
181 hci_del_off_timer(hdev);
182
f7b64e69
JH
183 hci_dev_lock_bh(hdev);
184
ebc99feb
JH
185 set_bit(HCI_MGMT, &hdev->flags);
186
a38528f1
JH
187 put_unaligned_le16(hdev->id, &rp.index);
188 rp.type = hdev->dev_type;
f7b64e69 189
a38528f1
JH
190 rp.powered = test_bit(HCI_UP, &hdev->flags);
191 rp.connectable = test_bit(HCI_PSCAN, &hdev->flags);
192 rp.discoverable = test_bit(HCI_ISCAN, &hdev->flags);
193 rp.pairable = test_bit(HCI_PSCAN, &hdev->flags);
f7b64e69
JH
194
195 if (test_bit(HCI_AUTH, &hdev->flags))
a38528f1 196 rp.sec_mode = 3;
f7b64e69 197 else if (hdev->ssp_mode > 0)
a38528f1 198 rp.sec_mode = 4;
f7b64e69 199 else
a38528f1 200 rp.sec_mode = 2;
f7b64e69 201
a38528f1
JH
202 bacpy(&rp.bdaddr, &hdev->bdaddr);
203 memcpy(rp.features, hdev->features, 8);
204 memcpy(rp.dev_class, hdev->dev_class, 3);
205 put_unaligned_le16(hdev->manufacturer, &rp.manufacturer);
206 rp.hci_ver = hdev->hci_ver;
207 put_unaligned_le16(hdev->hci_rev, &rp.hci_rev);
f7b64e69
JH
208
209 hci_dev_unlock_bh(hdev);
210 hci_dev_put(hdev);
0381101f 211
a38528f1 212 return cmd_complete(sk, MGMT_OP_READ_INFO, &rp, sizeof(rp));
0381101f
JH
213}
214
eec8d2bc
JH
215static void mgmt_pending_free(struct pending_cmd *cmd)
216{
217 sock_put(cmd->sk);
218 kfree(cmd->cmd);
219 kfree(cmd);
220}
221
366a0336
JH
222static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
223 u16 index, void *data, u16 len)
eec8d2bc
JH
224{
225 struct pending_cmd *cmd;
226
227 cmd = kmalloc(sizeof(*cmd), GFP_ATOMIC);
228 if (!cmd)
366a0336 229 return NULL;
eec8d2bc
JH
230
231 cmd->opcode = opcode;
232 cmd->index = index;
233
234 cmd->cmd = kmalloc(len, GFP_ATOMIC);
235 if (!cmd->cmd) {
236 kfree(cmd);
366a0336 237 return NULL;
eec8d2bc
JH
238 }
239
240 memcpy(cmd->cmd, data, len);
241
242 cmd->sk = sk;
243 sock_hold(sk);
244
245 list_add(&cmd->list, &cmd_list);
246
366a0336 247 return cmd;
eec8d2bc
JH
248}
249
250static void mgmt_pending_foreach(u16 opcode, int index,
251 void (*cb)(struct pending_cmd *cmd, void *data),
252 void *data)
253{
254 struct list_head *p, *n;
255
256 list_for_each_safe(p, n, &cmd_list) {
257 struct pending_cmd *cmd;
258
259 cmd = list_entry(p, struct pending_cmd, list);
260
261 if (cmd->opcode != opcode)
262 continue;
263
264 if (index >= 0 && cmd->index != index)
265 continue;
266
267 cb(cmd, data);
268 }
269}
270
271static struct pending_cmd *mgmt_pending_find(u16 opcode, int index)
272{
273 struct list_head *p;
274
275 list_for_each(p, &cmd_list) {
276 struct pending_cmd *cmd;
277
278 cmd = list_entry(p, struct pending_cmd, list);
279
280 if (cmd->opcode != opcode)
281 continue;
282
283 if (index >= 0 && cmd->index != index)
284 continue;
285
286 return cmd;
287 }
288
289 return NULL;
290}
291
73f22f62
JH
292static void mgmt_pending_remove(u16 opcode, int index)
293{
294 struct pending_cmd *cmd;
295
296 cmd = mgmt_pending_find(opcode, index);
297 if (cmd == NULL)
298 return;
299
300 list_del(&cmd->list);
301 mgmt_pending_free(cmd);
302}
303
eec8d2bc
JH
304static int set_powered(struct sock *sk, unsigned char *data, u16 len)
305{
72a734ec 306 struct mgmt_mode *cp;
eec8d2bc 307 struct hci_dev *hdev;
366a0336 308 struct pending_cmd *cmd;
eec8d2bc 309 u16 dev_id;
366a0336 310 int err, up;
eec8d2bc
JH
311
312 cp = (void *) data;
313 dev_id = get_unaligned_le16(&cp->index);
314
315 BT_DBG("request for hci%u", dev_id);
316
317 hdev = hci_dev_get(dev_id);
318 if (!hdev)
319 return cmd_status(sk, MGMT_OP_SET_POWERED, ENODEV);
320
321 hci_dev_lock_bh(hdev);
322
323 up = test_bit(HCI_UP, &hdev->flags);
72a734ec 324 if ((cp->val && up) || (!cp->val && !up)) {
366a0336 325 err = cmd_status(sk, MGMT_OP_SET_POWERED, EALREADY);
eec8d2bc
JH
326 goto failed;
327 }
328
329 if (mgmt_pending_find(MGMT_OP_SET_POWERED, dev_id)) {
366a0336 330 err = cmd_status(sk, MGMT_OP_SET_POWERED, EBUSY);
eec8d2bc
JH
331 goto failed;
332 }
333
366a0336
JH
334 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, dev_id, data, len);
335 if (!cmd) {
336 err = -ENOMEM;
eec8d2bc 337 goto failed;
366a0336 338 }
eec8d2bc 339
72a734ec 340 if (cp->val)
eec8d2bc
JH
341 queue_work(hdev->workqueue, &hdev->power_on);
342 else
343 queue_work(hdev->workqueue, &hdev->power_off);
344
366a0336 345 err = 0;
eec8d2bc
JH
346
347failed:
348 hci_dev_unlock_bh(hdev);
349 hci_dev_put(hdev);
366a0336 350 return err;
eec8d2bc
JH
351}
352
73f22f62
JH
353static int set_discoverable(struct sock *sk, unsigned char *data, u16 len)
354{
72a734ec 355 struct mgmt_mode *cp;
73f22f62 356 struct hci_dev *hdev;
366a0336 357 struct pending_cmd *cmd;
73f22f62
JH
358 u16 dev_id;
359 u8 scan;
360 int err;
361
362 cp = (void *) data;
363 dev_id = get_unaligned_le16(&cp->index);
364
365 BT_DBG("request for hci%u", dev_id);
366
367 hdev = hci_dev_get(dev_id);
368 if (!hdev)
369 return cmd_status(sk, MGMT_OP_SET_DISCOVERABLE, ENODEV);
370
371 hci_dev_lock_bh(hdev);
372
373 if (!test_bit(HCI_UP, &hdev->flags)) {
374 err = cmd_status(sk, MGMT_OP_SET_DISCOVERABLE, ENETDOWN);
375 goto failed;
376 }
377
378 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, dev_id) ||
9fbcbb45 379 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, dev_id)) {
73f22f62
JH
380 err = cmd_status(sk, MGMT_OP_SET_DISCOVERABLE, EBUSY);
381 goto failed;
382 }
383
72a734ec 384 if (cp->val == test_bit(HCI_ISCAN, &hdev->flags) &&
73f22f62
JH
385 test_bit(HCI_PSCAN, &hdev->flags)) {
386 err = cmd_status(sk, MGMT_OP_SET_DISCOVERABLE, EALREADY);
387 goto failed;
388 }
389
366a0336
JH
390 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, dev_id, data, len);
391 if (!cmd) {
392 err = -ENOMEM;
73f22f62 393 goto failed;
366a0336 394 }
73f22f62
JH
395
396 scan = SCAN_PAGE;
397
72a734ec 398 if (cp->val)
73f22f62
JH
399 scan |= SCAN_INQUIRY;
400
401 err = hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
402 if (err < 0)
403 mgmt_pending_remove(MGMT_OP_SET_DISCOVERABLE, dev_id);
404
405failed:
406 hci_dev_unlock_bh(hdev);
407 hci_dev_put(hdev);
408
409 return err;
410}
411
9fbcbb45
JH
412static int set_connectable(struct sock *sk, unsigned char *data, u16 len)
413{
72a734ec 414 struct mgmt_mode *cp;
9fbcbb45 415 struct hci_dev *hdev;
366a0336 416 struct pending_cmd *cmd;
9fbcbb45
JH
417 u16 dev_id;
418 u8 scan;
419 int err;
420
421 cp = (void *) data;
422 dev_id = get_unaligned_le16(&cp->index);
423
424 BT_DBG("request for hci%u", dev_id);
425
426 hdev = hci_dev_get(dev_id);
427 if (!hdev)
428 return cmd_status(sk, MGMT_OP_SET_CONNECTABLE, ENODEV);
429
430 hci_dev_lock_bh(hdev);
431
432 if (!test_bit(HCI_UP, &hdev->flags)) {
433 err = cmd_status(sk, MGMT_OP_SET_CONNECTABLE, ENETDOWN);
434 goto failed;
435 }
436
437 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, dev_id) ||
438 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, dev_id)) {
439 err = cmd_status(sk, MGMT_OP_SET_CONNECTABLE, EBUSY);
440 goto failed;
441 }
442
72a734ec 443 if (cp->val == test_bit(HCI_PSCAN, &hdev->flags)) {
9fbcbb45
JH
444 err = cmd_status(sk, MGMT_OP_SET_CONNECTABLE, EALREADY);
445 goto failed;
446 }
447
366a0336
JH
448 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, dev_id, data, len);
449 if (!cmd) {
450 err = -ENOMEM;
9fbcbb45 451 goto failed;
366a0336 452 }
9fbcbb45 453
72a734ec 454 if (cp->val)
9fbcbb45
JH
455 scan = SCAN_PAGE;
456 else
457 scan = 0;
458
459 err = hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
460 if (err < 0)
461 mgmt_pending_remove(MGMT_OP_SET_CONNECTABLE, dev_id);
462
463failed:
464 hci_dev_unlock_bh(hdev);
465 hci_dev_put(hdev);
466
467 return err;
468}
469
c542a06c
JH
470static int mgmt_event(u16 event, void *data, u16 data_len, struct sock *skip_sk)
471{
472 struct sk_buff *skb;
473 struct mgmt_hdr *hdr;
474
475 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_ATOMIC);
476 if (!skb)
477 return -ENOMEM;
478
479 bt_cb(skb)->channel = HCI_CHANNEL_CONTROL;
480
481 hdr = (void *) skb_put(skb, sizeof(*hdr));
482 hdr->opcode = cpu_to_le16(event);
483 hdr->len = cpu_to_le16(data_len);
484
485 memcpy(skb_put(skb, data_len), data, data_len);
486
487 hci_send_to_sock(NULL, skb, skip_sk);
488 kfree_skb(skb);
489
490 return 0;
491}
492
053f0211
JH
493static int send_mode_rsp(struct sock *sk, u16 opcode, u16 index, u8 val)
494{
a38528f1 495 struct mgmt_mode rp;
053f0211 496
a38528f1
JH
497 put_unaligned_le16(index, &rp.index);
498 rp.val = val;
053f0211 499
a38528f1 500 return cmd_complete(sk, opcode, &rp, sizeof(rp));
053f0211
JH
501}
502
c542a06c
JH
503static int set_pairable(struct sock *sk, unsigned char *data, u16 len)
504{
505 struct mgmt_mode *cp, ev;
506 struct hci_dev *hdev;
507 u16 dev_id;
508 int err;
509
510 cp = (void *) data;
511 dev_id = get_unaligned_le16(&cp->index);
512
513 BT_DBG("request for hci%u", dev_id);
514
515 hdev = hci_dev_get(dev_id);
516 if (!hdev)
517 return cmd_status(sk, MGMT_OP_SET_PAIRABLE, ENODEV);
518
519 hci_dev_lock_bh(hdev);
520
521 if (cp->val)
522 set_bit(HCI_PAIRABLE, &hdev->flags);
523 else
524 clear_bit(HCI_PAIRABLE, &hdev->flags);
525
526 err = send_mode_rsp(sk, MGMT_OP_SET_PAIRABLE, dev_id, cp->val);
527 if (err < 0)
528 goto failed;
529
530 put_unaligned_le16(dev_id, &ev.index);
531 ev.val = cp->val;
532
533 err = mgmt_event(MGMT_EV_PAIRABLE, &ev, sizeof(ev), sk);
534
535failed:
536 hci_dev_unlock_bh(hdev);
537 hci_dev_put(hdev);
538
539 return err;
540}
541
1aff6f09
JH
542static u8 get_service_classes(struct hci_dev *hdev)
543{
544 struct list_head *p;
545 u8 val = 0;
546
547 list_for_each(p, &hdev->uuids) {
548 struct bt_uuid *uuid = list_entry(p, struct bt_uuid, list);
549
550 val |= uuid->svc_hint;
551 }
552
553 return val;
554}
555
556static int update_class(struct hci_dev *hdev)
557{
558 u8 cod[3];
559
560 BT_DBG("%s", hdev->name);
561
562 if (test_bit(HCI_SERVICE_CACHE, &hdev->flags))
563 return 0;
564
565 cod[0] = hdev->minor_class;
566 cod[1] = hdev->major_class;
567 cod[2] = get_service_classes(hdev);
568
569 if (memcmp(cod, hdev->dev_class, 3) == 0)
570 return 0;
571
572 return hci_send_cmd(hdev, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
573}
574
2aeb9a1a
JH
575static int add_uuid(struct sock *sk, unsigned char *data, u16 len)
576{
577 struct mgmt_cp_add_uuid *cp;
578 struct hci_dev *hdev;
579 struct bt_uuid *uuid;
580 u16 dev_id;
581 int err;
582
583 cp = (void *) data;
584 dev_id = get_unaligned_le16(&cp->index);
585
586 BT_DBG("request for hci%u", dev_id);
587
588 hdev = hci_dev_get(dev_id);
589 if (!hdev)
590 return cmd_status(sk, MGMT_OP_ADD_UUID, ENODEV);
591
592 hci_dev_lock_bh(hdev);
593
594 uuid = kmalloc(sizeof(*uuid), GFP_ATOMIC);
595 if (!uuid) {
596 err = -ENOMEM;
597 goto failed;
598 }
599
600 memcpy(uuid->uuid, cp->uuid, 16);
1aff6f09 601 uuid->svc_hint = cp->svc_hint;
2aeb9a1a
JH
602
603 list_add(&uuid->list, &hdev->uuids);
604
1aff6f09
JH
605 err = update_class(hdev);
606 if (err < 0)
607 goto failed;
608
a38528f1 609 err = cmd_complete(sk, MGMT_OP_ADD_UUID, &dev_id, sizeof(dev_id));
2aeb9a1a
JH
610
611failed:
612 hci_dev_unlock_bh(hdev);
613 hci_dev_put(hdev);
614
615 return err;
616}
617
618static int remove_uuid(struct sock *sk, unsigned char *data, u16 len)
619{
620 struct list_head *p, *n;
621 struct mgmt_cp_add_uuid *cp;
622 struct hci_dev *hdev;
623 u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
624 u16 dev_id;
625 int err, found;
626
627 cp = (void *) data;
628 dev_id = get_unaligned_le16(&cp->index);
629
630 BT_DBG("request for hci%u", dev_id);
631
632 hdev = hci_dev_get(dev_id);
633 if (!hdev)
634 return cmd_status(sk, MGMT_OP_REMOVE_UUID, ENODEV);
635
636 hci_dev_lock_bh(hdev);
637
638 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
639 err = hci_uuids_clear(hdev);
640 goto unlock;
641 }
642
643 found = 0;
644
645 list_for_each_safe(p, n, &hdev->uuids) {
646 struct bt_uuid *match = list_entry(p, struct bt_uuid, list);
647
648 if (memcmp(match->uuid, cp->uuid, 16) != 0)
649 continue;
650
651 list_del(&match->list);
652 found++;
653 }
654
655 if (found == 0) {
656 err = cmd_status(sk, MGMT_OP_REMOVE_UUID, ENOENT);
657 goto unlock;
658 }
659
1aff6f09
JH
660 err = update_class(hdev);
661 if (err < 0)
662 goto unlock;
663
a38528f1 664 err = cmd_complete(sk, MGMT_OP_REMOVE_UUID, &dev_id, sizeof(dev_id));
2aeb9a1a
JH
665
666unlock:
667 hci_dev_unlock_bh(hdev);
668 hci_dev_put(hdev);
669
670 return err;
671}
672
1aff6f09
JH
673static int set_dev_class(struct sock *sk, unsigned char *data, u16 len)
674{
675 struct hci_dev *hdev;
676 struct mgmt_cp_set_dev_class *cp;
677 u16 dev_id;
678 int err;
679
680 cp = (void *) data;
681 dev_id = get_unaligned_le16(&cp->index);
682
683 BT_DBG("request for hci%u", dev_id);
684
685 hdev = hci_dev_get(dev_id);
686 if (!hdev)
687 return cmd_status(sk, MGMT_OP_SET_DEV_CLASS, ENODEV);
688
689 hci_dev_lock_bh(hdev);
690
691 hdev->major_class = cp->major;
692 hdev->minor_class = cp->minor;
693
694 err = update_class(hdev);
695
696 if (err == 0)
a38528f1
JH
697 err = cmd_complete(sk, MGMT_OP_SET_DEV_CLASS, &dev_id,
698 sizeof(dev_id));
1aff6f09
JH
699
700 hci_dev_unlock_bh(hdev);
701 hci_dev_put(hdev);
702
703 return err;
704}
705
706static int set_service_cache(struct sock *sk, unsigned char *data, u16 len)
707{
708 struct hci_dev *hdev;
709 struct mgmt_cp_set_service_cache *cp;
710 u16 dev_id;
711 int err;
712
713 cp = (void *) data;
714 dev_id = get_unaligned_le16(&cp->index);
715
716 hdev = hci_dev_get(dev_id);
717 if (!hdev)
718 return cmd_status(sk, MGMT_OP_SET_SERVICE_CACHE, ENODEV);
719
720 hci_dev_lock_bh(hdev);
721
722 BT_DBG("hci%u enable %d", dev_id, cp->enable);
723
724 if (cp->enable) {
725 set_bit(HCI_SERVICE_CACHE, &hdev->flags);
726 err = 0;
727 } else {
728 clear_bit(HCI_SERVICE_CACHE, &hdev->flags);
729 err = update_class(hdev);
730 }
731
732 if (err == 0)
a38528f1
JH
733 err = cmd_complete(sk, MGMT_OP_SET_SERVICE_CACHE, &dev_id,
734 sizeof(dev_id));
1aff6f09
JH
735
736 hci_dev_unlock_bh(hdev);
737 hci_dev_put(hdev);
738
739 return err;
740}
741
55ed8ca1
JH
742static int load_keys(struct sock *sk, unsigned char *data, u16 len)
743{
744 struct hci_dev *hdev;
745 struct mgmt_cp_load_keys *cp;
746 u16 dev_id, key_count, expected_len;
747 int i;
748
749 cp = (void *) data;
750 dev_id = get_unaligned_le16(&cp->index);
751 key_count = get_unaligned_le16(&cp->key_count);
752
753 expected_len = sizeof(*cp) + key_count * sizeof(struct mgmt_key_info);
754 if (expected_len != len) {
755 BT_ERR("load_keys: expected %u bytes, got %u bytes",
756 len, expected_len);
757 return -EINVAL;
758 }
759
760 hdev = hci_dev_get(dev_id);
761 if (!hdev)
762 return cmd_status(sk, MGMT_OP_LOAD_KEYS, ENODEV);
763
764 BT_DBG("hci%u debug_keys %u key_count %u", dev_id, cp->debug_keys,
765 key_count);
766
767 hci_dev_lock_bh(hdev);
768
769 hci_link_keys_clear(hdev);
770
771 set_bit(HCI_LINK_KEYS, &hdev->flags);
772
773 if (cp->debug_keys)
774 set_bit(HCI_DEBUG_KEYS, &hdev->flags);
775 else
776 clear_bit(HCI_DEBUG_KEYS, &hdev->flags);
777
778 for (i = 0; i < key_count; i++) {
779 struct mgmt_key_info *key = &cp->keys[i];
780
781 hci_add_link_key(hdev, 0, &key->bdaddr, key->val, key->type,
782 key->pin_len);
783 }
784
785 hci_dev_unlock_bh(hdev);
786 hci_dev_put(hdev);
787
788 return 0;
789}
790
791static int remove_key(struct sock *sk, unsigned char *data, u16 len)
792{
793 struct hci_dev *hdev;
794 struct mgmt_cp_remove_key *cp;
795 struct hci_conn *conn;
796 u16 dev_id;
797 int err;
798
799 cp = (void *) data;
800 dev_id = get_unaligned_le16(&cp->index);
801
802 hdev = hci_dev_get(dev_id);
803 if (!hdev)
804 return cmd_status(sk, MGMT_OP_REMOVE_KEY, ENODEV);
805
806 hci_dev_lock_bh(hdev);
807
808 err = hci_remove_link_key(hdev, &cp->bdaddr);
809 if (err < 0) {
810 err = cmd_status(sk, MGMT_OP_REMOVE_KEY, -err);
811 goto unlock;
812 }
813
814 err = 0;
815
816 if (!test_bit(HCI_UP, &hdev->flags) || !cp->disconnect)
817 goto unlock;
818
819 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
820 if (conn) {
821 struct hci_cp_disconnect dc;
822
823 put_unaligned_le16(conn->handle, &dc.handle);
824 dc.reason = 0x13; /* Remote User Terminated Connection */
825 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, 0, NULL);
826 }
827
828unlock:
829 hci_dev_unlock_bh(hdev);
830 hci_dev_put(hdev);
831
832 return err;
833}
834
8962ee74
JH
835static int disconnect(struct sock *sk, unsigned char *data, u16 len)
836{
837 struct hci_dev *hdev;
838 struct mgmt_cp_disconnect *cp;
839 struct hci_cp_disconnect dc;
366a0336 840 struct pending_cmd *cmd;
8962ee74
JH
841 struct hci_conn *conn;
842 u16 dev_id;
843 int err;
844
845 BT_DBG("");
846
847 cp = (void *) data;
848 dev_id = get_unaligned_le16(&cp->index);
849
850 hdev = hci_dev_get(dev_id);
851 if (!hdev)
852 return cmd_status(sk, MGMT_OP_DISCONNECT, ENODEV);
853
854 hci_dev_lock_bh(hdev);
855
856 if (!test_bit(HCI_UP, &hdev->flags)) {
857 err = cmd_status(sk, MGMT_OP_DISCONNECT, ENETDOWN);
858 goto failed;
859 }
860
861 if (mgmt_pending_find(MGMT_OP_DISCONNECT, dev_id)) {
862 err = cmd_status(sk, MGMT_OP_DISCONNECT, EBUSY);
863 goto failed;
864 }
865
866 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
867 if (!conn) {
868 err = cmd_status(sk, MGMT_OP_DISCONNECT, ENOTCONN);
869 goto failed;
870 }
871
366a0336
JH
872 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, dev_id, data, len);
873 if (!cmd) {
874 err = -ENOMEM;
8962ee74 875 goto failed;
366a0336 876 }
8962ee74
JH
877
878 put_unaligned_le16(conn->handle, &dc.handle);
879 dc.reason = 0x13; /* Remote User Terminated Connection */
880
881 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
882 if (err < 0)
883 mgmt_pending_remove(MGMT_OP_DISCONNECT, dev_id);
884
885failed:
886 hci_dev_unlock_bh(hdev);
887 hci_dev_put(hdev);
888
889 return err;
890}
891
2784eb41
JH
892static int get_connections(struct sock *sk, unsigned char *data, u16 len)
893{
2784eb41 894 struct mgmt_cp_get_connections *cp;
2784eb41
JH
895 struct mgmt_rp_get_connections *rp;
896 struct hci_dev *hdev;
897 struct list_head *p;
a38528f1 898 size_t rp_len;
2784eb41
JH
899 u16 dev_id, count;
900 int i, err;
901
902 BT_DBG("");
903
904 cp = (void *) data;
905 dev_id = get_unaligned_le16(&cp->index);
906
907 hdev = hci_dev_get(dev_id);
908 if (!hdev)
909 return cmd_status(sk, MGMT_OP_GET_CONNECTIONS, ENODEV);
910
911 hci_dev_lock_bh(hdev);
912
913 count = 0;
914 list_for_each(p, &hdev->conn_hash.list) {
915 count++;
916 }
917
a38528f1
JH
918 rp_len = sizeof(*rp) + (count * sizeof(bdaddr_t));
919 rp = kmalloc(rp_len, GFP_ATOMIC);
920 if (!rp) {
2784eb41
JH
921 err = -ENOMEM;
922 goto unlock;
923 }
924
2784eb41
JH
925 put_unaligned_le16(dev_id, &rp->index);
926 put_unaligned_le16(count, &rp->conn_count);
927
928 read_lock(&hci_dev_list_lock);
929
930 i = 0;
931 list_for_each(p, &hdev->conn_hash.list) {
932 struct hci_conn *c = list_entry(p, struct hci_conn, list);
933
934 bacpy(&rp->conn[i++], &c->dst);
935 }
936
937 read_unlock(&hci_dev_list_lock);
938
a38528f1 939 err = cmd_complete(sk, MGMT_OP_GET_CONNECTIONS, rp, rp_len);
2784eb41
JH
940
941unlock:
a38528f1 942 kfree(rp);
2784eb41
JH
943 hci_dev_unlock_bh(hdev);
944 hci_dev_put(hdev);
945 return err;
946}
947
980e1a53
JH
948static int pin_code_reply(struct sock *sk, unsigned char *data, u16 len)
949{
950 struct hci_dev *hdev;
951 struct mgmt_cp_pin_code_reply *cp;
952 struct hci_cp_pin_code_reply reply;
366a0336 953 struct pending_cmd *cmd;
980e1a53
JH
954 u16 dev_id;
955 int err;
956
957 BT_DBG("");
958
959 cp = (void *) data;
960 dev_id = get_unaligned_le16(&cp->index);
961
962 hdev = hci_dev_get(dev_id);
963 if (!hdev)
964 return cmd_status(sk, MGMT_OP_DISCONNECT, ENODEV);
965
966 hci_dev_lock_bh(hdev);
967
968 if (!test_bit(HCI_UP, &hdev->flags)) {
969 err = cmd_status(sk, MGMT_OP_PIN_CODE_REPLY, ENETDOWN);
970 goto failed;
971 }
972
366a0336
JH
973 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, dev_id, data, len);
974 if (!cmd) {
975 err = -ENOMEM;
980e1a53 976 goto failed;
366a0336 977 }
980e1a53
JH
978
979 bacpy(&reply.bdaddr, &cp->bdaddr);
980 reply.pin_len = cp->pin_len;
981 memcpy(reply.pin_code, cp->pin_code, 16);
982
983 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
984 if (err < 0)
985 mgmt_pending_remove(MGMT_OP_PIN_CODE_REPLY, dev_id);
986
987failed:
988 hci_dev_unlock_bh(hdev);
989 hci_dev_put(hdev);
990
991 return err;
992}
993
994static int pin_code_neg_reply(struct sock *sk, unsigned char *data, u16 len)
995{
996 struct hci_dev *hdev;
997 struct mgmt_cp_pin_code_neg_reply *cp;
366a0336 998 struct pending_cmd *cmd;
980e1a53
JH
999 u16 dev_id;
1000 int err;
1001
1002 BT_DBG("");
1003
1004 cp = (void *) data;
1005 dev_id = get_unaligned_le16(&cp->index);
1006
1007 hdev = hci_dev_get(dev_id);
1008 if (!hdev)
1009 return cmd_status(sk, MGMT_OP_PIN_CODE_NEG_REPLY, ENODEV);
1010
1011 hci_dev_lock_bh(hdev);
1012
1013 if (!test_bit(HCI_UP, &hdev->flags)) {
1014 err = cmd_status(sk, MGMT_OP_PIN_CODE_NEG_REPLY, ENETDOWN);
1015 goto failed;
1016 }
1017
366a0336 1018 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, dev_id,
980e1a53 1019 data, len);
366a0336
JH
1020 if (!cmd) {
1021 err = -ENOMEM;
980e1a53 1022 goto failed;
366a0336 1023 }
980e1a53
JH
1024
1025 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, sizeof(bdaddr_t),
1026 &cp->bdaddr);
1027 if (err < 0)
1028 mgmt_pending_remove(MGMT_OP_PIN_CODE_NEG_REPLY, dev_id);
1029
1030failed:
1031 hci_dev_unlock_bh(hdev);
1032 hci_dev_put(hdev);
1033
1034 return err;
1035}
1036
17fa4b9d
JH
1037static int set_io_capability(struct sock *sk, unsigned char *data, u16 len)
1038{
1039 struct hci_dev *hdev;
1040 struct mgmt_cp_set_io_capability *cp;
1041 u16 dev_id;
1042
1043 BT_DBG("");
1044
1045 cp = (void *) data;
1046 dev_id = get_unaligned_le16(&cp->index);
1047
1048 hdev = hci_dev_get(dev_id);
1049 if (!hdev)
1050 return cmd_status(sk, MGMT_OP_SET_IO_CAPABILITY, ENODEV);
1051
1052 hci_dev_lock_bh(hdev);
1053
1054 hdev->io_capability = cp->io_capability;
1055
1056 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
1057 hdev->io_capability);
1058
1059 hci_dev_unlock_bh(hdev);
1060 hci_dev_put(hdev);
1061
1062 return cmd_complete(sk, MGMT_OP_SET_IO_CAPABILITY,
1063 &dev_id, sizeof(dev_id));
1064}
1065
0381101f
JH
1066int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
1067{
1068 unsigned char *buf;
1069 struct mgmt_hdr *hdr;
1070 u16 opcode, len;
1071 int err;
1072
1073 BT_DBG("got %zu bytes", msglen);
1074
1075 if (msglen < sizeof(*hdr))
1076 return -EINVAL;
1077
1078 buf = kmalloc(msglen, GFP_ATOMIC);
1079 if (!buf)
1080 return -ENOMEM;
1081
1082 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
1083 err = -EFAULT;
1084 goto done;
1085 }
1086
1087 hdr = (struct mgmt_hdr *) buf;
1088 opcode = get_unaligned_le16(&hdr->opcode);
1089 len = get_unaligned_le16(&hdr->len);
1090
1091 if (len != msglen - sizeof(*hdr)) {
1092 err = -EINVAL;
1093 goto done;
1094 }
1095
1096 switch (opcode) {
02d98129
JH
1097 case MGMT_OP_READ_VERSION:
1098 err = read_version(sk);
1099 break;
faba42eb
JH
1100 case MGMT_OP_READ_INDEX_LIST:
1101 err = read_index_list(sk);
1102 break;
f7b64e69
JH
1103 case MGMT_OP_READ_INFO:
1104 err = read_controller_info(sk, buf + sizeof(*hdr), len);
1105 break;
eec8d2bc
JH
1106 case MGMT_OP_SET_POWERED:
1107 err = set_powered(sk, buf + sizeof(*hdr), len);
1108 break;
73f22f62
JH
1109 case MGMT_OP_SET_DISCOVERABLE:
1110 err = set_discoverable(sk, buf + sizeof(*hdr), len);
1111 break;
9fbcbb45
JH
1112 case MGMT_OP_SET_CONNECTABLE:
1113 err = set_connectable(sk, buf + sizeof(*hdr), len);
1114 break;
c542a06c
JH
1115 case MGMT_OP_SET_PAIRABLE:
1116 err = set_pairable(sk, buf + sizeof(*hdr), len);
1117 break;
2aeb9a1a
JH
1118 case MGMT_OP_ADD_UUID:
1119 err = add_uuid(sk, buf + sizeof(*hdr), len);
1120 break;
1121 case MGMT_OP_REMOVE_UUID:
1122 err = remove_uuid(sk, buf + sizeof(*hdr), len);
1123 break;
1aff6f09
JH
1124 case MGMT_OP_SET_DEV_CLASS:
1125 err = set_dev_class(sk, buf + sizeof(*hdr), len);
1126 break;
1127 case MGMT_OP_SET_SERVICE_CACHE:
1128 err = set_service_cache(sk, buf + sizeof(*hdr), len);
1129 break;
55ed8ca1
JH
1130 case MGMT_OP_LOAD_KEYS:
1131 err = load_keys(sk, buf + sizeof(*hdr), len);
1132 break;
1133 case MGMT_OP_REMOVE_KEY:
1134 err = remove_key(sk, buf + sizeof(*hdr), len);
1135 break;
8962ee74
JH
1136 case MGMT_OP_DISCONNECT:
1137 err = disconnect(sk, buf + sizeof(*hdr), len);
1138 break;
2784eb41
JH
1139 case MGMT_OP_GET_CONNECTIONS:
1140 err = get_connections(sk, buf + sizeof(*hdr), len);
1141 break;
980e1a53
JH
1142 case MGMT_OP_PIN_CODE_REPLY:
1143 err = pin_code_reply(sk, buf + sizeof(*hdr), len);
1144 break;
1145 case MGMT_OP_PIN_CODE_NEG_REPLY:
1146 err = pin_code_neg_reply(sk, buf + sizeof(*hdr), len);
1147 break;
17fa4b9d
JH
1148 case MGMT_OP_SET_IO_CAPABILITY:
1149 err = set_io_capability(sk, buf + sizeof(*hdr), len);
1150 break;
0381101f
JH
1151 default:
1152 BT_DBG("Unknown op %u", opcode);
e41d8b4e 1153 err = cmd_status(sk, opcode, 0x01);
0381101f
JH
1154 break;
1155 }
1156
e41d8b4e
JH
1157 if (err < 0)
1158 goto done;
1159
0381101f
JH
1160 err = msglen;
1161
1162done:
1163 kfree(buf);
1164 return err;
1165}
c71e97bf 1166
c71e97bf
JH
1167int mgmt_index_added(u16 index)
1168{
1169 struct mgmt_ev_index_added ev;
1170
1171 put_unaligned_le16(index, &ev.index);
1172
eec8d2bc 1173 return mgmt_event(MGMT_EV_INDEX_ADDED, &ev, sizeof(ev), NULL);
c71e97bf
JH
1174}
1175
1176int mgmt_index_removed(u16 index)
1177{
1178 struct mgmt_ev_index_added ev;
1179
1180 put_unaligned_le16(index, &ev.index);
1181
eec8d2bc
JH
1182 return mgmt_event(MGMT_EV_INDEX_REMOVED, &ev, sizeof(ev), NULL);
1183}
1184
73f22f62 1185struct cmd_lookup {
72a734ec 1186 u8 val;
eec8d2bc
JH
1187 struct sock *sk;
1188};
1189
72a734ec 1190static void mode_rsp(struct pending_cmd *cmd, void *data)
eec8d2bc 1191{
72a734ec 1192 struct mgmt_mode *cp = cmd->cmd;
73f22f62 1193 struct cmd_lookup *match = data;
eec8d2bc 1194
72a734ec 1195 if (cp->val != match->val)
eec8d2bc
JH
1196 return;
1197
053f0211 1198 send_mode_rsp(cmd->sk, cmd->opcode, cmd->index, cp->val);
eec8d2bc
JH
1199
1200 list_del(&cmd->list);
1201
1202 if (match->sk == NULL) {
1203 match->sk = cmd->sk;
1204 sock_hold(match->sk);
1205 }
1206
1207 mgmt_pending_free(cmd);
c71e97bf 1208}
5add6af8
JH
1209
1210int mgmt_powered(u16 index, u8 powered)
1211{
72a734ec 1212 struct mgmt_mode ev;
73f22f62 1213 struct cmd_lookup match = { powered, NULL };
eec8d2bc 1214 int ret;
5add6af8 1215
72a734ec 1216 mgmt_pending_foreach(MGMT_OP_SET_POWERED, index, mode_rsp, &match);
5add6af8 1217
72a734ec
JH
1218 put_unaligned_le16(index, &ev.index);
1219 ev.val = powered;
eec8d2bc
JH
1220
1221 ret = mgmt_event(MGMT_EV_POWERED, &ev, sizeof(ev), match.sk);
1222
1223 if (match.sk)
1224 sock_put(match.sk);
1225
1226 return ret;
5add6af8 1227}
73f22f62 1228
73f22f62
JH
1229int mgmt_discoverable(u16 index, u8 discoverable)
1230{
72a734ec 1231 struct mgmt_mode ev;
73f22f62
JH
1232 struct cmd_lookup match = { discoverable, NULL };
1233 int ret;
1234
73f22f62 1235 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, index,
72a734ec
JH
1236 mode_rsp, &match);
1237
1238 put_unaligned_le16(index, &ev.index);
1239 ev.val = discoverable;
73f22f62
JH
1240
1241 ret = mgmt_event(MGMT_EV_DISCOVERABLE, &ev, sizeof(ev), match.sk);
1242
1243 if (match.sk)
1244 sock_put(match.sk);
1245
1246 return ret;
1247}
9fbcbb45 1248
9fbcbb45
JH
1249int mgmt_connectable(u16 index, u8 connectable)
1250{
72a734ec 1251 struct mgmt_mode ev;
9fbcbb45
JH
1252 struct cmd_lookup match = { connectable, NULL };
1253 int ret;
1254
72a734ec 1255 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, index, mode_rsp, &match);
9fbcbb45 1256
72a734ec
JH
1257 put_unaligned_le16(index, &ev.index);
1258 ev.val = connectable;
9fbcbb45
JH
1259
1260 ret = mgmt_event(MGMT_EV_CONNECTABLE, &ev, sizeof(ev), match.sk);
1261
1262 if (match.sk)
1263 sock_put(match.sk);
1264
1265 return ret;
1266}
55ed8ca1
JH
1267
1268int mgmt_new_key(u16 index, struct link_key *key, u8 old_key_type)
1269{
1270 struct mgmt_ev_new_key ev;
1271
1272 memset(&ev, 0, sizeof(ev));
1273
1274 put_unaligned_le16(index, &ev.index);
1275
1276 bacpy(&ev.key.bdaddr, &key->bdaddr);
1277 ev.key.type = key->type;
1278 memcpy(ev.key.val, key->val, 16);
1279 ev.key.pin_len = key->pin_len;
1280 ev.old_key_type = old_key_type;
1281
1282 return mgmt_event(MGMT_EV_NEW_KEY, &ev, sizeof(ev), NULL);
1283}
f7520543
JH
1284
1285int mgmt_connected(u16 index, bdaddr_t *bdaddr)
1286{
1287 struct mgmt_ev_connected ev;
1288
1289 put_unaligned_le16(index, &ev.index);
1290 bacpy(&ev.bdaddr, bdaddr);
1291
1292 return mgmt_event(MGMT_EV_CONNECTED, &ev, sizeof(ev), NULL);
1293}
1294
8962ee74
JH
1295static void disconnect_rsp(struct pending_cmd *cmd, void *data)
1296{
1297 struct mgmt_cp_disconnect *cp = cmd->cmd;
1298 struct sock **sk = data;
a38528f1 1299 struct mgmt_rp_disconnect rp;
8962ee74 1300
a38528f1
JH
1301 put_unaligned_le16(cmd->index, &rp.index);
1302 bacpy(&rp.bdaddr, &cp->bdaddr);
8962ee74 1303
a38528f1 1304 cmd_complete(cmd->sk, MGMT_OP_DISCONNECT, &rp, sizeof(rp));
8962ee74
JH
1305
1306 *sk = cmd->sk;
1307 sock_hold(*sk);
1308
1309 list_del(&cmd->list);
1310 mgmt_pending_free(cmd);
1311}
1312
f7520543
JH
1313int mgmt_disconnected(u16 index, bdaddr_t *bdaddr)
1314{
1315 struct mgmt_ev_disconnected ev;
8962ee74
JH
1316 struct sock *sk = NULL;
1317 int err;
1318
1319 mgmt_pending_foreach(MGMT_OP_DISCONNECT, index, disconnect_rsp, &sk);
f7520543
JH
1320
1321 put_unaligned_le16(index, &ev.index);
1322 bacpy(&ev.bdaddr, bdaddr);
1323
8962ee74
JH
1324 err = mgmt_event(MGMT_EV_DISCONNECTED, &ev, sizeof(ev), sk);
1325
1326 if (sk)
1327 sock_put(sk);
1328
1329 return err;
1330}
1331
1332int mgmt_disconnect_failed(u16 index)
1333{
1334 struct pending_cmd *cmd;
1335 int err;
1336
1337 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, index);
1338 if (!cmd)
1339 return -ENOENT;
1340
1341 err = cmd_status(cmd->sk, MGMT_OP_DISCONNECT, EIO);
1342
1343 list_del(&cmd->list);
1344 mgmt_pending_free(cmd);
1345
1346 return err;
f7520543 1347}
17d5c04c
JH
1348
1349int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status)
1350{
1351 struct mgmt_ev_connect_failed ev;
1352
1353 put_unaligned_le16(index, &ev.index);
1354 bacpy(&ev.bdaddr, bdaddr);
1355 ev.status = status;
1356
1357 return mgmt_event(MGMT_EV_CONNECT_FAILED, &ev, sizeof(ev), NULL);
1358}
980e1a53
JH
1359
1360int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr)
1361{
1362 struct mgmt_ev_pin_code_request ev;
1363
1364 put_unaligned_le16(index, &ev.index);
1365 bacpy(&ev.bdaddr, bdaddr);
1366
1367 return mgmt_event(MGMT_EV_PIN_CODE_REQUEST, &ev, sizeof(ev), NULL);
1368}
1369
1370int mgmt_pin_code_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
1371{
1372 struct pending_cmd *cmd;
1373 int err;
1374
1375 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, index);
1376 if (!cmd)
1377 return -ENOENT;
1378
1379 if (status != 0)
1380 err = cmd_status(cmd->sk, MGMT_OP_PIN_CODE_REPLY, status);
1381 else
1382 err = cmd_complete(cmd->sk, MGMT_OP_PIN_CODE_REPLY,
1383 bdaddr, sizeof(*bdaddr));
1384
1385 list_del(&cmd->list);
1386 mgmt_pending_free(cmd);
1387
1388 return err;
1389}
1390
1391int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
1392{
1393 struct pending_cmd *cmd;
1394 int err;
1395
1396 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, index);
1397 if (!cmd)
1398 return -ENOENT;
1399
1400 if (status != 0)
1401 err = cmd_status(cmd->sk, MGMT_OP_PIN_CODE_NEG_REPLY, status);
1402 else
1403 err = cmd_complete(cmd->sk, MGMT_OP_PIN_CODE_NEG_REPLY,
1404 bdaddr, sizeof(*bdaddr));
1405
1406 list_del(&cmd->list);
1407 mgmt_pending_free(cmd);
1408
1409 return err;
1410}