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