aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2012-02-28 10:18:30 -0500
committerJohan Hedberg <johan.hedberg@intel.com>2012-03-01 16:55:58 -0500
commit0f4e68cf6e70fc219f219799c799a8a3e3c13100 (patch)
tree208b69caf263957571c5601c625157f46fea8f81 /net/bluetooth
parent6a919082e9b82a0de20f1248a33f3b3f005cebaf (diff)
Bluetooth: mgmt: Move command handlers into a table
By moving the command handlers into a table (the index being equal to the opcode) the lookup is made a bit more efficient. Having a struct to describe each handler also paves the way to add more meta-data for each handler, e.g. the minimum message size for the command and allow handling of common tasks like this in a centralized place. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com> Acked-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/mgmt.c219
1 files changed, 79 insertions, 140 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index cf8c8403571e..88a342a12593 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -267,7 +267,8 @@ static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
267 return err; 267 return err;
268} 268}
269 269
270static int read_version(struct sock *sk) 270static int read_version(struct sock *sk, struct hci_dev *hdev,
271 void *data, u16 data_len)
271{ 272{
272 struct mgmt_rp_read_version rp; 273 struct mgmt_rp_read_version rp;
273 274
@@ -280,7 +281,8 @@ static int read_version(struct sock *sk)
280 sizeof(rp)); 281 sizeof(rp));
281} 282}
282 283
283static int read_commands(struct sock *sk) 284static int read_commands(struct sock *sk, struct hci_dev *hdev,
285 void *data, u16 data_len)
284{ 286{
285 struct mgmt_rp_read_commands *rp; 287 struct mgmt_rp_read_commands *rp;
286 u16 num_commands = ARRAY_SIZE(mgmt_commands); 288 u16 num_commands = ARRAY_SIZE(mgmt_commands);
@@ -313,7 +315,8 @@ static int read_commands(struct sock *sk)
313 return err; 315 return err;
314} 316}
315 317
316static int read_index_list(struct sock *sk) 318static int read_index_list(struct sock *sk, struct hci_dev *hdev,
319 void *data, u16 data_len)
317{ 320{
318 struct mgmt_rp_read_index_list *rp; 321 struct mgmt_rp_read_index_list *rp;
319 struct list_head *p; 322 struct list_head *p;
@@ -627,7 +630,8 @@ static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
627 } 630 }
628} 631}
629 632
630static int read_controller_info(struct sock *sk, struct hci_dev *hdev) 633static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
634 void *data, u16 data_len)
631{ 635{
632 struct mgmt_rp_read_info rp; 636 struct mgmt_rp_read_info rp;
633 637
@@ -1689,7 +1693,8 @@ static u8 link_to_mgmt(u8 link_type, u8 addr_type)
1689 } 1693 }
1690} 1694}
1691 1695
1692static int get_connections(struct sock *sk, struct hci_dev *hdev) 1696static int get_connections(struct sock *sk, struct hci_dev *hdev,
1697 void *data, u16 data_len)
1693{ 1698{
1694 struct mgmt_rp_get_connections *rp; 1699 struct mgmt_rp_get_connections *rp;
1695 struct hci_conn *c; 1700 struct hci_conn *c;
@@ -2015,9 +2020,9 @@ unlock:
2015} 2020}
2016 2021
2017static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, 2022static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev,
2018 unsigned char *data, u16 len) 2023 void *data, u16 len)
2019{ 2024{
2020 struct mgmt_addr_info *addr = (void *) data; 2025 struct mgmt_addr_info *addr = data;
2021 struct pending_cmd *cmd; 2026 struct pending_cmd *cmd;
2022 struct hci_conn *conn; 2027 struct hci_conn *conn;
2023 int err; 2028 int err;
@@ -2240,7 +2245,8 @@ failed:
2240 return err; 2245 return err;
2241} 2246}
2242 2247
2243static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev) 2248static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
2249 void *data, u16 data_len)
2244{ 2250{
2245 struct pending_cmd *cmd; 2251 struct pending_cmd *cmd;
2246 int err; 2252 int err;
@@ -2718,6 +2724,53 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
2718 return 0; 2724 return 0;
2719} 2725}
2720 2726
2727struct mgmt_handler {
2728 int (*func) (struct sock *sk, struct hci_dev *hdev,
2729 void *data, u16 data_len);
2730} mgmt_handlers[] = {
2731 { NULL }, /* 0x0000 (no command) */
2732 { read_version, },
2733 { read_commands, },
2734 { read_index_list, },
2735 { read_controller_info, },
2736 { set_powered, },
2737 { set_discoverable, },
2738 { set_connectable, },
2739 { set_fast_connectable, },
2740 { set_pairable, },
2741 { set_link_security, },
2742 { set_ssp, },
2743 { set_hs, },
2744 { set_le, },
2745 { set_dev_class, },
2746 { set_local_name, },
2747 { add_uuid, },
2748 { remove_uuid, },
2749 { load_link_keys, },
2750 { load_long_term_keys, },
2751 { disconnect, },
2752 { get_connections, },
2753 { pin_code_reply, },
2754 { pin_code_neg_reply, },
2755 { set_io_capability, },
2756 { pair_device, },
2757 { cancel_pair_device, },
2758 { unpair_device, },
2759 { user_confirm_reply, },
2760 { user_confirm_neg_reply, },
2761 { user_passkey_reply, },
2762 { user_passkey_neg_reply, },
2763 { read_local_oob_data, },
2764 { add_remote_oob_data, },
2765 { remove_remote_oob_data, },
2766 { start_discovery, },
2767 { stop_discovery, },
2768 { confirm_name, },
2769 { block_device, },
2770 { unblock_device, },
2771};
2772
2773
2721int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) 2774int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
2722{ 2775{
2723 void *buf; 2776 void *buf;
@@ -2751,150 +2804,36 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
2751 goto done; 2804 goto done;
2752 } 2805 }
2753 2806
2754 if (opcode < MGMT_OP_READ_INFO) { 2807 if (index != MGMT_INDEX_NONE) {
2755 if (index != MGMT_INDEX_NONE) {
2756 err = cmd_status(sk, index, opcode,
2757 MGMT_STATUS_INVALID_PARAMS);
2758 goto done;
2759 }
2760 } else {
2761 hdev = hci_dev_get(index); 2808 hdev = hci_dev_get(index);
2762 if (!hdev) { 2809 if (!hdev) {
2763 err = cmd_status(sk, index, opcode, 2810 err = cmd_status(sk, index, opcode,
2764 MGMT_STATUS_INVALID_PARAMS); 2811 MGMT_STATUS_INVALID_PARAMS);
2765 goto done; 2812 goto done;
2766 } 2813 }
2767
2768 mgmt_init_hdev(sk, hdev);
2769 } 2814 }
2770 2815
2771 cp = buf + sizeof(*hdr); 2816 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
2772 2817 mgmt_handlers[opcode].func == NULL) {
2773 switch (opcode) {
2774 case MGMT_OP_READ_VERSION:
2775 err = read_version(sk);
2776 break;
2777 case MGMT_OP_READ_COMMANDS:
2778 err = read_commands(sk);
2779 break;
2780 case MGMT_OP_READ_INDEX_LIST:
2781 err = read_index_list(sk);
2782 break;
2783 case MGMT_OP_READ_INFO:
2784 err = read_controller_info(sk, hdev);
2785 break;
2786 case MGMT_OP_SET_POWERED:
2787 err = set_powered(sk, hdev, cp, len);
2788 break;
2789 case MGMT_OP_SET_DISCOVERABLE:
2790 err = set_discoverable(sk, hdev, cp, len);
2791 break;
2792 case MGMT_OP_SET_CONNECTABLE:
2793 err = set_connectable(sk, hdev, cp, len);
2794 break;
2795 case MGMT_OP_SET_FAST_CONNECTABLE:
2796 err = set_fast_connectable(sk, hdev, cp, len);
2797 break;
2798 case MGMT_OP_SET_PAIRABLE:
2799 err = set_pairable(sk, hdev, cp, len);
2800 break;
2801 case MGMT_OP_SET_LINK_SECURITY:
2802 err = set_link_security(sk, hdev, cp, len);
2803 break;
2804 case MGMT_OP_SET_SSP:
2805 err = set_ssp(sk, hdev, cp, len);
2806 break;
2807 case MGMT_OP_SET_HS:
2808 err = set_hs(sk, hdev, cp, len);
2809 break;
2810 case MGMT_OP_SET_LE:
2811 err = set_le(sk, hdev, cp, len);
2812 break;
2813 case MGMT_OP_ADD_UUID:
2814 err = add_uuid(sk, hdev, cp, len);
2815 break;
2816 case MGMT_OP_REMOVE_UUID:
2817 err = remove_uuid(sk, hdev, cp, len);
2818 break;
2819 case MGMT_OP_SET_DEV_CLASS:
2820 err = set_dev_class(sk, hdev, cp, len);
2821 break;
2822 case MGMT_OP_LOAD_LINK_KEYS:
2823 err = load_link_keys(sk, hdev, cp, len);
2824 break;
2825 case MGMT_OP_DISCONNECT:
2826 err = disconnect(sk, hdev, cp, len);
2827 break;
2828 case MGMT_OP_GET_CONNECTIONS:
2829 err = get_connections(sk, hdev);
2830 break;
2831 case MGMT_OP_PIN_CODE_REPLY:
2832 err = pin_code_reply(sk, hdev, cp, len);
2833 break;
2834 case MGMT_OP_PIN_CODE_NEG_REPLY:
2835 err = pin_code_neg_reply(sk, hdev, cp, len);
2836 break;
2837 case MGMT_OP_SET_IO_CAPABILITY:
2838 err = set_io_capability(sk, hdev, cp, len);
2839 break;
2840 case MGMT_OP_PAIR_DEVICE:
2841 err = pair_device(sk, hdev, cp, len);
2842 break;
2843 case MGMT_OP_CANCEL_PAIR_DEVICE:
2844 err = cancel_pair_device(sk, hdev, buf + sizeof(*hdr), len);
2845 break;
2846 case MGMT_OP_UNPAIR_DEVICE:
2847 err = unpair_device(sk, hdev, cp, len);
2848 break;
2849 case MGMT_OP_USER_CONFIRM_REPLY:
2850 err = user_confirm_reply(sk, hdev, cp, len);
2851 break;
2852 case MGMT_OP_USER_CONFIRM_NEG_REPLY:
2853 err = user_confirm_neg_reply(sk, hdev, cp, len);
2854 break;
2855 case MGMT_OP_USER_PASSKEY_REPLY:
2856 err = user_passkey_reply(sk, hdev, cp, len);
2857 break;
2858 case MGMT_OP_USER_PASSKEY_NEG_REPLY:
2859 err = user_passkey_neg_reply(sk, hdev, cp, len);
2860 break;
2861 case MGMT_OP_SET_LOCAL_NAME:
2862 err = set_local_name(sk, hdev, cp, len);
2863 break;
2864 case MGMT_OP_READ_LOCAL_OOB_DATA:
2865 err = read_local_oob_data(sk, hdev);
2866 break;
2867 case MGMT_OP_ADD_REMOTE_OOB_DATA:
2868 err = add_remote_oob_data(sk, hdev, cp, len);
2869 break;
2870 case MGMT_OP_REMOVE_REMOTE_OOB_DATA:
2871 err = remove_remote_oob_data(sk, hdev, cp, len);
2872 break;
2873 case MGMT_OP_START_DISCOVERY:
2874 err = start_discovery(sk, hdev, cp, len);
2875 break;
2876 case MGMT_OP_STOP_DISCOVERY:
2877 err = stop_discovery(sk, hdev, cp, len);
2878 break;
2879 case MGMT_OP_CONFIRM_NAME:
2880 err = confirm_name(sk, hdev, cp, len);
2881 break;
2882 case MGMT_OP_BLOCK_DEVICE:
2883 err = block_device(sk, hdev, cp, len);
2884 break;
2885 case MGMT_OP_UNBLOCK_DEVICE:
2886 err = unblock_device(sk, hdev, cp, len);
2887 break;
2888 case MGMT_OP_LOAD_LONG_TERM_KEYS:
2889 err = load_long_term_keys(sk, hdev, cp, len);
2890 break;
2891 default:
2892 BT_DBG("Unknown op %u", opcode); 2818 BT_DBG("Unknown op %u", opcode);
2893 err = cmd_status(sk, index, opcode, 2819 err = cmd_status(sk, index, opcode,
2894 MGMT_STATUS_UNKNOWN_COMMAND); 2820 MGMT_STATUS_UNKNOWN_COMMAND);
2895 break; 2821 goto done;
2822 }
2823
2824 if ((hdev && opcode < MGMT_OP_READ_INFO) ||
2825 (!hdev && opcode >= MGMT_OP_READ_INFO)) {
2826 err = cmd_status(sk, index, opcode,
2827 MGMT_STATUS_INVALID_PARAMS);
2828 goto done;
2896 } 2829 }
2897 2830
2831 if (hdev)
2832 mgmt_init_hdev(sk, hdev);
2833
2834 cp = buf + sizeof(*hdr);
2835
2836 err = mgmt_handlers[opcode].func(sk, hdev, cp, len);
2898 if (err < 0) 2837 if (err < 0)
2899 goto done; 2838 goto done;
2900 2839