diff options
author | Johan Hedberg <johan.hedberg@nokia.com> | 2010-12-29 17:38:22 -0500 |
---|---|---|
committer | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-02-07 22:40:05 -0500 |
commit | 72a734ec1aca8cd2ef3fc85428c11bde662e149e (patch) | |
tree | 7491e7e980f74b3806955ad8ae061c8ac190de79 /net/bluetooth/mgmt.c | |
parent | 9fbcbb455dd01abfad4f314b618ac51d566114cb (diff) |
Bluetooth: Unify mode related management messages to a single struct
The powered, connectable and discoverable messages all have the same
format. By using a single struct for all of them a lot of code can be
simplified and reused.
Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com>
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net/bluetooth/mgmt.c')
-rw-r--r-- | net/bluetooth/mgmt.c | 137 |
1 files changed, 28 insertions, 109 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index fc41cfc3f162..dbb1e5776644 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -322,7 +322,7 @@ static void mgmt_pending_remove(u16 opcode, int index) | |||
322 | 322 | ||
323 | static int set_powered(struct sock *sk, unsigned char *data, u16 len) | 323 | static int set_powered(struct sock *sk, unsigned char *data, u16 len) |
324 | { | 324 | { |
325 | struct mgmt_cp_set_powered *cp; | 325 | struct mgmt_mode *cp; |
326 | struct hci_dev *hdev; | 326 | struct hci_dev *hdev; |
327 | u16 dev_id; | 327 | u16 dev_id; |
328 | int ret, up; | 328 | int ret, up; |
@@ -339,7 +339,7 @@ static int set_powered(struct sock *sk, unsigned char *data, u16 len) | |||
339 | hci_dev_lock_bh(hdev); | 339 | hci_dev_lock_bh(hdev); |
340 | 340 | ||
341 | up = test_bit(HCI_UP, &hdev->flags); | 341 | up = test_bit(HCI_UP, &hdev->flags); |
342 | if ((cp->powered && up) || (!cp->powered && !up)) { | 342 | if ((cp->val && up) || (!cp->val && !up)) { |
343 | ret = cmd_status(sk, MGMT_OP_SET_POWERED, EALREADY); | 343 | ret = cmd_status(sk, MGMT_OP_SET_POWERED, EALREADY); |
344 | goto failed; | 344 | goto failed; |
345 | } | 345 | } |
@@ -353,7 +353,7 @@ static int set_powered(struct sock *sk, unsigned char *data, u16 len) | |||
353 | if (ret < 0) | 353 | if (ret < 0) |
354 | goto failed; | 354 | goto failed; |
355 | 355 | ||
356 | if (cp->powered) | 356 | if (cp->val) |
357 | queue_work(hdev->workqueue, &hdev->power_on); | 357 | queue_work(hdev->workqueue, &hdev->power_on); |
358 | else | 358 | else |
359 | queue_work(hdev->workqueue, &hdev->power_off); | 359 | queue_work(hdev->workqueue, &hdev->power_off); |
@@ -368,7 +368,7 @@ failed: | |||
368 | 368 | ||
369 | static int set_discoverable(struct sock *sk, unsigned char *data, u16 len) | 369 | static int set_discoverable(struct sock *sk, unsigned char *data, u16 len) |
370 | { | 370 | { |
371 | struct mgmt_cp_set_discoverable *cp; | 371 | struct mgmt_mode *cp; |
372 | struct hci_dev *hdev; | 372 | struct hci_dev *hdev; |
373 | u16 dev_id; | 373 | u16 dev_id; |
374 | u8 scan; | 374 | u8 scan; |
@@ -396,7 +396,7 @@ static int set_discoverable(struct sock *sk, unsigned char *data, u16 len) | |||
396 | goto failed; | 396 | goto failed; |
397 | } | 397 | } |
398 | 398 | ||
399 | if (cp->discoverable == test_bit(HCI_ISCAN, &hdev->flags) && | 399 | if (cp->val == test_bit(HCI_ISCAN, &hdev->flags) && |
400 | test_bit(HCI_PSCAN, &hdev->flags)) { | 400 | test_bit(HCI_PSCAN, &hdev->flags)) { |
401 | err = cmd_status(sk, MGMT_OP_SET_DISCOVERABLE, EALREADY); | 401 | err = cmd_status(sk, MGMT_OP_SET_DISCOVERABLE, EALREADY); |
402 | goto failed; | 402 | goto failed; |
@@ -408,7 +408,7 @@ static int set_discoverable(struct sock *sk, unsigned char *data, u16 len) | |||
408 | 408 | ||
409 | scan = SCAN_PAGE; | 409 | scan = SCAN_PAGE; |
410 | 410 | ||
411 | if (cp->discoverable) | 411 | if (cp->val) |
412 | scan |= SCAN_INQUIRY; | 412 | scan |= SCAN_INQUIRY; |
413 | 413 | ||
414 | err = hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); | 414 | err = hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); |
@@ -424,7 +424,7 @@ failed: | |||
424 | 424 | ||
425 | static int set_connectable(struct sock *sk, unsigned char *data, u16 len) | 425 | static int set_connectable(struct sock *sk, unsigned char *data, u16 len) |
426 | { | 426 | { |
427 | struct mgmt_cp_set_connectable *cp; | 427 | struct mgmt_mode *cp; |
428 | struct hci_dev *hdev; | 428 | struct hci_dev *hdev; |
429 | u16 dev_id; | 429 | u16 dev_id; |
430 | u8 scan; | 430 | u8 scan; |
@@ -452,7 +452,7 @@ static int set_connectable(struct sock *sk, unsigned char *data, u16 len) | |||
452 | goto failed; | 452 | goto failed; |
453 | } | 453 | } |
454 | 454 | ||
455 | if (cp->connectable == test_bit(HCI_PSCAN, &hdev->flags)) { | 455 | if (cp->val == test_bit(HCI_PSCAN, &hdev->flags)) { |
456 | err = cmd_status(sk, MGMT_OP_SET_CONNECTABLE, EALREADY); | 456 | err = cmd_status(sk, MGMT_OP_SET_CONNECTABLE, EALREADY); |
457 | goto failed; | 457 | goto failed; |
458 | } | 458 | } |
@@ -461,7 +461,7 @@ static int set_connectable(struct sock *sk, unsigned char *data, u16 len) | |||
461 | if (err < 0) | 461 | if (err < 0) |
462 | goto failed; | 462 | goto failed; |
463 | 463 | ||
464 | if (cp->connectable) | 464 | if (cp->val) |
465 | scan = SCAN_PAGE; | 465 | scan = SCAN_PAGE; |
466 | else | 466 | else |
467 | scan = 0; | 467 | scan = 0; |
@@ -584,20 +584,20 @@ int mgmt_index_removed(u16 index) | |||
584 | } | 584 | } |
585 | 585 | ||
586 | struct cmd_lookup { | 586 | struct cmd_lookup { |
587 | u8 value; | 587 | u8 val; |
588 | struct sock *sk; | 588 | struct sock *sk; |
589 | }; | 589 | }; |
590 | 590 | ||
591 | static void power_rsp(struct pending_cmd *cmd, void *data) | 591 | static void mode_rsp(struct pending_cmd *cmd, void *data) |
592 | { | 592 | { |
593 | struct mgmt_hdr *hdr; | 593 | struct mgmt_hdr *hdr; |
594 | struct mgmt_ev_cmd_complete *ev; | 594 | struct mgmt_ev_cmd_complete *ev; |
595 | struct mgmt_rp_set_powered *rp; | 595 | struct mgmt_mode *rp; |
596 | struct mgmt_cp_set_powered *cp = cmd->cmd; | 596 | struct mgmt_mode *cp = cmd->cmd; |
597 | struct sk_buff *skb; | 597 | struct sk_buff *skb; |
598 | struct cmd_lookup *match = data; | 598 | struct cmd_lookup *match = data; |
599 | 599 | ||
600 | if (cp->powered != match->value) | 600 | if (cp->val != match->val) |
601 | return; | 601 | return; |
602 | 602 | ||
603 | skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + sizeof(*rp), GFP_ATOMIC); | 603 | skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + sizeof(*rp), GFP_ATOMIC); |
@@ -613,7 +613,7 @@ static void power_rsp(struct pending_cmd *cmd, void *data) | |||
613 | 613 | ||
614 | rp = (void *) skb_put(skb, sizeof(*rp)); | 614 | rp = (void *) skb_put(skb, sizeof(*rp)); |
615 | put_unaligned_le16(cmd->index, &rp->index); | 615 | put_unaligned_le16(cmd->index, &rp->index); |
616 | rp->powered = cp->powered; | 616 | rp->val = cp->val; |
617 | 617 | ||
618 | if (sock_queue_rcv_skb(cmd->sk, skb) < 0) | 618 | if (sock_queue_rcv_skb(cmd->sk, skb) < 0) |
619 | kfree_skb(skb); | 619 | kfree_skb(skb); |
@@ -630,14 +630,14 @@ static void power_rsp(struct pending_cmd *cmd, void *data) | |||
630 | 630 | ||
631 | int mgmt_powered(u16 index, u8 powered) | 631 | int mgmt_powered(u16 index, u8 powered) |
632 | { | 632 | { |
633 | struct mgmt_ev_powered ev; | 633 | struct mgmt_mode ev; |
634 | struct cmd_lookup match = { powered, NULL }; | 634 | struct cmd_lookup match = { powered, NULL }; |
635 | int ret; | 635 | int ret; |
636 | 636 | ||
637 | put_unaligned_le16(index, &ev.index); | 637 | mgmt_pending_foreach(MGMT_OP_SET_POWERED, index, mode_rsp, &match); |
638 | ev.powered = powered; | ||
639 | 638 | ||
640 | mgmt_pending_foreach(MGMT_OP_SET_POWERED, index, power_rsp, &match); | 639 | put_unaligned_le16(index, &ev.index); |
640 | ev.val = powered; | ||
641 | 641 | ||
642 | ret = mgmt_event(MGMT_EV_POWERED, &ev, sizeof(ev), match.sk); | 642 | ret = mgmt_event(MGMT_EV_POWERED, &ev, sizeof(ev), match.sk); |
643 | 643 | ||
@@ -647,57 +647,17 @@ int mgmt_powered(u16 index, u8 powered) | |||
647 | return ret; | 647 | return ret; |
648 | } | 648 | } |
649 | 649 | ||
650 | static void discoverable_rsp(struct pending_cmd *cmd, void *data) | ||
651 | { | ||
652 | struct mgmt_cp_set_discoverable *cp = cmd->cmd; | ||
653 | struct cmd_lookup *match = data; | ||
654 | struct sk_buff *skb; | ||
655 | struct mgmt_hdr *hdr; | ||
656 | struct mgmt_ev_cmd_complete *ev; | ||
657 | struct mgmt_rp_set_discoverable *rp; | ||
658 | |||
659 | if (cp->discoverable != match->value) | ||
660 | return; | ||
661 | |||
662 | skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + sizeof(*rp), GFP_ATOMIC); | ||
663 | if (!skb) | ||
664 | return; | ||
665 | |||
666 | hdr = (void *) skb_put(skb, sizeof(*hdr)); | ||
667 | hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE); | ||
668 | hdr->len = cpu_to_le16(sizeof(*ev) + sizeof(*rp)); | ||
669 | |||
670 | ev = (void *) skb_put(skb, sizeof(*ev)); | ||
671 | put_unaligned_le16(MGMT_OP_SET_DISCOVERABLE, &ev->opcode); | ||
672 | |||
673 | rp = (void *) skb_put(skb, sizeof(*rp)); | ||
674 | put_unaligned_le16(cmd->index, &rp->index); | ||
675 | rp->discoverable = cp->discoverable; | ||
676 | |||
677 | if (sock_queue_rcv_skb(cmd->sk, skb) < 0) | ||
678 | kfree_skb(skb); | ||
679 | |||
680 | list_del(&cmd->list); | ||
681 | |||
682 | if (match->sk == NULL) { | ||
683 | match->sk = cmd->sk; | ||
684 | sock_hold(match->sk); | ||
685 | } | ||
686 | |||
687 | mgmt_pending_free(cmd); | ||
688 | } | ||
689 | |||
690 | int mgmt_discoverable(u16 index, u8 discoverable) | 650 | int mgmt_discoverable(u16 index, u8 discoverable) |
691 | { | 651 | { |
692 | struct mgmt_ev_discoverable ev; | 652 | struct mgmt_mode ev; |
693 | struct cmd_lookup match = { discoverable, NULL }; | 653 | struct cmd_lookup match = { discoverable, NULL }; |
694 | int ret; | 654 | int ret; |
695 | 655 | ||
696 | put_unaligned_le16(index, &ev.index); | ||
697 | ev.discoverable = discoverable; | ||
698 | |||
699 | mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, index, | 656 | mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, index, |
700 | discoverable_rsp, &match); | 657 | mode_rsp, &match); |
658 | |||
659 | put_unaligned_le16(index, &ev.index); | ||
660 | ev.val = discoverable; | ||
701 | 661 | ||
702 | ret = mgmt_event(MGMT_EV_DISCOVERABLE, &ev, sizeof(ev), match.sk); | 662 | ret = mgmt_event(MGMT_EV_DISCOVERABLE, &ev, sizeof(ev), match.sk); |
703 | 663 | ||
@@ -707,57 +667,16 @@ int mgmt_discoverable(u16 index, u8 discoverable) | |||
707 | return ret; | 667 | return ret; |
708 | } | 668 | } |
709 | 669 | ||
710 | static void connectable_rsp(struct pending_cmd *cmd, void *data) | ||
711 | { | ||
712 | struct mgmt_cp_set_connectable *cp = cmd->cmd; | ||
713 | struct cmd_lookup *match = data; | ||
714 | struct sk_buff *skb; | ||
715 | struct mgmt_hdr *hdr; | ||
716 | struct mgmt_ev_cmd_complete *ev; | ||
717 | struct mgmt_rp_set_connectable *rp; | ||
718 | |||
719 | if (cp->connectable != match->value) | ||
720 | return; | ||
721 | |||
722 | skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + sizeof(*rp), GFP_ATOMIC); | ||
723 | if (!skb) | ||
724 | return; | ||
725 | |||
726 | hdr = (void *) skb_put(skb, sizeof(*hdr)); | ||
727 | hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE); | ||
728 | hdr->len = cpu_to_le16(sizeof(*ev) + sizeof(*rp)); | ||
729 | |||
730 | ev = (void *) skb_put(skb, sizeof(*ev)); | ||
731 | put_unaligned_le16(MGMT_OP_SET_CONNECTABLE, &ev->opcode); | ||
732 | |||
733 | rp = (void *) skb_put(skb, sizeof(*rp)); | ||
734 | put_unaligned_le16(cmd->index, &rp->index); | ||
735 | rp->connectable = cp->connectable; | ||
736 | |||
737 | if (sock_queue_rcv_skb(cmd->sk, skb) < 0) | ||
738 | kfree_skb(skb); | ||
739 | |||
740 | list_del(&cmd->list); | ||
741 | |||
742 | if (match->sk == NULL) { | ||
743 | match->sk = cmd->sk; | ||
744 | sock_hold(match->sk); | ||
745 | } | ||
746 | |||
747 | mgmt_pending_free(cmd); | ||
748 | } | ||
749 | |||
750 | int mgmt_connectable(u16 index, u8 connectable) | 670 | int mgmt_connectable(u16 index, u8 connectable) |
751 | { | 671 | { |
752 | struct mgmt_ev_connectable ev; | 672 | struct mgmt_mode ev; |
753 | struct cmd_lookup match = { connectable, NULL }; | 673 | struct cmd_lookup match = { connectable, NULL }; |
754 | int ret; | 674 | int ret; |
755 | 675 | ||
756 | put_unaligned_le16(index, &ev.index); | 676 | mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, index, mode_rsp, &match); |
757 | ev.connectable = connectable; | ||
758 | 677 | ||
759 | mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, index, | 678 | put_unaligned_le16(index, &ev.index); |
760 | connectable_rsp, &match); | 679 | ev.val = connectable; |
761 | 680 | ||
762 | ret = mgmt_event(MGMT_EV_CONNECTABLE, &ev, sizeof(ev), match.sk); | 681 | ret = mgmt_event(MGMT_EV_CONNECTABLE, &ev, sizeof(ev), match.sk); |
763 | 682 | ||