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