diff options
Diffstat (limited to 'net/bluetooth/mgmt.c')
-rw-r--r-- | net/bluetooth/mgmt.c | 500 |
1 files changed, 278 insertions, 222 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 5caff4d47596..a6720c6a4d2c 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -32,22 +32,23 @@ | |||
32 | #define MGMT_VERSION 0 | 32 | #define MGMT_VERSION 0 |
33 | #define MGMT_REVISION 1 | 33 | #define MGMT_REVISION 1 |
34 | 34 | ||
35 | #define INQUIRY_LEN_BREDR 0x08 /* TGAP(100) */ | ||
36 | |||
35 | struct pending_cmd { | 37 | struct pending_cmd { |
36 | struct list_head list; | 38 | struct list_head list; |
37 | __u16 opcode; | 39 | u16 opcode; |
38 | int index; | 40 | int index; |
39 | void *param; | 41 | void *param; |
40 | struct sock *sk; | 42 | struct sock *sk; |
41 | void *user_data; | 43 | void *user_data; |
42 | }; | 44 | }; |
43 | 45 | ||
44 | static LIST_HEAD(cmd_list); | ||
45 | |||
46 | static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status) | 46 | static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status) |
47 | { | 47 | { |
48 | struct sk_buff *skb; | 48 | struct sk_buff *skb; |
49 | struct mgmt_hdr *hdr; | 49 | struct mgmt_hdr *hdr; |
50 | struct mgmt_ev_cmd_status *ev; | 50 | struct mgmt_ev_cmd_status *ev; |
51 | int err; | ||
51 | 52 | ||
52 | BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status); | 53 | BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status); |
53 | 54 | ||
@@ -65,10 +66,11 @@ static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status) | |||
65 | ev->status = status; | 66 | ev->status = status; |
66 | put_unaligned_le16(cmd, &ev->opcode); | 67 | put_unaligned_le16(cmd, &ev->opcode); |
67 | 68 | ||
68 | if (sock_queue_rcv_skb(sk, skb) < 0) | 69 | err = sock_queue_rcv_skb(sk, skb); |
70 | if (err < 0) | ||
69 | kfree_skb(skb); | 71 | kfree_skb(skb); |
70 | 72 | ||
71 | return 0; | 73 | return err; |
72 | } | 74 | } |
73 | 75 | ||
74 | static int cmd_complete(struct sock *sk, u16 index, u16 cmd, void *rp, | 76 | static int cmd_complete(struct sock *sk, u16 index, u16 cmd, void *rp, |
@@ -77,6 +79,7 @@ static int cmd_complete(struct sock *sk, u16 index, u16 cmd, void *rp, | |||
77 | struct sk_buff *skb; | 79 | struct sk_buff *skb; |
78 | struct mgmt_hdr *hdr; | 80 | struct mgmt_hdr *hdr; |
79 | struct mgmt_ev_cmd_complete *ev; | 81 | struct mgmt_ev_cmd_complete *ev; |
82 | int err; | ||
80 | 83 | ||
81 | BT_DBG("sock %p", sk); | 84 | BT_DBG("sock %p", sk); |
82 | 85 | ||
@@ -96,10 +99,11 @@ static int cmd_complete(struct sock *sk, u16 index, u16 cmd, void *rp, | |||
96 | if (rp) | 99 | if (rp) |
97 | memcpy(ev->data, rp, rp_len); | 100 | memcpy(ev->data, rp, rp_len); |
98 | 101 | ||
99 | if (sock_queue_rcv_skb(sk, skb) < 0) | 102 | err = sock_queue_rcv_skb(sk, skb); |
103 | if (err < 0) | ||
100 | kfree_skb(skb); | 104 | kfree_skb(skb); |
101 | 105 | ||
102 | return 0; | 106 | return err;; |
103 | } | 107 | } |
104 | 108 | ||
105 | static int read_version(struct sock *sk) | 109 | static int read_version(struct sock *sk) |
@@ -119,6 +123,7 @@ static int read_index_list(struct sock *sk) | |||
119 | { | 123 | { |
120 | struct mgmt_rp_read_index_list *rp; | 124 | struct mgmt_rp_read_index_list *rp; |
121 | struct list_head *p; | 125 | struct list_head *p; |
126 | struct hci_dev *d; | ||
122 | size_t rp_len; | 127 | size_t rp_len; |
123 | u16 count; | 128 | u16 count; |
124 | int i, err; | 129 | int i, err; |
@@ -142,10 +147,9 @@ static int read_index_list(struct sock *sk) | |||
142 | put_unaligned_le16(count, &rp->num_controllers); | 147 | put_unaligned_le16(count, &rp->num_controllers); |
143 | 148 | ||
144 | i = 0; | 149 | i = 0; |
145 | list_for_each(p, &hci_dev_list) { | 150 | list_for_each_entry(d, &hci_dev_list, list) { |
146 | struct hci_dev *d = list_entry(p, struct hci_dev, list); | 151 | if (test_and_clear_bit(HCI_AUTO_OFF, &d->flags)) |
147 | 152 | cancel_delayed_work(&d->power_off); | |
148 | hci_del_off_timer(d); | ||
149 | 153 | ||
150 | if (test_bit(HCI_SETUP, &d->flags)) | 154 | if (test_bit(HCI_SETUP, &d->flags)) |
151 | continue; | 155 | continue; |
@@ -175,7 +179,8 @@ static int read_controller_info(struct sock *sk, u16 index) | |||
175 | if (!hdev) | 179 | if (!hdev) |
176 | return cmd_status(sk, index, MGMT_OP_READ_INFO, ENODEV); | 180 | return cmd_status(sk, index, MGMT_OP_READ_INFO, ENODEV); |
177 | 181 | ||
178 | hci_del_off_timer(hdev); | 182 | if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->flags)) |
183 | cancel_delayed_work_sync(&hdev->power_off); | ||
179 | 184 | ||
180 | hci_dev_lock_bh(hdev); | 185 | hci_dev_lock_bh(hdev); |
181 | 186 | ||
@@ -220,7 +225,8 @@ static void mgmt_pending_free(struct pending_cmd *cmd) | |||
220 | } | 225 | } |
221 | 226 | ||
222 | static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode, | 227 | static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode, |
223 | u16 index, void *data, u16 len) | 228 | struct hci_dev *hdev, |
229 | void *data, u16 len) | ||
224 | { | 230 | { |
225 | struct pending_cmd *cmd; | 231 | struct pending_cmd *cmd; |
226 | 232 | ||
@@ -229,7 +235,7 @@ static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode, | |||
229 | return NULL; | 235 | return NULL; |
230 | 236 | ||
231 | cmd->opcode = opcode; | 237 | cmd->opcode = opcode; |
232 | cmd->index = index; | 238 | cmd->index = hdev->id; |
233 | 239 | ||
234 | cmd->param = kmalloc(len, GFP_ATOMIC); | 240 | cmd->param = kmalloc(len, GFP_ATOMIC); |
235 | if (!cmd->param) { | 241 | if (!cmd->param) { |
@@ -243,48 +249,36 @@ static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode, | |||
243 | cmd->sk = sk; | 249 | cmd->sk = sk; |
244 | sock_hold(sk); | 250 | sock_hold(sk); |
245 | 251 | ||
246 | list_add(&cmd->list, &cmd_list); | 252 | list_add(&cmd->list, &hdev->mgmt_pending); |
247 | 253 | ||
248 | return cmd; | 254 | return cmd; |
249 | } | 255 | } |
250 | 256 | ||
251 | static void mgmt_pending_foreach(u16 opcode, int index, | 257 | static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev, |
252 | void (*cb)(struct pending_cmd *cmd, void *data), | 258 | void (*cb)(struct pending_cmd *cmd, void *data), |
253 | void *data) | 259 | void *data) |
254 | { | 260 | { |
255 | struct list_head *p, *n; | 261 | struct list_head *p, *n; |
256 | 262 | ||
257 | list_for_each_safe(p, n, &cmd_list) { | 263 | list_for_each_safe(p, n, &hdev->mgmt_pending) { |
258 | struct pending_cmd *cmd; | 264 | struct pending_cmd *cmd; |
259 | 265 | ||
260 | cmd = list_entry(p, struct pending_cmd, list); | 266 | cmd = list_entry(p, struct pending_cmd, list); |
261 | 267 | ||
262 | if (cmd->opcode != opcode) | 268 | if (opcode > 0 && cmd->opcode != opcode) |
263 | continue; | ||
264 | |||
265 | if (index >= 0 && cmd->index != index) | ||
266 | continue; | 269 | continue; |
267 | 270 | ||
268 | cb(cmd, data); | 271 | cb(cmd, data); |
269 | } | 272 | } |
270 | } | 273 | } |
271 | 274 | ||
272 | static struct pending_cmd *mgmt_pending_find(u16 opcode, int index) | 275 | static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev) |
273 | { | 276 | { |
274 | struct list_head *p; | 277 | struct pending_cmd *cmd; |
275 | |||
276 | list_for_each(p, &cmd_list) { | ||
277 | struct pending_cmd *cmd; | ||
278 | |||
279 | cmd = list_entry(p, struct pending_cmd, list); | ||
280 | |||
281 | if (cmd->opcode != opcode) | ||
282 | continue; | ||
283 | |||
284 | if (index >= 0 && cmd->index != index) | ||
285 | continue; | ||
286 | 278 | ||
287 | return cmd; | 279 | list_for_each_entry(cmd, &hdev->mgmt_pending, list) { |
280 | if (cmd->opcode == opcode) | ||
281 | return cmd; | ||
288 | } | 282 | } |
289 | 283 | ||
290 | return NULL; | 284 | return NULL; |
@@ -322,12 +316,12 @@ static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
322 | goto failed; | 316 | goto failed; |
323 | } | 317 | } |
324 | 318 | ||
325 | if (mgmt_pending_find(MGMT_OP_SET_POWERED, index)) { | 319 | if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) { |
326 | err = cmd_status(sk, index, MGMT_OP_SET_POWERED, EBUSY); | 320 | err = cmd_status(sk, index, MGMT_OP_SET_POWERED, EBUSY); |
327 | goto failed; | 321 | goto failed; |
328 | } | 322 | } |
329 | 323 | ||
330 | cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, index, data, len); | 324 | cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len); |
331 | if (!cmd) { | 325 | if (!cmd) { |
332 | err = -ENOMEM; | 326 | err = -ENOMEM; |
333 | goto failed; | 327 | goto failed; |
@@ -336,7 +330,7 @@ static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
336 | if (cp->val) | 330 | if (cp->val) |
337 | queue_work(hdev->workqueue, &hdev->power_on); | 331 | queue_work(hdev->workqueue, &hdev->power_on); |
338 | else | 332 | else |
339 | queue_work(hdev->workqueue, &hdev->power_off); | 333 | queue_work(hdev->workqueue, &hdev->power_off.work); |
340 | 334 | ||
341 | err = 0; | 335 | err = 0; |
342 | 336 | ||
@@ -349,7 +343,7 @@ failed: | |||
349 | static int set_discoverable(struct sock *sk, u16 index, unsigned char *data, | 343 | static int set_discoverable(struct sock *sk, u16 index, unsigned char *data, |
350 | u16 len) | 344 | u16 len) |
351 | { | 345 | { |
352 | struct mgmt_mode *cp; | 346 | struct mgmt_cp_set_discoverable *cp; |
353 | struct hci_dev *hdev; | 347 | struct hci_dev *hdev; |
354 | struct pending_cmd *cmd; | 348 | struct pending_cmd *cmd; |
355 | u8 scan; | 349 | u8 scan; |
@@ -373,8 +367,8 @@ static int set_discoverable(struct sock *sk, u16 index, unsigned char *data, | |||
373 | goto failed; | 367 | goto failed; |
374 | } | 368 | } |
375 | 369 | ||
376 | if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, index) || | 370 | if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) || |
377 | mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, index)) { | 371 | mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) { |
378 | err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, EBUSY); | 372 | err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, EBUSY); |
379 | goto failed; | 373 | goto failed; |
380 | } | 374 | } |
@@ -385,7 +379,7 @@ static int set_discoverable(struct sock *sk, u16 index, unsigned char *data, | |||
385 | goto failed; | 379 | goto failed; |
386 | } | 380 | } |
387 | 381 | ||
388 | cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, index, data, len); | 382 | cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len); |
389 | if (!cmd) { | 383 | if (!cmd) { |
390 | err = -ENOMEM; | 384 | err = -ENOMEM; |
391 | goto failed; | 385 | goto failed; |
@@ -395,11 +389,16 @@ static int set_discoverable(struct sock *sk, u16 index, unsigned char *data, | |||
395 | 389 | ||
396 | if (cp->val) | 390 | if (cp->val) |
397 | scan |= SCAN_INQUIRY; | 391 | scan |= SCAN_INQUIRY; |
392 | else | ||
393 | cancel_delayed_work(&hdev->discov_off); | ||
398 | 394 | ||
399 | err = hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); | 395 | err = hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); |
400 | if (err < 0) | 396 | if (err < 0) |
401 | mgmt_pending_remove(cmd); | 397 | mgmt_pending_remove(cmd); |
402 | 398 | ||
399 | if (cp->val) | ||
400 | hdev->discov_timeout = get_unaligned_le16(&cp->timeout); | ||
401 | |||
403 | failed: | 402 | failed: |
404 | hci_dev_unlock_bh(hdev); | 403 | hci_dev_unlock_bh(hdev); |
405 | hci_dev_put(hdev); | 404 | hci_dev_put(hdev); |
@@ -434,8 +433,8 @@ static int set_connectable(struct sock *sk, u16 index, unsigned char *data, | |||
434 | goto failed; | 433 | goto failed; |
435 | } | 434 | } |
436 | 435 | ||
437 | if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, index) || | 436 | if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) || |
438 | mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, index)) { | 437 | mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) { |
439 | err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, EBUSY); | 438 | err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, EBUSY); |
440 | goto failed; | 439 | goto failed; |
441 | } | 440 | } |
@@ -445,7 +444,7 @@ static int set_connectable(struct sock *sk, u16 index, unsigned char *data, | |||
445 | goto failed; | 444 | goto failed; |
446 | } | 445 | } |
447 | 446 | ||
448 | cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, index, data, len); | 447 | cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len); |
449 | if (!cmd) { | 448 | if (!cmd) { |
450 | err = -ENOMEM; | 449 | err = -ENOMEM; |
451 | goto failed; | 450 | goto failed; |
@@ -467,8 +466,8 @@ failed: | |||
467 | return err; | 466 | return err; |
468 | } | 467 | } |
469 | 468 | ||
470 | static int mgmt_event(u16 event, u16 index, void *data, u16 data_len, | 469 | static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, |
471 | struct sock *skip_sk) | 470 | u16 data_len, struct sock *skip_sk) |
472 | { | 471 | { |
473 | struct sk_buff *skb; | 472 | struct sk_buff *skb; |
474 | struct mgmt_hdr *hdr; | 473 | struct mgmt_hdr *hdr; |
@@ -481,7 +480,10 @@ static int mgmt_event(u16 event, u16 index, void *data, u16 data_len, | |||
481 | 480 | ||
482 | hdr = (void *) skb_put(skb, sizeof(*hdr)); | 481 | hdr = (void *) skb_put(skb, sizeof(*hdr)); |
483 | hdr->opcode = cpu_to_le16(event); | 482 | hdr->opcode = cpu_to_le16(event); |
484 | hdr->index = cpu_to_le16(index); | 483 | if (hdev) |
484 | hdr->index = cpu_to_le16(hdev->id); | ||
485 | else | ||
486 | hdr->index = cpu_to_le16(MGMT_INDEX_NONE); | ||
485 | hdr->len = cpu_to_le16(data_len); | 487 | hdr->len = cpu_to_le16(data_len); |
486 | 488 | ||
487 | if (data) | 489 | if (data) |
@@ -533,7 +535,7 @@ static int set_pairable(struct sock *sk, u16 index, unsigned char *data, | |||
533 | 535 | ||
534 | ev.val = cp->val; | 536 | ev.val = cp->val; |
535 | 537 | ||
536 | err = mgmt_event(MGMT_EV_PAIRABLE, index, &ev, sizeof(ev), sk); | 538 | err = mgmt_event(MGMT_EV_PAIRABLE, hdev, &ev, sizeof(ev), sk); |
537 | 539 | ||
538 | failed: | 540 | failed: |
539 | hci_dev_unlock_bh(hdev); | 541 | hci_dev_unlock_bh(hdev); |
@@ -586,7 +588,7 @@ static void create_eir(struct hci_dev *hdev, u8 *data) | |||
586 | u16 eir_len = 0; | 588 | u16 eir_len = 0; |
587 | u16 uuid16_list[HCI_MAX_EIR_LENGTH / sizeof(u16)]; | 589 | u16 uuid16_list[HCI_MAX_EIR_LENGTH / sizeof(u16)]; |
588 | int i, truncated = 0; | 590 | int i, truncated = 0; |
589 | struct list_head *p; | 591 | struct bt_uuid *uuid; |
590 | size_t name_len; | 592 | size_t name_len; |
591 | 593 | ||
592 | name_len = strlen(hdev->dev_name); | 594 | name_len = strlen(hdev->dev_name); |
@@ -611,8 +613,7 @@ static void create_eir(struct hci_dev *hdev, u8 *data) | |||
611 | memset(uuid16_list, 0, sizeof(uuid16_list)); | 613 | memset(uuid16_list, 0, sizeof(uuid16_list)); |
612 | 614 | ||
613 | /* Group all UUID16 types */ | 615 | /* Group all UUID16 types */ |
614 | list_for_each(p, &hdev->uuids) { | 616 | list_for_each_entry(uuid, &hdev->uuids, list) { |
615 | struct bt_uuid *uuid = list_entry(p, struct bt_uuid, list); | ||
616 | u16 uuid16; | 617 | u16 uuid16; |
617 | 618 | ||
618 | uuid16 = get_uuid16(uuid->uuid); | 619 | uuid16 = get_uuid16(uuid->uuid); |
@@ -688,14 +689,11 @@ static int update_eir(struct hci_dev *hdev) | |||
688 | 689 | ||
689 | static u8 get_service_classes(struct hci_dev *hdev) | 690 | static u8 get_service_classes(struct hci_dev *hdev) |
690 | { | 691 | { |
691 | struct list_head *p; | 692 | struct bt_uuid *uuid; |
692 | u8 val = 0; | 693 | u8 val = 0; |
693 | 694 | ||
694 | list_for_each(p, &hdev->uuids) { | 695 | list_for_each_entry(uuid, &hdev->uuids, list) |
695 | struct bt_uuid *uuid = list_entry(p, struct bt_uuid, list); | ||
696 | |||
697 | val |= uuid->svc_hint; | 696 | val |= uuid->svc_hint; |
698 | } | ||
699 | 697 | ||
700 | return val; | 698 | return val; |
701 | } | 699 | } |
@@ -894,6 +892,9 @@ static int set_service_cache(struct sock *sk, u16 index, unsigned char *data, | |||
894 | if (err == 0) | 892 | if (err == 0) |
895 | err = cmd_complete(sk, index, MGMT_OP_SET_SERVICE_CACHE, NULL, | 893 | err = cmd_complete(sk, index, MGMT_OP_SET_SERVICE_CACHE, NULL, |
896 | 0); | 894 | 0); |
895 | else | ||
896 | cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE, -err); | ||
897 | |||
897 | 898 | ||
898 | hci_dev_unlock_bh(hdev); | 899 | hci_dev_unlock_bh(hdev); |
899 | hci_dev_put(hdev); | 900 | hci_dev_put(hdev); |
@@ -901,30 +902,32 @@ static int set_service_cache(struct sock *sk, u16 index, unsigned char *data, | |||
901 | return err; | 902 | return err; |
902 | } | 903 | } |
903 | 904 | ||
904 | static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len) | 905 | static int load_link_keys(struct sock *sk, u16 index, unsigned char *data, |
906 | u16 len) | ||
905 | { | 907 | { |
906 | struct hci_dev *hdev; | 908 | struct hci_dev *hdev; |
907 | struct mgmt_cp_load_keys *cp; | 909 | struct mgmt_cp_load_link_keys *cp; |
908 | u16 key_count, expected_len; | 910 | u16 key_count, expected_len; |
909 | int i; | 911 | int i; |
910 | 912 | ||
911 | cp = (void *) data; | 913 | cp = (void *) data; |
912 | 914 | ||
913 | if (len < sizeof(*cp)) | 915 | if (len < sizeof(*cp)) |
914 | return -EINVAL; | 916 | return cmd_status(sk, index, MGMT_OP_LOAD_LINK_KEYS, EINVAL); |
915 | 917 | ||
916 | key_count = get_unaligned_le16(&cp->key_count); | 918 | key_count = get_unaligned_le16(&cp->key_count); |
917 | 919 | ||
918 | expected_len = sizeof(*cp) + key_count * sizeof(struct mgmt_key_info); | 920 | expected_len = sizeof(*cp) + key_count * |
921 | sizeof(struct mgmt_link_key_info); | ||
919 | if (expected_len != len) { | 922 | if (expected_len != len) { |
920 | BT_ERR("load_keys: expected %u bytes, got %u bytes", | 923 | BT_ERR("load_link_keys: expected %u bytes, got %u bytes", |
921 | len, expected_len); | 924 | len, expected_len); |
922 | return -EINVAL; | 925 | return cmd_status(sk, index, MGMT_OP_LOAD_LINK_KEYS, EINVAL); |
923 | } | 926 | } |
924 | 927 | ||
925 | hdev = hci_dev_get(index); | 928 | hdev = hci_dev_get(index); |
926 | if (!hdev) | 929 | if (!hdev) |
927 | return cmd_status(sk, index, MGMT_OP_LOAD_KEYS, ENODEV); | 930 | return cmd_status(sk, index, MGMT_OP_LOAD_LINK_KEYS, ENODEV); |
928 | 931 | ||
929 | BT_DBG("hci%u debug_keys %u key_count %u", index, cp->debug_keys, | 932 | BT_DBG("hci%u debug_keys %u key_count %u", index, cp->debug_keys, |
930 | key_count); | 933 | key_count); |
@@ -941,7 +944,7 @@ static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
941 | clear_bit(HCI_DEBUG_KEYS, &hdev->flags); | 944 | clear_bit(HCI_DEBUG_KEYS, &hdev->flags); |
942 | 945 | ||
943 | for (i = 0; i < key_count; i++) { | 946 | for (i = 0; i < key_count; i++) { |
944 | struct mgmt_key_info *key = &cp->keys[i]; | 947 | struct mgmt_link_key_info *key = &cp->keys[i]; |
945 | 948 | ||
946 | hci_add_link_key(hdev, NULL, 0, &key->bdaddr, key->val, key->type, | 949 | hci_add_link_key(hdev, NULL, 0, &key->bdaddr, key->val, key->type, |
947 | key->pin_len); | 950 | key->pin_len); |
@@ -953,27 +956,28 @@ static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
953 | return 0; | 956 | return 0; |
954 | } | 957 | } |
955 | 958 | ||
956 | static int remove_key(struct sock *sk, u16 index, unsigned char *data, u16 len) | 959 | static int remove_keys(struct sock *sk, u16 index, unsigned char *data, |
960 | u16 len) | ||
957 | { | 961 | { |
958 | struct hci_dev *hdev; | 962 | struct hci_dev *hdev; |
959 | struct mgmt_cp_remove_key *cp; | 963 | struct mgmt_cp_remove_keys *cp; |
960 | struct hci_conn *conn; | 964 | struct hci_conn *conn; |
961 | int err; | 965 | int err; |
962 | 966 | ||
963 | cp = (void *) data; | 967 | cp = (void *) data; |
964 | 968 | ||
965 | if (len != sizeof(*cp)) | 969 | if (len != sizeof(*cp)) |
966 | return cmd_status(sk, index, MGMT_OP_REMOVE_KEY, EINVAL); | 970 | return cmd_status(sk, index, MGMT_OP_REMOVE_KEYS, EINVAL); |
967 | 971 | ||
968 | hdev = hci_dev_get(index); | 972 | hdev = hci_dev_get(index); |
969 | if (!hdev) | 973 | if (!hdev) |
970 | return cmd_status(sk, index, MGMT_OP_REMOVE_KEY, ENODEV); | 974 | return cmd_status(sk, index, MGMT_OP_REMOVE_KEYS, ENODEV); |
971 | 975 | ||
972 | hci_dev_lock_bh(hdev); | 976 | hci_dev_lock_bh(hdev); |
973 | 977 | ||
974 | err = hci_remove_link_key(hdev, &cp->bdaddr); | 978 | err = hci_remove_link_key(hdev, &cp->bdaddr); |
975 | if (err < 0) { | 979 | if (err < 0) { |
976 | err = cmd_status(sk, index, MGMT_OP_REMOVE_KEY, -err); | 980 | err = cmd_status(sk, index, MGMT_OP_REMOVE_KEYS, -err); |
977 | goto unlock; | 981 | goto unlock; |
978 | } | 982 | } |
979 | 983 | ||
@@ -1025,7 +1029,7 @@ static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
1025 | goto failed; | 1029 | goto failed; |
1026 | } | 1030 | } |
1027 | 1031 | ||
1028 | if (mgmt_pending_find(MGMT_OP_DISCONNECT, index)) { | 1032 | if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) { |
1029 | err = cmd_status(sk, index, MGMT_OP_DISCONNECT, EBUSY); | 1033 | err = cmd_status(sk, index, MGMT_OP_DISCONNECT, EBUSY); |
1030 | goto failed; | 1034 | goto failed; |
1031 | } | 1035 | } |
@@ -1039,7 +1043,7 @@ static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
1039 | goto failed; | 1043 | goto failed; |
1040 | } | 1044 | } |
1041 | 1045 | ||
1042 | cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, index, data, len); | 1046 | cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len); |
1043 | if (!cmd) { | 1047 | if (!cmd) { |
1044 | err = -ENOMEM; | 1048 | err = -ENOMEM; |
1045 | goto failed; | 1049 | goto failed; |
@@ -1059,10 +1063,23 @@ failed: | |||
1059 | return err; | 1063 | return err; |
1060 | } | 1064 | } |
1061 | 1065 | ||
1066 | static u8 link_to_mgmt(u8 link_type) | ||
1067 | { | ||
1068 | switch (link_type) { | ||
1069 | case LE_LINK: | ||
1070 | return MGMT_ADDR_LE; | ||
1071 | case ACL_LINK: | ||
1072 | return MGMT_ADDR_BREDR; | ||
1073 | default: | ||
1074 | return MGMT_ADDR_INVALID; | ||
1075 | } | ||
1076 | } | ||
1077 | |||
1062 | static int get_connections(struct sock *sk, u16 index) | 1078 | static int get_connections(struct sock *sk, u16 index) |
1063 | { | 1079 | { |
1064 | struct mgmt_rp_get_connections *rp; | 1080 | struct mgmt_rp_get_connections *rp; |
1065 | struct hci_dev *hdev; | 1081 | struct hci_dev *hdev; |
1082 | struct hci_conn *c; | ||
1066 | struct list_head *p; | 1083 | struct list_head *p; |
1067 | size_t rp_len; | 1084 | size_t rp_len; |
1068 | u16 count; | 1085 | u16 count; |
@@ -1081,7 +1098,7 @@ static int get_connections(struct sock *sk, u16 index) | |||
1081 | count++; | 1098 | count++; |
1082 | } | 1099 | } |
1083 | 1100 | ||
1084 | rp_len = sizeof(*rp) + (count * sizeof(bdaddr_t)); | 1101 | rp_len = sizeof(*rp) + (count * sizeof(struct mgmt_addr_info)); |
1085 | rp = kmalloc(rp_len, GFP_ATOMIC); | 1102 | rp = kmalloc(rp_len, GFP_ATOMIC); |
1086 | if (!rp) { | 1103 | if (!rp) { |
1087 | err = -ENOMEM; | 1104 | err = -ENOMEM; |
@@ -1091,12 +1108,17 @@ static int get_connections(struct sock *sk, u16 index) | |||
1091 | put_unaligned_le16(count, &rp->conn_count); | 1108 | put_unaligned_le16(count, &rp->conn_count); |
1092 | 1109 | ||
1093 | i = 0; | 1110 | i = 0; |
1094 | list_for_each(p, &hdev->conn_hash.list) { | 1111 | list_for_each_entry(c, &hdev->conn_hash.list, list) { |
1095 | struct hci_conn *c = list_entry(p, struct hci_conn, list); | 1112 | bacpy(&rp->addr[i].bdaddr, &c->dst); |
1096 | 1113 | rp->addr[i].type = link_to_mgmt(c->type); | |
1097 | bacpy(&rp->conn[i++], &c->dst); | 1114 | if (rp->addr[i].type == MGMT_ADDR_INVALID) |
1115 | continue; | ||
1116 | i++; | ||
1098 | } | 1117 | } |
1099 | 1118 | ||
1119 | /* Recalculate length in case of filtered SCO connections, etc */ | ||
1120 | rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info)); | ||
1121 | |||
1100 | err = cmd_complete(sk, index, MGMT_OP_GET_CONNECTIONS, rp, rp_len); | 1122 | err = cmd_complete(sk, index, MGMT_OP_GET_CONNECTIONS, rp, rp_len); |
1101 | 1123 | ||
1102 | unlock: | 1124 | unlock: |
@@ -1112,7 +1134,7 @@ static int send_pin_code_neg_reply(struct sock *sk, u16 index, | |||
1112 | struct pending_cmd *cmd; | 1134 | struct pending_cmd *cmd; |
1113 | int err; | 1135 | int err; |
1114 | 1136 | ||
1115 | cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, index, cp, | 1137 | cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp, |
1116 | sizeof(*cp)); | 1138 | sizeof(*cp)); |
1117 | if (!cmd) | 1139 | if (!cmd) |
1118 | return -ENOMEM; | 1140 | return -ENOMEM; |
@@ -1173,7 +1195,7 @@ static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data, | |||
1173 | goto failed; | 1195 | goto failed; |
1174 | } | 1196 | } |
1175 | 1197 | ||
1176 | cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, index, data, len); | 1198 | cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len); |
1177 | if (!cmd) { | 1199 | if (!cmd) { |
1178 | err = -ENOMEM; | 1200 | err = -ENOMEM; |
1179 | goto failed; | 1201 | goto failed; |
@@ -1264,19 +1286,12 @@ static int set_io_capability(struct sock *sk, u16 index, unsigned char *data, | |||
1264 | static inline struct pending_cmd *find_pairing(struct hci_conn *conn) | 1286 | static inline struct pending_cmd *find_pairing(struct hci_conn *conn) |
1265 | { | 1287 | { |
1266 | struct hci_dev *hdev = conn->hdev; | 1288 | struct hci_dev *hdev = conn->hdev; |
1267 | struct list_head *p; | 1289 | struct pending_cmd *cmd; |
1268 | |||
1269 | list_for_each(p, &cmd_list) { | ||
1270 | struct pending_cmd *cmd; | ||
1271 | |||
1272 | cmd = list_entry(p, struct pending_cmd, list); | ||
1273 | 1290 | ||
1291 | list_for_each_entry(cmd, &hdev->mgmt_pending, list) { | ||
1274 | if (cmd->opcode != MGMT_OP_PAIR_DEVICE) | 1292 | if (cmd->opcode != MGMT_OP_PAIR_DEVICE) |
1275 | continue; | 1293 | continue; |
1276 | 1294 | ||
1277 | if (cmd->index != hdev->id) | ||
1278 | continue; | ||
1279 | |||
1280 | if (cmd->user_data != conn) | 1295 | if (cmd->user_data != conn) |
1281 | continue; | 1296 | continue; |
1282 | 1297 | ||
@@ -1309,16 +1324,19 @@ static void pairing_complete(struct pending_cmd *cmd, u8 status) | |||
1309 | static void pairing_complete_cb(struct hci_conn *conn, u8 status) | 1324 | static void pairing_complete_cb(struct hci_conn *conn, u8 status) |
1310 | { | 1325 | { |
1311 | struct pending_cmd *cmd; | 1326 | struct pending_cmd *cmd; |
1327 | struct hci_dev *hdev = conn->hdev; | ||
1312 | 1328 | ||
1313 | BT_DBG("status %u", status); | 1329 | BT_DBG("status %u", status); |
1314 | 1330 | ||
1331 | hci_dev_lock_bh(hdev); | ||
1332 | |||
1315 | cmd = find_pairing(conn); | 1333 | cmd = find_pairing(conn); |
1316 | if (!cmd) { | 1334 | if (!cmd) |
1317 | BT_DBG("Unable to find a pending command"); | 1335 | BT_DBG("Unable to find a pending command"); |
1318 | return; | 1336 | else |
1319 | } | 1337 | pairing_complete(cmd, status); |
1320 | 1338 | ||
1321 | pairing_complete(cmd, status); | 1339 | hci_dev_unlock_bh(hdev); |
1322 | } | 1340 | } |
1323 | 1341 | ||
1324 | static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len) | 1342 | static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len) |
@@ -1369,7 +1387,7 @@ static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
1369 | goto unlock; | 1387 | goto unlock; |
1370 | } | 1388 | } |
1371 | 1389 | ||
1372 | cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, index, data, len); | 1390 | cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len); |
1373 | if (!cmd) { | 1391 | if (!cmd) { |
1374 | err = -ENOMEM; | 1392 | err = -ENOMEM; |
1375 | hci_conn_put(conn); | 1393 | hci_conn_put(conn); |
@@ -1431,7 +1449,7 @@ static int user_confirm_reply(struct sock *sk, u16 index, unsigned char *data, | |||
1431 | goto failed; | 1449 | goto failed; |
1432 | } | 1450 | } |
1433 | 1451 | ||
1434 | cmd = mgmt_pending_add(sk, mgmt_op, index, data, len); | 1452 | cmd = mgmt_pending_add(sk, mgmt_op, hdev, data, len); |
1435 | if (!cmd) { | 1453 | if (!cmd) { |
1436 | err = -ENOMEM; | 1454 | err = -ENOMEM; |
1437 | goto failed; | 1455 | goto failed; |
@@ -1468,7 +1486,7 @@ static int set_local_name(struct sock *sk, u16 index, unsigned char *data, | |||
1468 | 1486 | ||
1469 | hci_dev_lock_bh(hdev); | 1487 | hci_dev_lock_bh(hdev); |
1470 | 1488 | ||
1471 | cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, index, data, len); | 1489 | cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len); |
1472 | if (!cmd) { | 1490 | if (!cmd) { |
1473 | err = -ENOMEM; | 1491 | err = -ENOMEM; |
1474 | goto failed; | 1492 | goto failed; |
@@ -1514,12 +1532,12 @@ static int read_local_oob_data(struct sock *sk, u16 index) | |||
1514 | goto unlock; | 1532 | goto unlock; |
1515 | } | 1533 | } |
1516 | 1534 | ||
1517 | if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, index)) { | 1535 | if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) { |
1518 | err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, EBUSY); | 1536 | err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, EBUSY); |
1519 | goto unlock; | 1537 | goto unlock; |
1520 | } | 1538 | } |
1521 | 1539 | ||
1522 | cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, index, NULL, 0); | 1540 | cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0); |
1523 | if (!cmd) { | 1541 | if (!cmd) { |
1524 | err = -ENOMEM; | 1542 | err = -ENOMEM; |
1525 | goto unlock; | 1543 | goto unlock; |
@@ -1606,8 +1624,6 @@ static int remove_remote_oob_data(struct sock *sk, u16 index, | |||
1606 | 1624 | ||
1607 | static int start_discovery(struct sock *sk, u16 index) | 1625 | static int start_discovery(struct sock *sk, u16 index) |
1608 | { | 1626 | { |
1609 | u8 lap[3] = { 0x33, 0x8b, 0x9e }; | ||
1610 | struct hci_cp_inquiry cp; | ||
1611 | struct pending_cmd *cmd; | 1627 | struct pending_cmd *cmd; |
1612 | struct hci_dev *hdev; | 1628 | struct hci_dev *hdev; |
1613 | int err; | 1629 | int err; |
@@ -1620,18 +1636,18 @@ static int start_discovery(struct sock *sk, u16 index) | |||
1620 | 1636 | ||
1621 | hci_dev_lock_bh(hdev); | 1637 | hci_dev_lock_bh(hdev); |
1622 | 1638 | ||
1623 | cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, index, NULL, 0); | 1639 | if (!test_bit(HCI_UP, &hdev->flags)) { |
1640 | err = cmd_status(sk, index, MGMT_OP_START_DISCOVERY, ENETDOWN); | ||
1641 | goto failed; | ||
1642 | } | ||
1643 | |||
1644 | cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0); | ||
1624 | if (!cmd) { | 1645 | if (!cmd) { |
1625 | err = -ENOMEM; | 1646 | err = -ENOMEM; |
1626 | goto failed; | 1647 | goto failed; |
1627 | } | 1648 | } |
1628 | 1649 | ||
1629 | memset(&cp, 0, sizeof(cp)); | 1650 | err = hci_do_inquiry(hdev, INQUIRY_LEN_BREDR); |
1630 | memcpy(&cp.lap, lap, 3); | ||
1631 | cp.length = 0x08; | ||
1632 | cp.num_rsp = 0x00; | ||
1633 | |||
1634 | err = hci_send_cmd(hdev, HCI_OP_INQUIRY, sizeof(cp), &cp); | ||
1635 | if (err < 0) | 1651 | if (err < 0) |
1636 | mgmt_pending_remove(cmd); | 1652 | mgmt_pending_remove(cmd); |
1637 | 1653 | ||
@@ -1656,13 +1672,13 @@ static int stop_discovery(struct sock *sk, u16 index) | |||
1656 | 1672 | ||
1657 | hci_dev_lock_bh(hdev); | 1673 | hci_dev_lock_bh(hdev); |
1658 | 1674 | ||
1659 | cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, index, NULL, 0); | 1675 | cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0); |
1660 | if (!cmd) { | 1676 | if (!cmd) { |
1661 | err = -ENOMEM; | 1677 | err = -ENOMEM; |
1662 | goto failed; | 1678 | goto failed; |
1663 | } | 1679 | } |
1664 | 1680 | ||
1665 | err = hci_send_cmd(hdev, HCI_OP_INQUIRY_CANCEL, 0, NULL); | 1681 | err = hci_cancel_inquiry(hdev); |
1666 | if (err < 0) | 1682 | if (err < 0) |
1667 | mgmt_pending_remove(cmd); | 1683 | mgmt_pending_remove(cmd); |
1668 | 1684 | ||
@@ -1677,7 +1693,6 @@ static int block_device(struct sock *sk, u16 index, unsigned char *data, | |||
1677 | u16 len) | 1693 | u16 len) |
1678 | { | 1694 | { |
1679 | struct hci_dev *hdev; | 1695 | struct hci_dev *hdev; |
1680 | struct pending_cmd *cmd; | ||
1681 | struct mgmt_cp_block_device *cp = (void *) data; | 1696 | struct mgmt_cp_block_device *cp = (void *) data; |
1682 | int err; | 1697 | int err; |
1683 | 1698 | ||
@@ -1694,23 +1709,13 @@ static int block_device(struct sock *sk, u16 index, unsigned char *data, | |||
1694 | 1709 | ||
1695 | hci_dev_lock_bh(hdev); | 1710 | hci_dev_lock_bh(hdev); |
1696 | 1711 | ||
1697 | cmd = mgmt_pending_add(sk, MGMT_OP_BLOCK_DEVICE, index, NULL, 0); | ||
1698 | if (!cmd) { | ||
1699 | err = -ENOMEM; | ||
1700 | goto failed; | ||
1701 | } | ||
1702 | |||
1703 | err = hci_blacklist_add(hdev, &cp->bdaddr); | 1712 | err = hci_blacklist_add(hdev, &cp->bdaddr); |
1704 | |||
1705 | if (err < 0) | 1713 | if (err < 0) |
1706 | err = cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE, -err); | 1714 | err = cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE, -err); |
1707 | else | 1715 | else |
1708 | err = cmd_complete(sk, index, MGMT_OP_BLOCK_DEVICE, | 1716 | err = cmd_complete(sk, index, MGMT_OP_BLOCK_DEVICE, |
1709 | NULL, 0); | 1717 | NULL, 0); |
1710 | 1718 | ||
1711 | mgmt_pending_remove(cmd); | ||
1712 | |||
1713 | failed: | ||
1714 | hci_dev_unlock_bh(hdev); | 1719 | hci_dev_unlock_bh(hdev); |
1715 | hci_dev_put(hdev); | 1720 | hci_dev_put(hdev); |
1716 | 1721 | ||
@@ -1721,7 +1726,6 @@ static int unblock_device(struct sock *sk, u16 index, unsigned char *data, | |||
1721 | u16 len) | 1726 | u16 len) |
1722 | { | 1727 | { |
1723 | struct hci_dev *hdev; | 1728 | struct hci_dev *hdev; |
1724 | struct pending_cmd *cmd; | ||
1725 | struct mgmt_cp_unblock_device *cp = (void *) data; | 1729 | struct mgmt_cp_unblock_device *cp = (void *) data; |
1726 | int err; | 1730 | int err; |
1727 | 1731 | ||
@@ -1738,12 +1742,6 @@ static int unblock_device(struct sock *sk, u16 index, unsigned char *data, | |||
1738 | 1742 | ||
1739 | hci_dev_lock_bh(hdev); | 1743 | hci_dev_lock_bh(hdev); |
1740 | 1744 | ||
1741 | cmd = mgmt_pending_add(sk, MGMT_OP_UNBLOCK_DEVICE, index, NULL, 0); | ||
1742 | if (!cmd) { | ||
1743 | err = -ENOMEM; | ||
1744 | goto failed; | ||
1745 | } | ||
1746 | |||
1747 | err = hci_blacklist_del(hdev, &cp->bdaddr); | 1745 | err = hci_blacklist_del(hdev, &cp->bdaddr); |
1748 | 1746 | ||
1749 | if (err < 0) | 1747 | if (err < 0) |
@@ -1752,9 +1750,6 @@ static int unblock_device(struct sock *sk, u16 index, unsigned char *data, | |||
1752 | err = cmd_complete(sk, index, MGMT_OP_UNBLOCK_DEVICE, | 1750 | err = cmd_complete(sk, index, MGMT_OP_UNBLOCK_DEVICE, |
1753 | NULL, 0); | 1751 | NULL, 0); |
1754 | 1752 | ||
1755 | mgmt_pending_remove(cmd); | ||
1756 | |||
1757 | failed: | ||
1758 | hci_dev_unlock_bh(hdev); | 1753 | hci_dev_unlock_bh(hdev); |
1759 | hci_dev_put(hdev); | 1754 | hci_dev_put(hdev); |
1760 | 1755 | ||
@@ -1882,11 +1877,11 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) | |||
1882 | case MGMT_OP_SET_SERVICE_CACHE: | 1877 | case MGMT_OP_SET_SERVICE_CACHE: |
1883 | err = set_service_cache(sk, index, buf + sizeof(*hdr), len); | 1878 | err = set_service_cache(sk, index, buf + sizeof(*hdr), len); |
1884 | break; | 1879 | break; |
1885 | case MGMT_OP_LOAD_KEYS: | 1880 | case MGMT_OP_LOAD_LINK_KEYS: |
1886 | err = load_keys(sk, index, buf + sizeof(*hdr), len); | 1881 | err = load_link_keys(sk, index, buf + sizeof(*hdr), len); |
1887 | break; | 1882 | break; |
1888 | case MGMT_OP_REMOVE_KEY: | 1883 | case MGMT_OP_REMOVE_KEYS: |
1889 | err = remove_key(sk, index, buf + sizeof(*hdr), len); | 1884 | err = remove_keys(sk, index, buf + sizeof(*hdr), len); |
1890 | break; | 1885 | break; |
1891 | case MGMT_OP_DISCONNECT: | 1886 | case MGMT_OP_DISCONNECT: |
1892 | err = disconnect(sk, index, buf + sizeof(*hdr), len); | 1887 | err = disconnect(sk, index, buf + sizeof(*hdr), len); |
@@ -1957,14 +1952,26 @@ done: | |||
1957 | return err; | 1952 | return err; |
1958 | } | 1953 | } |
1959 | 1954 | ||
1960 | int mgmt_index_added(u16 index) | 1955 | static void cmd_status_rsp(struct pending_cmd *cmd, void *data) |
1961 | { | 1956 | { |
1962 | return mgmt_event(MGMT_EV_INDEX_ADDED, index, NULL, 0, NULL); | 1957 | u8 *status = data; |
1958 | |||
1959 | cmd_status(cmd->sk, cmd->index, cmd->opcode, *status); | ||
1960 | mgmt_pending_remove(cmd); | ||
1963 | } | 1961 | } |
1964 | 1962 | ||
1965 | int mgmt_index_removed(u16 index) | 1963 | int mgmt_index_added(struct hci_dev *hdev) |
1966 | { | 1964 | { |
1967 | return mgmt_event(MGMT_EV_INDEX_REMOVED, index, NULL, 0, NULL); | 1965 | return mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL); |
1966 | } | ||
1967 | |||
1968 | int mgmt_index_removed(struct hci_dev *hdev) | ||
1969 | { | ||
1970 | u8 status = ENODEV; | ||
1971 | |||
1972 | mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status); | ||
1973 | |||
1974 | return mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL); | ||
1968 | } | 1975 | } |
1969 | 1976 | ||
1970 | struct cmd_lookup { | 1977 | struct cmd_lookup { |
@@ -1992,17 +1999,22 @@ static void mode_rsp(struct pending_cmd *cmd, void *data) | |||
1992 | mgmt_pending_free(cmd); | 1999 | mgmt_pending_free(cmd); |
1993 | } | 2000 | } |
1994 | 2001 | ||
1995 | int mgmt_powered(u16 index, u8 powered) | 2002 | int mgmt_powered(struct hci_dev *hdev, u8 powered) |
1996 | { | 2003 | { |
1997 | struct mgmt_mode ev; | 2004 | struct mgmt_mode ev; |
1998 | struct cmd_lookup match = { powered, NULL }; | 2005 | struct cmd_lookup match = { powered, NULL }; |
1999 | int ret; | 2006 | int ret; |
2000 | 2007 | ||
2001 | mgmt_pending_foreach(MGMT_OP_SET_POWERED, index, mode_rsp, &match); | 2008 | mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, mode_rsp, &match); |
2009 | |||
2010 | if (!powered) { | ||
2011 | u8 status = ENETDOWN; | ||
2012 | mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status); | ||
2013 | } | ||
2002 | 2014 | ||
2003 | ev.val = powered; | 2015 | ev.val = powered; |
2004 | 2016 | ||
2005 | ret = mgmt_event(MGMT_EV_POWERED, index, &ev, sizeof(ev), match.sk); | 2017 | ret = mgmt_event(MGMT_EV_POWERED, hdev, &ev, sizeof(ev), match.sk); |
2006 | 2018 | ||
2007 | if (match.sk) | 2019 | if (match.sk) |
2008 | sock_put(match.sk); | 2020 | sock_put(match.sk); |
@@ -2010,17 +2022,17 @@ int mgmt_powered(u16 index, u8 powered) | |||
2010 | return ret; | 2022 | return ret; |
2011 | } | 2023 | } |
2012 | 2024 | ||
2013 | int mgmt_discoverable(u16 index, u8 discoverable) | 2025 | int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable) |
2014 | { | 2026 | { |
2015 | struct mgmt_mode ev; | 2027 | struct mgmt_mode ev; |
2016 | struct cmd_lookup match = { discoverable, NULL }; | 2028 | struct cmd_lookup match = { discoverable, NULL }; |
2017 | int ret; | 2029 | int ret; |
2018 | 2030 | ||
2019 | mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, index, mode_rsp, &match); | 2031 | mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev, mode_rsp, &match); |
2020 | 2032 | ||
2021 | ev.val = discoverable; | 2033 | ev.val = discoverable; |
2022 | 2034 | ||
2023 | ret = mgmt_event(MGMT_EV_DISCOVERABLE, index, &ev, sizeof(ev), | 2035 | ret = mgmt_event(MGMT_EV_DISCOVERABLE, hdev, &ev, sizeof(ev), |
2024 | match.sk); | 2036 | match.sk); |
2025 | 2037 | ||
2026 | if (match.sk) | 2038 | if (match.sk) |
@@ -2029,17 +2041,17 @@ int mgmt_discoverable(u16 index, u8 discoverable) | |||
2029 | return ret; | 2041 | return ret; |
2030 | } | 2042 | } |
2031 | 2043 | ||
2032 | int mgmt_connectable(u16 index, u8 connectable) | 2044 | int mgmt_connectable(struct hci_dev *hdev, u8 connectable) |
2033 | { | 2045 | { |
2034 | struct mgmt_mode ev; | 2046 | struct mgmt_mode ev; |
2035 | struct cmd_lookup match = { connectable, NULL }; | 2047 | struct cmd_lookup match = { connectable, NULL }; |
2036 | int ret; | 2048 | int ret; |
2037 | 2049 | ||
2038 | mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, index, mode_rsp, &match); | 2050 | mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev, mode_rsp, &match); |
2039 | 2051 | ||
2040 | ev.val = connectable; | 2052 | ev.val = connectable; |
2041 | 2053 | ||
2042 | ret = mgmt_event(MGMT_EV_CONNECTABLE, index, &ev, sizeof(ev), match.sk); | 2054 | ret = mgmt_event(MGMT_EV_CONNECTABLE, hdev, &ev, sizeof(ev), match.sk); |
2043 | 2055 | ||
2044 | if (match.sk) | 2056 | if (match.sk) |
2045 | sock_put(match.sk); | 2057 | sock_put(match.sk); |
@@ -2047,9 +2059,23 @@ int mgmt_connectable(u16 index, u8 connectable) | |||
2047 | return ret; | 2059 | return ret; |
2048 | } | 2060 | } |
2049 | 2061 | ||
2050 | int mgmt_new_key(u16 index, struct link_key *key, u8 persistent) | 2062 | int mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status) |
2063 | { | ||
2064 | if (scan & SCAN_PAGE) | ||
2065 | mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev, | ||
2066 | cmd_status_rsp, &status); | ||
2067 | |||
2068 | if (scan & SCAN_INQUIRY) | ||
2069 | mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev, | ||
2070 | cmd_status_rsp, &status); | ||
2071 | |||
2072 | return 0; | ||
2073 | } | ||
2074 | |||
2075 | int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, | ||
2076 | u8 persistent) | ||
2051 | { | 2077 | { |
2052 | struct mgmt_ev_new_key ev; | 2078 | struct mgmt_ev_new_link_key ev; |
2053 | 2079 | ||
2054 | memset(&ev, 0, sizeof(ev)); | 2080 | memset(&ev, 0, sizeof(ev)); |
2055 | 2081 | ||
@@ -2059,17 +2085,17 @@ int mgmt_new_key(u16 index, struct link_key *key, u8 persistent) | |||
2059 | memcpy(ev.key.val, key->val, 16); | 2085 | memcpy(ev.key.val, key->val, 16); |
2060 | ev.key.pin_len = key->pin_len; | 2086 | ev.key.pin_len = key->pin_len; |
2061 | 2087 | ||
2062 | return mgmt_event(MGMT_EV_NEW_KEY, index, &ev, sizeof(ev), NULL); | 2088 | return mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL); |
2063 | } | 2089 | } |
2064 | 2090 | ||
2065 | int mgmt_connected(u16 index, bdaddr_t *bdaddr, u8 link_type) | 2091 | int mgmt_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type) |
2066 | { | 2092 | { |
2067 | struct mgmt_ev_connected ev; | 2093 | struct mgmt_addr_info ev; |
2068 | 2094 | ||
2069 | bacpy(&ev.bdaddr, bdaddr); | 2095 | bacpy(&ev.bdaddr, bdaddr); |
2070 | ev.link_type = link_type; | 2096 | ev.type = link_to_mgmt(link_type); |
2071 | 2097 | ||
2072 | return mgmt_event(MGMT_EV_CONNECTED, index, &ev, sizeof(ev), NULL); | 2098 | return mgmt_event(MGMT_EV_CONNECTED, hdev, &ev, sizeof(ev), NULL); |
2073 | } | 2099 | } |
2074 | 2100 | ||
2075 | static void disconnect_rsp(struct pending_cmd *cmd, void *data) | 2101 | static void disconnect_rsp(struct pending_cmd *cmd, void *data) |
@@ -2088,17 +2114,18 @@ static void disconnect_rsp(struct pending_cmd *cmd, void *data) | |||
2088 | mgmt_pending_remove(cmd); | 2114 | mgmt_pending_remove(cmd); |
2089 | } | 2115 | } |
2090 | 2116 | ||
2091 | int mgmt_disconnected(u16 index, bdaddr_t *bdaddr) | 2117 | int mgmt_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) |
2092 | { | 2118 | { |
2093 | struct mgmt_ev_disconnected ev; | 2119 | struct mgmt_addr_info ev; |
2094 | struct sock *sk = NULL; | 2120 | struct sock *sk = NULL; |
2095 | int err; | 2121 | int err; |
2096 | 2122 | ||
2097 | mgmt_pending_foreach(MGMT_OP_DISCONNECT, index, disconnect_rsp, &sk); | 2123 | mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk); |
2098 | 2124 | ||
2099 | bacpy(&ev.bdaddr, bdaddr); | 2125 | bacpy(&ev.bdaddr, bdaddr); |
2126 | ev.type = link_to_mgmt(type); | ||
2100 | 2127 | ||
2101 | err = mgmt_event(MGMT_EV_DISCONNECTED, index, &ev, sizeof(ev), sk); | 2128 | err = mgmt_event(MGMT_EV_DISCONNECTED, hdev, &ev, sizeof(ev), sk); |
2102 | 2129 | ||
2103 | if (sk) | 2130 | if (sk) |
2104 | sock_put(sk); | 2131 | sock_put(sk); |
@@ -2106,57 +2133,60 @@ int mgmt_disconnected(u16 index, bdaddr_t *bdaddr) | |||
2106 | return err; | 2133 | return err; |
2107 | } | 2134 | } |
2108 | 2135 | ||
2109 | int mgmt_disconnect_failed(u16 index) | 2136 | int mgmt_disconnect_failed(struct hci_dev *hdev) |
2110 | { | 2137 | { |
2111 | struct pending_cmd *cmd; | 2138 | struct pending_cmd *cmd; |
2112 | int err; | 2139 | int err; |
2113 | 2140 | ||
2114 | cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, index); | 2141 | cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev); |
2115 | if (!cmd) | 2142 | if (!cmd) |
2116 | return -ENOENT; | 2143 | return -ENOENT; |
2117 | 2144 | ||
2118 | err = cmd_status(cmd->sk, index, MGMT_OP_DISCONNECT, EIO); | 2145 | err = cmd_status(cmd->sk, hdev->id, MGMT_OP_DISCONNECT, EIO); |
2119 | 2146 | ||
2120 | mgmt_pending_remove(cmd); | 2147 | mgmt_pending_remove(cmd); |
2121 | 2148 | ||
2122 | return err; | 2149 | return err; |
2123 | } | 2150 | } |
2124 | 2151 | ||
2125 | int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status) | 2152 | int mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type, |
2153 | u8 status) | ||
2126 | { | 2154 | { |
2127 | struct mgmt_ev_connect_failed ev; | 2155 | struct mgmt_ev_connect_failed ev; |
2128 | 2156 | ||
2129 | bacpy(&ev.bdaddr, bdaddr); | 2157 | bacpy(&ev.addr.bdaddr, bdaddr); |
2158 | ev.addr.type = link_to_mgmt(type); | ||
2130 | ev.status = status; | 2159 | ev.status = status; |
2131 | 2160 | ||
2132 | return mgmt_event(MGMT_EV_CONNECT_FAILED, index, &ev, sizeof(ev), NULL); | 2161 | return mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL); |
2133 | } | 2162 | } |
2134 | 2163 | ||
2135 | int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr, u8 secure) | 2164 | int mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure) |
2136 | { | 2165 | { |
2137 | struct mgmt_ev_pin_code_request ev; | 2166 | struct mgmt_ev_pin_code_request ev; |
2138 | 2167 | ||
2139 | bacpy(&ev.bdaddr, bdaddr); | 2168 | bacpy(&ev.bdaddr, bdaddr); |
2140 | ev.secure = secure; | 2169 | ev.secure = secure; |
2141 | 2170 | ||
2142 | return mgmt_event(MGMT_EV_PIN_CODE_REQUEST, index, &ev, sizeof(ev), | 2171 | return mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), |
2143 | NULL); | 2172 | NULL); |
2144 | } | 2173 | } |
2145 | 2174 | ||
2146 | int mgmt_pin_code_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status) | 2175 | int mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, |
2176 | u8 status) | ||
2147 | { | 2177 | { |
2148 | struct pending_cmd *cmd; | 2178 | struct pending_cmd *cmd; |
2149 | struct mgmt_rp_pin_code_reply rp; | 2179 | struct mgmt_rp_pin_code_reply rp; |
2150 | int err; | 2180 | int err; |
2151 | 2181 | ||
2152 | cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, index); | 2182 | cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev); |
2153 | if (!cmd) | 2183 | if (!cmd) |
2154 | return -ENOENT; | 2184 | return -ENOENT; |
2155 | 2185 | ||
2156 | bacpy(&rp.bdaddr, bdaddr); | 2186 | bacpy(&rp.bdaddr, bdaddr); |
2157 | rp.status = status; | 2187 | rp.status = status; |
2158 | 2188 | ||
2159 | err = cmd_complete(cmd->sk, index, MGMT_OP_PIN_CODE_REPLY, &rp, | 2189 | err = cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY, &rp, |
2160 | sizeof(rp)); | 2190 | sizeof(rp)); |
2161 | 2191 | ||
2162 | mgmt_pending_remove(cmd); | 2192 | mgmt_pending_remove(cmd); |
@@ -2164,20 +2194,21 @@ int mgmt_pin_code_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status) | |||
2164 | return err; | 2194 | return err; |
2165 | } | 2195 | } |
2166 | 2196 | ||
2167 | int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status) | 2197 | int mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, |
2198 | u8 status) | ||
2168 | { | 2199 | { |
2169 | struct pending_cmd *cmd; | 2200 | struct pending_cmd *cmd; |
2170 | struct mgmt_rp_pin_code_reply rp; | 2201 | struct mgmt_rp_pin_code_reply rp; |
2171 | int err; | 2202 | int err; |
2172 | 2203 | ||
2173 | cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, index); | 2204 | cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev); |
2174 | if (!cmd) | 2205 | if (!cmd) |
2175 | return -ENOENT; | 2206 | return -ENOENT; |
2176 | 2207 | ||
2177 | bacpy(&rp.bdaddr, bdaddr); | 2208 | bacpy(&rp.bdaddr, bdaddr); |
2178 | rp.status = status; | 2209 | rp.status = status; |
2179 | 2210 | ||
2180 | err = cmd_complete(cmd->sk, index, MGMT_OP_PIN_CODE_NEG_REPLY, &rp, | 2211 | err = cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY, &rp, |
2181 | sizeof(rp)); | 2212 | sizeof(rp)); |
2182 | 2213 | ||
2183 | mgmt_pending_remove(cmd); | 2214 | mgmt_pending_remove(cmd); |
@@ -2185,97 +2216,93 @@ int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status) | |||
2185 | return err; | 2216 | return err; |
2186 | } | 2217 | } |
2187 | 2218 | ||
2188 | int mgmt_user_confirm_request(u16 index, bdaddr_t *bdaddr, __le32 value, | 2219 | int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr, |
2189 | u8 confirm_hint) | 2220 | __le32 value, u8 confirm_hint) |
2190 | { | 2221 | { |
2191 | struct mgmt_ev_user_confirm_request ev; | 2222 | struct mgmt_ev_user_confirm_request ev; |
2192 | 2223 | ||
2193 | BT_DBG("hci%u", index); | 2224 | BT_DBG("%s", hdev->name); |
2194 | 2225 | ||
2195 | bacpy(&ev.bdaddr, bdaddr); | 2226 | bacpy(&ev.bdaddr, bdaddr); |
2196 | ev.confirm_hint = confirm_hint; | 2227 | ev.confirm_hint = confirm_hint; |
2197 | put_unaligned_le32(value, &ev.value); | 2228 | put_unaligned_le32(value, &ev.value); |
2198 | 2229 | ||
2199 | return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, index, &ev, sizeof(ev), | 2230 | return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev), |
2200 | NULL); | 2231 | NULL); |
2201 | } | 2232 | } |
2202 | 2233 | ||
2203 | static int confirm_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status, | 2234 | static int confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, |
2204 | u8 opcode) | 2235 | u8 status, u8 opcode) |
2205 | { | 2236 | { |
2206 | struct pending_cmd *cmd; | 2237 | struct pending_cmd *cmd; |
2207 | struct mgmt_rp_user_confirm_reply rp; | 2238 | struct mgmt_rp_user_confirm_reply rp; |
2208 | int err; | 2239 | int err; |
2209 | 2240 | ||
2210 | cmd = mgmt_pending_find(opcode, index); | 2241 | cmd = mgmt_pending_find(opcode, hdev); |
2211 | if (!cmd) | 2242 | if (!cmd) |
2212 | return -ENOENT; | 2243 | return -ENOENT; |
2213 | 2244 | ||
2214 | bacpy(&rp.bdaddr, bdaddr); | 2245 | bacpy(&rp.bdaddr, bdaddr); |
2215 | rp.status = status; | 2246 | rp.status = status; |
2216 | err = cmd_complete(cmd->sk, index, opcode, &rp, sizeof(rp)); | 2247 | err = cmd_complete(cmd->sk, hdev->id, opcode, &rp, sizeof(rp)); |
2217 | 2248 | ||
2218 | mgmt_pending_remove(cmd); | 2249 | mgmt_pending_remove(cmd); |
2219 | 2250 | ||
2220 | return err; | 2251 | return err; |
2221 | } | 2252 | } |
2222 | 2253 | ||
2223 | int mgmt_user_confirm_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status) | 2254 | int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, |
2255 | u8 status) | ||
2224 | { | 2256 | { |
2225 | return confirm_reply_complete(index, bdaddr, status, | 2257 | return confirm_reply_complete(hdev, bdaddr, status, |
2226 | MGMT_OP_USER_CONFIRM_REPLY); | 2258 | MGMT_OP_USER_CONFIRM_REPLY); |
2227 | } | 2259 | } |
2228 | 2260 | ||
2229 | int mgmt_user_confirm_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status) | 2261 | int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, |
2262 | bdaddr_t *bdaddr, u8 status) | ||
2230 | { | 2263 | { |
2231 | return confirm_reply_complete(index, bdaddr, status, | 2264 | return confirm_reply_complete(hdev, bdaddr, status, |
2232 | MGMT_OP_USER_CONFIRM_NEG_REPLY); | 2265 | MGMT_OP_USER_CONFIRM_NEG_REPLY); |
2233 | } | 2266 | } |
2234 | 2267 | ||
2235 | int mgmt_auth_failed(u16 index, bdaddr_t *bdaddr, u8 status) | 2268 | int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status) |
2236 | { | 2269 | { |
2237 | struct mgmt_ev_auth_failed ev; | 2270 | struct mgmt_ev_auth_failed ev; |
2238 | 2271 | ||
2239 | bacpy(&ev.bdaddr, bdaddr); | 2272 | bacpy(&ev.bdaddr, bdaddr); |
2240 | ev.status = status; | 2273 | ev.status = status; |
2241 | 2274 | ||
2242 | return mgmt_event(MGMT_EV_AUTH_FAILED, index, &ev, sizeof(ev), NULL); | 2275 | return mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL); |
2243 | } | 2276 | } |
2244 | 2277 | ||
2245 | int mgmt_set_local_name_complete(u16 index, u8 *name, u8 status) | 2278 | int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status) |
2246 | { | 2279 | { |
2247 | struct pending_cmd *cmd; | 2280 | struct pending_cmd *cmd; |
2248 | struct hci_dev *hdev; | ||
2249 | struct mgmt_cp_set_local_name ev; | 2281 | struct mgmt_cp_set_local_name ev; |
2250 | int err; | 2282 | int err; |
2251 | 2283 | ||
2252 | memset(&ev, 0, sizeof(ev)); | 2284 | memset(&ev, 0, sizeof(ev)); |
2253 | memcpy(ev.name, name, HCI_MAX_NAME_LENGTH); | 2285 | memcpy(ev.name, name, HCI_MAX_NAME_LENGTH); |
2254 | 2286 | ||
2255 | cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, index); | 2287 | cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev); |
2256 | if (!cmd) | 2288 | if (!cmd) |
2257 | goto send_event; | 2289 | goto send_event; |
2258 | 2290 | ||
2259 | if (status) { | 2291 | if (status) { |
2260 | err = cmd_status(cmd->sk, index, MGMT_OP_SET_LOCAL_NAME, EIO); | 2292 | err = cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, |
2293 | EIO); | ||
2261 | goto failed; | 2294 | goto failed; |
2262 | } | 2295 | } |
2263 | 2296 | ||
2264 | hdev = hci_dev_get(index); | 2297 | update_eir(hdev); |
2265 | if (hdev) { | ||
2266 | hci_dev_lock_bh(hdev); | ||
2267 | update_eir(hdev); | ||
2268 | hci_dev_unlock_bh(hdev); | ||
2269 | hci_dev_put(hdev); | ||
2270 | } | ||
2271 | 2298 | ||
2272 | err = cmd_complete(cmd->sk, index, MGMT_OP_SET_LOCAL_NAME, &ev, | 2299 | err = cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, &ev, |
2273 | sizeof(ev)); | 2300 | sizeof(ev)); |
2274 | if (err < 0) | 2301 | if (err < 0) |
2275 | goto failed; | 2302 | goto failed; |
2276 | 2303 | ||
2277 | send_event: | 2304 | send_event: |
2278 | err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, index, &ev, sizeof(ev), | 2305 | err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev), |
2279 | cmd ? cmd->sk : NULL); | 2306 | cmd ? cmd->sk : NULL); |
2280 | 2307 | ||
2281 | failed: | 2308 | failed: |
@@ -2284,29 +2311,30 @@ failed: | |||
2284 | return err; | 2311 | return err; |
2285 | } | 2312 | } |
2286 | 2313 | ||
2287 | int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer, | 2314 | int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash, |
2288 | u8 status) | 2315 | u8 *randomizer, u8 status) |
2289 | { | 2316 | { |
2290 | struct pending_cmd *cmd; | 2317 | struct pending_cmd *cmd; |
2291 | int err; | 2318 | int err; |
2292 | 2319 | ||
2293 | BT_DBG("hci%u status %u", index, status); | 2320 | BT_DBG("%s status %u", hdev->name, status); |
2294 | 2321 | ||
2295 | cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, index); | 2322 | cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev); |
2296 | if (!cmd) | 2323 | if (!cmd) |
2297 | return -ENOENT; | 2324 | return -ENOENT; |
2298 | 2325 | ||
2299 | if (status) { | 2326 | if (status) { |
2300 | err = cmd_status(cmd->sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, | 2327 | err = cmd_status(cmd->sk, hdev->id, |
2301 | EIO); | 2328 | MGMT_OP_READ_LOCAL_OOB_DATA, EIO); |
2302 | } else { | 2329 | } else { |
2303 | struct mgmt_rp_read_local_oob_data rp; | 2330 | struct mgmt_rp_read_local_oob_data rp; |
2304 | 2331 | ||
2305 | memcpy(rp.hash, hash, sizeof(rp.hash)); | 2332 | memcpy(rp.hash, hash, sizeof(rp.hash)); |
2306 | memcpy(rp.randomizer, randomizer, sizeof(rp.randomizer)); | 2333 | memcpy(rp.randomizer, randomizer, sizeof(rp.randomizer)); |
2307 | 2334 | ||
2308 | err = cmd_complete(cmd->sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, | 2335 | err = cmd_complete(cmd->sk, hdev->id, |
2309 | &rp, sizeof(rp)); | 2336 | MGMT_OP_READ_LOCAL_OOB_DATA, |
2337 | &rp, sizeof(rp)); | ||
2310 | } | 2338 | } |
2311 | 2339 | ||
2312 | mgmt_pending_remove(cmd); | 2340 | mgmt_pending_remove(cmd); |
@@ -2314,14 +2342,15 @@ int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer, | |||
2314 | return err; | 2342 | return err; |
2315 | } | 2343 | } |
2316 | 2344 | ||
2317 | int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi, | 2345 | int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type, |
2318 | u8 *eir) | 2346 | u8 *dev_class, s8 rssi, u8 *eir) |
2319 | { | 2347 | { |
2320 | struct mgmt_ev_device_found ev; | 2348 | struct mgmt_ev_device_found ev; |
2321 | 2349 | ||
2322 | memset(&ev, 0, sizeof(ev)); | 2350 | memset(&ev, 0, sizeof(ev)); |
2323 | 2351 | ||
2324 | bacpy(&ev.bdaddr, bdaddr); | 2352 | bacpy(&ev.addr.bdaddr, bdaddr); |
2353 | ev.addr.type = link_to_mgmt(type); | ||
2325 | ev.rssi = rssi; | 2354 | ev.rssi = rssi; |
2326 | 2355 | ||
2327 | if (eir) | 2356 | if (eir) |
@@ -2330,10 +2359,10 @@ int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi, | |||
2330 | if (dev_class) | 2359 | if (dev_class) |
2331 | memcpy(ev.dev_class, dev_class, sizeof(ev.dev_class)); | 2360 | memcpy(ev.dev_class, dev_class, sizeof(ev.dev_class)); |
2332 | 2361 | ||
2333 | return mgmt_event(MGMT_EV_DEVICE_FOUND, index, &ev, sizeof(ev), NULL); | 2362 | return mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, &ev, sizeof(ev), NULL); |
2334 | } | 2363 | } |
2335 | 2364 | ||
2336 | int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name) | 2365 | int mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *name) |
2337 | { | 2366 | { |
2338 | struct mgmt_ev_remote_name ev; | 2367 | struct mgmt_ev_remote_name ev; |
2339 | 2368 | ||
@@ -2342,37 +2371,64 @@ int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name) | |||
2342 | bacpy(&ev.bdaddr, bdaddr); | 2371 | bacpy(&ev.bdaddr, bdaddr); |
2343 | memcpy(ev.name, name, HCI_MAX_NAME_LENGTH); | 2372 | memcpy(ev.name, name, HCI_MAX_NAME_LENGTH); |
2344 | 2373 | ||
2345 | return mgmt_event(MGMT_EV_REMOTE_NAME, index, &ev, sizeof(ev), NULL); | 2374 | return mgmt_event(MGMT_EV_REMOTE_NAME, hdev, &ev, sizeof(ev), NULL); |
2346 | } | 2375 | } |
2347 | 2376 | ||
2348 | int mgmt_discovering(u16 index, u8 discovering) | 2377 | int mgmt_inquiry_failed(struct hci_dev *hdev, u8 status) |
2349 | { | 2378 | { |
2350 | return mgmt_event(MGMT_EV_DISCOVERING, index, &discovering, | 2379 | struct pending_cmd *cmd; |
2380 | int err; | ||
2381 | |||
2382 | cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev); | ||
2383 | if (!cmd) | ||
2384 | return -ENOENT; | ||
2385 | |||
2386 | err = cmd_status(cmd->sk, hdev->id, cmd->opcode, status); | ||
2387 | mgmt_pending_remove(cmd); | ||
2388 | |||
2389 | return err; | ||
2390 | } | ||
2391 | |||
2392 | int mgmt_discovering(struct hci_dev *hdev, u8 discovering) | ||
2393 | { | ||
2394 | struct pending_cmd *cmd; | ||
2395 | |||
2396 | if (discovering) | ||
2397 | cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev); | ||
2398 | else | ||
2399 | cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev); | ||
2400 | |||
2401 | if (cmd != NULL) { | ||
2402 | cmd_complete(cmd->sk, hdev->id, cmd->opcode, NULL, 0); | ||
2403 | mgmt_pending_remove(cmd); | ||
2404 | } | ||
2405 | |||
2406 | return mgmt_event(MGMT_EV_DISCOVERING, hdev, &discovering, | ||
2351 | sizeof(discovering), NULL); | 2407 | sizeof(discovering), NULL); |
2352 | } | 2408 | } |
2353 | 2409 | ||
2354 | int mgmt_device_blocked(u16 index, bdaddr_t *bdaddr) | 2410 | int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr) |
2355 | { | 2411 | { |
2356 | struct pending_cmd *cmd; | 2412 | struct pending_cmd *cmd; |
2357 | struct mgmt_ev_device_blocked ev; | 2413 | struct mgmt_ev_device_blocked ev; |
2358 | 2414 | ||
2359 | cmd = mgmt_pending_find(MGMT_OP_BLOCK_DEVICE, index); | 2415 | cmd = mgmt_pending_find(MGMT_OP_BLOCK_DEVICE, hdev); |
2360 | 2416 | ||
2361 | bacpy(&ev.bdaddr, bdaddr); | 2417 | bacpy(&ev.bdaddr, bdaddr); |
2362 | 2418 | ||
2363 | return mgmt_event(MGMT_EV_DEVICE_BLOCKED, index, &ev, sizeof(ev), | 2419 | return mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &ev, sizeof(ev), |
2364 | cmd ? cmd->sk : NULL); | 2420 | cmd ? cmd->sk : NULL); |
2365 | } | 2421 | } |
2366 | 2422 | ||
2367 | int mgmt_device_unblocked(u16 index, bdaddr_t *bdaddr) | 2423 | int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr) |
2368 | { | 2424 | { |
2369 | struct pending_cmd *cmd; | 2425 | struct pending_cmd *cmd; |
2370 | struct mgmt_ev_device_unblocked ev; | 2426 | struct mgmt_ev_device_unblocked ev; |
2371 | 2427 | ||
2372 | cmd = mgmt_pending_find(MGMT_OP_UNBLOCK_DEVICE, index); | 2428 | cmd = mgmt_pending_find(MGMT_OP_UNBLOCK_DEVICE, hdev); |
2373 | 2429 | ||
2374 | bacpy(&ev.bdaddr, bdaddr); | 2430 | bacpy(&ev.bdaddr, bdaddr); |
2375 | 2431 | ||
2376 | return mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, index, &ev, sizeof(ev), | 2432 | return mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &ev, sizeof(ev), |
2377 | cmd ? cmd->sk : NULL); | 2433 | cmd ? cmd->sk : NULL); |
2378 | } | 2434 | } |