diff options
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/mgmt.c | 62 |
1 files changed, 40 insertions, 22 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index f5ef7a3374c7..52e5f88b753a 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -219,14 +219,14 @@ static void mgmt_pending_free(struct pending_cmd *cmd) | |||
219 | kfree(cmd); | 219 | kfree(cmd); |
220 | } | 220 | } |
221 | 221 | ||
222 | static int mgmt_pending_add(struct sock *sk, u16 opcode, int index, | 222 | static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode, |
223 | void *data, u16 len) | 223 | u16 index, void *data, u16 len) |
224 | { | 224 | { |
225 | struct pending_cmd *cmd; | 225 | struct pending_cmd *cmd; |
226 | 226 | ||
227 | cmd = kmalloc(sizeof(*cmd), GFP_ATOMIC); | 227 | cmd = kmalloc(sizeof(*cmd), GFP_ATOMIC); |
228 | if (!cmd) | 228 | if (!cmd) |
229 | return -ENOMEM; | 229 | return NULL; |
230 | 230 | ||
231 | cmd->opcode = opcode; | 231 | cmd->opcode = opcode; |
232 | cmd->index = index; | 232 | cmd->index = index; |
@@ -234,7 +234,7 @@ static int mgmt_pending_add(struct sock *sk, u16 opcode, int index, | |||
234 | cmd->cmd = kmalloc(len, GFP_ATOMIC); | 234 | cmd->cmd = kmalloc(len, GFP_ATOMIC); |
235 | if (!cmd->cmd) { | 235 | if (!cmd->cmd) { |
236 | kfree(cmd); | 236 | kfree(cmd); |
237 | return -ENOMEM; | 237 | return NULL; |
238 | } | 238 | } |
239 | 239 | ||
240 | memcpy(cmd->cmd, data, len); | 240 | memcpy(cmd->cmd, data, len); |
@@ -244,7 +244,7 @@ static int mgmt_pending_add(struct sock *sk, u16 opcode, int index, | |||
244 | 244 | ||
245 | list_add(&cmd->list, &cmd_list); | 245 | list_add(&cmd->list, &cmd_list); |
246 | 246 | ||
247 | return 0; | 247 | return cmd; |
248 | } | 248 | } |
249 | 249 | ||
250 | static void mgmt_pending_foreach(u16 opcode, int index, | 250 | static void mgmt_pending_foreach(u16 opcode, int index, |
@@ -305,8 +305,9 @@ static int set_powered(struct sock *sk, unsigned char *data, u16 len) | |||
305 | { | 305 | { |
306 | struct mgmt_mode *cp; | 306 | struct mgmt_mode *cp; |
307 | struct hci_dev *hdev; | 307 | struct hci_dev *hdev; |
308 | struct pending_cmd *cmd; | ||
308 | u16 dev_id; | 309 | u16 dev_id; |
309 | int ret, up; | 310 | int err, up; |
310 | 311 | ||
311 | cp = (void *) data; | 312 | cp = (void *) data; |
312 | dev_id = get_unaligned_le16(&cp->index); | 313 | dev_id = get_unaligned_le16(&cp->index); |
@@ -321,36 +322,39 @@ static int set_powered(struct sock *sk, unsigned char *data, u16 len) | |||
321 | 322 | ||
322 | up = test_bit(HCI_UP, &hdev->flags); | 323 | up = test_bit(HCI_UP, &hdev->flags); |
323 | if ((cp->val && up) || (!cp->val && !up)) { | 324 | if ((cp->val && up) || (!cp->val && !up)) { |
324 | ret = cmd_status(sk, MGMT_OP_SET_POWERED, EALREADY); | 325 | err = cmd_status(sk, MGMT_OP_SET_POWERED, EALREADY); |
325 | goto failed; | 326 | goto failed; |
326 | } | 327 | } |
327 | 328 | ||
328 | if (mgmt_pending_find(MGMT_OP_SET_POWERED, dev_id)) { | 329 | if (mgmt_pending_find(MGMT_OP_SET_POWERED, dev_id)) { |
329 | ret = cmd_status(sk, MGMT_OP_SET_POWERED, EBUSY); | 330 | err = cmd_status(sk, MGMT_OP_SET_POWERED, EBUSY); |
330 | goto failed; | 331 | goto failed; |
331 | } | 332 | } |
332 | 333 | ||
333 | ret = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, dev_id, data, len); | 334 | cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, dev_id, data, len); |
334 | if (ret < 0) | 335 | if (!cmd) { |
336 | err = -ENOMEM; | ||
335 | goto failed; | 337 | goto failed; |
338 | } | ||
336 | 339 | ||
337 | if (cp->val) | 340 | if (cp->val) |
338 | queue_work(hdev->workqueue, &hdev->power_on); | 341 | queue_work(hdev->workqueue, &hdev->power_on); |
339 | else | 342 | else |
340 | queue_work(hdev->workqueue, &hdev->power_off); | 343 | queue_work(hdev->workqueue, &hdev->power_off); |
341 | 344 | ||
342 | ret = 0; | 345 | err = 0; |
343 | 346 | ||
344 | failed: | 347 | failed: |
345 | hci_dev_unlock_bh(hdev); | 348 | hci_dev_unlock_bh(hdev); |
346 | hci_dev_put(hdev); | 349 | hci_dev_put(hdev); |
347 | return ret; | 350 | return err; |
348 | } | 351 | } |
349 | 352 | ||
350 | static int set_discoverable(struct sock *sk, unsigned char *data, u16 len) | 353 | static int set_discoverable(struct sock *sk, unsigned char *data, u16 len) |
351 | { | 354 | { |
352 | struct mgmt_mode *cp; | 355 | struct mgmt_mode *cp; |
353 | struct hci_dev *hdev; | 356 | struct hci_dev *hdev; |
357 | struct pending_cmd *cmd; | ||
354 | u16 dev_id; | 358 | u16 dev_id; |
355 | u8 scan; | 359 | u8 scan; |
356 | int err; | 360 | int err; |
@@ -383,9 +387,11 @@ static int set_discoverable(struct sock *sk, unsigned char *data, u16 len) | |||
383 | goto failed; | 387 | goto failed; |
384 | } | 388 | } |
385 | 389 | ||
386 | err = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, dev_id, data, len); | 390 | cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, dev_id, data, len); |
387 | if (err < 0) | 391 | if (!cmd) { |
392 | err = -ENOMEM; | ||
388 | goto failed; | 393 | goto failed; |
394 | } | ||
389 | 395 | ||
390 | scan = SCAN_PAGE; | 396 | scan = SCAN_PAGE; |
391 | 397 | ||
@@ -407,6 +413,7 @@ static int set_connectable(struct sock *sk, unsigned char *data, u16 len) | |||
407 | { | 413 | { |
408 | struct mgmt_mode *cp; | 414 | struct mgmt_mode *cp; |
409 | struct hci_dev *hdev; | 415 | struct hci_dev *hdev; |
416 | struct pending_cmd *cmd; | ||
410 | u16 dev_id; | 417 | u16 dev_id; |
411 | u8 scan; | 418 | u8 scan; |
412 | int err; | 419 | int err; |
@@ -438,9 +445,11 @@ static int set_connectable(struct sock *sk, unsigned char *data, u16 len) | |||
438 | goto failed; | 445 | goto failed; |
439 | } | 446 | } |
440 | 447 | ||
441 | err = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, dev_id, data, len); | 448 | cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, dev_id, data, len); |
442 | if (err < 0) | 449 | if (!cmd) { |
450 | err = -ENOMEM; | ||
443 | goto failed; | 451 | goto failed; |
452 | } | ||
444 | 453 | ||
445 | if (cp->val) | 454 | if (cp->val) |
446 | scan = SCAN_PAGE; | 455 | scan = SCAN_PAGE; |
@@ -828,6 +837,7 @@ static int disconnect(struct sock *sk, unsigned char *data, u16 len) | |||
828 | struct hci_dev *hdev; | 837 | struct hci_dev *hdev; |
829 | struct mgmt_cp_disconnect *cp; | 838 | struct mgmt_cp_disconnect *cp; |
830 | struct hci_cp_disconnect dc; | 839 | struct hci_cp_disconnect dc; |
840 | struct pending_cmd *cmd; | ||
831 | struct hci_conn *conn; | 841 | struct hci_conn *conn; |
832 | u16 dev_id; | 842 | u16 dev_id; |
833 | int err; | 843 | int err; |
@@ -859,9 +869,11 @@ static int disconnect(struct sock *sk, unsigned char *data, u16 len) | |||
859 | goto failed; | 869 | goto failed; |
860 | } | 870 | } |
861 | 871 | ||
862 | err = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, dev_id, data, len); | 872 | cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, dev_id, data, len); |
863 | if (err < 0) | 873 | if (!cmd) { |
874 | err = -ENOMEM; | ||
864 | goto failed; | 875 | goto failed; |
876 | } | ||
865 | 877 | ||
866 | put_unaligned_le16(conn->handle, &dc.handle); | 878 | put_unaligned_le16(conn->handle, &dc.handle); |
867 | dc.reason = 0x13; /* Remote User Terminated Connection */ | 879 | dc.reason = 0x13; /* Remote User Terminated Connection */ |
@@ -938,6 +950,7 @@ static int pin_code_reply(struct sock *sk, unsigned char *data, u16 len) | |||
938 | struct hci_dev *hdev; | 950 | struct hci_dev *hdev; |
939 | struct mgmt_cp_pin_code_reply *cp; | 951 | struct mgmt_cp_pin_code_reply *cp; |
940 | struct hci_cp_pin_code_reply reply; | 952 | struct hci_cp_pin_code_reply reply; |
953 | struct pending_cmd *cmd; | ||
941 | u16 dev_id; | 954 | u16 dev_id; |
942 | int err; | 955 | int err; |
943 | 956 | ||
@@ -957,9 +970,11 @@ static int pin_code_reply(struct sock *sk, unsigned char *data, u16 len) | |||
957 | goto failed; | 970 | goto failed; |
958 | } | 971 | } |
959 | 972 | ||
960 | err = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, dev_id, data, len); | 973 | cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, dev_id, data, len); |
961 | if (err < 0) | 974 | if (!cmd) { |
975 | err = -ENOMEM; | ||
962 | goto failed; | 976 | goto failed; |
977 | } | ||
963 | 978 | ||
964 | bacpy(&reply.bdaddr, &cp->bdaddr); | 979 | bacpy(&reply.bdaddr, &cp->bdaddr); |
965 | reply.pin_len = cp->pin_len; | 980 | reply.pin_len = cp->pin_len; |
@@ -980,6 +995,7 @@ static int pin_code_neg_reply(struct sock *sk, unsigned char *data, u16 len) | |||
980 | { | 995 | { |
981 | struct hci_dev *hdev; | 996 | struct hci_dev *hdev; |
982 | struct mgmt_cp_pin_code_neg_reply *cp; | 997 | struct mgmt_cp_pin_code_neg_reply *cp; |
998 | struct pending_cmd *cmd; | ||
983 | u16 dev_id; | 999 | u16 dev_id; |
984 | int err; | 1000 | int err; |
985 | 1001 | ||
@@ -999,10 +1015,12 @@ static int pin_code_neg_reply(struct sock *sk, unsigned char *data, u16 len) | |||
999 | goto failed; | 1015 | goto failed; |
1000 | } | 1016 | } |
1001 | 1017 | ||
1002 | err = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, dev_id, | 1018 | cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, dev_id, |
1003 | data, len); | 1019 | data, len); |
1004 | if (err < 0) | 1020 | if (!cmd) { |
1021 | err = -ENOMEM; | ||
1005 | goto failed; | 1022 | goto failed; |
1023 | } | ||
1006 | 1024 | ||
1007 | err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, sizeof(bdaddr_t), | 1025 | err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, sizeof(bdaddr_t), |
1008 | &cp->bdaddr); | 1026 | &cp->bdaddr); |