diff options
author | John W. Linville <linville@tuxdriver.com> | 2011-03-04 13:59:44 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-03-04 13:59:44 -0500 |
commit | a177584609f7eb2ab1f1c0211bee4ec20d98d892 (patch) | |
tree | 3a625f41560800f64f89e4c54ee75851b0913091 /net/bluetooth | |
parent | e46395a4b3d32d161d8b6d8e4a002972b1faae3e (diff) | |
parent | b8534e0f2b09e47790c261af0aee86fc88c6eb3c (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/padovan/bluetooth-next-2.6
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/af_bluetooth.c | 4 | ||||
-rw-r--r-- | net/bluetooth/hci_conn.c | 8 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 69 | ||||
-rw-r--r-- | net/bluetooth/hci_sock.c | 2 | ||||
-rw-r--r-- | net/bluetooth/l2cap_core.c | 13 | ||||
-rw-r--r-- | net/bluetooth/mgmt.c | 751 | ||||
-rw-r--r-- | net/bluetooth/sco.c | 7 |
7 files changed, 585 insertions, 269 deletions
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 88af9eb9aa48..8add9b499912 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c | |||
@@ -550,10 +550,8 @@ static int __init bt_init(void) | |||
550 | goto error; | 550 | goto error; |
551 | 551 | ||
552 | err = l2cap_init(); | 552 | err = l2cap_init(); |
553 | if (err < 0) { | 553 | if (err < 0) |
554 | hci_sock_cleanup(); | ||
555 | goto sock_err; | 554 | goto sock_err; |
556 | } | ||
557 | 555 | ||
558 | err = sco_init(); | 556 | err = sco_init(); |
559 | if (err < 0) { | 557 | if (err < 0) { |
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index a050a6984901..7a6f56b2f49d 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -286,6 +286,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) | |||
286 | conn->state = BT_OPEN; | 286 | conn->state = BT_OPEN; |
287 | conn->auth_type = HCI_AT_GENERAL_BONDING; | 287 | conn->auth_type = HCI_AT_GENERAL_BONDING; |
288 | conn->io_capability = hdev->io_capability; | 288 | conn->io_capability = hdev->io_capability; |
289 | conn->remote_auth = 0xff; | ||
289 | 290 | ||
290 | conn->power_save = 1; | 291 | conn->power_save = 1; |
291 | conn->disc_timeout = HCI_DISCONN_TIMEOUT; | 292 | conn->disc_timeout = HCI_DISCONN_TIMEOUT; |
@@ -429,10 +430,11 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 | |||
429 | 430 | ||
430 | if (type == LE_LINK) { | 431 | if (type == LE_LINK) { |
431 | le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst); | 432 | le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst); |
433 | if (le) | ||
434 | return ERR_PTR(-EBUSY); | ||
435 | le = hci_conn_add(hdev, LE_LINK, dst); | ||
432 | if (!le) | 436 | if (!le) |
433 | le = hci_conn_add(hdev, LE_LINK, dst); | 437 | return ERR_PTR(-ENOMEM); |
434 | if (!le) | ||
435 | return NULL; | ||
436 | if (le->state == BT_OPEN) | 438 | if (le->state == BT_OPEN) |
437 | hci_le_connect(le); | 439 | hci_le_connect(le); |
438 | 440 | ||
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 98b5764e4315..3fbfa50c2bff 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -796,6 +796,29 @@ static void hci_cc_le_read_buffer_size(struct hci_dev *hdev, | |||
796 | hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status); | 796 | hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status); |
797 | } | 797 | } |
798 | 798 | ||
799 | static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) | ||
800 | { | ||
801 | struct hci_rp_user_confirm_reply *rp = (void *) skb->data; | ||
802 | |||
803 | BT_DBG("%s status 0x%x", hdev->name, rp->status); | ||
804 | |||
805 | if (test_bit(HCI_MGMT, &hdev->flags)) | ||
806 | mgmt_user_confirm_reply_complete(hdev->id, &rp->bdaddr, | ||
807 | rp->status); | ||
808 | } | ||
809 | |||
810 | static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, | ||
811 | struct sk_buff *skb) | ||
812 | { | ||
813 | struct hci_rp_user_confirm_reply *rp = (void *) skb->data; | ||
814 | |||
815 | BT_DBG("%s status 0x%x", hdev->name, rp->status); | ||
816 | |||
817 | if (test_bit(HCI_MGMT, &hdev->flags)) | ||
818 | mgmt_user_confirm_neg_reply_complete(hdev->id, &rp->bdaddr, | ||
819 | rp->status); | ||
820 | } | ||
821 | |||
799 | static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) | 822 | static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) |
800 | { | 823 | { |
801 | BT_DBG("%s status 0x%x", hdev->name, status); | 824 | BT_DBG("%s status 0x%x", hdev->name, status); |
@@ -1401,8 +1424,10 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s | |||
1401 | if (!ev->status) { | 1424 | if (!ev->status) { |
1402 | conn->link_mode |= HCI_LM_AUTH; | 1425 | conn->link_mode |= HCI_LM_AUTH; |
1403 | conn->sec_level = conn->pending_sec_level; | 1426 | conn->sec_level = conn->pending_sec_level; |
1404 | } else | 1427 | } else { |
1428 | mgmt_auth_failed(hdev->id, &conn->dst, ev->status); | ||
1405 | conn->sec_level = BT_SECURITY_LOW; | 1429 | conn->sec_level = BT_SECURITY_LOW; |
1430 | } | ||
1406 | 1431 | ||
1407 | clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); | 1432 | clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); |
1408 | 1433 | ||
@@ -1728,6 +1753,14 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk | |||
1728 | hci_cc_le_read_buffer_size(hdev, skb); | 1753 | hci_cc_le_read_buffer_size(hdev, skb); |
1729 | break; | 1754 | break; |
1730 | 1755 | ||
1756 | case HCI_OP_USER_CONFIRM_REPLY: | ||
1757 | hci_cc_user_confirm_reply(hdev, skb); | ||
1758 | break; | ||
1759 | |||
1760 | case HCI_OP_USER_CONFIRM_NEG_REPLY: | ||
1761 | hci_cc_user_confirm_neg_reply(hdev, skb); | ||
1762 | break; | ||
1763 | |||
1731 | default: | 1764 | default: |
1732 | BT_DBG("%s opcode 0x%x", hdev->name, opcode); | 1765 | BT_DBG("%s opcode 0x%x", hdev->name, opcode); |
1733 | break; | 1766 | break; |
@@ -2362,6 +2395,21 @@ unlock: | |||
2362 | hci_dev_unlock(hdev); | 2395 | hci_dev_unlock(hdev); |
2363 | } | 2396 | } |
2364 | 2397 | ||
2398 | static inline void hci_user_confirm_request_evt(struct hci_dev *hdev, | ||
2399 | struct sk_buff *skb) | ||
2400 | { | ||
2401 | struct hci_ev_user_confirm_req *ev = (void *) skb->data; | ||
2402 | |||
2403 | BT_DBG("%s", hdev->name); | ||
2404 | |||
2405 | hci_dev_lock(hdev); | ||
2406 | |||
2407 | if (test_bit(HCI_MGMT, &hdev->flags)) | ||
2408 | mgmt_user_confirm_request(hdev->id, &ev->bdaddr, ev->passkey); | ||
2409 | |||
2410 | hci_dev_unlock(hdev); | ||
2411 | } | ||
2412 | |||
2365 | static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | 2413 | static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) |
2366 | { | 2414 | { |
2367 | struct hci_ev_simple_pair_complete *ev = (void *) skb->data; | 2415 | struct hci_ev_simple_pair_complete *ev = (void *) skb->data; |
@@ -2372,9 +2420,20 @@ static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_ | |||
2372 | hci_dev_lock(hdev); | 2420 | hci_dev_lock(hdev); |
2373 | 2421 | ||
2374 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); | 2422 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); |
2375 | if (conn) | 2423 | if (!conn) |
2376 | hci_conn_put(conn); | 2424 | goto unlock; |
2377 | 2425 | ||
2426 | /* To avoid duplicate auth_failed events to user space we check | ||
2427 | * the HCI_CONN_AUTH_PEND flag which will be set if we | ||
2428 | * initiated the authentication. A traditional auth_complete | ||
2429 | * event gets always produced as initiator and is also mapped to | ||
2430 | * the mgmt_auth_failed event */ | ||
2431 | if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend) && ev->status != 0) | ||
2432 | mgmt_auth_failed(hdev->id, &conn->dst, ev->status); | ||
2433 | |||
2434 | hci_conn_put(conn); | ||
2435 | |||
2436 | unlock: | ||
2378 | hci_dev_unlock(hdev); | 2437 | hci_dev_unlock(hdev); |
2379 | } | 2438 | } |
2380 | 2439 | ||
@@ -2580,6 +2639,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) | |||
2580 | hci_io_capa_reply_evt(hdev, skb); | 2639 | hci_io_capa_reply_evt(hdev, skb); |
2581 | break; | 2640 | break; |
2582 | 2641 | ||
2642 | case HCI_EV_USER_CONFIRM_REQUEST: | ||
2643 | hci_user_confirm_request_evt(hdev, skb); | ||
2644 | break; | ||
2645 | |||
2583 | case HCI_EV_SIMPLE_PAIR_COMPLETE: | 2646 | case HCI_EV_SIMPLE_PAIR_COMPLETE: |
2584 | hci_simple_pair_complete_evt(hdev, skb); | 2647 | hci_simple_pair_complete_evt(hdev, skb); |
2585 | break; | 2648 | break; |
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index d50e96136608..295e4a88fff8 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c | |||
@@ -861,7 +861,7 @@ error: | |||
861 | return err; | 861 | return err; |
862 | } | 862 | } |
863 | 863 | ||
864 | void __exit hci_sock_cleanup(void) | 864 | void hci_sock_cleanup(void) |
865 | { | 865 | { |
866 | if (bt_sock_unregister(BTPROTO_HCI) < 0) | 866 | if (bt_sock_unregister(BTPROTO_HCI) < 0) |
867 | BT_ERR("HCI socket unregistration failed"); | 867 | BT_ERR("HCI socket unregistration failed"); |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index efcef0dc1259..c9f9cecca527 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -852,8 +852,6 @@ int l2cap_do_connect(struct sock *sk) | |||
852 | 852 | ||
853 | hci_dev_lock_bh(hdev); | 853 | hci_dev_lock_bh(hdev); |
854 | 854 | ||
855 | err = -ENOMEM; | ||
856 | |||
857 | auth_type = l2cap_get_auth_type(sk); | 855 | auth_type = l2cap_get_auth_type(sk); |
858 | 856 | ||
859 | if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA) | 857 | if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA) |
@@ -863,17 +861,18 @@ int l2cap_do_connect(struct sock *sk) | |||
863 | hcon = hci_connect(hdev, ACL_LINK, dst, | 861 | hcon = hci_connect(hdev, ACL_LINK, dst, |
864 | l2cap_pi(sk)->sec_level, auth_type); | 862 | l2cap_pi(sk)->sec_level, auth_type); |
865 | 863 | ||
866 | if (!hcon) | 864 | if (IS_ERR(hcon)) { |
865 | err = PTR_ERR(hcon); | ||
867 | goto done; | 866 | goto done; |
867 | } | ||
868 | 868 | ||
869 | conn = l2cap_conn_add(hcon, 0); | 869 | conn = l2cap_conn_add(hcon, 0); |
870 | if (!conn) { | 870 | if (!conn) { |
871 | hci_conn_put(hcon); | 871 | hci_conn_put(hcon); |
872 | err = -ENOMEM; | ||
872 | goto done; | 873 | goto done; |
873 | } | 874 | } |
874 | 875 | ||
875 | err = 0; | ||
876 | |||
877 | /* Update source addr of the socket */ | 876 | /* Update source addr of the socket */ |
878 | bacpy(src, conn->src); | 877 | bacpy(src, conn->src); |
879 | 878 | ||
@@ -892,6 +891,8 @@ int l2cap_do_connect(struct sock *sk) | |||
892 | l2cap_do_start(sk); | 891 | l2cap_do_start(sk); |
893 | } | 892 | } |
894 | 893 | ||
894 | err = 0; | ||
895 | |||
895 | done: | 896 | done: |
896 | hci_dev_unlock_bh(hdev); | 897 | hci_dev_unlock_bh(hdev); |
897 | hci_dev_put(hdev); | 898 | hci_dev_put(hdev); |
@@ -4033,8 +4034,6 @@ int __init l2cap_init(void) | |||
4033 | BT_ERR("Failed to create L2CAP debug file"); | 4034 | BT_ERR("Failed to create L2CAP debug file"); |
4034 | } | 4035 | } |
4035 | 4036 | ||
4036 | BT_INFO("L2CAP socket layer initialized"); | ||
4037 | |||
4038 | return 0; | 4037 | return 0; |
4039 | 4038 | ||
4040 | error: | 4039 | error: |
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index f5ef7a3374c7..0054c74e27b7 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -38,17 +38,18 @@ struct pending_cmd { | |||
38 | int index; | 38 | int index; |
39 | void *cmd; | 39 | void *cmd; |
40 | struct sock *sk; | 40 | struct sock *sk; |
41 | void *user_data; | ||
41 | }; | 42 | }; |
42 | 43 | ||
43 | LIST_HEAD(cmd_list); | 44 | LIST_HEAD(cmd_list); |
44 | 45 | ||
45 | static int cmd_status(struct sock *sk, u16 cmd, u8 status) | 46 | static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status) |
46 | { | 47 | { |
47 | struct sk_buff *skb; | 48 | struct sk_buff *skb; |
48 | struct mgmt_hdr *hdr; | 49 | struct mgmt_hdr *hdr; |
49 | struct mgmt_ev_cmd_status *ev; | 50 | struct mgmt_ev_cmd_status *ev; |
50 | 51 | ||
51 | BT_DBG("sock %p", sk); | 52 | BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status); |
52 | 53 | ||
53 | skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_ATOMIC); | 54 | skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_ATOMIC); |
54 | if (!skb) | 55 | if (!skb) |
@@ -57,6 +58,7 @@ static int cmd_status(struct sock *sk, u16 cmd, u8 status) | |||
57 | hdr = (void *) skb_put(skb, sizeof(*hdr)); | 58 | hdr = (void *) skb_put(skb, sizeof(*hdr)); |
58 | 59 | ||
59 | hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS); | 60 | hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS); |
61 | hdr->index = cpu_to_le16(index); | ||
60 | hdr->len = cpu_to_le16(sizeof(*ev)); | 62 | hdr->len = cpu_to_le16(sizeof(*ev)); |
61 | 63 | ||
62 | ev = (void *) skb_put(skb, sizeof(*ev)); | 64 | ev = (void *) skb_put(skb, sizeof(*ev)); |
@@ -69,7 +71,8 @@ static int cmd_status(struct sock *sk, u16 cmd, u8 status) | |||
69 | return 0; | 71 | return 0; |
70 | } | 72 | } |
71 | 73 | ||
72 | static int cmd_complete(struct sock *sk, u16 cmd, void *rp, size_t rp_len) | 74 | static int cmd_complete(struct sock *sk, u16 index, u16 cmd, void *rp, |
75 | size_t rp_len) | ||
73 | { | 76 | { |
74 | struct sk_buff *skb; | 77 | struct sk_buff *skb; |
75 | struct mgmt_hdr *hdr; | 78 | struct mgmt_hdr *hdr; |
@@ -84,11 +87,14 @@ static int cmd_complete(struct sock *sk, u16 cmd, void *rp, size_t rp_len) | |||
84 | hdr = (void *) skb_put(skb, sizeof(*hdr)); | 87 | hdr = (void *) skb_put(skb, sizeof(*hdr)); |
85 | 88 | ||
86 | hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE); | 89 | hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE); |
90 | hdr->index = cpu_to_le16(index); | ||
87 | hdr->len = cpu_to_le16(sizeof(*ev) + rp_len); | 91 | hdr->len = cpu_to_le16(sizeof(*ev) + rp_len); |
88 | 92 | ||
89 | ev = (void *) skb_put(skb, sizeof(*ev) + rp_len); | 93 | ev = (void *) skb_put(skb, sizeof(*ev) + rp_len); |
90 | put_unaligned_le16(cmd, &ev->opcode); | 94 | put_unaligned_le16(cmd, &ev->opcode); |
91 | memcpy(ev->data, rp, rp_len); | 95 | |
96 | if (rp) | ||
97 | memcpy(ev->data, rp, rp_len); | ||
92 | 98 | ||
93 | if (sock_queue_rcv_skb(sk, skb) < 0) | 99 | if (sock_queue_rcv_skb(sk, skb) < 0) |
94 | kfree_skb(skb); | 100 | kfree_skb(skb); |
@@ -105,7 +111,8 @@ static int read_version(struct sock *sk) | |||
105 | rp.version = MGMT_VERSION; | 111 | rp.version = MGMT_VERSION; |
106 | put_unaligned_le16(MGMT_REVISION, &rp.revision); | 112 | put_unaligned_le16(MGMT_REVISION, &rp.revision); |
107 | 113 | ||
108 | return cmd_complete(sk, MGMT_OP_READ_VERSION, &rp, sizeof(rp)); | 114 | return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, &rp, |
115 | sizeof(rp)); | ||
109 | } | 116 | } |
110 | 117 | ||
111 | static int read_index_list(struct sock *sk) | 118 | static int read_index_list(struct sock *sk) |
@@ -151,32 +158,24 @@ static int read_index_list(struct sock *sk) | |||
151 | 158 | ||
152 | read_unlock(&hci_dev_list_lock); | 159 | read_unlock(&hci_dev_list_lock); |
153 | 160 | ||
154 | err = cmd_complete(sk, MGMT_OP_READ_INDEX_LIST, rp, rp_len); | 161 | err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, rp, |
162 | rp_len); | ||
155 | 163 | ||
156 | kfree(rp); | 164 | kfree(rp); |
157 | 165 | ||
158 | return err; | 166 | return err; |
159 | } | 167 | } |
160 | 168 | ||
161 | static int read_controller_info(struct sock *sk, unsigned char *data, u16 len) | 169 | static int read_controller_info(struct sock *sk, u16 index) |
162 | { | 170 | { |
163 | struct mgmt_rp_read_info rp; | 171 | struct mgmt_rp_read_info rp; |
164 | struct mgmt_cp_read_info *cp = (void *) data; | ||
165 | struct hci_dev *hdev; | 172 | struct hci_dev *hdev; |
166 | u16 dev_id; | ||
167 | |||
168 | BT_DBG("sock %p", sk); | ||
169 | 173 | ||
170 | if (len != 2) | 174 | BT_DBG("sock %p hci%u", sk, index); |
171 | return cmd_status(sk, MGMT_OP_READ_INFO, EINVAL); | ||
172 | 175 | ||
173 | dev_id = get_unaligned_le16(&cp->index); | 176 | hdev = hci_dev_get(index); |
174 | |||
175 | BT_DBG("request for hci%u", dev_id); | ||
176 | |||
177 | hdev = hci_dev_get(dev_id); | ||
178 | if (!hdev) | 177 | if (!hdev) |
179 | return cmd_status(sk, MGMT_OP_READ_INFO, ENODEV); | 178 | return cmd_status(sk, index, MGMT_OP_READ_INFO, ENODEV); |
180 | 179 | ||
181 | hci_del_off_timer(hdev); | 180 | hci_del_off_timer(hdev); |
182 | 181 | ||
@@ -184,7 +183,6 @@ static int read_controller_info(struct sock *sk, unsigned char *data, u16 len) | |||
184 | 183 | ||
185 | set_bit(HCI_MGMT, &hdev->flags); | 184 | set_bit(HCI_MGMT, &hdev->flags); |
186 | 185 | ||
187 | put_unaligned_le16(hdev->id, &rp.index); | ||
188 | rp.type = hdev->dev_type; | 186 | rp.type = hdev->dev_type; |
189 | 187 | ||
190 | rp.powered = test_bit(HCI_UP, &hdev->flags); | 188 | rp.powered = test_bit(HCI_UP, &hdev->flags); |
@@ -209,7 +207,7 @@ static int read_controller_info(struct sock *sk, unsigned char *data, u16 len) | |||
209 | hci_dev_unlock_bh(hdev); | 207 | hci_dev_unlock_bh(hdev); |
210 | hci_dev_put(hdev); | 208 | hci_dev_put(hdev); |
211 | 209 | ||
212 | return cmd_complete(sk, MGMT_OP_READ_INFO, &rp, sizeof(rp)); | 210 | return cmd_complete(sk, index, MGMT_OP_READ_INFO, &rp, sizeof(rp)); |
213 | } | 211 | } |
214 | 212 | ||
215 | static void mgmt_pending_free(struct pending_cmd *cmd) | 213 | static void mgmt_pending_free(struct pending_cmd *cmd) |
@@ -219,14 +217,14 @@ static void mgmt_pending_free(struct pending_cmd *cmd) | |||
219 | kfree(cmd); | 217 | kfree(cmd); |
220 | } | 218 | } |
221 | 219 | ||
222 | static int mgmt_pending_add(struct sock *sk, u16 opcode, int index, | 220 | static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode, |
223 | void *data, u16 len) | 221 | u16 index, void *data, u16 len) |
224 | { | 222 | { |
225 | struct pending_cmd *cmd; | 223 | struct pending_cmd *cmd; |
226 | 224 | ||
227 | cmd = kmalloc(sizeof(*cmd), GFP_ATOMIC); | 225 | cmd = kmalloc(sizeof(*cmd), GFP_ATOMIC); |
228 | if (!cmd) | 226 | if (!cmd) |
229 | return -ENOMEM; | 227 | return NULL; |
230 | 228 | ||
231 | cmd->opcode = opcode; | 229 | cmd->opcode = opcode; |
232 | cmd->index = index; | 230 | cmd->index = index; |
@@ -234,7 +232,7 @@ static int mgmt_pending_add(struct sock *sk, u16 opcode, int index, | |||
234 | cmd->cmd = kmalloc(len, GFP_ATOMIC); | 232 | cmd->cmd = kmalloc(len, GFP_ATOMIC); |
235 | if (!cmd->cmd) { | 233 | if (!cmd->cmd) { |
236 | kfree(cmd); | 234 | kfree(cmd); |
237 | return -ENOMEM; | 235 | return NULL; |
238 | } | 236 | } |
239 | 237 | ||
240 | memcpy(cmd->cmd, data, len); | 238 | memcpy(cmd->cmd, data, len); |
@@ -244,7 +242,7 @@ static int mgmt_pending_add(struct sock *sk, u16 opcode, int index, | |||
244 | 242 | ||
245 | list_add(&cmd->list, &cmd_list); | 243 | list_add(&cmd->list, &cmd_list); |
246 | 244 | ||
247 | return 0; | 245 | return cmd; |
248 | } | 246 | } |
249 | 247 | ||
250 | static void mgmt_pending_foreach(u16 opcode, int index, | 248 | static void mgmt_pending_foreach(u16 opcode, int index, |
@@ -289,103 +287,106 @@ static struct pending_cmd *mgmt_pending_find(u16 opcode, int index) | |||
289 | return NULL; | 287 | return NULL; |
290 | } | 288 | } |
291 | 289 | ||
292 | static void mgmt_pending_remove(u16 opcode, int index) | 290 | static void mgmt_pending_remove(struct pending_cmd *cmd) |
293 | { | 291 | { |
294 | struct pending_cmd *cmd; | ||
295 | |||
296 | cmd = mgmt_pending_find(opcode, index); | ||
297 | if (cmd == NULL) | ||
298 | return; | ||
299 | |||
300 | list_del(&cmd->list); | 292 | list_del(&cmd->list); |
301 | mgmt_pending_free(cmd); | 293 | mgmt_pending_free(cmd); |
302 | } | 294 | } |
303 | 295 | ||
304 | static int set_powered(struct sock *sk, unsigned char *data, u16 len) | 296 | static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len) |
305 | { | 297 | { |
306 | struct mgmt_mode *cp; | 298 | struct mgmt_mode *cp; |
307 | struct hci_dev *hdev; | 299 | struct hci_dev *hdev; |
308 | u16 dev_id; | 300 | struct pending_cmd *cmd; |
309 | int ret, up; | 301 | int err, up; |
310 | 302 | ||
311 | cp = (void *) data; | 303 | cp = (void *) data; |
312 | dev_id = get_unaligned_le16(&cp->index); | ||
313 | 304 | ||
314 | BT_DBG("request for hci%u", dev_id); | 305 | BT_DBG("request for hci%u", index); |
306 | |||
307 | if (len != sizeof(*cp)) | ||
308 | return cmd_status(sk, index, MGMT_OP_SET_POWERED, EINVAL); | ||
315 | 309 | ||
316 | hdev = hci_dev_get(dev_id); | 310 | hdev = hci_dev_get(index); |
317 | if (!hdev) | 311 | if (!hdev) |
318 | return cmd_status(sk, MGMT_OP_SET_POWERED, ENODEV); | 312 | return cmd_status(sk, index, MGMT_OP_SET_POWERED, ENODEV); |
319 | 313 | ||
320 | hci_dev_lock_bh(hdev); | 314 | hci_dev_lock_bh(hdev); |
321 | 315 | ||
322 | up = test_bit(HCI_UP, &hdev->flags); | 316 | up = test_bit(HCI_UP, &hdev->flags); |
323 | if ((cp->val && up) || (!cp->val && !up)) { | 317 | if ((cp->val && up) || (!cp->val && !up)) { |
324 | ret = cmd_status(sk, MGMT_OP_SET_POWERED, EALREADY); | 318 | err = cmd_status(sk, index, MGMT_OP_SET_POWERED, EALREADY); |
325 | goto failed; | 319 | goto failed; |
326 | } | 320 | } |
327 | 321 | ||
328 | if (mgmt_pending_find(MGMT_OP_SET_POWERED, dev_id)) { | 322 | if (mgmt_pending_find(MGMT_OP_SET_POWERED, index)) { |
329 | ret = cmd_status(sk, MGMT_OP_SET_POWERED, EBUSY); | 323 | err = cmd_status(sk, index, MGMT_OP_SET_POWERED, EBUSY); |
330 | goto failed; | 324 | goto failed; |
331 | } | 325 | } |
332 | 326 | ||
333 | ret = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, dev_id, data, len); | 327 | cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, index, data, len); |
334 | if (ret < 0) | 328 | if (!cmd) { |
329 | err = -ENOMEM; | ||
335 | goto failed; | 330 | goto failed; |
331 | } | ||
336 | 332 | ||
337 | if (cp->val) | 333 | if (cp->val) |
338 | queue_work(hdev->workqueue, &hdev->power_on); | 334 | queue_work(hdev->workqueue, &hdev->power_on); |
339 | else | 335 | else |
340 | queue_work(hdev->workqueue, &hdev->power_off); | 336 | queue_work(hdev->workqueue, &hdev->power_off); |
341 | 337 | ||
342 | ret = 0; | 338 | err = 0; |
343 | 339 | ||
344 | failed: | 340 | failed: |
345 | hci_dev_unlock_bh(hdev); | 341 | hci_dev_unlock_bh(hdev); |
346 | hci_dev_put(hdev); | 342 | hci_dev_put(hdev); |
347 | return ret; | 343 | return err; |
348 | } | 344 | } |
349 | 345 | ||
350 | static int set_discoverable(struct sock *sk, unsigned char *data, u16 len) | 346 | static int set_discoverable(struct sock *sk, u16 index, unsigned char *data, |
347 | u16 len) | ||
351 | { | 348 | { |
352 | struct mgmt_mode *cp; | 349 | struct mgmt_mode *cp; |
353 | struct hci_dev *hdev; | 350 | struct hci_dev *hdev; |
354 | u16 dev_id; | 351 | struct pending_cmd *cmd; |
355 | u8 scan; | 352 | u8 scan; |
356 | int err; | 353 | int err; |
357 | 354 | ||
358 | cp = (void *) data; | 355 | cp = (void *) data; |
359 | dev_id = get_unaligned_le16(&cp->index); | ||
360 | 356 | ||
361 | BT_DBG("request for hci%u", dev_id); | 357 | BT_DBG("request for hci%u", index); |
358 | |||
359 | if (len != sizeof(*cp)) | ||
360 | return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, EINVAL); | ||
362 | 361 | ||
363 | hdev = hci_dev_get(dev_id); | 362 | hdev = hci_dev_get(index); |
364 | if (!hdev) | 363 | if (!hdev) |
365 | return cmd_status(sk, MGMT_OP_SET_DISCOVERABLE, ENODEV); | 364 | return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, ENODEV); |
366 | 365 | ||
367 | hci_dev_lock_bh(hdev); | 366 | hci_dev_lock_bh(hdev); |
368 | 367 | ||
369 | if (!test_bit(HCI_UP, &hdev->flags)) { | 368 | if (!test_bit(HCI_UP, &hdev->flags)) { |
370 | err = cmd_status(sk, MGMT_OP_SET_DISCOVERABLE, ENETDOWN); | 369 | err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, ENETDOWN); |
371 | goto failed; | 370 | goto failed; |
372 | } | 371 | } |
373 | 372 | ||
374 | if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, dev_id) || | 373 | if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, index) || |
375 | mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, dev_id)) { | 374 | mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, index)) { |
376 | err = cmd_status(sk, MGMT_OP_SET_DISCOVERABLE, EBUSY); | 375 | err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, EBUSY); |
377 | goto failed; | 376 | goto failed; |
378 | } | 377 | } |
379 | 378 | ||
380 | if (cp->val == test_bit(HCI_ISCAN, &hdev->flags) && | 379 | if (cp->val == test_bit(HCI_ISCAN, &hdev->flags) && |
381 | test_bit(HCI_PSCAN, &hdev->flags)) { | 380 | test_bit(HCI_PSCAN, &hdev->flags)) { |
382 | err = cmd_status(sk, MGMT_OP_SET_DISCOVERABLE, EALREADY); | 381 | err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, EALREADY); |
383 | goto failed; | 382 | goto failed; |
384 | } | 383 | } |
385 | 384 | ||
386 | err = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, dev_id, data, len); | 385 | cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, index, data, len); |
387 | if (err < 0) | 386 | if (!cmd) { |
387 | err = -ENOMEM; | ||
388 | goto failed; | 388 | goto failed; |
389 | } | ||
389 | 390 | ||
390 | scan = SCAN_PAGE; | 391 | scan = SCAN_PAGE; |
391 | 392 | ||
@@ -394,7 +395,7 @@ static int set_discoverable(struct sock *sk, unsigned char *data, u16 len) | |||
394 | 395 | ||
395 | err = hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); | 396 | err = hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); |
396 | if (err < 0) | 397 | if (err < 0) |
397 | mgmt_pending_remove(MGMT_OP_SET_DISCOVERABLE, dev_id); | 398 | mgmt_pending_remove(cmd); |
398 | 399 | ||
399 | failed: | 400 | failed: |
400 | hci_dev_unlock_bh(hdev); | 401 | hci_dev_unlock_bh(hdev); |
@@ -403,44 +404,49 @@ failed: | |||
403 | return err; | 404 | return err; |
404 | } | 405 | } |
405 | 406 | ||
406 | static int set_connectable(struct sock *sk, unsigned char *data, u16 len) | 407 | static int set_connectable(struct sock *sk, u16 index, unsigned char *data, |
408 | u16 len) | ||
407 | { | 409 | { |
408 | struct mgmt_mode *cp; | 410 | struct mgmt_mode *cp; |
409 | struct hci_dev *hdev; | 411 | struct hci_dev *hdev; |
410 | u16 dev_id; | 412 | struct pending_cmd *cmd; |
411 | u8 scan; | 413 | u8 scan; |
412 | int err; | 414 | int err; |
413 | 415 | ||
414 | cp = (void *) data; | 416 | cp = (void *) data; |
415 | dev_id = get_unaligned_le16(&cp->index); | ||
416 | 417 | ||
417 | BT_DBG("request for hci%u", dev_id); | 418 | BT_DBG("request for hci%u", index); |
419 | |||
420 | if (len != sizeof(*cp)) | ||
421 | return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, EINVAL); | ||
418 | 422 | ||
419 | hdev = hci_dev_get(dev_id); | 423 | hdev = hci_dev_get(index); |
420 | if (!hdev) | 424 | if (!hdev) |
421 | return cmd_status(sk, MGMT_OP_SET_CONNECTABLE, ENODEV); | 425 | return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, ENODEV); |
422 | 426 | ||
423 | hci_dev_lock_bh(hdev); | 427 | hci_dev_lock_bh(hdev); |
424 | 428 | ||
425 | if (!test_bit(HCI_UP, &hdev->flags)) { | 429 | if (!test_bit(HCI_UP, &hdev->flags)) { |
426 | err = cmd_status(sk, MGMT_OP_SET_CONNECTABLE, ENETDOWN); | 430 | err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, ENETDOWN); |
427 | goto failed; | 431 | goto failed; |
428 | } | 432 | } |
429 | 433 | ||
430 | if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, dev_id) || | 434 | if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, index) || |
431 | mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, dev_id)) { | 435 | mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, index)) { |
432 | err = cmd_status(sk, MGMT_OP_SET_CONNECTABLE, EBUSY); | 436 | err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, EBUSY); |
433 | goto failed; | 437 | goto failed; |
434 | } | 438 | } |
435 | 439 | ||
436 | if (cp->val == test_bit(HCI_PSCAN, &hdev->flags)) { | 440 | if (cp->val == test_bit(HCI_PSCAN, &hdev->flags)) { |
437 | err = cmd_status(sk, MGMT_OP_SET_CONNECTABLE, EALREADY); | 441 | err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, EALREADY); |
438 | goto failed; | 442 | goto failed; |
439 | } | 443 | } |
440 | 444 | ||
441 | err = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, dev_id, data, len); | 445 | cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, index, data, len); |
442 | if (err < 0) | 446 | if (!cmd) { |
447 | err = -ENOMEM; | ||
443 | goto failed; | 448 | goto failed; |
449 | } | ||
444 | 450 | ||
445 | if (cp->val) | 451 | if (cp->val) |
446 | scan = SCAN_PAGE; | 452 | scan = SCAN_PAGE; |
@@ -449,7 +455,7 @@ static int set_connectable(struct sock *sk, unsigned char *data, u16 len) | |||
449 | 455 | ||
450 | err = hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); | 456 | err = hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); |
451 | if (err < 0) | 457 | if (err < 0) |
452 | mgmt_pending_remove(MGMT_OP_SET_CONNECTABLE, dev_id); | 458 | mgmt_pending_remove(cmd); |
453 | 459 | ||
454 | failed: | 460 | failed: |
455 | hci_dev_unlock_bh(hdev); | 461 | hci_dev_unlock_bh(hdev); |
@@ -458,7 +464,8 @@ failed: | |||
458 | return err; | 464 | return err; |
459 | } | 465 | } |
460 | 466 | ||
461 | static int mgmt_event(u16 event, void *data, u16 data_len, struct sock *skip_sk) | 467 | static int mgmt_event(u16 event, u16 index, void *data, u16 data_len, |
468 | struct sock *skip_sk) | ||
462 | { | 469 | { |
463 | struct sk_buff *skb; | 470 | struct sk_buff *skb; |
464 | struct mgmt_hdr *hdr; | 471 | struct mgmt_hdr *hdr; |
@@ -471,9 +478,11 @@ static int mgmt_event(u16 event, void *data, u16 data_len, struct sock *skip_sk) | |||
471 | 478 | ||
472 | hdr = (void *) skb_put(skb, sizeof(*hdr)); | 479 | hdr = (void *) skb_put(skb, sizeof(*hdr)); |
473 | hdr->opcode = cpu_to_le16(event); | 480 | hdr->opcode = cpu_to_le16(event); |
481 | hdr->index = cpu_to_le16(index); | ||
474 | hdr->len = cpu_to_le16(data_len); | 482 | hdr->len = cpu_to_le16(data_len); |
475 | 483 | ||
476 | memcpy(skb_put(skb, data_len), data, data_len); | 484 | if (data) |
485 | memcpy(skb_put(skb, data_len), data, data_len); | ||
477 | 486 | ||
478 | hci_send_to_sock(NULL, skb, skip_sk); | 487 | hci_send_to_sock(NULL, skb, skip_sk); |
479 | kfree_skb(skb); | 488 | kfree_skb(skb); |
@@ -485,27 +494,28 @@ static int send_mode_rsp(struct sock *sk, u16 opcode, u16 index, u8 val) | |||
485 | { | 494 | { |
486 | struct mgmt_mode rp; | 495 | struct mgmt_mode rp; |
487 | 496 | ||
488 | put_unaligned_le16(index, &rp.index); | ||
489 | rp.val = val; | 497 | rp.val = val; |
490 | 498 | ||
491 | return cmd_complete(sk, opcode, &rp, sizeof(rp)); | 499 | return cmd_complete(sk, index, opcode, &rp, sizeof(rp)); |
492 | } | 500 | } |
493 | 501 | ||
494 | static int set_pairable(struct sock *sk, unsigned char *data, u16 len) | 502 | static int set_pairable(struct sock *sk, u16 index, unsigned char *data, |
503 | u16 len) | ||
495 | { | 504 | { |
496 | struct mgmt_mode *cp, ev; | 505 | struct mgmt_mode *cp, ev; |
497 | struct hci_dev *hdev; | 506 | struct hci_dev *hdev; |
498 | u16 dev_id; | ||
499 | int err; | 507 | int err; |
500 | 508 | ||
501 | cp = (void *) data; | 509 | cp = (void *) data; |
502 | dev_id = get_unaligned_le16(&cp->index); | ||
503 | 510 | ||
504 | BT_DBG("request for hci%u", dev_id); | 511 | BT_DBG("request for hci%u", index); |
512 | |||
513 | if (len != sizeof(*cp)) | ||
514 | return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE, EINVAL); | ||
505 | 515 | ||
506 | hdev = hci_dev_get(dev_id); | 516 | hdev = hci_dev_get(index); |
507 | if (!hdev) | 517 | if (!hdev) |
508 | return cmd_status(sk, MGMT_OP_SET_PAIRABLE, ENODEV); | 518 | return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE, ENODEV); |
509 | 519 | ||
510 | hci_dev_lock_bh(hdev); | 520 | hci_dev_lock_bh(hdev); |
511 | 521 | ||
@@ -514,14 +524,13 @@ static int set_pairable(struct sock *sk, unsigned char *data, u16 len) | |||
514 | else | 524 | else |
515 | clear_bit(HCI_PAIRABLE, &hdev->flags); | 525 | clear_bit(HCI_PAIRABLE, &hdev->flags); |
516 | 526 | ||
517 | err = send_mode_rsp(sk, MGMT_OP_SET_PAIRABLE, dev_id, cp->val); | 527 | err = send_mode_rsp(sk, MGMT_OP_SET_PAIRABLE, index, cp->val); |
518 | if (err < 0) | 528 | if (err < 0) |
519 | goto failed; | 529 | goto failed; |
520 | 530 | ||
521 | put_unaligned_le16(dev_id, &ev.index); | ||
522 | ev.val = cp->val; | 531 | ev.val = cp->val; |
523 | 532 | ||
524 | err = mgmt_event(MGMT_EV_PAIRABLE, &ev, sizeof(ev), sk); | 533 | err = mgmt_event(MGMT_EV_PAIRABLE, index, &ev, sizeof(ev), sk); |
525 | 534 | ||
526 | failed: | 535 | failed: |
527 | hci_dev_unlock_bh(hdev); | 536 | hci_dev_unlock_bh(hdev); |
@@ -563,22 +572,23 @@ static int update_class(struct hci_dev *hdev) | |||
563 | return hci_send_cmd(hdev, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod); | 572 | return hci_send_cmd(hdev, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod); |
564 | } | 573 | } |
565 | 574 | ||
566 | static int add_uuid(struct sock *sk, unsigned char *data, u16 len) | 575 | static int add_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len) |
567 | { | 576 | { |
568 | struct mgmt_cp_add_uuid *cp; | 577 | struct mgmt_cp_add_uuid *cp; |
569 | struct hci_dev *hdev; | 578 | struct hci_dev *hdev; |
570 | struct bt_uuid *uuid; | 579 | struct bt_uuid *uuid; |
571 | u16 dev_id; | ||
572 | int err; | 580 | int err; |
573 | 581 | ||
574 | cp = (void *) data; | 582 | cp = (void *) data; |
575 | dev_id = get_unaligned_le16(&cp->index); | ||
576 | 583 | ||
577 | BT_DBG("request for hci%u", dev_id); | 584 | BT_DBG("request for hci%u", index); |
578 | 585 | ||
579 | hdev = hci_dev_get(dev_id); | 586 | if (len != sizeof(*cp)) |
587 | return cmd_status(sk, index, MGMT_OP_ADD_UUID, EINVAL); | ||
588 | |||
589 | hdev = hci_dev_get(index); | ||
580 | if (!hdev) | 590 | if (!hdev) |
581 | return cmd_status(sk, MGMT_OP_ADD_UUID, ENODEV); | 591 | return cmd_status(sk, index, MGMT_OP_ADD_UUID, ENODEV); |
582 | 592 | ||
583 | hci_dev_lock_bh(hdev); | 593 | hci_dev_lock_bh(hdev); |
584 | 594 | ||
@@ -597,7 +607,7 @@ static int add_uuid(struct sock *sk, unsigned char *data, u16 len) | |||
597 | if (err < 0) | 607 | if (err < 0) |
598 | goto failed; | 608 | goto failed; |
599 | 609 | ||
600 | err = cmd_complete(sk, MGMT_OP_ADD_UUID, &dev_id, sizeof(dev_id)); | 610 | err = cmd_complete(sk, index, MGMT_OP_ADD_UUID, NULL, 0); |
601 | 611 | ||
602 | failed: | 612 | failed: |
603 | hci_dev_unlock_bh(hdev); | 613 | hci_dev_unlock_bh(hdev); |
@@ -606,23 +616,24 @@ failed: | |||
606 | return err; | 616 | return err; |
607 | } | 617 | } |
608 | 618 | ||
609 | static int remove_uuid(struct sock *sk, unsigned char *data, u16 len) | 619 | static int remove_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len) |
610 | { | 620 | { |
611 | struct list_head *p, *n; | 621 | struct list_head *p, *n; |
612 | struct mgmt_cp_add_uuid *cp; | 622 | struct mgmt_cp_remove_uuid *cp; |
613 | struct hci_dev *hdev; | 623 | struct hci_dev *hdev; |
614 | u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | 624 | u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; |
615 | u16 dev_id; | ||
616 | int err, found; | 625 | int err, found; |
617 | 626 | ||
618 | cp = (void *) data; | 627 | cp = (void *) data; |
619 | dev_id = get_unaligned_le16(&cp->index); | ||
620 | 628 | ||
621 | BT_DBG("request for hci%u", dev_id); | 629 | BT_DBG("request for hci%u", index); |
630 | |||
631 | if (len != sizeof(*cp)) | ||
632 | return cmd_status(sk, index, MGMT_OP_REMOVE_UUID, EINVAL); | ||
622 | 633 | ||
623 | hdev = hci_dev_get(dev_id); | 634 | hdev = hci_dev_get(index); |
624 | if (!hdev) | 635 | if (!hdev) |
625 | return cmd_status(sk, MGMT_OP_REMOVE_UUID, ENODEV); | 636 | return cmd_status(sk, index, MGMT_OP_REMOVE_UUID, ENODEV); |
626 | 637 | ||
627 | hci_dev_lock_bh(hdev); | 638 | hci_dev_lock_bh(hdev); |
628 | 639 | ||
@@ -644,7 +655,7 @@ static int remove_uuid(struct sock *sk, unsigned char *data, u16 len) | |||
644 | } | 655 | } |
645 | 656 | ||
646 | if (found == 0) { | 657 | if (found == 0) { |
647 | err = cmd_status(sk, MGMT_OP_REMOVE_UUID, ENOENT); | 658 | err = cmd_status(sk, index, MGMT_OP_REMOVE_UUID, ENOENT); |
648 | goto unlock; | 659 | goto unlock; |
649 | } | 660 | } |
650 | 661 | ||
@@ -652,7 +663,7 @@ static int remove_uuid(struct sock *sk, unsigned char *data, u16 len) | |||
652 | if (err < 0) | 663 | if (err < 0) |
653 | goto unlock; | 664 | goto unlock; |
654 | 665 | ||
655 | err = cmd_complete(sk, MGMT_OP_REMOVE_UUID, &dev_id, sizeof(dev_id)); | 666 | err = cmd_complete(sk, index, MGMT_OP_REMOVE_UUID, NULL, 0); |
656 | 667 | ||
657 | unlock: | 668 | unlock: |
658 | hci_dev_unlock_bh(hdev); | 669 | hci_dev_unlock_bh(hdev); |
@@ -661,21 +672,23 @@ unlock: | |||
661 | return err; | 672 | return err; |
662 | } | 673 | } |
663 | 674 | ||
664 | static int set_dev_class(struct sock *sk, unsigned char *data, u16 len) | 675 | static int set_dev_class(struct sock *sk, u16 index, unsigned char *data, |
676 | u16 len) | ||
665 | { | 677 | { |
666 | struct hci_dev *hdev; | 678 | struct hci_dev *hdev; |
667 | struct mgmt_cp_set_dev_class *cp; | 679 | struct mgmt_cp_set_dev_class *cp; |
668 | u16 dev_id; | ||
669 | int err; | 680 | int err; |
670 | 681 | ||
671 | cp = (void *) data; | 682 | cp = (void *) data; |
672 | dev_id = get_unaligned_le16(&cp->index); | ||
673 | 683 | ||
674 | BT_DBG("request for hci%u", dev_id); | 684 | BT_DBG("request for hci%u", index); |
675 | 685 | ||
676 | hdev = hci_dev_get(dev_id); | 686 | if (len != sizeof(*cp)) |
687 | return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS, EINVAL); | ||
688 | |||
689 | hdev = hci_dev_get(index); | ||
677 | if (!hdev) | 690 | if (!hdev) |
678 | return cmd_status(sk, MGMT_OP_SET_DEV_CLASS, ENODEV); | 691 | return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS, ENODEV); |
679 | 692 | ||
680 | hci_dev_lock_bh(hdev); | 693 | hci_dev_lock_bh(hdev); |
681 | 694 | ||
@@ -685,8 +698,7 @@ static int set_dev_class(struct sock *sk, unsigned char *data, u16 len) | |||
685 | err = update_class(hdev); | 698 | err = update_class(hdev); |
686 | 699 | ||
687 | if (err == 0) | 700 | if (err == 0) |
688 | err = cmd_complete(sk, MGMT_OP_SET_DEV_CLASS, &dev_id, | 701 | err = cmd_complete(sk, index, MGMT_OP_SET_DEV_CLASS, NULL, 0); |
689 | sizeof(dev_id)); | ||
690 | 702 | ||
691 | hci_dev_unlock_bh(hdev); | 703 | hci_dev_unlock_bh(hdev); |
692 | hci_dev_put(hdev); | 704 | hci_dev_put(hdev); |
@@ -694,23 +706,25 @@ static int set_dev_class(struct sock *sk, unsigned char *data, u16 len) | |||
694 | return err; | 706 | return err; |
695 | } | 707 | } |
696 | 708 | ||
697 | static int set_service_cache(struct sock *sk, unsigned char *data, u16 len) | 709 | static int set_service_cache(struct sock *sk, u16 index, unsigned char *data, |
710 | u16 len) | ||
698 | { | 711 | { |
699 | struct hci_dev *hdev; | 712 | struct hci_dev *hdev; |
700 | struct mgmt_cp_set_service_cache *cp; | 713 | struct mgmt_cp_set_service_cache *cp; |
701 | u16 dev_id; | ||
702 | int err; | 714 | int err; |
703 | 715 | ||
704 | cp = (void *) data; | 716 | cp = (void *) data; |
705 | dev_id = get_unaligned_le16(&cp->index); | ||
706 | 717 | ||
707 | hdev = hci_dev_get(dev_id); | 718 | if (len != sizeof(*cp)) |
719 | return cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE, EINVAL); | ||
720 | |||
721 | hdev = hci_dev_get(index); | ||
708 | if (!hdev) | 722 | if (!hdev) |
709 | return cmd_status(sk, MGMT_OP_SET_SERVICE_CACHE, ENODEV); | 723 | return cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE, ENODEV); |
710 | 724 | ||
711 | hci_dev_lock_bh(hdev); | 725 | hci_dev_lock_bh(hdev); |
712 | 726 | ||
713 | BT_DBG("hci%u enable %d", dev_id, cp->enable); | 727 | BT_DBG("hci%u enable %d", index, cp->enable); |
714 | 728 | ||
715 | if (cp->enable) { | 729 | if (cp->enable) { |
716 | set_bit(HCI_SERVICE_CACHE, &hdev->flags); | 730 | set_bit(HCI_SERVICE_CACHE, &hdev->flags); |
@@ -721,8 +735,8 @@ static int set_service_cache(struct sock *sk, unsigned char *data, u16 len) | |||
721 | } | 735 | } |
722 | 736 | ||
723 | if (err == 0) | 737 | if (err == 0) |
724 | err = cmd_complete(sk, MGMT_OP_SET_SERVICE_CACHE, &dev_id, | 738 | err = cmd_complete(sk, index, MGMT_OP_SET_SERVICE_CACHE, NULL, |
725 | sizeof(dev_id)); | 739 | 0); |
726 | 740 | ||
727 | hci_dev_unlock_bh(hdev); | 741 | hci_dev_unlock_bh(hdev); |
728 | hci_dev_put(hdev); | 742 | hci_dev_put(hdev); |
@@ -730,15 +744,18 @@ static int set_service_cache(struct sock *sk, unsigned char *data, u16 len) | |||
730 | return err; | 744 | return err; |
731 | } | 745 | } |
732 | 746 | ||
733 | static int load_keys(struct sock *sk, unsigned char *data, u16 len) | 747 | static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len) |
734 | { | 748 | { |
735 | struct hci_dev *hdev; | 749 | struct hci_dev *hdev; |
736 | struct mgmt_cp_load_keys *cp; | 750 | struct mgmt_cp_load_keys *cp; |
737 | u16 dev_id, key_count, expected_len; | 751 | u16 key_count, expected_len; |
738 | int i; | 752 | int i; |
739 | 753 | ||
740 | cp = (void *) data; | 754 | cp = (void *) data; |
741 | dev_id = get_unaligned_le16(&cp->index); | 755 | |
756 | if (len < sizeof(*cp)) | ||
757 | return -EINVAL; | ||
758 | |||
742 | key_count = get_unaligned_le16(&cp->key_count); | 759 | key_count = get_unaligned_le16(&cp->key_count); |
743 | 760 | ||
744 | expected_len = sizeof(*cp) + key_count * sizeof(struct mgmt_key_info); | 761 | expected_len = sizeof(*cp) + key_count * sizeof(struct mgmt_key_info); |
@@ -748,11 +765,11 @@ static int load_keys(struct sock *sk, unsigned char *data, u16 len) | |||
748 | return -EINVAL; | 765 | return -EINVAL; |
749 | } | 766 | } |
750 | 767 | ||
751 | hdev = hci_dev_get(dev_id); | 768 | hdev = hci_dev_get(index); |
752 | if (!hdev) | 769 | if (!hdev) |
753 | return cmd_status(sk, MGMT_OP_LOAD_KEYS, ENODEV); | 770 | return cmd_status(sk, index, MGMT_OP_LOAD_KEYS, ENODEV); |
754 | 771 | ||
755 | BT_DBG("hci%u debug_keys %u key_count %u", dev_id, cp->debug_keys, | 772 | BT_DBG("hci%u debug_keys %u key_count %u", index, cp->debug_keys, |
756 | key_count); | 773 | key_count); |
757 | 774 | ||
758 | hci_dev_lock_bh(hdev); | 775 | hci_dev_lock_bh(hdev); |
@@ -779,26 +796,27 @@ static int load_keys(struct sock *sk, unsigned char *data, u16 len) | |||
779 | return 0; | 796 | return 0; |
780 | } | 797 | } |
781 | 798 | ||
782 | static int remove_key(struct sock *sk, unsigned char *data, u16 len) | 799 | static int remove_key(struct sock *sk, u16 index, unsigned char *data, u16 len) |
783 | { | 800 | { |
784 | struct hci_dev *hdev; | 801 | struct hci_dev *hdev; |
785 | struct mgmt_cp_remove_key *cp; | 802 | struct mgmt_cp_remove_key *cp; |
786 | struct hci_conn *conn; | 803 | struct hci_conn *conn; |
787 | u16 dev_id; | ||
788 | int err; | 804 | int err; |
789 | 805 | ||
790 | cp = (void *) data; | 806 | cp = (void *) data; |
791 | dev_id = get_unaligned_le16(&cp->index); | ||
792 | 807 | ||
793 | hdev = hci_dev_get(dev_id); | 808 | if (len != sizeof(*cp)) |
809 | return cmd_status(sk, index, MGMT_OP_REMOVE_KEY, EINVAL); | ||
810 | |||
811 | hdev = hci_dev_get(index); | ||
794 | if (!hdev) | 812 | if (!hdev) |
795 | return cmd_status(sk, MGMT_OP_REMOVE_KEY, ENODEV); | 813 | return cmd_status(sk, index, MGMT_OP_REMOVE_KEY, ENODEV); |
796 | 814 | ||
797 | hci_dev_lock_bh(hdev); | 815 | hci_dev_lock_bh(hdev); |
798 | 816 | ||
799 | err = hci_remove_link_key(hdev, &cp->bdaddr); | 817 | err = hci_remove_link_key(hdev, &cp->bdaddr); |
800 | if (err < 0) { | 818 | if (err < 0) { |
801 | err = cmd_status(sk, MGMT_OP_REMOVE_KEY, -err); | 819 | err = cmd_status(sk, index, MGMT_OP_REMOVE_KEY, -err); |
802 | goto unlock; | 820 | goto unlock; |
803 | } | 821 | } |
804 | 822 | ||
@@ -823,52 +841,56 @@ unlock: | |||
823 | return err; | 841 | return err; |
824 | } | 842 | } |
825 | 843 | ||
826 | static int disconnect(struct sock *sk, unsigned char *data, u16 len) | 844 | static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len) |
827 | { | 845 | { |
828 | struct hci_dev *hdev; | 846 | struct hci_dev *hdev; |
829 | struct mgmt_cp_disconnect *cp; | 847 | struct mgmt_cp_disconnect *cp; |
830 | struct hci_cp_disconnect dc; | 848 | struct hci_cp_disconnect dc; |
849 | struct pending_cmd *cmd; | ||
831 | struct hci_conn *conn; | 850 | struct hci_conn *conn; |
832 | u16 dev_id; | ||
833 | int err; | 851 | int err; |
834 | 852 | ||
835 | BT_DBG(""); | 853 | BT_DBG(""); |
836 | 854 | ||
837 | cp = (void *) data; | 855 | cp = (void *) data; |
838 | dev_id = get_unaligned_le16(&cp->index); | ||
839 | 856 | ||
840 | hdev = hci_dev_get(dev_id); | 857 | if (len != sizeof(*cp)) |
858 | return cmd_status(sk, index, MGMT_OP_DISCONNECT, EINVAL); | ||
859 | |||
860 | hdev = hci_dev_get(index); | ||
841 | if (!hdev) | 861 | if (!hdev) |
842 | return cmd_status(sk, MGMT_OP_DISCONNECT, ENODEV); | 862 | return cmd_status(sk, index, MGMT_OP_DISCONNECT, ENODEV); |
843 | 863 | ||
844 | hci_dev_lock_bh(hdev); | 864 | hci_dev_lock_bh(hdev); |
845 | 865 | ||
846 | if (!test_bit(HCI_UP, &hdev->flags)) { | 866 | if (!test_bit(HCI_UP, &hdev->flags)) { |
847 | err = cmd_status(sk, MGMT_OP_DISCONNECT, ENETDOWN); | 867 | err = cmd_status(sk, index, MGMT_OP_DISCONNECT, ENETDOWN); |
848 | goto failed; | 868 | goto failed; |
849 | } | 869 | } |
850 | 870 | ||
851 | if (mgmt_pending_find(MGMT_OP_DISCONNECT, dev_id)) { | 871 | if (mgmt_pending_find(MGMT_OP_DISCONNECT, index)) { |
852 | err = cmd_status(sk, MGMT_OP_DISCONNECT, EBUSY); | 872 | err = cmd_status(sk, index, MGMT_OP_DISCONNECT, EBUSY); |
853 | goto failed; | 873 | goto failed; |
854 | } | 874 | } |
855 | 875 | ||
856 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); | 876 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); |
857 | if (!conn) { | 877 | if (!conn) { |
858 | err = cmd_status(sk, MGMT_OP_DISCONNECT, ENOTCONN); | 878 | err = cmd_status(sk, index, MGMT_OP_DISCONNECT, ENOTCONN); |
859 | goto failed; | 879 | goto failed; |
860 | } | 880 | } |
861 | 881 | ||
862 | err = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, dev_id, data, len); | 882 | cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, index, data, len); |
863 | if (err < 0) | 883 | if (!cmd) { |
884 | err = -ENOMEM; | ||
864 | goto failed; | 885 | goto failed; |
886 | } | ||
865 | 887 | ||
866 | put_unaligned_le16(conn->handle, &dc.handle); | 888 | put_unaligned_le16(conn->handle, &dc.handle); |
867 | dc.reason = 0x13; /* Remote User Terminated Connection */ | 889 | dc.reason = 0x13; /* Remote User Terminated Connection */ |
868 | 890 | ||
869 | err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc); | 891 | err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc); |
870 | if (err < 0) | 892 | if (err < 0) |
871 | mgmt_pending_remove(MGMT_OP_DISCONNECT, dev_id); | 893 | mgmt_pending_remove(cmd); |
872 | 894 | ||
873 | failed: | 895 | failed: |
874 | hci_dev_unlock_bh(hdev); | 896 | hci_dev_unlock_bh(hdev); |
@@ -877,24 +899,20 @@ failed: | |||
877 | return err; | 899 | return err; |
878 | } | 900 | } |
879 | 901 | ||
880 | static int get_connections(struct sock *sk, unsigned char *data, u16 len) | 902 | static int get_connections(struct sock *sk, u16 index) |
881 | { | 903 | { |
882 | struct mgmt_cp_get_connections *cp; | ||
883 | struct mgmt_rp_get_connections *rp; | 904 | struct mgmt_rp_get_connections *rp; |
884 | struct hci_dev *hdev; | 905 | struct hci_dev *hdev; |
885 | struct list_head *p; | 906 | struct list_head *p; |
886 | size_t rp_len; | 907 | size_t rp_len; |
887 | u16 dev_id, count; | 908 | u16 count; |
888 | int i, err; | 909 | int i, err; |
889 | 910 | ||
890 | BT_DBG(""); | 911 | BT_DBG(""); |
891 | 912 | ||
892 | cp = (void *) data; | 913 | hdev = hci_dev_get(index); |
893 | dev_id = get_unaligned_le16(&cp->index); | ||
894 | |||
895 | hdev = hci_dev_get(dev_id); | ||
896 | if (!hdev) | 914 | if (!hdev) |
897 | return cmd_status(sk, MGMT_OP_GET_CONNECTIONS, ENODEV); | 915 | return cmd_status(sk, index, MGMT_OP_GET_CONNECTIONS, ENODEV); |
898 | 916 | ||
899 | hci_dev_lock_bh(hdev); | 917 | hci_dev_lock_bh(hdev); |
900 | 918 | ||
@@ -910,7 +928,6 @@ static int get_connections(struct sock *sk, unsigned char *data, u16 len) | |||
910 | goto unlock; | 928 | goto unlock; |
911 | } | 929 | } |
912 | 930 | ||
913 | put_unaligned_le16(dev_id, &rp->index); | ||
914 | put_unaligned_le16(count, &rp->conn_count); | 931 | put_unaligned_le16(count, &rp->conn_count); |
915 | 932 | ||
916 | read_lock(&hci_dev_list_lock); | 933 | read_lock(&hci_dev_list_lock); |
@@ -924,7 +941,7 @@ static int get_connections(struct sock *sk, unsigned char *data, u16 len) | |||
924 | 941 | ||
925 | read_unlock(&hci_dev_list_lock); | 942 | read_unlock(&hci_dev_list_lock); |
926 | 943 | ||
927 | err = cmd_complete(sk, MGMT_OP_GET_CONNECTIONS, rp, rp_len); | 944 | err = cmd_complete(sk, index, MGMT_OP_GET_CONNECTIONS, rp, rp_len); |
928 | 945 | ||
929 | unlock: | 946 | unlock: |
930 | kfree(rp); | 947 | kfree(rp); |
@@ -933,33 +950,38 @@ unlock: | |||
933 | return err; | 950 | return err; |
934 | } | 951 | } |
935 | 952 | ||
936 | static int pin_code_reply(struct sock *sk, unsigned char *data, u16 len) | 953 | static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data, |
954 | u16 len) | ||
937 | { | 955 | { |
938 | struct hci_dev *hdev; | 956 | struct hci_dev *hdev; |
939 | struct mgmt_cp_pin_code_reply *cp; | 957 | struct mgmt_cp_pin_code_reply *cp; |
940 | struct hci_cp_pin_code_reply reply; | 958 | struct hci_cp_pin_code_reply reply; |
941 | u16 dev_id; | 959 | struct pending_cmd *cmd; |
942 | int err; | 960 | int err; |
943 | 961 | ||
944 | BT_DBG(""); | 962 | BT_DBG(""); |
945 | 963 | ||
946 | cp = (void *) data; | 964 | cp = (void *) data; |
947 | dev_id = get_unaligned_le16(&cp->index); | ||
948 | 965 | ||
949 | hdev = hci_dev_get(dev_id); | 966 | if (len != sizeof(*cp)) |
967 | return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, EINVAL); | ||
968 | |||
969 | hdev = hci_dev_get(index); | ||
950 | if (!hdev) | 970 | if (!hdev) |
951 | return cmd_status(sk, MGMT_OP_DISCONNECT, ENODEV); | 971 | return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENODEV); |
952 | 972 | ||
953 | hci_dev_lock_bh(hdev); | 973 | hci_dev_lock_bh(hdev); |
954 | 974 | ||
955 | if (!test_bit(HCI_UP, &hdev->flags)) { | 975 | if (!test_bit(HCI_UP, &hdev->flags)) { |
956 | err = cmd_status(sk, MGMT_OP_PIN_CODE_REPLY, ENETDOWN); | 976 | err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENETDOWN); |
957 | goto failed; | 977 | goto failed; |
958 | } | 978 | } |
959 | 979 | ||
960 | err = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, dev_id, data, len); | 980 | cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, index, data, len); |
961 | if (err < 0) | 981 | if (!cmd) { |
982 | err = -ENOMEM; | ||
962 | goto failed; | 983 | goto failed; |
984 | } | ||
963 | 985 | ||
964 | bacpy(&reply.bdaddr, &cp->bdaddr); | 986 | bacpy(&reply.bdaddr, &cp->bdaddr); |
965 | reply.pin_len = cp->pin_len; | 987 | reply.pin_len = cp->pin_len; |
@@ -967,7 +989,7 @@ static int pin_code_reply(struct sock *sk, unsigned char *data, u16 len) | |||
967 | 989 | ||
968 | err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply); | 990 | err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply); |
969 | if (err < 0) | 991 | if (err < 0) |
970 | mgmt_pending_remove(MGMT_OP_PIN_CODE_REPLY, dev_id); | 992 | mgmt_pending_remove(cmd); |
971 | 993 | ||
972 | failed: | 994 | failed: |
973 | hci_dev_unlock_bh(hdev); | 995 | hci_dev_unlock_bh(hdev); |
@@ -976,38 +998,46 @@ failed: | |||
976 | return err; | 998 | return err; |
977 | } | 999 | } |
978 | 1000 | ||
979 | static int pin_code_neg_reply(struct sock *sk, unsigned char *data, u16 len) | 1001 | static int pin_code_neg_reply(struct sock *sk, u16 index, unsigned char *data, |
1002 | u16 len) | ||
980 | { | 1003 | { |
981 | struct hci_dev *hdev; | 1004 | struct hci_dev *hdev; |
982 | struct mgmt_cp_pin_code_neg_reply *cp; | 1005 | struct mgmt_cp_pin_code_neg_reply *cp; |
983 | u16 dev_id; | 1006 | struct pending_cmd *cmd; |
984 | int err; | 1007 | int err; |
985 | 1008 | ||
986 | BT_DBG(""); | 1009 | BT_DBG(""); |
987 | 1010 | ||
988 | cp = (void *) data; | 1011 | cp = (void *) data; |
989 | dev_id = get_unaligned_le16(&cp->index); | ||
990 | 1012 | ||
991 | hdev = hci_dev_get(dev_id); | 1013 | if (len != sizeof(*cp)) |
1014 | return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY, | ||
1015 | EINVAL); | ||
1016 | |||
1017 | hdev = hci_dev_get(index); | ||
992 | if (!hdev) | 1018 | if (!hdev) |
993 | return cmd_status(sk, MGMT_OP_PIN_CODE_NEG_REPLY, ENODEV); | 1019 | return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY, |
1020 | ENODEV); | ||
994 | 1021 | ||
995 | hci_dev_lock_bh(hdev); | 1022 | hci_dev_lock_bh(hdev); |
996 | 1023 | ||
997 | if (!test_bit(HCI_UP, &hdev->flags)) { | 1024 | if (!test_bit(HCI_UP, &hdev->flags)) { |
998 | err = cmd_status(sk, MGMT_OP_PIN_CODE_NEG_REPLY, ENETDOWN); | 1025 | err = cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY, |
1026 | ENETDOWN); | ||
999 | goto failed; | 1027 | goto failed; |
1000 | } | 1028 | } |
1001 | 1029 | ||
1002 | err = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, dev_id, | 1030 | cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, index, |
1003 | data, len); | 1031 | data, len); |
1004 | if (err < 0) | 1032 | if (!cmd) { |
1033 | err = -ENOMEM; | ||
1005 | goto failed; | 1034 | goto failed; |
1035 | } | ||
1006 | 1036 | ||
1007 | err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, sizeof(bdaddr_t), | 1037 | err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, sizeof(cp->bdaddr), |
1008 | &cp->bdaddr); | 1038 | &cp->bdaddr); |
1009 | if (err < 0) | 1039 | if (err < 0) |
1010 | mgmt_pending_remove(MGMT_OP_PIN_CODE_NEG_REPLY, dev_id); | 1040 | mgmt_pending_remove(cmd); |
1011 | 1041 | ||
1012 | failed: | 1042 | failed: |
1013 | hci_dev_unlock_bh(hdev); | 1043 | hci_dev_unlock_bh(hdev); |
@@ -1016,40 +1046,217 @@ failed: | |||
1016 | return err; | 1046 | return err; |
1017 | } | 1047 | } |
1018 | 1048 | ||
1019 | static int set_io_capability(struct sock *sk, unsigned char *data, u16 len) | 1049 | static int set_io_capability(struct sock *sk, u16 index, unsigned char *data, |
1050 | u16 len) | ||
1020 | { | 1051 | { |
1021 | struct hci_dev *hdev; | 1052 | struct hci_dev *hdev; |
1022 | struct mgmt_cp_set_io_capability *cp; | 1053 | struct mgmt_cp_set_io_capability *cp; |
1023 | u16 dev_id; | ||
1024 | 1054 | ||
1025 | BT_DBG(""); | 1055 | BT_DBG(""); |
1026 | 1056 | ||
1027 | cp = (void *) data; | 1057 | cp = (void *) data; |
1028 | dev_id = get_unaligned_le16(&cp->index); | ||
1029 | 1058 | ||
1030 | hdev = hci_dev_get(dev_id); | 1059 | if (len != sizeof(*cp)) |
1060 | return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY, EINVAL); | ||
1061 | |||
1062 | hdev = hci_dev_get(index); | ||
1031 | if (!hdev) | 1063 | if (!hdev) |
1032 | return cmd_status(sk, MGMT_OP_SET_IO_CAPABILITY, ENODEV); | 1064 | return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY, ENODEV); |
1033 | 1065 | ||
1034 | hci_dev_lock_bh(hdev); | 1066 | hci_dev_lock_bh(hdev); |
1035 | 1067 | ||
1036 | hdev->io_capability = cp->io_capability; | 1068 | hdev->io_capability = cp->io_capability; |
1037 | 1069 | ||
1038 | BT_DBG("%s IO capability set to 0x%02x", hdev->name, | 1070 | BT_DBG("%s IO capability set to 0x%02x", hdev->name, |
1039 | hdev->io_capability); | 1071 | hdev->io_capability); |
1040 | 1072 | ||
1041 | hci_dev_unlock_bh(hdev); | 1073 | hci_dev_unlock_bh(hdev); |
1042 | hci_dev_put(hdev); | 1074 | hci_dev_put(hdev); |
1043 | 1075 | ||
1044 | return cmd_complete(sk, MGMT_OP_SET_IO_CAPABILITY, | 1076 | return cmd_complete(sk, index, MGMT_OP_SET_IO_CAPABILITY, NULL, 0); |
1045 | &dev_id, sizeof(dev_id)); | 1077 | } |
1078 | |||
1079 | static inline struct pending_cmd *find_pairing(struct hci_conn *conn) | ||
1080 | { | ||
1081 | struct hci_dev *hdev = conn->hdev; | ||
1082 | struct list_head *p; | ||
1083 | |||
1084 | list_for_each(p, &cmd_list) { | ||
1085 | struct pending_cmd *cmd; | ||
1086 | |||
1087 | cmd = list_entry(p, struct pending_cmd, list); | ||
1088 | |||
1089 | if (cmd->opcode != MGMT_OP_PAIR_DEVICE) | ||
1090 | continue; | ||
1091 | |||
1092 | if (cmd->index != hdev->id) | ||
1093 | continue; | ||
1094 | |||
1095 | if (cmd->user_data != conn) | ||
1096 | continue; | ||
1097 | |||
1098 | return cmd; | ||
1099 | } | ||
1100 | |||
1101 | return NULL; | ||
1102 | } | ||
1103 | |||
1104 | static void pairing_complete(struct pending_cmd *cmd, u8 status) | ||
1105 | { | ||
1106 | struct mgmt_rp_pair_device rp; | ||
1107 | struct hci_conn *conn = cmd->user_data; | ||
1108 | |||
1109 | bacpy(&rp.bdaddr, &conn->dst); | ||
1110 | rp.status = status; | ||
1111 | |||
1112 | cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, &rp, sizeof(rp)); | ||
1113 | |||
1114 | /* So we don't get further callbacks for this connection */ | ||
1115 | conn->connect_cfm_cb = NULL; | ||
1116 | conn->security_cfm_cb = NULL; | ||
1117 | conn->disconn_cfm_cb = NULL; | ||
1118 | |||
1119 | hci_conn_put(conn); | ||
1120 | |||
1121 | mgmt_pending_remove(cmd); | ||
1122 | } | ||
1123 | |||
1124 | static void pairing_complete_cb(struct hci_conn *conn, u8 status) | ||
1125 | { | ||
1126 | struct pending_cmd *cmd; | ||
1127 | |||
1128 | BT_DBG("status %u", status); | ||
1129 | |||
1130 | cmd = find_pairing(conn); | ||
1131 | if (!cmd) { | ||
1132 | BT_DBG("Unable to find a pending command"); | ||
1133 | return; | ||
1134 | } | ||
1135 | |||
1136 | pairing_complete(cmd, status); | ||
1137 | } | ||
1138 | |||
1139 | static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len) | ||
1140 | { | ||
1141 | struct hci_dev *hdev; | ||
1142 | struct mgmt_cp_pair_device *cp; | ||
1143 | struct pending_cmd *cmd; | ||
1144 | u8 sec_level, auth_type; | ||
1145 | struct hci_conn *conn; | ||
1146 | int err; | ||
1147 | |||
1148 | BT_DBG(""); | ||
1149 | |||
1150 | cp = (void *) data; | ||
1151 | |||
1152 | if (len != sizeof(*cp)) | ||
1153 | return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, EINVAL); | ||
1154 | |||
1155 | hdev = hci_dev_get(index); | ||
1156 | if (!hdev) | ||
1157 | return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, ENODEV); | ||
1158 | |||
1159 | hci_dev_lock_bh(hdev); | ||
1160 | |||
1161 | if (cp->io_cap == 0x03) { | ||
1162 | sec_level = BT_SECURITY_MEDIUM; | ||
1163 | auth_type = HCI_AT_DEDICATED_BONDING; | ||
1164 | } else { | ||
1165 | sec_level = BT_SECURITY_HIGH; | ||
1166 | auth_type = HCI_AT_DEDICATED_BONDING_MITM; | ||
1167 | } | ||
1168 | |||
1169 | conn = hci_connect(hdev, ACL_LINK, &cp->bdaddr, sec_level, auth_type); | ||
1170 | if (IS_ERR(conn)) { | ||
1171 | err = PTR_ERR(conn); | ||
1172 | goto unlock; | ||
1173 | } | ||
1174 | |||
1175 | if (conn->connect_cfm_cb) { | ||
1176 | hci_conn_put(conn); | ||
1177 | err = cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, EBUSY); | ||
1178 | goto unlock; | ||
1179 | } | ||
1180 | |||
1181 | cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, index, data, len); | ||
1182 | if (!cmd) { | ||
1183 | err = -ENOMEM; | ||
1184 | hci_conn_put(conn); | ||
1185 | goto unlock; | ||
1186 | } | ||
1187 | |||
1188 | conn->connect_cfm_cb = pairing_complete_cb; | ||
1189 | conn->security_cfm_cb = pairing_complete_cb; | ||
1190 | conn->disconn_cfm_cb = pairing_complete_cb; | ||
1191 | conn->io_capability = cp->io_cap; | ||
1192 | cmd->user_data = conn; | ||
1193 | |||
1194 | if (conn->state == BT_CONNECTED && | ||
1195 | hci_conn_security(conn, sec_level, auth_type)) | ||
1196 | pairing_complete(cmd, 0); | ||
1197 | |||
1198 | err = 0; | ||
1199 | |||
1200 | unlock: | ||
1201 | hci_dev_unlock_bh(hdev); | ||
1202 | hci_dev_put(hdev); | ||
1203 | |||
1204 | return err; | ||
1205 | } | ||
1206 | |||
1207 | static int user_confirm_reply(struct sock *sk, u16 index, unsigned char *data, | ||
1208 | u16 len, int success) | ||
1209 | { | ||
1210 | struct mgmt_cp_user_confirm_reply *cp = (void *) data; | ||
1211 | u16 mgmt_op, hci_op; | ||
1212 | struct pending_cmd *cmd; | ||
1213 | struct hci_dev *hdev; | ||
1214 | int err; | ||
1215 | |||
1216 | BT_DBG(""); | ||
1217 | |||
1218 | if (success) { | ||
1219 | mgmt_op = MGMT_OP_USER_CONFIRM_REPLY; | ||
1220 | hci_op = HCI_OP_USER_CONFIRM_REPLY; | ||
1221 | } else { | ||
1222 | mgmt_op = MGMT_OP_USER_CONFIRM_NEG_REPLY; | ||
1223 | hci_op = HCI_OP_USER_CONFIRM_NEG_REPLY; | ||
1224 | } | ||
1225 | |||
1226 | if (len != sizeof(*cp)) | ||
1227 | return cmd_status(sk, index, mgmt_op, EINVAL); | ||
1228 | |||
1229 | hdev = hci_dev_get(index); | ||
1230 | if (!hdev) | ||
1231 | return cmd_status(sk, index, mgmt_op, ENODEV); | ||
1232 | |||
1233 | if (!test_bit(HCI_UP, &hdev->flags)) { | ||
1234 | err = cmd_status(sk, index, mgmt_op, ENETDOWN); | ||
1235 | goto failed; | ||
1236 | } | ||
1237 | |||
1238 | cmd = mgmt_pending_add(sk, mgmt_op, index, data, len); | ||
1239 | if (!cmd) { | ||
1240 | err = -ENOMEM; | ||
1241 | goto failed; | ||
1242 | } | ||
1243 | |||
1244 | err = hci_send_cmd(hdev, hci_op, sizeof(cp->bdaddr), &cp->bdaddr); | ||
1245 | if (err < 0) | ||
1246 | mgmt_pending_remove(cmd); | ||
1247 | |||
1248 | failed: | ||
1249 | hci_dev_unlock_bh(hdev); | ||
1250 | hci_dev_put(hdev); | ||
1251 | |||
1252 | return err; | ||
1046 | } | 1253 | } |
1047 | 1254 | ||
1048 | int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) | 1255 | int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) |
1049 | { | 1256 | { |
1050 | unsigned char *buf; | 1257 | unsigned char *buf; |
1051 | struct mgmt_hdr *hdr; | 1258 | struct mgmt_hdr *hdr; |
1052 | u16 opcode, len; | 1259 | u16 opcode, index, len; |
1053 | int err; | 1260 | int err; |
1054 | 1261 | ||
1055 | BT_DBG("got %zu bytes", msglen); | 1262 | BT_DBG("got %zu bytes", msglen); |
@@ -1068,6 +1275,7 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) | |||
1068 | 1275 | ||
1069 | hdr = (struct mgmt_hdr *) buf; | 1276 | hdr = (struct mgmt_hdr *) buf; |
1070 | opcode = get_unaligned_le16(&hdr->opcode); | 1277 | opcode = get_unaligned_le16(&hdr->opcode); |
1278 | index = get_unaligned_le16(&hdr->index); | ||
1071 | len = get_unaligned_le16(&hdr->len); | 1279 | len = get_unaligned_le16(&hdr->len); |
1072 | 1280 | ||
1073 | if (len != msglen - sizeof(*hdr)) { | 1281 | if (len != msglen - sizeof(*hdr)) { |
@@ -1083,56 +1291,65 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) | |||
1083 | err = read_index_list(sk); | 1291 | err = read_index_list(sk); |
1084 | break; | 1292 | break; |
1085 | case MGMT_OP_READ_INFO: | 1293 | case MGMT_OP_READ_INFO: |
1086 | err = read_controller_info(sk, buf + sizeof(*hdr), len); | 1294 | err = read_controller_info(sk, index); |
1087 | break; | 1295 | break; |
1088 | case MGMT_OP_SET_POWERED: | 1296 | case MGMT_OP_SET_POWERED: |
1089 | err = set_powered(sk, buf + sizeof(*hdr), len); | 1297 | err = set_powered(sk, index, buf + sizeof(*hdr), len); |
1090 | break; | 1298 | break; |
1091 | case MGMT_OP_SET_DISCOVERABLE: | 1299 | case MGMT_OP_SET_DISCOVERABLE: |
1092 | err = set_discoverable(sk, buf + sizeof(*hdr), len); | 1300 | err = set_discoverable(sk, index, buf + sizeof(*hdr), len); |
1093 | break; | 1301 | break; |
1094 | case MGMT_OP_SET_CONNECTABLE: | 1302 | case MGMT_OP_SET_CONNECTABLE: |
1095 | err = set_connectable(sk, buf + sizeof(*hdr), len); | 1303 | err = set_connectable(sk, index, buf + sizeof(*hdr), len); |
1096 | break; | 1304 | break; |
1097 | case MGMT_OP_SET_PAIRABLE: | 1305 | case MGMT_OP_SET_PAIRABLE: |
1098 | err = set_pairable(sk, buf + sizeof(*hdr), len); | 1306 | err = set_pairable(sk, index, buf + sizeof(*hdr), len); |
1099 | break; | 1307 | break; |
1100 | case MGMT_OP_ADD_UUID: | 1308 | case MGMT_OP_ADD_UUID: |
1101 | err = add_uuid(sk, buf + sizeof(*hdr), len); | 1309 | err = add_uuid(sk, index, buf + sizeof(*hdr), len); |
1102 | break; | 1310 | break; |
1103 | case MGMT_OP_REMOVE_UUID: | 1311 | case MGMT_OP_REMOVE_UUID: |
1104 | err = remove_uuid(sk, buf + sizeof(*hdr), len); | 1312 | err = remove_uuid(sk, index, buf + sizeof(*hdr), len); |
1105 | break; | 1313 | break; |
1106 | case MGMT_OP_SET_DEV_CLASS: | 1314 | case MGMT_OP_SET_DEV_CLASS: |
1107 | err = set_dev_class(sk, buf + sizeof(*hdr), len); | 1315 | err = set_dev_class(sk, index, buf + sizeof(*hdr), len); |
1108 | break; | 1316 | break; |
1109 | case MGMT_OP_SET_SERVICE_CACHE: | 1317 | case MGMT_OP_SET_SERVICE_CACHE: |
1110 | err = set_service_cache(sk, buf + sizeof(*hdr), len); | 1318 | err = set_service_cache(sk, index, buf + sizeof(*hdr), len); |
1111 | break; | 1319 | break; |
1112 | case MGMT_OP_LOAD_KEYS: | 1320 | case MGMT_OP_LOAD_KEYS: |
1113 | err = load_keys(sk, buf + sizeof(*hdr), len); | 1321 | err = load_keys(sk, index, buf + sizeof(*hdr), len); |
1114 | break; | 1322 | break; |
1115 | case MGMT_OP_REMOVE_KEY: | 1323 | case MGMT_OP_REMOVE_KEY: |
1116 | err = remove_key(sk, buf + sizeof(*hdr), len); | 1324 | err = remove_key(sk, index, buf + sizeof(*hdr), len); |
1117 | break; | 1325 | break; |
1118 | case MGMT_OP_DISCONNECT: | 1326 | case MGMT_OP_DISCONNECT: |
1119 | err = disconnect(sk, buf + sizeof(*hdr), len); | 1327 | err = disconnect(sk, index, buf + sizeof(*hdr), len); |
1120 | break; | 1328 | break; |
1121 | case MGMT_OP_GET_CONNECTIONS: | 1329 | case MGMT_OP_GET_CONNECTIONS: |
1122 | err = get_connections(sk, buf + sizeof(*hdr), len); | 1330 | err = get_connections(sk, index); |
1123 | break; | 1331 | break; |
1124 | case MGMT_OP_PIN_CODE_REPLY: | 1332 | case MGMT_OP_PIN_CODE_REPLY: |
1125 | err = pin_code_reply(sk, buf + sizeof(*hdr), len); | 1333 | err = pin_code_reply(sk, index, buf + sizeof(*hdr), len); |
1126 | break; | 1334 | break; |
1127 | case MGMT_OP_PIN_CODE_NEG_REPLY: | 1335 | case MGMT_OP_PIN_CODE_NEG_REPLY: |
1128 | err = pin_code_neg_reply(sk, buf + sizeof(*hdr), len); | 1336 | err = pin_code_neg_reply(sk, index, buf + sizeof(*hdr), len); |
1129 | break; | 1337 | break; |
1130 | case MGMT_OP_SET_IO_CAPABILITY: | 1338 | case MGMT_OP_SET_IO_CAPABILITY: |
1131 | err = set_io_capability(sk, buf + sizeof(*hdr), len); | 1339 | err = set_io_capability(sk, index, buf + sizeof(*hdr), len); |
1340 | break; | ||
1341 | case MGMT_OP_PAIR_DEVICE: | ||
1342 | err = pair_device(sk, index, buf + sizeof(*hdr), len); | ||
1343 | break; | ||
1344 | case MGMT_OP_USER_CONFIRM_REPLY: | ||
1345 | err = user_confirm_reply(sk, index, buf + sizeof(*hdr), len, 1); | ||
1346 | break; | ||
1347 | case MGMT_OP_USER_CONFIRM_NEG_REPLY: | ||
1348 | err = user_confirm_reply(sk, index, buf + sizeof(*hdr), len, 0); | ||
1132 | break; | 1349 | break; |
1133 | default: | 1350 | default: |
1134 | BT_DBG("Unknown op %u", opcode); | 1351 | BT_DBG("Unknown op %u", opcode); |
1135 | err = cmd_status(sk, opcode, 0x01); | 1352 | err = cmd_status(sk, index, opcode, 0x01); |
1136 | break; | 1353 | break; |
1137 | } | 1354 | } |
1138 | 1355 | ||
@@ -1148,20 +1365,12 @@ done: | |||
1148 | 1365 | ||
1149 | int mgmt_index_added(u16 index) | 1366 | int mgmt_index_added(u16 index) |
1150 | { | 1367 | { |
1151 | struct mgmt_ev_index_added ev; | 1368 | return mgmt_event(MGMT_EV_INDEX_ADDED, index, NULL, 0, NULL); |
1152 | |||
1153 | put_unaligned_le16(index, &ev.index); | ||
1154 | |||
1155 | return mgmt_event(MGMT_EV_INDEX_ADDED, &ev, sizeof(ev), NULL); | ||
1156 | } | 1369 | } |
1157 | 1370 | ||
1158 | int mgmt_index_removed(u16 index) | 1371 | int mgmt_index_removed(u16 index) |
1159 | { | 1372 | { |
1160 | struct mgmt_ev_index_added ev; | 1373 | return mgmt_event(MGMT_EV_INDEX_REMOVED, index, NULL, 0, NULL); |
1161 | |||
1162 | put_unaligned_le16(index, &ev.index); | ||
1163 | |||
1164 | return mgmt_event(MGMT_EV_INDEX_REMOVED, &ev, sizeof(ev), NULL); | ||
1165 | } | 1374 | } |
1166 | 1375 | ||
1167 | struct cmd_lookup { | 1376 | struct cmd_lookup { |
@@ -1197,10 +1406,9 @@ int mgmt_powered(u16 index, u8 powered) | |||
1197 | 1406 | ||
1198 | mgmt_pending_foreach(MGMT_OP_SET_POWERED, index, mode_rsp, &match); | 1407 | mgmt_pending_foreach(MGMT_OP_SET_POWERED, index, mode_rsp, &match); |
1199 | 1408 | ||
1200 | put_unaligned_le16(index, &ev.index); | ||
1201 | ev.val = powered; | 1409 | ev.val = powered; |
1202 | 1410 | ||
1203 | ret = mgmt_event(MGMT_EV_POWERED, &ev, sizeof(ev), match.sk); | 1411 | ret = mgmt_event(MGMT_EV_POWERED, index, &ev, sizeof(ev), match.sk); |
1204 | 1412 | ||
1205 | if (match.sk) | 1413 | if (match.sk) |
1206 | sock_put(match.sk); | 1414 | sock_put(match.sk); |
@@ -1214,13 +1422,12 @@ int mgmt_discoverable(u16 index, u8 discoverable) | |||
1214 | struct cmd_lookup match = { discoverable, NULL }; | 1422 | struct cmd_lookup match = { discoverable, NULL }; |
1215 | int ret; | 1423 | int ret; |
1216 | 1424 | ||
1217 | mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, index, | 1425 | mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, index, mode_rsp, &match); |
1218 | mode_rsp, &match); | ||
1219 | 1426 | ||
1220 | put_unaligned_le16(index, &ev.index); | ||
1221 | ev.val = discoverable; | 1427 | ev.val = discoverable; |
1222 | 1428 | ||
1223 | ret = mgmt_event(MGMT_EV_DISCOVERABLE, &ev, sizeof(ev), match.sk); | 1429 | ret = mgmt_event(MGMT_EV_DISCOVERABLE, index, &ev, sizeof(ev), |
1430 | match.sk); | ||
1224 | 1431 | ||
1225 | if (match.sk) | 1432 | if (match.sk) |
1226 | sock_put(match.sk); | 1433 | sock_put(match.sk); |
@@ -1236,10 +1443,9 @@ int mgmt_connectable(u16 index, u8 connectable) | |||
1236 | 1443 | ||
1237 | mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, index, mode_rsp, &match); | 1444 | mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, index, mode_rsp, &match); |
1238 | 1445 | ||
1239 | put_unaligned_le16(index, &ev.index); | ||
1240 | ev.val = connectable; | 1446 | ev.val = connectable; |
1241 | 1447 | ||
1242 | ret = mgmt_event(MGMT_EV_CONNECTABLE, &ev, sizeof(ev), match.sk); | 1448 | ret = mgmt_event(MGMT_EV_CONNECTABLE, index, &ev, sizeof(ev), match.sk); |
1243 | 1449 | ||
1244 | if (match.sk) | 1450 | if (match.sk) |
1245 | sock_put(match.sk); | 1451 | sock_put(match.sk); |
@@ -1253,25 +1459,22 @@ int mgmt_new_key(u16 index, struct link_key *key, u8 old_key_type) | |||
1253 | 1459 | ||
1254 | memset(&ev, 0, sizeof(ev)); | 1460 | memset(&ev, 0, sizeof(ev)); |
1255 | 1461 | ||
1256 | put_unaligned_le16(index, &ev.index); | ||
1257 | |||
1258 | bacpy(&ev.key.bdaddr, &key->bdaddr); | 1462 | bacpy(&ev.key.bdaddr, &key->bdaddr); |
1259 | ev.key.type = key->type; | 1463 | ev.key.type = key->type; |
1260 | memcpy(ev.key.val, key->val, 16); | 1464 | memcpy(ev.key.val, key->val, 16); |
1261 | ev.key.pin_len = key->pin_len; | 1465 | ev.key.pin_len = key->pin_len; |
1262 | ev.old_key_type = old_key_type; | 1466 | ev.old_key_type = old_key_type; |
1263 | 1467 | ||
1264 | return mgmt_event(MGMT_EV_NEW_KEY, &ev, sizeof(ev), NULL); | 1468 | return mgmt_event(MGMT_EV_NEW_KEY, index, &ev, sizeof(ev), NULL); |
1265 | } | 1469 | } |
1266 | 1470 | ||
1267 | int mgmt_connected(u16 index, bdaddr_t *bdaddr) | 1471 | int mgmt_connected(u16 index, bdaddr_t *bdaddr) |
1268 | { | 1472 | { |
1269 | struct mgmt_ev_connected ev; | 1473 | struct mgmt_ev_connected ev; |
1270 | 1474 | ||
1271 | put_unaligned_le16(index, &ev.index); | ||
1272 | bacpy(&ev.bdaddr, bdaddr); | 1475 | bacpy(&ev.bdaddr, bdaddr); |
1273 | 1476 | ||
1274 | return mgmt_event(MGMT_EV_CONNECTED, &ev, sizeof(ev), NULL); | 1477 | return mgmt_event(MGMT_EV_CONNECTED, index, &ev, sizeof(ev), NULL); |
1275 | } | 1478 | } |
1276 | 1479 | ||
1277 | static void disconnect_rsp(struct pending_cmd *cmd, void *data) | 1480 | static void disconnect_rsp(struct pending_cmd *cmd, void *data) |
@@ -1280,16 +1483,14 @@ static void disconnect_rsp(struct pending_cmd *cmd, void *data) | |||
1280 | struct sock **sk = data; | 1483 | struct sock **sk = data; |
1281 | struct mgmt_rp_disconnect rp; | 1484 | struct mgmt_rp_disconnect rp; |
1282 | 1485 | ||
1283 | put_unaligned_le16(cmd->index, &rp.index); | ||
1284 | bacpy(&rp.bdaddr, &cp->bdaddr); | 1486 | bacpy(&rp.bdaddr, &cp->bdaddr); |
1285 | 1487 | ||
1286 | cmd_complete(cmd->sk, MGMT_OP_DISCONNECT, &rp, sizeof(rp)); | 1488 | cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, &rp, sizeof(rp)); |
1287 | 1489 | ||
1288 | *sk = cmd->sk; | 1490 | *sk = cmd->sk; |
1289 | sock_hold(*sk); | 1491 | sock_hold(*sk); |
1290 | 1492 | ||
1291 | list_del(&cmd->list); | 1493 | mgmt_pending_remove(cmd); |
1292 | mgmt_pending_free(cmd); | ||
1293 | } | 1494 | } |
1294 | 1495 | ||
1295 | int mgmt_disconnected(u16 index, bdaddr_t *bdaddr) | 1496 | int mgmt_disconnected(u16 index, bdaddr_t *bdaddr) |
@@ -1300,10 +1501,9 @@ int mgmt_disconnected(u16 index, bdaddr_t *bdaddr) | |||
1300 | 1501 | ||
1301 | mgmt_pending_foreach(MGMT_OP_DISCONNECT, index, disconnect_rsp, &sk); | 1502 | mgmt_pending_foreach(MGMT_OP_DISCONNECT, index, disconnect_rsp, &sk); |
1302 | 1503 | ||
1303 | put_unaligned_le16(index, &ev.index); | ||
1304 | bacpy(&ev.bdaddr, bdaddr); | 1504 | bacpy(&ev.bdaddr, bdaddr); |
1305 | 1505 | ||
1306 | err = mgmt_event(MGMT_EV_DISCONNECTED, &ev, sizeof(ev), sk); | 1506 | err = mgmt_event(MGMT_EV_DISCONNECTED, index, &ev, sizeof(ev), sk); |
1307 | 1507 | ||
1308 | if (sk) | 1508 | if (sk) |
1309 | sock_put(sk); | 1509 | sock_put(sk); |
@@ -1320,10 +1520,9 @@ int mgmt_disconnect_failed(u16 index) | |||
1320 | if (!cmd) | 1520 | if (!cmd) |
1321 | return -ENOENT; | 1521 | return -ENOENT; |
1322 | 1522 | ||
1323 | err = cmd_status(cmd->sk, MGMT_OP_DISCONNECT, EIO); | 1523 | err = cmd_status(cmd->sk, index, MGMT_OP_DISCONNECT, EIO); |
1324 | 1524 | ||
1325 | list_del(&cmd->list); | 1525 | mgmt_pending_remove(cmd); |
1326 | mgmt_pending_free(cmd); | ||
1327 | 1526 | ||
1328 | return err; | 1527 | return err; |
1329 | } | 1528 | } |
@@ -1332,40 +1531,39 @@ int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status) | |||
1332 | { | 1531 | { |
1333 | struct mgmt_ev_connect_failed ev; | 1532 | struct mgmt_ev_connect_failed ev; |
1334 | 1533 | ||
1335 | put_unaligned_le16(index, &ev.index); | ||
1336 | bacpy(&ev.bdaddr, bdaddr); | 1534 | bacpy(&ev.bdaddr, bdaddr); |
1337 | ev.status = status; | 1535 | ev.status = status; |
1338 | 1536 | ||
1339 | return mgmt_event(MGMT_EV_CONNECT_FAILED, &ev, sizeof(ev), NULL); | 1537 | return mgmt_event(MGMT_EV_CONNECT_FAILED, index, &ev, sizeof(ev), NULL); |
1340 | } | 1538 | } |
1341 | 1539 | ||
1342 | int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr) | 1540 | int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr) |
1343 | { | 1541 | { |
1344 | struct mgmt_ev_pin_code_request ev; | 1542 | struct mgmt_ev_pin_code_request ev; |
1345 | 1543 | ||
1346 | put_unaligned_le16(index, &ev.index); | ||
1347 | bacpy(&ev.bdaddr, bdaddr); | 1544 | bacpy(&ev.bdaddr, bdaddr); |
1348 | 1545 | ||
1349 | return mgmt_event(MGMT_EV_PIN_CODE_REQUEST, &ev, sizeof(ev), NULL); | 1546 | return mgmt_event(MGMT_EV_PIN_CODE_REQUEST, index, &ev, sizeof(ev), |
1547 | NULL); | ||
1350 | } | 1548 | } |
1351 | 1549 | ||
1352 | int mgmt_pin_code_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status) | 1550 | int mgmt_pin_code_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status) |
1353 | { | 1551 | { |
1354 | struct pending_cmd *cmd; | 1552 | struct pending_cmd *cmd; |
1553 | struct mgmt_rp_pin_code_reply rp; | ||
1355 | int err; | 1554 | int err; |
1356 | 1555 | ||
1357 | cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, index); | 1556 | cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, index); |
1358 | if (!cmd) | 1557 | if (!cmd) |
1359 | return -ENOENT; | 1558 | return -ENOENT; |
1360 | 1559 | ||
1361 | if (status != 0) | 1560 | bacpy(&rp.bdaddr, bdaddr); |
1362 | err = cmd_status(cmd->sk, MGMT_OP_PIN_CODE_REPLY, status); | 1561 | rp.status = status; |
1363 | else | ||
1364 | err = cmd_complete(cmd->sk, MGMT_OP_PIN_CODE_REPLY, | ||
1365 | bdaddr, sizeof(*bdaddr)); | ||
1366 | 1562 | ||
1367 | list_del(&cmd->list); | 1563 | err = cmd_complete(cmd->sk, index, MGMT_OP_PIN_CODE_REPLY, &rp, |
1368 | mgmt_pending_free(cmd); | 1564 | sizeof(rp)); |
1565 | |||
1566 | mgmt_pending_remove(cmd); | ||
1369 | 1567 | ||
1370 | return err; | 1568 | return err; |
1371 | } | 1569 | } |
@@ -1373,20 +1571,75 @@ int mgmt_pin_code_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status) | |||
1373 | int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status) | 1571 | int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status) |
1374 | { | 1572 | { |
1375 | struct pending_cmd *cmd; | 1573 | struct pending_cmd *cmd; |
1574 | struct mgmt_rp_pin_code_reply rp; | ||
1376 | int err; | 1575 | int err; |
1377 | 1576 | ||
1378 | cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, index); | 1577 | cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, index); |
1379 | if (!cmd) | 1578 | if (!cmd) |
1380 | return -ENOENT; | 1579 | return -ENOENT; |
1381 | 1580 | ||
1382 | if (status != 0) | 1581 | bacpy(&rp.bdaddr, bdaddr); |
1383 | err = cmd_status(cmd->sk, MGMT_OP_PIN_CODE_NEG_REPLY, status); | 1582 | rp.status = status; |
1384 | else | ||
1385 | err = cmd_complete(cmd->sk, MGMT_OP_PIN_CODE_NEG_REPLY, | ||
1386 | bdaddr, sizeof(*bdaddr)); | ||
1387 | 1583 | ||
1388 | list_del(&cmd->list); | 1584 | err = cmd_complete(cmd->sk, index, MGMT_OP_PIN_CODE_NEG_REPLY, &rp, |
1389 | mgmt_pending_free(cmd); | 1585 | sizeof(rp)); |
1586 | |||
1587 | mgmt_pending_remove(cmd); | ||
1588 | |||
1589 | return err; | ||
1590 | } | ||
1591 | |||
1592 | int mgmt_user_confirm_request(u16 index, bdaddr_t *bdaddr, __le32 value) | ||
1593 | { | ||
1594 | struct mgmt_ev_user_confirm_request ev; | ||
1595 | |||
1596 | BT_DBG("hci%u", index); | ||
1597 | |||
1598 | bacpy(&ev.bdaddr, bdaddr); | ||
1599 | put_unaligned_le32(value, &ev.value); | ||
1600 | |||
1601 | return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, index, &ev, sizeof(ev), | ||
1602 | NULL); | ||
1603 | } | ||
1604 | |||
1605 | static int confirm_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status, | ||
1606 | u8 opcode) | ||
1607 | { | ||
1608 | struct pending_cmd *cmd; | ||
1609 | struct mgmt_rp_user_confirm_reply rp; | ||
1610 | int err; | ||
1611 | |||
1612 | cmd = mgmt_pending_find(opcode, index); | ||
1613 | if (!cmd) | ||
1614 | return -ENOENT; | ||
1615 | |||
1616 | bacpy(&rp.bdaddr, bdaddr); | ||
1617 | rp.status = status; | ||
1618 | err = cmd_complete(cmd->sk, index, opcode, &rp, sizeof(rp)); | ||
1619 | |||
1620 | mgmt_pending_remove(cmd); | ||
1390 | 1621 | ||
1391 | return err; | 1622 | return err; |
1392 | } | 1623 | } |
1624 | |||
1625 | int mgmt_user_confirm_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status) | ||
1626 | { | ||
1627 | return confirm_reply_complete(index, bdaddr, status, | ||
1628 | MGMT_OP_USER_CONFIRM_REPLY); | ||
1629 | } | ||
1630 | |||
1631 | int mgmt_user_confirm_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status) | ||
1632 | { | ||
1633 | return confirm_reply_complete(index, bdaddr, status, | ||
1634 | MGMT_OP_USER_CONFIRM_NEG_REPLY); | ||
1635 | } | ||
1636 | |||
1637 | int mgmt_auth_failed(u16 index, bdaddr_t *bdaddr, u8 status) | ||
1638 | { | ||
1639 | struct mgmt_ev_auth_failed ev; | ||
1640 | |||
1641 | bacpy(&ev.bdaddr, bdaddr); | ||
1642 | ev.status = status; | ||
1643 | |||
1644 | return mgmt_event(MGMT_EV_AUTH_FAILED, index, &ev, sizeof(ev), NULL); | ||
1645 | } | ||
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index c9348ddda877..42fdffd1d76c 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c | |||
@@ -190,20 +190,21 @@ static int sco_connect(struct sock *sk) | |||
190 | 190 | ||
191 | hci_dev_lock_bh(hdev); | 191 | hci_dev_lock_bh(hdev); |
192 | 192 | ||
193 | err = -ENOMEM; | ||
194 | |||
195 | if (lmp_esco_capable(hdev) && !disable_esco) | 193 | if (lmp_esco_capable(hdev) && !disable_esco) |
196 | type = ESCO_LINK; | 194 | type = ESCO_LINK; |
197 | else | 195 | else |
198 | type = SCO_LINK; | 196 | type = SCO_LINK; |
199 | 197 | ||
200 | hcon = hci_connect(hdev, type, dst, BT_SECURITY_LOW, HCI_AT_NO_BONDING); | 198 | hcon = hci_connect(hdev, type, dst, BT_SECURITY_LOW, HCI_AT_NO_BONDING); |
201 | if (!hcon) | 199 | if (IS_ERR(hcon)) { |
200 | err = PTR_ERR(hcon); | ||
202 | goto done; | 201 | goto done; |
202 | } | ||
203 | 203 | ||
204 | conn = sco_conn_add(hcon, 0); | 204 | conn = sco_conn_add(hcon, 0); |
205 | if (!conn) { | 205 | if (!conn) { |
206 | hci_conn_put(hcon); | 206 | hci_conn_put(hcon); |
207 | err = -ENOMEM; | ||
207 | goto done; | 208 | goto done; |
208 | } | 209 | } |
209 | 210 | ||