Bluetooth: Remove mgmt_set_service_cache
[deliverable/linux.git] / net / bluetooth / mgmt.c
CommitLineData
0381101f
JH
1/*
2 BlueZ - Bluetooth protocol stack for Linux
3 Copyright (C) 2010 Nokia Corporation
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License version 2 as
7 published by the Free Software Foundation;
8
9 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
10 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
11 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
12 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
13 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
18 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
19 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
20 SOFTWARE IS DISCLAIMED.
21*/
22
23/* Bluetooth HCI Management interface */
24
ca69b795 25#include <linux/kernel.h>
72359753 26#include <linux/uaccess.h>
0381101f
JH
27#include <asm/unaligned.h>
28
29#include <net/bluetooth/bluetooth.h>
30#include <net/bluetooth/hci_core.h>
31#include <net/bluetooth/mgmt.h>
32
02d98129
JH
33#define MGMT_VERSION 0
34#define MGMT_REVISION 1
35
2519a1fc
AG
36#define INQUIRY_LEN_BREDR 0x08 /* TGAP(100) */
37
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
69ab39ea
JH
245static u32 get_supported_settings(struct hci_dev *hdev)
246{
247 u32 settings = 0;
248
249 settings |= MGMT_SETTING_POWERED;
250 settings |= MGMT_SETTING_CONNECTABLE;
251 settings |= MGMT_SETTING_FAST_CONNECTABLE;
252 settings |= MGMT_SETTING_DISCOVERABLE;
253 settings |= MGMT_SETTING_PAIRABLE;
254
255 if (hdev->features[6] & LMP_SIMPLE_PAIR)
256 settings |= MGMT_SETTING_SSP;
257
258 if (!(hdev->features[4] & LMP_NO_BREDR)) {
259 settings |= MGMT_SETTING_BREDR;
260 settings |= MGMT_SETTING_LINK_SECURITY;
261 }
262
263 if (hdev->features[4] & LMP_LE)
264 settings |= MGMT_SETTING_LE;
265
266 return settings;
267}
268
269static u32 get_current_settings(struct hci_dev *hdev)
270{
271 u32 settings = 0;
272
273 if (test_bit(HCI_UP, &hdev->flags))
274 settings |= MGMT_SETTING_POWERED;
275 else
276 return settings;
277
278 if (test_bit(HCI_PSCAN, &hdev->flags))
279 settings |= MGMT_SETTING_CONNECTABLE;
280
281 if (test_bit(HCI_ISCAN, &hdev->flags))
282 settings |= MGMT_SETTING_DISCOVERABLE;
283
284 if (test_bit(HCI_PAIRABLE, &hdev->flags))
285 settings |= MGMT_SETTING_PAIRABLE;
286
287 if (!(hdev->features[4] & LMP_NO_BREDR))
288 settings |= MGMT_SETTING_BREDR;
289
290 if (hdev->extfeatures[0] & LMP_HOST_LE)
291 settings |= MGMT_SETTING_LE;
292
293 if (test_bit(HCI_AUTH, &hdev->flags))
294 settings |= MGMT_SETTING_LINK_SECURITY;
295
296 if (hdev->ssp_mode > 0)
297 settings |= MGMT_SETTING_SSP;
298
299 return settings;
300}
301
4e51eae9 302static int read_controller_info(struct sock *sk, u16 index)
0381101f 303{
a38528f1 304 struct mgmt_rp_read_info rp;
f7b64e69 305 struct hci_dev *hdev;
0381101f 306
4e51eae9 307 BT_DBG("sock %p hci%u", sk, index);
f7b64e69 308
4e51eae9 309 hdev = hci_dev_get(index);
a38528f1 310 if (!hdev)
ca69b795
JH
311 return cmd_status(sk, index, MGMT_OP_READ_INFO,
312 MGMT_STATUS_INVALID_PARAMS);
f7b64e69 313
3243553f
JH
314 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->flags))
315 cancel_delayed_work_sync(&hdev->power_off);
ab81cbf9 316
09fd0de5 317 hci_dev_lock(hdev);
f7b64e69 318
14c0b608
JH
319 if (test_and_clear_bit(HCI_PI_MGMT_INIT, &hci_pi(sk)->flags)) {
320 set_bit(HCI_MGMT, &hdev->flags);
321 set_bit(HCI_SERVICE_CACHE, &hdev->flags);
322 }
ebc99feb 323
dc4fe30b
JH
324 memset(&rp, 0, sizeof(rp));
325
69ab39ea 326 bacpy(&rp.bdaddr, &hdev->bdaddr);
f7b64e69 327
69ab39ea 328 rp.version = hdev->hci_ver;
f7b64e69 329
69ab39ea
JH
330 put_unaligned_le16(hdev->manufacturer, &rp.manufacturer);
331
332 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
333 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
f7b64e69 334
a38528f1 335 memcpy(rp.dev_class, hdev->dev_class, 3);
f7b64e69 336
dc4fe30b
JH
337 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
338
09fd0de5 339 hci_dev_unlock(hdev);
f7b64e69 340 hci_dev_put(hdev);
0381101f 341
4e51eae9 342 return cmd_complete(sk, index, MGMT_OP_READ_INFO, &rp, sizeof(rp));
0381101f
JH
343}
344
eec8d2bc
JH
345static void mgmt_pending_free(struct pending_cmd *cmd)
346{
347 sock_put(cmd->sk);
c68fb7ff 348 kfree(cmd->param);
eec8d2bc
JH
349 kfree(cmd);
350}
351
366a0336 352static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
2e58ef3e
JH
353 struct hci_dev *hdev,
354 void *data, u16 len)
eec8d2bc
JH
355{
356 struct pending_cmd *cmd;
357
358 cmd = kmalloc(sizeof(*cmd), GFP_ATOMIC);
359 if (!cmd)
366a0336 360 return NULL;
eec8d2bc
JH
361
362 cmd->opcode = opcode;
2e58ef3e 363 cmd->index = hdev->id;
eec8d2bc 364
c68fb7ff
SJ
365 cmd->param = kmalloc(len, GFP_ATOMIC);
366 if (!cmd->param) {
eec8d2bc 367 kfree(cmd);
366a0336 368 return NULL;
eec8d2bc
JH
369 }
370
8fce6357
SJ
371 if (data)
372 memcpy(cmd->param, data, len);
eec8d2bc
JH
373
374 cmd->sk = sk;
375 sock_hold(sk);
376
2e58ef3e 377 list_add(&cmd->list, &hdev->mgmt_pending);
eec8d2bc 378
366a0336 379 return cmd;
eec8d2bc
JH
380}
381
744cf19e 382static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
eec8d2bc
JH
383 void (*cb)(struct pending_cmd *cmd, void *data),
384 void *data)
385{
386 struct list_head *p, *n;
387
2e58ef3e 388 list_for_each_safe(p, n, &hdev->mgmt_pending) {
eec8d2bc
JH
389 struct pending_cmd *cmd;
390
391 cmd = list_entry(p, struct pending_cmd, list);
392
b24752fe 393 if (opcode > 0 && cmd->opcode != opcode)
eec8d2bc
JH
394 continue;
395
eec8d2bc
JH
396 cb(cmd, data);
397 }
398}
399
2e58ef3e 400static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
eec8d2bc 401{
8035ded4 402 struct pending_cmd *cmd;
eec8d2bc 403
2e58ef3e 404 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2aeabcbe
JH
405 if (cmd->opcode == opcode)
406 return cmd;
eec8d2bc
JH
407 }
408
409 return NULL;
410}
411
a664b5bc 412static void mgmt_pending_remove(struct pending_cmd *cmd)
73f22f62 413{
73f22f62
JH
414 list_del(&cmd->list);
415 mgmt_pending_free(cmd);
416}
417
69ab39ea 418static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
8680570b 419{
69ab39ea 420 __le32 settings = cpu_to_le32(get_current_settings(hdev));
8680570b 421
69ab39ea 422 return cmd_complete(sk, hdev->id, opcode, &settings, sizeof(settings));
8680570b
JH
423}
424
4e51eae9 425static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len)
eec8d2bc 426{
72a734ec 427 struct mgmt_mode *cp;
eec8d2bc 428 struct hci_dev *hdev;
366a0336 429 struct pending_cmd *cmd;
366a0336 430 int err, up;
eec8d2bc
JH
431
432 cp = (void *) data;
eec8d2bc 433
4e51eae9 434 BT_DBG("request for hci%u", index);
eec8d2bc 435
bdce7baf 436 if (len != sizeof(*cp))
ca69b795
JH
437 return cmd_status(sk, index, MGMT_OP_SET_POWERED,
438 MGMT_STATUS_INVALID_PARAMS);
bdce7baf 439
4e51eae9 440 hdev = hci_dev_get(index);
eec8d2bc 441 if (!hdev)
ca69b795
JH
442 return cmd_status(sk, index, MGMT_OP_SET_POWERED,
443 MGMT_STATUS_INVALID_PARAMS);
eec8d2bc 444
09fd0de5 445 hci_dev_lock(hdev);
eec8d2bc
JH
446
447 up = test_bit(HCI_UP, &hdev->flags);
72a734ec 448 if ((cp->val && up) || (!cp->val && !up)) {
69ab39ea 449 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
eec8d2bc
JH
450 goto failed;
451 }
452
2e58ef3e 453 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
ca69b795
JH
454 err = cmd_status(sk, index, MGMT_OP_SET_POWERED,
455 MGMT_STATUS_BUSY);
eec8d2bc
JH
456 goto failed;
457 }
458
2e58ef3e 459 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
366a0336
JH
460 if (!cmd) {
461 err = -ENOMEM;
eec8d2bc 462 goto failed;
366a0336 463 }
eec8d2bc 464
72a734ec 465 if (cp->val)
7f971041 466 schedule_work(&hdev->power_on);
eec8d2bc 467 else
80b7ab33 468 schedule_work(&hdev->power_off.work);
eec8d2bc 469
366a0336 470 err = 0;
eec8d2bc
JH
471
472failed:
09fd0de5 473 hci_dev_unlock(hdev);
eec8d2bc 474 hci_dev_put(hdev);
366a0336 475 return err;
eec8d2bc
JH
476}
477
4e51eae9
SJ
478static int set_discoverable(struct sock *sk, u16 index, unsigned char *data,
479 u16 len)
73f22f62 480{
16ab91ab 481 struct mgmt_cp_set_discoverable *cp;
73f22f62 482 struct hci_dev *hdev;
366a0336 483 struct pending_cmd *cmd;
73f22f62
JH
484 u8 scan;
485 int err;
486
487 cp = (void *) data;
73f22f62 488
4e51eae9 489 BT_DBG("request for hci%u", index);
73f22f62 490
bdce7baf 491 if (len != sizeof(*cp))
ca69b795
JH
492 return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE,
493 MGMT_STATUS_INVALID_PARAMS);
bdce7baf 494
4e51eae9 495 hdev = hci_dev_get(index);
73f22f62 496 if (!hdev)
ca69b795
JH
497 return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE,
498 MGMT_STATUS_INVALID_PARAMS);
73f22f62 499
09fd0de5 500 hci_dev_lock(hdev);
73f22f62
JH
501
502 if (!test_bit(HCI_UP, &hdev->flags)) {
ca69b795
JH
503 err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE,
504 MGMT_STATUS_NOT_POWERED);
73f22f62
JH
505 goto failed;
506 }
507
2e58ef3e
JH
508 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
509 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
ca69b795
JH
510 err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE,
511 MGMT_STATUS_BUSY);
73f22f62
JH
512 goto failed;
513 }
514
72a734ec 515 if (cp->val == test_bit(HCI_ISCAN, &hdev->flags) &&
73f22f62 516 test_bit(HCI_PSCAN, &hdev->flags)) {
69ab39ea 517 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
73f22f62
JH
518 goto failed;
519 }
520
2e58ef3e 521 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
366a0336
JH
522 if (!cmd) {
523 err = -ENOMEM;
73f22f62 524 goto failed;
366a0336 525 }
73f22f62
JH
526
527 scan = SCAN_PAGE;
528
72a734ec 529 if (cp->val)
73f22f62 530 scan |= SCAN_INQUIRY;
16ab91ab 531 else
e0f9309f 532 cancel_delayed_work(&hdev->discov_off);
73f22f62
JH
533
534 err = hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
535 if (err < 0)
a664b5bc 536 mgmt_pending_remove(cmd);
73f22f62 537
16ab91ab
JH
538 if (cp->val)
539 hdev->discov_timeout = get_unaligned_le16(&cp->timeout);
540
73f22f62 541failed:
09fd0de5 542 hci_dev_unlock(hdev);
73f22f62
JH
543 hci_dev_put(hdev);
544
545 return err;
546}
547
4e51eae9
SJ
548static int set_connectable(struct sock *sk, u16 index, unsigned char *data,
549 u16 len)
9fbcbb45 550{
72a734ec 551 struct mgmt_mode *cp;
9fbcbb45 552 struct hci_dev *hdev;
366a0336 553 struct pending_cmd *cmd;
9fbcbb45
JH
554 u8 scan;
555 int err;
556
557 cp = (void *) data;
9fbcbb45 558
4e51eae9 559 BT_DBG("request for hci%u", index);
9fbcbb45 560
bdce7baf 561 if (len != sizeof(*cp))
ca69b795
JH
562 return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE,
563 MGMT_STATUS_INVALID_PARAMS);
bdce7baf 564
4e51eae9 565 hdev = hci_dev_get(index);
9fbcbb45 566 if (!hdev)
ca69b795
JH
567 return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE,
568 MGMT_STATUS_INVALID_PARAMS);
9fbcbb45 569
09fd0de5 570 hci_dev_lock(hdev);
9fbcbb45
JH
571
572 if (!test_bit(HCI_UP, &hdev->flags)) {
ca69b795
JH
573 err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE,
574 MGMT_STATUS_NOT_POWERED);
9fbcbb45
JH
575 goto failed;
576 }
577
2e58ef3e
JH
578 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
579 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
ca69b795
JH
580 err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE,
581 MGMT_STATUS_BUSY);
9fbcbb45
JH
582 goto failed;
583 }
584
72a734ec 585 if (cp->val == test_bit(HCI_PSCAN, &hdev->flags)) {
69ab39ea 586 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
9fbcbb45
JH
587 goto failed;
588 }
589
2e58ef3e 590 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
366a0336
JH
591 if (!cmd) {
592 err = -ENOMEM;
9fbcbb45 593 goto failed;
366a0336 594 }
9fbcbb45 595
72a734ec 596 if (cp->val)
9fbcbb45
JH
597 scan = SCAN_PAGE;
598 else
599 scan = 0;
600
601 err = hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
602 if (err < 0)
a664b5bc 603 mgmt_pending_remove(cmd);
9fbcbb45
JH
604
605failed:
09fd0de5 606 hci_dev_unlock(hdev);
9fbcbb45
JH
607 hci_dev_put(hdev);
608
609 return err;
610}
611
744cf19e
JH
612static int mgmt_event(u16 event, struct hci_dev *hdev, void *data,
613 u16 data_len, struct sock *skip_sk)
c542a06c
JH
614{
615 struct sk_buff *skb;
616 struct mgmt_hdr *hdr;
617
618 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_ATOMIC);
619 if (!skb)
620 return -ENOMEM;
621
622 bt_cb(skb)->channel = HCI_CHANNEL_CONTROL;
623
624 hdr = (void *) skb_put(skb, sizeof(*hdr));
625 hdr->opcode = cpu_to_le16(event);
744cf19e
JH
626 if (hdev)
627 hdr->index = cpu_to_le16(hdev->id);
628 else
629 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
c542a06c
JH
630 hdr->len = cpu_to_le16(data_len);
631
4e51eae9
SJ
632 if (data)
633 memcpy(skb_put(skb, data_len), data, data_len);
c542a06c
JH
634
635 hci_send_to_sock(NULL, skb, skip_sk);
636 kfree_skb(skb);
637
638 return 0;
639}
640
4e51eae9
SJ
641static int set_pairable(struct sock *sk, u16 index, unsigned char *data,
642 u16 len)
c542a06c 643{
69ab39ea 644 struct mgmt_mode *cp;
c542a06c 645 struct hci_dev *hdev;
69ab39ea 646 __le32 ev;
c542a06c
JH
647 int err;
648
649 cp = (void *) data;
c542a06c 650
4e51eae9 651 BT_DBG("request for hci%u", index);
c542a06c 652
bdce7baf 653 if (len != sizeof(*cp))
ca69b795
JH
654 return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE,
655 MGMT_STATUS_INVALID_PARAMS);
bdce7baf 656
4e51eae9 657 hdev = hci_dev_get(index);
c542a06c 658 if (!hdev)
ca69b795
JH
659 return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE,
660 MGMT_STATUS_INVALID_PARAMS);
c542a06c 661
09fd0de5 662 hci_dev_lock(hdev);
c542a06c
JH
663
664 if (cp->val)
665 set_bit(HCI_PAIRABLE, &hdev->flags);
666 else
667 clear_bit(HCI_PAIRABLE, &hdev->flags);
668
69ab39ea 669 err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev);
c542a06c
JH
670 if (err < 0)
671 goto failed;
672
69ab39ea 673 ev = cpu_to_le32(get_current_settings(hdev));
c542a06c 674
69ab39ea 675 err = mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), sk);
c542a06c
JH
676
677failed:
09fd0de5 678 hci_dev_unlock(hdev);
c542a06c
JH
679 hci_dev_put(hdev);
680
681 return err;
682}
683
80a1e1db
JH
684#define EIR_FLAGS 0x01 /* flags */
685#define EIR_UUID16_SOME 0x02 /* 16-bit UUID, more available */
686#define EIR_UUID16_ALL 0x03 /* 16-bit UUID, all listed */
687#define EIR_UUID32_SOME 0x04 /* 32-bit UUID, more available */
688#define EIR_UUID32_ALL 0x05 /* 32-bit UUID, all listed */
689#define EIR_UUID128_SOME 0x06 /* 128-bit UUID, more available */
690#define EIR_UUID128_ALL 0x07 /* 128-bit UUID, all listed */
691#define EIR_NAME_SHORT 0x08 /* shortened local name */
692#define EIR_NAME_COMPLETE 0x09 /* complete local name */
693#define EIR_TX_POWER 0x0A /* transmit power level */
694#define EIR_DEVICE_ID 0x10 /* device ID */
695
696#define PNP_INFO_SVCLASS_ID 0x1200
697
698static u8 bluetooth_base_uuid[] = {
699 0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
700 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
701};
702
703static u16 get_uuid16(u8 *uuid128)
704{
705 u32 val;
706 int i;
707
708 for (i = 0; i < 12; i++) {
709 if (bluetooth_base_uuid[i] != uuid128[i])
710 return 0;
711 }
712
713 memcpy(&val, &uuid128[12], 4);
714
715 val = le32_to_cpu(val);
716 if (val > 0xffff)
717 return 0;
718
719 return (u16) val;
720}
721
722static void create_eir(struct hci_dev *hdev, u8 *data)
723{
724 u8 *ptr = data;
725 u16 eir_len = 0;
726 u16 uuid16_list[HCI_MAX_EIR_LENGTH / sizeof(u16)];
727 int i, truncated = 0;
8035ded4 728 struct bt_uuid *uuid;
80a1e1db
JH
729 size_t name_len;
730
731 name_len = strlen(hdev->dev_name);
732
733 if (name_len > 0) {
734 /* EIR Data type */
735 if (name_len > 48) {
736 name_len = 48;
737 ptr[1] = EIR_NAME_SHORT;
738 } else
739 ptr[1] = EIR_NAME_COMPLETE;
740
741 /* EIR Data length */
742 ptr[0] = name_len + 1;
743
744 memcpy(ptr + 2, hdev->dev_name, name_len);
745
746 eir_len += (name_len + 2);
747 ptr += (name_len + 2);
748 }
749
750 memset(uuid16_list, 0, sizeof(uuid16_list));
751
752 /* Group all UUID16 types */
8035ded4 753 list_for_each_entry(uuid, &hdev->uuids, list) {
80a1e1db
JH
754 u16 uuid16;
755
756 uuid16 = get_uuid16(uuid->uuid);
757 if (uuid16 == 0)
758 return;
759
760 if (uuid16 < 0x1100)
761 continue;
762
763 if (uuid16 == PNP_INFO_SVCLASS_ID)
764 continue;
765
766 /* Stop if not enough space to put next UUID */
767 if (eir_len + 2 + sizeof(u16) > HCI_MAX_EIR_LENGTH) {
768 truncated = 1;
769 break;
770 }
771
772 /* Check for duplicates */
773 for (i = 0; uuid16_list[i] != 0; i++)
774 if (uuid16_list[i] == uuid16)
775 break;
776
777 if (uuid16_list[i] == 0) {
778 uuid16_list[i] = uuid16;
779 eir_len += sizeof(u16);
780 }
781 }
782
783 if (uuid16_list[0] != 0) {
784 u8 *length = ptr;
785
786 /* EIR Data type */
787 ptr[1] = truncated ? EIR_UUID16_SOME : EIR_UUID16_ALL;
788
789 ptr += 2;
790 eir_len += 2;
791
792 for (i = 0; uuid16_list[i] != 0; i++) {
793 *ptr++ = (uuid16_list[i] & 0x00ff);
794 *ptr++ = (uuid16_list[i] & 0xff00) >> 8;
795 }
796
797 /* EIR Data length */
798 *length = (i * sizeof(u16)) + 1;
799 }
800}
801
802static int update_eir(struct hci_dev *hdev)
803{
804 struct hci_cp_write_eir cp;
805
806 if (!(hdev->features[6] & LMP_EXT_INQ))
807 return 0;
808
809 if (hdev->ssp_mode == 0)
810 return 0;
811
812 if (test_bit(HCI_SERVICE_CACHE, &hdev->flags))
813 return 0;
814
815 memset(&cp, 0, sizeof(cp));
816
817 create_eir(hdev, cp.data);
818
819 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
820 return 0;
821
822 memcpy(hdev->eir, cp.data, sizeof(cp.data));
823
824 return hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
825}
826
1aff6f09
JH
827static u8 get_service_classes(struct hci_dev *hdev)
828{
12dc0743 829 struct bt_uuid *uuid;
1aff6f09
JH
830 u8 val = 0;
831
12dc0743 832 list_for_each_entry(uuid, &hdev->uuids, list)
1aff6f09 833 val |= uuid->svc_hint;
1aff6f09
JH
834
835 return val;
836}
837
838static int update_class(struct hci_dev *hdev)
839{
840 u8 cod[3];
841
842 BT_DBG("%s", hdev->name);
843
844 if (test_bit(HCI_SERVICE_CACHE, &hdev->flags))
845 return 0;
846
847 cod[0] = hdev->minor_class;
848 cod[1] = hdev->major_class;
849 cod[2] = get_service_classes(hdev);
850
851 if (memcmp(cod, hdev->dev_class, 3) == 0)
852 return 0;
853
854 return hci_send_cmd(hdev, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
855}
856
4e51eae9 857static int add_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len)
2aeb9a1a
JH
858{
859 struct mgmt_cp_add_uuid *cp;
860 struct hci_dev *hdev;
861 struct bt_uuid *uuid;
2aeb9a1a
JH
862 int err;
863
864 cp = (void *) data;
2aeb9a1a 865
4e51eae9 866 BT_DBG("request for hci%u", index);
2aeb9a1a 867
bdce7baf 868 if (len != sizeof(*cp))
ca69b795
JH
869 return cmd_status(sk, index, MGMT_OP_ADD_UUID,
870 MGMT_STATUS_INVALID_PARAMS);
bdce7baf 871
4e51eae9 872 hdev = hci_dev_get(index);
2aeb9a1a 873 if (!hdev)
ca69b795
JH
874 return cmd_status(sk, index, MGMT_OP_ADD_UUID,
875 MGMT_STATUS_INVALID_PARAMS);
2aeb9a1a 876
09fd0de5 877 hci_dev_lock(hdev);
2aeb9a1a
JH
878
879 uuid = kmalloc(sizeof(*uuid), GFP_ATOMIC);
880 if (!uuid) {
881 err = -ENOMEM;
882 goto failed;
883 }
884
885 memcpy(uuid->uuid, cp->uuid, 16);
1aff6f09 886 uuid->svc_hint = cp->svc_hint;
2aeb9a1a
JH
887
888 list_add(&uuid->list, &hdev->uuids);
889
1aff6f09
JH
890 err = update_class(hdev);
891 if (err < 0)
892 goto failed;
893
80a1e1db
JH
894 err = update_eir(hdev);
895 if (err < 0)
896 goto failed;
897
4e51eae9 898 err = cmd_complete(sk, index, MGMT_OP_ADD_UUID, NULL, 0);
2aeb9a1a
JH
899
900failed:
09fd0de5 901 hci_dev_unlock(hdev);
2aeb9a1a
JH
902 hci_dev_put(hdev);
903
904 return err;
905}
906
4e51eae9 907static int remove_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len)
2aeb9a1a
JH
908{
909 struct list_head *p, *n;
779cb850 910 struct mgmt_cp_remove_uuid *cp;
2aeb9a1a
JH
911 struct hci_dev *hdev;
912 u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2aeb9a1a
JH
913 int err, found;
914
915 cp = (void *) data;
2aeb9a1a 916
4e51eae9 917 BT_DBG("request for hci%u", index);
2aeb9a1a 918
bdce7baf 919 if (len != sizeof(*cp))
ca69b795
JH
920 return cmd_status(sk, index, MGMT_OP_REMOVE_UUID,
921 MGMT_STATUS_INVALID_PARAMS);
bdce7baf 922
4e51eae9 923 hdev = hci_dev_get(index);
2aeb9a1a 924 if (!hdev)
ca69b795
JH
925 return cmd_status(sk, index, MGMT_OP_REMOVE_UUID,
926 MGMT_STATUS_INVALID_PARAMS);
2aeb9a1a 927
09fd0de5 928 hci_dev_lock(hdev);
2aeb9a1a
JH
929
930 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
931 err = hci_uuids_clear(hdev);
932 goto unlock;
933 }
934
935 found = 0;
936
937 list_for_each_safe(p, n, &hdev->uuids) {
938 struct bt_uuid *match = list_entry(p, struct bt_uuid, list);
939
940 if (memcmp(match->uuid, cp->uuid, 16) != 0)
941 continue;
942
943 list_del(&match->list);
944 found++;
945 }
946
947 if (found == 0) {
ca69b795
JH
948 err = cmd_status(sk, index, MGMT_OP_REMOVE_UUID,
949 MGMT_STATUS_INVALID_PARAMS);
2aeb9a1a
JH
950 goto unlock;
951 }
952
1aff6f09
JH
953 err = update_class(hdev);
954 if (err < 0)
955 goto unlock;
956
80a1e1db
JH
957 err = update_eir(hdev);
958 if (err < 0)
959 goto unlock;
960
4e51eae9 961 err = cmd_complete(sk, index, MGMT_OP_REMOVE_UUID, NULL, 0);
2aeb9a1a
JH
962
963unlock:
09fd0de5 964 hci_dev_unlock(hdev);
2aeb9a1a
JH
965 hci_dev_put(hdev);
966
967 return err;
968}
969
4e51eae9
SJ
970static int set_dev_class(struct sock *sk, u16 index, unsigned char *data,
971 u16 len)
1aff6f09
JH
972{
973 struct hci_dev *hdev;
974 struct mgmt_cp_set_dev_class *cp;
1aff6f09
JH
975 int err;
976
977 cp = (void *) data;
1aff6f09 978
4e51eae9 979 BT_DBG("request for hci%u", index);
1aff6f09 980
bdce7baf 981 if (len != sizeof(*cp))
ca69b795
JH
982 return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS,
983 MGMT_STATUS_INVALID_PARAMS);
bdce7baf 984
4e51eae9 985 hdev = hci_dev_get(index);
1aff6f09 986 if (!hdev)
ca69b795
JH
987 return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS,
988 MGMT_STATUS_INVALID_PARAMS);
1aff6f09 989
09fd0de5 990 hci_dev_lock(hdev);
1aff6f09
JH
991
992 hdev->major_class = cp->major;
993 hdev->minor_class = cp->minor;
994
14c0b608
JH
995 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->flags))
996 update_eir(hdev);
997
1aff6f09
JH
998 err = update_class(hdev);
999
1000 if (err == 0)
4e51eae9 1001 err = cmd_complete(sk, index, MGMT_OP_SET_DEV_CLASS, NULL, 0);
1aff6f09 1002
09fd0de5 1003 hci_dev_unlock(hdev);
1aff6f09
JH
1004 hci_dev_put(hdev);
1005
1006 return err;
1007}
1008
86742e1e
JH
1009static int load_link_keys(struct sock *sk, u16 index, unsigned char *data,
1010 u16 len)
55ed8ca1
JH
1011{
1012 struct hci_dev *hdev;
86742e1e 1013 struct mgmt_cp_load_link_keys *cp;
4e51eae9 1014 u16 key_count, expected_len;
a492cd52 1015 int i;
55ed8ca1
JH
1016
1017 cp = (void *) data;
bdce7baf
SJ
1018
1019 if (len < sizeof(*cp))
ca69b795
JH
1020 return cmd_status(sk, index, MGMT_OP_LOAD_LINK_KEYS,
1021 MGMT_STATUS_INVALID_PARAMS);
bdce7baf 1022
55ed8ca1
JH
1023 key_count = get_unaligned_le16(&cp->key_count);
1024
86742e1e
JH
1025 expected_len = sizeof(*cp) + key_count *
1026 sizeof(struct mgmt_link_key_info);
a492cd52 1027 if (expected_len != len) {
86742e1e 1028 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
a492cd52 1029 len, expected_len);
ca69b795
JH
1030 return cmd_status(sk, index, MGMT_OP_LOAD_LINK_KEYS,
1031 MGMT_STATUS_INVALID_PARAMS);
55ed8ca1
JH
1032 }
1033
4e51eae9 1034 hdev = hci_dev_get(index);
55ed8ca1 1035 if (!hdev)
ca69b795
JH
1036 return cmd_status(sk, index, MGMT_OP_LOAD_LINK_KEYS,
1037 MGMT_STATUS_INVALID_PARAMS);
55ed8ca1 1038
4e51eae9 1039 BT_DBG("hci%u debug_keys %u key_count %u", index, cp->debug_keys,
55ed8ca1
JH
1040 key_count);
1041
09fd0de5 1042 hci_dev_lock(hdev);
55ed8ca1
JH
1043
1044 hci_link_keys_clear(hdev);
1045
1046 set_bit(HCI_LINK_KEYS, &hdev->flags);
1047
1048 if (cp->debug_keys)
1049 set_bit(HCI_DEBUG_KEYS, &hdev->flags);
1050 else
1051 clear_bit(HCI_DEBUG_KEYS, &hdev->flags);
1052
a492cd52 1053 for (i = 0; i < key_count; i++) {
86742e1e 1054 struct mgmt_link_key_info *key = &cp->keys[i];
55ed8ca1 1055
d25e28ab 1056 hci_add_link_key(hdev, NULL, 0, &key->bdaddr, key->val, key->type,
55ed8ca1
JH
1057 key->pin_len);
1058 }
1059
0e5f875a
JH
1060 cmd_complete(sk, index, MGMT_OP_LOAD_LINK_KEYS, NULL, 0);
1061
09fd0de5 1062 hci_dev_unlock(hdev);
55ed8ca1
JH
1063 hci_dev_put(hdev);
1064
a492cd52 1065 return 0;
55ed8ca1
JH
1066}
1067
86742e1e
JH
1068static int remove_keys(struct sock *sk, u16 index, unsigned char *data,
1069 u16 len)
55ed8ca1
JH
1070{
1071 struct hci_dev *hdev;
86742e1e 1072 struct mgmt_cp_remove_keys *cp;
a8a1d19e
JH
1073 struct mgmt_rp_remove_keys rp;
1074 struct hci_cp_disconnect dc;
1075 struct pending_cmd *cmd;
55ed8ca1 1076 struct hci_conn *conn;
55ed8ca1
JH
1077 int err;
1078
1079 cp = (void *) data;
55ed8ca1 1080
bdce7baf 1081 if (len != sizeof(*cp))
ca69b795
JH
1082 return cmd_status(sk, index, MGMT_OP_REMOVE_KEYS,
1083 MGMT_STATUS_INVALID_PARAMS);
bdce7baf 1084
4e51eae9 1085 hdev = hci_dev_get(index);
55ed8ca1 1086 if (!hdev)
ca69b795
JH
1087 return cmd_status(sk, index, MGMT_OP_REMOVE_KEYS,
1088 MGMT_STATUS_INVALID_PARAMS);
55ed8ca1 1089
09fd0de5 1090 hci_dev_lock(hdev);
55ed8ca1 1091
a8a1d19e
JH
1092 memset(&rp, 0, sizeof(rp));
1093 bacpy(&rp.bdaddr, &cp->bdaddr);
ca69b795 1094 rp.status = MGMT_STATUS_FAILED;
a8a1d19e 1095
55ed8ca1 1096 err = hci_remove_link_key(hdev, &cp->bdaddr);
ca69b795
JH
1097 if (err < 0) {
1098 rp.status = MGMT_STATUS_NOT_PAIRED;
55ed8ca1 1099 goto unlock;
ca69b795 1100 }
55ed8ca1 1101
a8a1d19e
JH
1102 if (!test_bit(HCI_UP, &hdev->flags) || !cp->disconnect) {
1103 err = cmd_complete(sk, index, MGMT_OP_REMOVE_KEYS, &rp,
1104 sizeof(rp));
55ed8ca1 1105 goto unlock;
a8a1d19e 1106 }
55ed8ca1
JH
1107
1108 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
a8a1d19e
JH
1109 if (!conn) {
1110 err = cmd_complete(sk, index, MGMT_OP_REMOVE_KEYS, &rp,
1111 sizeof(rp));
1112 goto unlock;
1113 }
55ed8ca1 1114
a8a1d19e
JH
1115 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_KEYS, hdev, cp, sizeof(*cp));
1116 if (!cmd) {
1117 err = -ENOMEM;
1118 goto unlock;
55ed8ca1
JH
1119 }
1120
a8a1d19e
JH
1121 put_unaligned_le16(conn->handle, &dc.handle);
1122 dc.reason = 0x13; /* Remote User Terminated Connection */
1123 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1124 if (err < 0)
1125 mgmt_pending_remove(cmd);
1126
55ed8ca1 1127unlock:
ca69b795 1128 if (err < 0)
a8a1d19e
JH
1129 err = cmd_complete(sk, index, MGMT_OP_REMOVE_KEYS, &rp,
1130 sizeof(rp));
09fd0de5 1131 hci_dev_unlock(hdev);
55ed8ca1
JH
1132 hci_dev_put(hdev);
1133
1134 return err;
1135}
1136
4e51eae9 1137static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len)
8962ee74
JH
1138{
1139 struct hci_dev *hdev;
1140 struct mgmt_cp_disconnect *cp;
1141 struct hci_cp_disconnect dc;
366a0336 1142 struct pending_cmd *cmd;
8962ee74 1143 struct hci_conn *conn;
8962ee74
JH
1144 int err;
1145
1146 BT_DBG("");
1147
1148 cp = (void *) data;
8962ee74 1149
bdce7baf 1150 if (len != sizeof(*cp))
ca69b795
JH
1151 return cmd_status(sk, index, MGMT_OP_DISCONNECT,
1152 MGMT_STATUS_INVALID_PARAMS);
bdce7baf 1153
4e51eae9 1154 hdev = hci_dev_get(index);
8962ee74 1155 if (!hdev)
ca69b795
JH
1156 return cmd_status(sk, index, MGMT_OP_DISCONNECT,
1157 MGMT_STATUS_INVALID_PARAMS);
8962ee74 1158
09fd0de5 1159 hci_dev_lock(hdev);
8962ee74
JH
1160
1161 if (!test_bit(HCI_UP, &hdev->flags)) {
ca69b795
JH
1162 err = cmd_status(sk, index, MGMT_OP_DISCONNECT,
1163 MGMT_STATUS_NOT_POWERED);
8962ee74
JH
1164 goto failed;
1165 }
1166
2e58ef3e 1167 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
ca69b795
JH
1168 err = cmd_status(sk, index, MGMT_OP_DISCONNECT,
1169 MGMT_STATUS_BUSY);
8962ee74
JH
1170 goto failed;
1171 }
1172
1173 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
365227e5
VCG
1174 if (!conn)
1175 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->bdaddr);
1176
8962ee74 1177 if (!conn) {
ca69b795
JH
1178 err = cmd_status(sk, index, MGMT_OP_DISCONNECT,
1179 MGMT_STATUS_NOT_CONNECTED);
8962ee74
JH
1180 goto failed;
1181 }
1182
2e58ef3e 1183 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
366a0336
JH
1184 if (!cmd) {
1185 err = -ENOMEM;
8962ee74 1186 goto failed;
366a0336 1187 }
8962ee74
JH
1188
1189 put_unaligned_le16(conn->handle, &dc.handle);
1190 dc.reason = 0x13; /* Remote User Terminated Connection */
1191
1192 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1193 if (err < 0)
a664b5bc 1194 mgmt_pending_remove(cmd);
8962ee74
JH
1195
1196failed:
09fd0de5 1197 hci_dev_unlock(hdev);
8962ee74
JH
1198 hci_dev_put(hdev);
1199
1200 return err;
1201}
1202
48264f06 1203static u8 link_to_mgmt(u8 link_type, u8 addr_type)
4c659c39
JH
1204{
1205 switch (link_type) {
1206 case LE_LINK:
48264f06
JH
1207 switch (addr_type) {
1208 case ADDR_LE_DEV_PUBLIC:
1209 return MGMT_ADDR_LE_PUBLIC;
1210 case ADDR_LE_DEV_RANDOM:
1211 return MGMT_ADDR_LE_RANDOM;
1212 default:
1213 return MGMT_ADDR_INVALID;
1214 }
4c659c39
JH
1215 case ACL_LINK:
1216 return MGMT_ADDR_BREDR;
1217 default:
1218 return MGMT_ADDR_INVALID;
1219 }
1220}
1221
8ce6284e 1222static int get_connections(struct sock *sk, u16 index)
2784eb41 1223{
2784eb41
JH
1224 struct mgmt_rp_get_connections *rp;
1225 struct hci_dev *hdev;
8035ded4 1226 struct hci_conn *c;
2784eb41 1227 struct list_head *p;
a38528f1 1228 size_t rp_len;
4e51eae9 1229 u16 count;
2784eb41
JH
1230 int i, err;
1231
1232 BT_DBG("");
1233
4e51eae9 1234 hdev = hci_dev_get(index);
2784eb41 1235 if (!hdev)
ca69b795
JH
1236 return cmd_status(sk, index, MGMT_OP_GET_CONNECTIONS,
1237 MGMT_STATUS_INVALID_PARAMS);
2784eb41 1238
09fd0de5 1239 hci_dev_lock(hdev);
2784eb41
JH
1240
1241 count = 0;
1242 list_for_each(p, &hdev->conn_hash.list) {
1243 count++;
1244 }
1245
4c659c39 1246 rp_len = sizeof(*rp) + (count * sizeof(struct mgmt_addr_info));
a38528f1
JH
1247 rp = kmalloc(rp_len, GFP_ATOMIC);
1248 if (!rp) {
2784eb41
JH
1249 err = -ENOMEM;
1250 goto unlock;
1251 }
1252
2784eb41
JH
1253 put_unaligned_le16(count, &rp->conn_count);
1254
2784eb41 1255 i = 0;
4c659c39
JH
1256 list_for_each_entry(c, &hdev->conn_hash.list, list) {
1257 bacpy(&rp->addr[i].bdaddr, &c->dst);
48264f06 1258 rp->addr[i].type = link_to_mgmt(c->type, c->dst_type);
4c659c39
JH
1259 if (rp->addr[i].type == MGMT_ADDR_INVALID)
1260 continue;
1261 i++;
1262 }
1263
1264 /* Recalculate length in case of filtered SCO connections, etc */
1265 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
2784eb41 1266
4e51eae9 1267 err = cmd_complete(sk, index, MGMT_OP_GET_CONNECTIONS, rp, rp_len);
2784eb41
JH
1268
1269unlock:
a38528f1 1270 kfree(rp);
09fd0de5 1271 hci_dev_unlock(hdev);
2784eb41
JH
1272 hci_dev_put(hdev);
1273 return err;
1274}
1275
96d97a67
WR
1276static int send_pin_code_neg_reply(struct sock *sk, u16 index,
1277 struct hci_dev *hdev, struct mgmt_cp_pin_code_neg_reply *cp)
1278{
1279 struct pending_cmd *cmd;
1280 int err;
1281
2e58ef3e 1282 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
96d97a67
WR
1283 sizeof(*cp));
1284 if (!cmd)
1285 return -ENOMEM;
1286
1287 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, sizeof(cp->bdaddr),
1288 &cp->bdaddr);
1289 if (err < 0)
1290 mgmt_pending_remove(cmd);
1291
1292 return err;
1293}
1294
4e51eae9
SJ
1295static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data,
1296 u16 len)
980e1a53
JH
1297{
1298 struct hci_dev *hdev;
96d97a67 1299 struct hci_conn *conn;
980e1a53 1300 struct mgmt_cp_pin_code_reply *cp;
96d97a67 1301 struct mgmt_cp_pin_code_neg_reply ncp;
980e1a53 1302 struct hci_cp_pin_code_reply reply;
366a0336 1303 struct pending_cmd *cmd;
980e1a53
JH
1304 int err;
1305
1306 BT_DBG("");
1307
1308 cp = (void *) data;
980e1a53 1309
bdce7baf 1310 if (len != sizeof(*cp))
ca69b795
JH
1311 return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY,
1312 MGMT_STATUS_INVALID_PARAMS);
bdce7baf 1313
4e51eae9 1314 hdev = hci_dev_get(index);
980e1a53 1315 if (!hdev)
ca69b795
JH
1316 return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY,
1317 MGMT_STATUS_INVALID_PARAMS);
980e1a53 1318
09fd0de5 1319 hci_dev_lock(hdev);
980e1a53
JH
1320
1321 if (!test_bit(HCI_UP, &hdev->flags)) {
ca69b795
JH
1322 err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY,
1323 MGMT_STATUS_NOT_POWERED);
980e1a53
JH
1324 goto failed;
1325 }
1326
96d97a67
WR
1327 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1328 if (!conn) {
ca69b795
JH
1329 err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY,
1330 MGMT_STATUS_NOT_CONNECTED);
96d97a67
WR
1331 goto failed;
1332 }
1333
1334 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
1335 bacpy(&ncp.bdaddr, &cp->bdaddr);
1336
1337 BT_ERR("PIN code is not 16 bytes long");
1338
1339 err = send_pin_code_neg_reply(sk, index, hdev, &ncp);
1340 if (err >= 0)
1341 err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY,
ca69b795 1342 MGMT_STATUS_INVALID_PARAMS);
96d97a67
WR
1343
1344 goto failed;
1345 }
1346
2e58ef3e 1347 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
366a0336
JH
1348 if (!cmd) {
1349 err = -ENOMEM;
980e1a53 1350 goto failed;
366a0336 1351 }
980e1a53
JH
1352
1353 bacpy(&reply.bdaddr, &cp->bdaddr);
1354 reply.pin_len = cp->pin_len;
24718ca5 1355 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
980e1a53
JH
1356
1357 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
1358 if (err < 0)
a664b5bc 1359 mgmt_pending_remove(cmd);
980e1a53
JH
1360
1361failed:
09fd0de5 1362 hci_dev_unlock(hdev);
980e1a53
JH
1363 hci_dev_put(hdev);
1364
1365 return err;
1366}
1367
4e51eae9
SJ
1368static int pin_code_neg_reply(struct sock *sk, u16 index, unsigned char *data,
1369 u16 len)
980e1a53
JH
1370{
1371 struct hci_dev *hdev;
1372 struct mgmt_cp_pin_code_neg_reply *cp;
980e1a53
JH
1373 int err;
1374
1375 BT_DBG("");
1376
1377 cp = (void *) data;
980e1a53 1378
bdce7baf
SJ
1379 if (len != sizeof(*cp))
1380 return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
ca69b795 1381 MGMT_STATUS_INVALID_PARAMS);
bdce7baf 1382
4e51eae9 1383 hdev = hci_dev_get(index);
980e1a53 1384 if (!hdev)
4e51eae9 1385 return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
ca69b795 1386 MGMT_STATUS_INVALID_PARAMS);
980e1a53 1387
09fd0de5 1388 hci_dev_lock(hdev);
980e1a53
JH
1389
1390 if (!test_bit(HCI_UP, &hdev->flags)) {
4e51eae9 1391 err = cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
ca69b795 1392 MGMT_STATUS_NOT_POWERED);
980e1a53
JH
1393 goto failed;
1394 }
1395
96d97a67 1396 err = send_pin_code_neg_reply(sk, index, hdev, cp);
980e1a53
JH
1397
1398failed:
09fd0de5 1399 hci_dev_unlock(hdev);
980e1a53
JH
1400 hci_dev_put(hdev);
1401
1402 return err;
1403}
1404
4e51eae9
SJ
1405static int set_io_capability(struct sock *sk, u16 index, unsigned char *data,
1406 u16 len)
17fa4b9d
JH
1407{
1408 struct hci_dev *hdev;
1409 struct mgmt_cp_set_io_capability *cp;
17fa4b9d
JH
1410
1411 BT_DBG("");
1412
1413 cp = (void *) data;
17fa4b9d 1414
bdce7baf 1415 if (len != sizeof(*cp))
ca69b795
JH
1416 return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY,
1417 MGMT_STATUS_INVALID_PARAMS);
bdce7baf 1418
4e51eae9 1419 hdev = hci_dev_get(index);
17fa4b9d 1420 if (!hdev)
ca69b795
JH
1421 return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY,
1422 MGMT_STATUS_INVALID_PARAMS);
17fa4b9d 1423
09fd0de5 1424 hci_dev_lock(hdev);
17fa4b9d
JH
1425
1426 hdev->io_capability = cp->io_capability;
1427
1428 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
b8534e0f 1429 hdev->io_capability);
17fa4b9d 1430
09fd0de5 1431 hci_dev_unlock(hdev);
17fa4b9d
JH
1432 hci_dev_put(hdev);
1433
4e51eae9 1434 return cmd_complete(sk, index, MGMT_OP_SET_IO_CAPABILITY, NULL, 0);
17fa4b9d
JH
1435}
1436
e9a416b5
JH
1437static inline struct pending_cmd *find_pairing(struct hci_conn *conn)
1438{
1439 struct hci_dev *hdev = conn->hdev;
8035ded4 1440 struct pending_cmd *cmd;
e9a416b5 1441
2e58ef3e 1442 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
e9a416b5
JH
1443 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
1444 continue;
1445
e9a416b5
JH
1446 if (cmd->user_data != conn)
1447 continue;
1448
1449 return cmd;
1450 }
1451
1452 return NULL;
1453}
1454
1455static void pairing_complete(struct pending_cmd *cmd, u8 status)
1456{
1457 struct mgmt_rp_pair_device rp;
1458 struct hci_conn *conn = cmd->user_data;
1459
ba4e564f
JH
1460 bacpy(&rp.addr.bdaddr, &conn->dst);
1461 rp.addr.type = link_to_mgmt(conn->type, conn->dst_type);
e9a416b5
JH
1462 rp.status = status;
1463
4e51eae9 1464 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, &rp, sizeof(rp));
e9a416b5
JH
1465
1466 /* So we don't get further callbacks for this connection */
1467 conn->connect_cfm_cb = NULL;
1468 conn->security_cfm_cb = NULL;
1469 conn->disconn_cfm_cb = NULL;
1470
1471 hci_conn_put(conn);
1472
a664b5bc 1473 mgmt_pending_remove(cmd);
e9a416b5
JH
1474}
1475
1476static void pairing_complete_cb(struct hci_conn *conn, u8 status)
1477{
1478 struct pending_cmd *cmd;
1479
1480 BT_DBG("status %u", status);
1481
1482 cmd = find_pairing(conn);
56e5cb86 1483 if (!cmd)
e9a416b5 1484 BT_DBG("Unable to find a pending command");
56e5cb86
JH
1485 else
1486 pairing_complete(cmd, status);
e9a416b5
JH
1487}
1488
4e51eae9 1489static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len)
e9a416b5
JH
1490{
1491 struct hci_dev *hdev;
1492 struct mgmt_cp_pair_device *cp;
1425acb7 1493 struct mgmt_rp_pair_device rp;
e9a416b5
JH
1494 struct pending_cmd *cmd;
1495 u8 sec_level, auth_type;
1496 struct hci_conn *conn;
e9a416b5
JH
1497 int err;
1498
1499 BT_DBG("");
1500
1501 cp = (void *) data;
e9a416b5 1502
bdce7baf 1503 if (len != sizeof(*cp))
ca69b795
JH
1504 return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE,
1505 MGMT_STATUS_INVALID_PARAMS);
bdce7baf 1506
4e51eae9 1507 hdev = hci_dev_get(index);
e9a416b5 1508 if (!hdev)
ca69b795
JH
1509 return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE,
1510 MGMT_STATUS_INVALID_PARAMS);
e9a416b5 1511
09fd0de5 1512 hci_dev_lock(hdev);
e9a416b5 1513
c908df36
VCG
1514 sec_level = BT_SECURITY_MEDIUM;
1515 if (cp->io_cap == 0x03)
e9a416b5 1516 auth_type = HCI_AT_DEDICATED_BONDING;
c908df36 1517 else
e9a416b5 1518 auth_type = HCI_AT_DEDICATED_BONDING_MITM;
e9a416b5 1519
ba4e564f
JH
1520 if (cp->addr.type == MGMT_ADDR_BREDR)
1521 conn = hci_connect(hdev, ACL_LINK, &cp->addr.bdaddr, sec_level,
7a512d01
VCG
1522 auth_type);
1523 else
ba4e564f 1524 conn = hci_connect(hdev, LE_LINK, &cp->addr.bdaddr, sec_level,
7a512d01
VCG
1525 auth_type);
1526
1425acb7
JH
1527 memset(&rp, 0, sizeof(rp));
1528 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
1529 rp.addr.type = cp->addr.type;
1530
30e76272 1531 if (IS_ERR(conn)) {
1425acb7
JH
1532 rp.status = -PTR_ERR(conn);
1533 err = cmd_complete(sk, index, MGMT_OP_PAIR_DEVICE,
1534 &rp, sizeof(rp));
e9a416b5
JH
1535 goto unlock;
1536 }
1537
1538 if (conn->connect_cfm_cb) {
1539 hci_conn_put(conn);
1425acb7
JH
1540 rp.status = EBUSY;
1541 err = cmd_complete(sk, index, MGMT_OP_PAIR_DEVICE,
1542 &rp, sizeof(rp));
e9a416b5
JH
1543 goto unlock;
1544 }
1545
2e58ef3e 1546 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
e9a416b5
JH
1547 if (!cmd) {
1548 err = -ENOMEM;
1549 hci_conn_put(conn);
1550 goto unlock;
1551 }
1552
7a512d01 1553 /* For LE, just connecting isn't a proof that the pairing finished */
ba4e564f 1554 if (cp->addr.type == MGMT_ADDR_BREDR)
7a512d01
VCG
1555 conn->connect_cfm_cb = pairing_complete_cb;
1556
e9a416b5
JH
1557 conn->security_cfm_cb = pairing_complete_cb;
1558 conn->disconn_cfm_cb = pairing_complete_cb;
1559 conn->io_capability = cp->io_cap;
1560 cmd->user_data = conn;
1561
1562 if (conn->state == BT_CONNECTED &&
1563 hci_conn_security(conn, sec_level, auth_type))
1564 pairing_complete(cmd, 0);
1565
1566 err = 0;
1567
1568unlock:
09fd0de5 1569 hci_dev_unlock(hdev);
e9a416b5
JH
1570 hci_dev_put(hdev);
1571
1572 return err;
1573}
1574
0df4c185
BG
1575static int user_pairing_resp(struct sock *sk, u16 index, bdaddr_t *bdaddr,
1576 u16 mgmt_op, u16 hci_op, __le32 passkey)
a5c29683 1577{
a5c29683
JH
1578 struct pending_cmd *cmd;
1579 struct hci_dev *hdev;
0df4c185 1580 struct hci_conn *conn;
a5c29683
JH
1581 int err;
1582
4e51eae9 1583 hdev = hci_dev_get(index);
a5c29683 1584 if (!hdev)
ca69b795
JH
1585 return cmd_status(sk, index, mgmt_op,
1586 MGMT_STATUS_INVALID_PARAMS);
a5c29683 1587
09fd0de5 1588 hci_dev_lock(hdev);
08ba5382 1589
a5c29683 1590 if (!test_bit(HCI_UP, &hdev->flags)) {
0df4c185
BG
1591 err = cmd_status(sk, index, mgmt_op, MGMT_STATUS_NOT_POWERED);
1592 goto done;
a5c29683
JH
1593 }
1594
47c15e2b
BG
1595 /*
1596 * Check for an existing ACL link, if present pair via
1597 * HCI commands.
1598 *
1599 * If no ACL link is present, check for an LE link and if
1600 * present, pair via the SMP engine.
1601 *
1602 * If neither ACL nor LE links are present, fail with error.
1603 */
1604 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, bdaddr);
1605 if (!conn) {
1606 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, bdaddr);
1607 if (!conn) {
1608 err = cmd_status(sk, index, mgmt_op,
1609 MGMT_STATUS_NOT_CONNECTED);
1610 goto done;
1611 }
1612
1613 /* Continue with pairing via SMP */
1614
1615 err = cmd_status(sk, index, mgmt_op, MGMT_STATUS_SUCCESS);
1616 goto done;
1617 }
1618
0df4c185 1619 cmd = mgmt_pending_add(sk, mgmt_op, hdev, bdaddr, sizeof(*bdaddr));
a5c29683
JH
1620 if (!cmd) {
1621 err = -ENOMEM;
0df4c185 1622 goto done;
a5c29683
JH
1623 }
1624
0df4c185 1625 /* Continue with pairing via HCI */
604086b7
BG
1626 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
1627 struct hci_cp_user_passkey_reply cp;
1628
1629 bacpy(&cp.bdaddr, bdaddr);
1630 cp.passkey = passkey;
1631 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
1632 } else
1633 err = hci_send_cmd(hdev, hci_op, sizeof(*bdaddr), bdaddr);
1634
a664b5bc
JH
1635 if (err < 0)
1636 mgmt_pending_remove(cmd);
a5c29683 1637
0df4c185 1638done:
09fd0de5 1639 hci_dev_unlock(hdev);
a5c29683
JH
1640 hci_dev_put(hdev);
1641
1642 return err;
1643}
1644
0df4c185
BG
1645static int user_confirm_reply(struct sock *sk, u16 index, void *data, u16 len)
1646{
1647 struct mgmt_cp_user_confirm_reply *cp = (void *) data;
1648
1649 BT_DBG("");
1650
1651 if (len != sizeof(*cp))
1652 return cmd_status(sk, index, MGMT_OP_USER_CONFIRM_REPLY,
1653 MGMT_STATUS_INVALID_PARAMS);
1654
1655 return user_pairing_resp(sk, index, &cp->bdaddr,
1656 MGMT_OP_USER_CONFIRM_REPLY,
1657 HCI_OP_USER_CONFIRM_REPLY, 0);
1658}
1659
1660static int user_confirm_neg_reply(struct sock *sk, u16 index, void *data,
1661 u16 len)
1662{
1663 struct mgmt_cp_user_confirm_reply *cp = (void *) data;
1664
1665 BT_DBG("");
1666
1667 if (len != sizeof(*cp))
1668 return cmd_status(sk, index, MGMT_OP_USER_CONFIRM_NEG_REPLY,
1669 MGMT_STATUS_INVALID_PARAMS);
1670
1671 return user_pairing_resp(sk, index, &cp->bdaddr,
1672 MGMT_OP_USER_CONFIRM_NEG_REPLY,
1673 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
1674}
1675
604086b7
BG
1676static int user_passkey_reply(struct sock *sk, u16 index, void *data, u16 len)
1677{
1678 struct mgmt_cp_user_passkey_reply *cp = (void *) data;
1679
1680 BT_DBG("");
1681
1682 if (len != sizeof(*cp))
1683 return cmd_status(sk, index, MGMT_OP_USER_PASSKEY_REPLY,
1684 EINVAL);
1685
1686 return user_pairing_resp(sk, index, &cp->bdaddr,
1687 MGMT_OP_USER_PASSKEY_REPLY,
1688 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
1689}
1690
1691static int user_passkey_neg_reply(struct sock *sk, u16 index, void *data,
1692 u16 len)
1693{
1694 struct mgmt_cp_user_passkey_neg_reply *cp = (void *) data;
1695
1696 BT_DBG("");
1697
1698 if (len != sizeof(*cp))
1699 return cmd_status(sk, index, MGMT_OP_USER_PASSKEY_NEG_REPLY,
1700 EINVAL);
1701
1702 return user_pairing_resp(sk, index, &cp->bdaddr,
1703 MGMT_OP_USER_PASSKEY_NEG_REPLY,
1704 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
1705}
1706
b312b161
JH
1707static int set_local_name(struct sock *sk, u16 index, unsigned char *data,
1708 u16 len)
1709{
1710 struct mgmt_cp_set_local_name *mgmt_cp = (void *) data;
1711 struct hci_cp_write_local_name hci_cp;
1712 struct hci_dev *hdev;
1713 struct pending_cmd *cmd;
1714 int err;
1715
1716 BT_DBG("");
1717
1718 if (len != sizeof(*mgmt_cp))
ca69b795
JH
1719 return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME,
1720 MGMT_STATUS_INVALID_PARAMS);
b312b161
JH
1721
1722 hdev = hci_dev_get(index);
1723 if (!hdev)
ca69b795
JH
1724 return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME,
1725 MGMT_STATUS_INVALID_PARAMS);
b312b161 1726
09fd0de5 1727 hci_dev_lock(hdev);
b312b161 1728
2e58ef3e 1729 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
b312b161
JH
1730 if (!cmd) {
1731 err = -ENOMEM;
1732 goto failed;
1733 }
1734
1735 memcpy(hci_cp.name, mgmt_cp->name, sizeof(hci_cp.name));
1736 err = hci_send_cmd(hdev, HCI_OP_WRITE_LOCAL_NAME, sizeof(hci_cp),
1737 &hci_cp);
1738 if (err < 0)
1739 mgmt_pending_remove(cmd);
1740
1741failed:
09fd0de5 1742 hci_dev_unlock(hdev);
b312b161
JH
1743 hci_dev_put(hdev);
1744
1745 return err;
1746}
1747
c35938b2
SJ
1748static int read_local_oob_data(struct sock *sk, u16 index)
1749{
1750 struct hci_dev *hdev;
1751 struct pending_cmd *cmd;
1752 int err;
1753
1754 BT_DBG("hci%u", index);
1755
1756 hdev = hci_dev_get(index);
1757 if (!hdev)
1758 return cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
ca69b795 1759 MGMT_STATUS_INVALID_PARAMS);
c35938b2 1760
09fd0de5 1761 hci_dev_lock(hdev);
c35938b2
SJ
1762
1763 if (!test_bit(HCI_UP, &hdev->flags)) {
1764 err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
ca69b795 1765 MGMT_STATUS_NOT_POWERED);
c35938b2
SJ
1766 goto unlock;
1767 }
1768
1769 if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) {
1770 err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
ca69b795 1771 MGMT_STATUS_NOT_SUPPORTED);
c35938b2
SJ
1772 goto unlock;
1773 }
1774
2e58ef3e 1775 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
ca69b795
JH
1776 err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
1777 MGMT_STATUS_BUSY);
c35938b2
SJ
1778 goto unlock;
1779 }
1780
2e58ef3e 1781 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
c35938b2
SJ
1782 if (!cmd) {
1783 err = -ENOMEM;
1784 goto unlock;
1785 }
1786
1787 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
1788 if (err < 0)
1789 mgmt_pending_remove(cmd);
1790
1791unlock:
09fd0de5 1792 hci_dev_unlock(hdev);
c35938b2
SJ
1793 hci_dev_put(hdev);
1794
1795 return err;
1796}
1797
2763eda6
SJ
1798static int add_remote_oob_data(struct sock *sk, u16 index, unsigned char *data,
1799 u16 len)
1800{
1801 struct hci_dev *hdev;
1802 struct mgmt_cp_add_remote_oob_data *cp = (void *) data;
1803 int err;
1804
1805 BT_DBG("hci%u ", index);
1806
1807 if (len != sizeof(*cp))
1808 return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA,
ca69b795 1809 MGMT_STATUS_INVALID_PARAMS);
2763eda6
SJ
1810
1811 hdev = hci_dev_get(index);
1812 if (!hdev)
1813 return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA,
ca69b795 1814 MGMT_STATUS_INVALID_PARAMS);
2763eda6 1815
09fd0de5 1816 hci_dev_lock(hdev);
2763eda6
SJ
1817
1818 err = hci_add_remote_oob_data(hdev, &cp->bdaddr, cp->hash,
1819 cp->randomizer);
1820 if (err < 0)
ca69b795
JH
1821 err = cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA,
1822 MGMT_STATUS_FAILED);
2763eda6
SJ
1823 else
1824 err = cmd_complete(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, NULL,
1825 0);
1826
09fd0de5 1827 hci_dev_unlock(hdev);
2763eda6
SJ
1828 hci_dev_put(hdev);
1829
1830 return err;
1831}
1832
1833static int remove_remote_oob_data(struct sock *sk, u16 index,
1834 unsigned char *data, u16 len)
1835{
1836 struct hci_dev *hdev;
1837 struct mgmt_cp_remove_remote_oob_data *cp = (void *) data;
1838 int err;
1839
1840 BT_DBG("hci%u ", index);
1841
1842 if (len != sizeof(*cp))
1843 return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
ca69b795 1844 MGMT_STATUS_INVALID_PARAMS);
2763eda6
SJ
1845
1846 hdev = hci_dev_get(index);
1847 if (!hdev)
1848 return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
ca69b795 1849 MGMT_STATUS_INVALID_PARAMS);
2763eda6 1850
09fd0de5 1851 hci_dev_lock(hdev);
2763eda6
SJ
1852
1853 err = hci_remove_remote_oob_data(hdev, &cp->bdaddr);
1854 if (err < 0)
1855 err = cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
ca69b795 1856 MGMT_STATUS_INVALID_PARAMS);
2763eda6
SJ
1857 else
1858 err = cmd_complete(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
1859 NULL, 0);
1860
09fd0de5 1861 hci_dev_unlock(hdev);
2763eda6
SJ
1862 hci_dev_put(hdev);
1863
1864 return err;
1865}
1866
450dfdaf
JH
1867static int start_discovery(struct sock *sk, u16 index,
1868 unsigned char *data, u16 len)
14a53664 1869{
450dfdaf 1870 struct mgmt_cp_start_discovery *cp = (void *) data;
14a53664
JH
1871 struct pending_cmd *cmd;
1872 struct hci_dev *hdev;
1873 int err;
1874
1875 BT_DBG("hci%u", index);
1876
450dfdaf
JH
1877 if (len != sizeof(*cp))
1878 return cmd_status(sk, index, MGMT_OP_START_DISCOVERY,
1879 MGMT_STATUS_INVALID_PARAMS);
1880
14a53664
JH
1881 hdev = hci_dev_get(index);
1882 if (!hdev)
ca69b795
JH
1883 return cmd_status(sk, index, MGMT_OP_START_DISCOVERY,
1884 MGMT_STATUS_INVALID_PARAMS);
14a53664 1885
09fd0de5 1886 hci_dev_lock(hdev);
14a53664 1887
bd2d1334 1888 if (!test_bit(HCI_UP, &hdev->flags)) {
ca69b795
JH
1889 err = cmd_status(sk, index, MGMT_OP_START_DISCOVERY,
1890 MGMT_STATUS_NOT_POWERED);
bd2d1334
JH
1891 goto failed;
1892 }
1893
2e58ef3e 1894 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
14a53664
JH
1895 if (!cmd) {
1896 err = -ENOMEM;
1897 goto failed;
1898 }
1899
2519a1fc 1900 err = hci_do_inquiry(hdev, INQUIRY_LEN_BREDR);
14a53664
JH
1901 if (err < 0)
1902 mgmt_pending_remove(cmd);
1903
1904failed:
09fd0de5 1905 hci_dev_unlock(hdev);
14a53664
JH
1906 hci_dev_put(hdev);
1907
1908 return err;
1909}
1910
1911static int stop_discovery(struct sock *sk, u16 index)
1912{
1913 struct hci_dev *hdev;
1914 struct pending_cmd *cmd;
1915 int err;
1916
1917 BT_DBG("hci%u", index);
1918
1919 hdev = hci_dev_get(index);
1920 if (!hdev)
ca69b795
JH
1921 return cmd_status(sk, index, MGMT_OP_STOP_DISCOVERY,
1922 MGMT_STATUS_INVALID_PARAMS);
14a53664 1923
09fd0de5 1924 hci_dev_lock(hdev);
14a53664 1925
2e58ef3e 1926 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
14a53664
JH
1927 if (!cmd) {
1928 err = -ENOMEM;
1929 goto failed;
1930 }
1931
023d5049 1932 err = hci_cancel_inquiry(hdev);
14a53664
JH
1933 if (err < 0)
1934 mgmt_pending_remove(cmd);
1935
1936failed:
09fd0de5 1937 hci_dev_unlock(hdev);
14a53664
JH
1938 hci_dev_put(hdev);
1939
1940 return err;
1941}
1942
7fbec224
AJ
1943static int block_device(struct sock *sk, u16 index, unsigned char *data,
1944 u16 len)
1945{
1946 struct hci_dev *hdev;
5e762444 1947 struct mgmt_cp_block_device *cp = (void *) data;
7fbec224
AJ
1948 int err;
1949
1950 BT_DBG("hci%u", index);
1951
7fbec224
AJ
1952 if (len != sizeof(*cp))
1953 return cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE,
ca69b795 1954 MGMT_STATUS_INVALID_PARAMS);
7fbec224
AJ
1955
1956 hdev = hci_dev_get(index);
1957 if (!hdev)
1958 return cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE,
ca69b795 1959 MGMT_STATUS_INVALID_PARAMS);
7fbec224 1960
09fd0de5 1961 hci_dev_lock(hdev);
5e762444 1962
7fbec224 1963 err = hci_blacklist_add(hdev, &cp->bdaddr);
7fbec224 1964 if (err < 0)
ca69b795
JH
1965 err = cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE,
1966 MGMT_STATUS_FAILED);
7fbec224
AJ
1967 else
1968 err = cmd_complete(sk, index, MGMT_OP_BLOCK_DEVICE,
1969 NULL, 0);
5e762444 1970
09fd0de5 1971 hci_dev_unlock(hdev);
7fbec224
AJ
1972 hci_dev_put(hdev);
1973
1974 return err;
1975}
1976
1977static int unblock_device(struct sock *sk, u16 index, unsigned char *data,
1978 u16 len)
1979{
1980 struct hci_dev *hdev;
5e762444 1981 struct mgmt_cp_unblock_device *cp = (void *) data;
7fbec224
AJ
1982 int err;
1983
1984 BT_DBG("hci%u", index);
1985
7fbec224
AJ
1986 if (len != sizeof(*cp))
1987 return cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE,
ca69b795 1988 MGMT_STATUS_INVALID_PARAMS);
7fbec224
AJ
1989
1990 hdev = hci_dev_get(index);
1991 if (!hdev)
1992 return cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE,
ca69b795 1993 MGMT_STATUS_INVALID_PARAMS);
7fbec224 1994
09fd0de5 1995 hci_dev_lock(hdev);
5e762444 1996
7fbec224
AJ
1997 err = hci_blacklist_del(hdev, &cp->bdaddr);
1998
1999 if (err < 0)
ca69b795
JH
2000 err = cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE,
2001 MGMT_STATUS_INVALID_PARAMS);
7fbec224
AJ
2002 else
2003 err = cmd_complete(sk, index, MGMT_OP_UNBLOCK_DEVICE,
2004 NULL, 0);
5e762444 2005
09fd0de5 2006 hci_dev_unlock(hdev);
7fbec224
AJ
2007 hci_dev_put(hdev);
2008
2009 return err;
2010}
2011
f6422ec6
AJ
2012static int set_fast_connectable(struct sock *sk, u16 index,
2013 unsigned char *data, u16 len)
2014{
2015 struct hci_dev *hdev;
f7c6869c 2016 struct mgmt_mode *cp = (void *) data;
f6422ec6
AJ
2017 struct hci_cp_write_page_scan_activity acp;
2018 u8 type;
2019 int err;
2020
2021 BT_DBG("hci%u", index);
2022
2023 if (len != sizeof(*cp))
2024 return cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE,
ca69b795 2025 MGMT_STATUS_INVALID_PARAMS);
f6422ec6
AJ
2026
2027 hdev = hci_dev_get(index);
2028 if (!hdev)
2029 return cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE,
ca69b795 2030 MGMT_STATUS_INVALID_PARAMS);
f6422ec6
AJ
2031
2032 hci_dev_lock(hdev);
2033
f7c6869c 2034 if (cp->val) {
f6422ec6
AJ
2035 type = PAGE_SCAN_TYPE_INTERLACED;
2036 acp.interval = 0x0024; /* 22.5 msec page scan interval */
2037 } else {
2038 type = PAGE_SCAN_TYPE_STANDARD; /* default */
2039 acp.interval = 0x0800; /* default 1.28 sec page scan */
2040 }
2041
2042 acp.window = 0x0012; /* default 11.25 msec page scan window */
2043
2044 err = hci_send_cmd(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
2045 sizeof(acp), &acp);
2046 if (err < 0) {
2047 err = cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE,
ca69b795 2048 MGMT_STATUS_FAILED);
f6422ec6
AJ
2049 goto done;
2050 }
2051
2052 err = hci_send_cmd(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
2053 if (err < 0) {
2054 err = cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE,
ca69b795 2055 MGMT_STATUS_FAILED);
f6422ec6
AJ
2056 goto done;
2057 }
2058
2059 err = cmd_complete(sk, index, MGMT_OP_SET_FAST_CONNECTABLE,
2060 NULL, 0);
2061done:
2062 hci_dev_unlock(hdev);
2063 hci_dev_put(hdev);
2064
2065 return err;
2066}
2067
0381101f
JH
2068int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
2069{
2070 unsigned char *buf;
2071 struct mgmt_hdr *hdr;
4e51eae9 2072 u16 opcode, index, len;
0381101f
JH
2073 int err;
2074
2075 BT_DBG("got %zu bytes", msglen);
2076
2077 if (msglen < sizeof(*hdr))
2078 return -EINVAL;
2079
e63a15ec 2080 buf = kmalloc(msglen, GFP_KERNEL);
0381101f
JH
2081 if (!buf)
2082 return -ENOMEM;
2083
2084 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
2085 err = -EFAULT;
2086 goto done;
2087 }
2088
2089 hdr = (struct mgmt_hdr *) buf;
2090 opcode = get_unaligned_le16(&hdr->opcode);
4e51eae9 2091 index = get_unaligned_le16(&hdr->index);
0381101f
JH
2092 len = get_unaligned_le16(&hdr->len);
2093
2094 if (len != msglen - sizeof(*hdr)) {
2095 err = -EINVAL;
2096 goto done;
2097 }
2098
2099 switch (opcode) {
02d98129
JH
2100 case MGMT_OP_READ_VERSION:
2101 err = read_version(sk);
2102 break;
faba42eb
JH
2103 case MGMT_OP_READ_INDEX_LIST:
2104 err = read_index_list(sk);
2105 break;
f7b64e69 2106 case MGMT_OP_READ_INFO:
4e51eae9 2107 err = read_controller_info(sk, index);
f7b64e69 2108 break;
eec8d2bc 2109 case MGMT_OP_SET_POWERED:
4e51eae9 2110 err = set_powered(sk, index, buf + sizeof(*hdr), len);
eec8d2bc 2111 break;
73f22f62 2112 case MGMT_OP_SET_DISCOVERABLE:
4e51eae9 2113 err = set_discoverable(sk, index, buf + sizeof(*hdr), len);
73f22f62 2114 break;
9fbcbb45 2115 case MGMT_OP_SET_CONNECTABLE:
4e51eae9 2116 err = set_connectable(sk, index, buf + sizeof(*hdr), len);
9fbcbb45 2117 break;
f7c6869c
JH
2118 case MGMT_OP_SET_FAST_CONNECTABLE:
2119 err = set_fast_connectable(sk, index, buf + sizeof(*hdr),
2120 len);
2121 break;
c542a06c 2122 case MGMT_OP_SET_PAIRABLE:
4e51eae9 2123 err = set_pairable(sk, index, buf + sizeof(*hdr), len);
c542a06c 2124 break;
2aeb9a1a 2125 case MGMT_OP_ADD_UUID:
4e51eae9 2126 err = add_uuid(sk, index, buf + sizeof(*hdr), len);
2aeb9a1a
JH
2127 break;
2128 case MGMT_OP_REMOVE_UUID:
4e51eae9 2129 err = remove_uuid(sk, index, buf + sizeof(*hdr), len);
2aeb9a1a 2130 break;
1aff6f09 2131 case MGMT_OP_SET_DEV_CLASS:
4e51eae9 2132 err = set_dev_class(sk, index, buf + sizeof(*hdr), len);
1aff6f09 2133 break;
86742e1e
JH
2134 case MGMT_OP_LOAD_LINK_KEYS:
2135 err = load_link_keys(sk, index, buf + sizeof(*hdr), len);
55ed8ca1 2136 break;
86742e1e
JH
2137 case MGMT_OP_REMOVE_KEYS:
2138 err = remove_keys(sk, index, buf + sizeof(*hdr), len);
55ed8ca1 2139 break;
8962ee74 2140 case MGMT_OP_DISCONNECT:
4e51eae9 2141 err = disconnect(sk, index, buf + sizeof(*hdr), len);
8962ee74 2142 break;
2784eb41 2143 case MGMT_OP_GET_CONNECTIONS:
8ce6284e 2144 err = get_connections(sk, index);
2784eb41 2145 break;
980e1a53 2146 case MGMT_OP_PIN_CODE_REPLY:
4e51eae9 2147 err = pin_code_reply(sk, index, buf + sizeof(*hdr), len);
980e1a53
JH
2148 break;
2149 case MGMT_OP_PIN_CODE_NEG_REPLY:
4e51eae9 2150 err = pin_code_neg_reply(sk, index, buf + sizeof(*hdr), len);
980e1a53 2151 break;
17fa4b9d 2152 case MGMT_OP_SET_IO_CAPABILITY:
4e51eae9 2153 err = set_io_capability(sk, index, buf + sizeof(*hdr), len);
17fa4b9d 2154 break;
e9a416b5 2155 case MGMT_OP_PAIR_DEVICE:
4e51eae9 2156 err = pair_device(sk, index, buf + sizeof(*hdr), len);
e9a416b5 2157 break;
a5c29683 2158 case MGMT_OP_USER_CONFIRM_REPLY:
0df4c185 2159 err = user_confirm_reply(sk, index, buf + sizeof(*hdr), len);
a5c29683
JH
2160 break;
2161 case MGMT_OP_USER_CONFIRM_NEG_REPLY:
0df4c185
BG
2162 err = user_confirm_neg_reply(sk, index, buf + sizeof(*hdr),
2163 len);
a5c29683 2164 break;
604086b7
BG
2165 case MGMT_OP_USER_PASSKEY_REPLY:
2166 err = user_passkey_reply(sk, index, buf + sizeof(*hdr), len);
2167 break;
2168 case MGMT_OP_USER_PASSKEY_NEG_REPLY:
2169 err = user_passkey_neg_reply(sk, index, buf + sizeof(*hdr),
2170 len);
2171 break;
b312b161
JH
2172 case MGMT_OP_SET_LOCAL_NAME:
2173 err = set_local_name(sk, index, buf + sizeof(*hdr), len);
2174 break;
c35938b2
SJ
2175 case MGMT_OP_READ_LOCAL_OOB_DATA:
2176 err = read_local_oob_data(sk, index);
2177 break;
2763eda6
SJ
2178 case MGMT_OP_ADD_REMOTE_OOB_DATA:
2179 err = add_remote_oob_data(sk, index, buf + sizeof(*hdr), len);
2180 break;
2181 case MGMT_OP_REMOVE_REMOTE_OOB_DATA:
2182 err = remove_remote_oob_data(sk, index, buf + sizeof(*hdr),
2183 len);
2184 break;
14a53664 2185 case MGMT_OP_START_DISCOVERY:
450dfdaf 2186 err = start_discovery(sk, index, buf + sizeof(*hdr), len);
14a53664
JH
2187 break;
2188 case MGMT_OP_STOP_DISCOVERY:
2189 err = stop_discovery(sk, index);
2190 break;
7fbec224
AJ
2191 case MGMT_OP_BLOCK_DEVICE:
2192 err = block_device(sk, index, buf + sizeof(*hdr), len);
2193 break;
2194 case MGMT_OP_UNBLOCK_DEVICE:
2195 err = unblock_device(sk, index, buf + sizeof(*hdr), len);
2196 break;
0381101f
JH
2197 default:
2198 BT_DBG("Unknown op %u", opcode);
ca69b795
JH
2199 err = cmd_status(sk, index, opcode,
2200 MGMT_STATUS_UNKNOWN_COMMAND);
0381101f
JH
2201 break;
2202 }
2203
e41d8b4e
JH
2204 if (err < 0)
2205 goto done;
2206
0381101f
JH
2207 err = msglen;
2208
2209done:
2210 kfree(buf);
2211 return err;
2212}
c71e97bf 2213
b24752fe
JH
2214static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
2215{
2216 u8 *status = data;
2217
2218 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
2219 mgmt_pending_remove(cmd);
2220}
2221
744cf19e 2222int mgmt_index_added(struct hci_dev *hdev)
c71e97bf 2223{
744cf19e 2224 return mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
c71e97bf
JH
2225}
2226
744cf19e 2227int mgmt_index_removed(struct hci_dev *hdev)
c71e97bf 2228{
b24752fe
JH
2229 u8 status = ENODEV;
2230
744cf19e 2231 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
b24752fe 2232
744cf19e 2233 return mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
eec8d2bc
JH
2234}
2235
73f22f62 2236struct cmd_lookup {
72a734ec 2237 u8 val;
eec8d2bc 2238 struct sock *sk;
69ab39ea 2239 struct hci_dev *hdev;
eec8d2bc
JH
2240};
2241
69ab39ea 2242static void settings_rsp(struct pending_cmd *cmd, void *data)
eec8d2bc 2243{
73f22f62 2244 struct cmd_lookup *match = data;
eec8d2bc 2245
69ab39ea 2246 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
eec8d2bc
JH
2247
2248 list_del(&cmd->list);
2249
2250 if (match->sk == NULL) {
2251 match->sk = cmd->sk;
2252 sock_hold(match->sk);
2253 }
2254
2255 mgmt_pending_free(cmd);
c71e97bf 2256}
5add6af8 2257
744cf19e 2258int mgmt_powered(struct hci_dev *hdev, u8 powered)
5add6af8 2259{
69ab39ea
JH
2260 struct cmd_lookup match = { powered, NULL, hdev };
2261 __le32 ev;
eec8d2bc 2262 int ret;
5add6af8 2263
69ab39ea 2264 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5add6af8 2265
b24752fe
JH
2266 if (!powered) {
2267 u8 status = ENETDOWN;
744cf19e 2268 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
b24752fe
JH
2269 }
2270
69ab39ea 2271 ev = cpu_to_le32(get_current_settings(hdev));
eec8d2bc 2272
69ab39ea
JH
2273 ret = mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev),
2274 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{
69ab39ea
JH
2284 struct cmd_lookup match = { discoverable, NULL, hdev };
2285 __le32 ev;
73f22f62
JH
2286 int ret;
2287
69ab39ea 2288 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev, settings_rsp, &match);
72a734ec 2289
69ab39ea 2290 ev = cpu_to_le32(get_current_settings(hdev));
73f22f62 2291
69ab39ea 2292 ret = mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev),
4e51eae9 2293 match.sk);
73f22f62
JH
2294 if (match.sk)
2295 sock_put(match.sk);
2296
2297 return ret;
2298}
9fbcbb45 2299
744cf19e 2300int mgmt_connectable(struct hci_dev *hdev, u8 connectable)
9fbcbb45 2301{
69ab39ea
JH
2302 __le32 ev;
2303 struct cmd_lookup match = { connectable, NULL, hdev };
9fbcbb45
JH
2304 int ret;
2305
69ab39ea
JH
2306 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev, settings_rsp,
2307 &match);
9fbcbb45 2308
69ab39ea 2309 ev = cpu_to_le32(get_current_settings(hdev));
9fbcbb45 2310
69ab39ea 2311 ret = mgmt_event(MGMT_EV_NEW_SETTINGS, 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}
This page took 0.41475 seconds and 5 git commands to generate.