diff options
| author | Johan Hedberg <johan.hedberg@intel.com> | 2015-03-06 14:08:51 -0500 |
|---|---|---|
| committer | Marcel Holtmann <marcel@holtmann.org> | 2015-03-06 14:15:21 -0500 |
| commit | 6d785aa345f525e1fdf098b7c590168f0b00f3f1 (patch) | |
| tree | 90aa79cca35cabed308ca3719bef5b516867b490 | |
| parent | 801c1e8da57499a9922223ee1882b2b59debd47c (diff) | |
Bluetooth: Convert mgmt to use HCI chan registration API
This patch converts the existing mgmt code to use the newly introduced
generic API for registering HCI channels with mgmt-like semantics.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
| -rw-r--r-- | include/net/bluetooth/bluetooth.h | 3 | ||||
| -rw-r--r-- | include/net/bluetooth/hci_core.h | 4 | ||||
| -rw-r--r-- | net/bluetooth/af_bluetooth.c | 9 | ||||
| -rw-r--r-- | net/bluetooth/hci_sock.c | 19 | ||||
| -rw-r--r-- | net/bluetooth/mgmt.c | 34 |
5 files changed, 39 insertions, 30 deletions
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 6bb97df16d2d..e598ca096ec9 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h | |||
| @@ -354,6 +354,9 @@ void l2cap_exit(void); | |||
| 354 | int sco_init(void); | 354 | int sco_init(void); |
| 355 | void sco_exit(void); | 355 | void sco_exit(void); |
| 356 | 356 | ||
| 357 | int mgmt_init(void); | ||
| 358 | void mgmt_exit(void); | ||
| 359 | |||
| 357 | void bt_sock_reclassify_lock(struct sock *sk, int proto); | 360 | void bt_sock_reclassify_lock(struct sock *sk, int proto); |
| 358 | 361 | ||
| 359 | #endif /* __BLUETOOTH_H */ | 362 | #endif /* __BLUETOOTH_H */ |
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 0c84d48e5517..b2a183d201b7 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
| @@ -1309,7 +1309,9 @@ void hci_mgmt_chan_unregister(struct hci_mgmt_chan *c); | |||
| 1309 | #define DISCOV_BREDR_INQUIRY_LEN 0x08 | 1309 | #define DISCOV_BREDR_INQUIRY_LEN 0x08 |
| 1310 | #define DISCOV_LE_RESTART_DELAY msecs_to_jiffies(200) /* msec */ | 1310 | #define DISCOV_LE_RESTART_DELAY msecs_to_jiffies(200) /* msec */ |
| 1311 | 1311 | ||
| 1312 | int mgmt_control(struct sock *sk, struct msghdr *msg, size_t len); | 1312 | int mgmt_control(struct hci_mgmt_chan *chan, struct sock *sk, |
| 1313 | struct msghdr *msg, size_t msglen); | ||
| 1314 | |||
| 1313 | int mgmt_new_settings(struct hci_dev *hdev); | 1315 | int mgmt_new_settings(struct hci_dev *hdev); |
| 1314 | void mgmt_index_added(struct hci_dev *hdev); | 1316 | void mgmt_index_added(struct hci_dev *hdev); |
| 1315 | void mgmt_index_removed(struct hci_dev *hdev); | 1317 | void mgmt_index_removed(struct hci_dev *hdev); |
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 20a4698e2255..70f9d945faf7 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c | |||
| @@ -749,6 +749,13 @@ static int __init bt_init(void) | |||
| 749 | goto sock_err; | 749 | goto sock_err; |
| 750 | } | 750 | } |
| 751 | 751 | ||
| 752 | err = mgmt_init(); | ||
| 753 | if (err < 0) { | ||
| 754 | sco_exit(); | ||
| 755 | l2cap_exit(); | ||
| 756 | goto sock_err; | ||
| 757 | } | ||
| 758 | |||
| 752 | return 0; | 759 | return 0; |
| 753 | 760 | ||
| 754 | sock_err: | 761 | sock_err: |
| @@ -763,6 +770,8 @@ error: | |||
| 763 | 770 | ||
| 764 | static void __exit bt_exit(void) | 771 | static void __exit bt_exit(void) |
| 765 | { | 772 | { |
| 773 | mgmt_exit(); | ||
| 774 | |||
| 766 | sco_exit(); | 775 | sco_exit(); |
| 767 | 776 | ||
| 768 | l2cap_exit(); | 777 | l2cap_exit(); |
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 0d5ace8922b1..aa9ffcb9481f 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c | |||
| @@ -741,19 +741,6 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, | |||
| 741 | hci_pi(sk)->hdev = hdev; | 741 | hci_pi(sk)->hdev = hdev; |
| 742 | break; | 742 | break; |
| 743 | 743 | ||
| 744 | case HCI_CHANNEL_CONTROL: | ||
| 745 | if (haddr.hci_dev != HCI_DEV_NONE) { | ||
| 746 | err = -EINVAL; | ||
| 747 | goto done; | ||
| 748 | } | ||
| 749 | |||
| 750 | if (!capable(CAP_NET_ADMIN)) { | ||
| 751 | err = -EPERM; | ||
| 752 | goto done; | ||
| 753 | } | ||
| 754 | |||
| 755 | break; | ||
| 756 | |||
| 757 | case HCI_CHANNEL_MONITOR: | 744 | case HCI_CHANNEL_MONITOR: |
| 758 | if (haddr.hci_dev != HCI_DEV_NONE) { | 745 | if (haddr.hci_dev != HCI_DEV_NONE) { |
| 759 | err = -EINVAL; | 746 | err = -EINVAL; |
| @@ -900,7 +887,6 @@ static int hci_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, | |||
| 900 | hci_sock_cmsg(sk, msg, skb); | 887 | hci_sock_cmsg(sk, msg, skb); |
| 901 | break; | 888 | break; |
| 902 | case HCI_CHANNEL_USER: | 889 | case HCI_CHANNEL_USER: |
| 903 | case HCI_CHANNEL_CONTROL: | ||
| 904 | case HCI_CHANNEL_MONITOR: | 890 | case HCI_CHANNEL_MONITOR: |
| 905 | sock_recv_timestamp(msg, sk, skb); | 891 | sock_recv_timestamp(msg, sk, skb); |
| 906 | break; | 892 | break; |
| @@ -941,9 +927,6 @@ static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg, | |||
| 941 | case HCI_CHANNEL_RAW: | 927 | case HCI_CHANNEL_RAW: |
| 942 | case HCI_CHANNEL_USER: | 928 | case HCI_CHANNEL_USER: |
| 943 | break; | 929 | break; |
| 944 | case HCI_CHANNEL_CONTROL: | ||
| 945 | err = mgmt_control(sk, msg, len); | ||
| 946 | goto done; | ||
| 947 | case HCI_CHANNEL_MONITOR: | 930 | case HCI_CHANNEL_MONITOR: |
| 948 | err = -EOPNOTSUPP; | 931 | err = -EOPNOTSUPP; |
| 949 | goto done; | 932 | goto done; |
| @@ -951,7 +934,7 @@ static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg, | |||
| 951 | mutex_lock(&mgmt_chan_list_lock); | 934 | mutex_lock(&mgmt_chan_list_lock); |
| 952 | chan = __hci_mgmt_chan_find(hci_pi(sk)->channel); | 935 | chan = __hci_mgmt_chan_find(hci_pi(sk)->channel); |
| 953 | if (chan) | 936 | if (chan) |
| 954 | err = -ENOSYS; /* FIXME: call handler */ | 937 | err = mgmt_control(chan, sk, msg, len); |
| 955 | else | 938 | else |
| 956 | err = -EINVAL; | 939 | err = -EINVAL; |
| 957 | 940 | ||
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index d185a9800983..bb02dd1b82bf 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
| @@ -6130,12 +6130,7 @@ unlock: | |||
| 6130 | return err; | 6130 | return err; |
| 6131 | } | 6131 | } |
| 6132 | 6132 | ||
| 6133 | static const struct mgmt_handler { | 6133 | static const struct hci_mgmt_handler mgmt_handlers[] = { |
| 6134 | int (*func) (struct sock *sk, struct hci_dev *hdev, void *data, | ||
| 6135 | u16 data_len); | ||
| 6136 | bool var_len; | ||
| 6137 | size_t data_len; | ||
| 6138 | } mgmt_handlers[] = { | ||
| 6139 | { NULL }, /* 0x0000 (no command) */ | 6134 | { NULL }, /* 0x0000 (no command) */ |
| 6140 | { read_version, false, MGMT_READ_VERSION_SIZE }, | 6135 | { read_version, false, MGMT_READ_VERSION_SIZE }, |
| 6141 | { read_commands, false, MGMT_READ_COMMANDS_SIZE }, | 6136 | { read_commands, false, MGMT_READ_COMMANDS_SIZE }, |
| @@ -6197,14 +6192,15 @@ static const struct mgmt_handler { | |||
| 6197 | { start_service_discovery,true, MGMT_START_SERVICE_DISCOVERY_SIZE }, | 6192 | { start_service_discovery,true, MGMT_START_SERVICE_DISCOVERY_SIZE }, |
| 6198 | }; | 6193 | }; |
| 6199 | 6194 | ||
| 6200 | int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) | 6195 | int mgmt_control(struct hci_mgmt_chan *chan, struct sock *sk, |
| 6196 | struct msghdr *msg, size_t msglen) | ||
| 6201 | { | 6197 | { |
| 6202 | void *buf; | 6198 | void *buf; |
| 6203 | u8 *cp; | 6199 | u8 *cp; |
| 6204 | struct mgmt_hdr *hdr; | 6200 | struct mgmt_hdr *hdr; |
| 6205 | u16 opcode, index, len; | 6201 | u16 opcode, index, len; |
| 6206 | struct hci_dev *hdev = NULL; | 6202 | struct hci_dev *hdev = NULL; |
| 6207 | const struct mgmt_handler *handler; | 6203 | const struct hci_mgmt_handler *handler; |
| 6208 | int err; | 6204 | int err; |
| 6209 | 6205 | ||
| 6210 | BT_DBG("got %zu bytes", msglen); | 6206 | BT_DBG("got %zu bytes", msglen); |
| @@ -6257,8 +6253,8 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) | |||
| 6257 | } | 6253 | } |
| 6258 | } | 6254 | } |
| 6259 | 6255 | ||
| 6260 | if (opcode >= ARRAY_SIZE(mgmt_handlers) || | 6256 | if (opcode >= chan->handler_count || |
| 6261 | mgmt_handlers[opcode].func == NULL) { | 6257 | chan->handlers[opcode].func == NULL) { |
| 6262 | BT_DBG("Unknown op %u", opcode); | 6258 | BT_DBG("Unknown op %u", opcode); |
| 6263 | err = cmd_status(sk, index, opcode, | 6259 | err = cmd_status(sk, index, opcode, |
| 6264 | MGMT_STATUS_UNKNOWN_COMMAND); | 6260 | MGMT_STATUS_UNKNOWN_COMMAND); |
| @@ -6279,7 +6275,7 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) | |||
| 6279 | goto done; | 6275 | goto done; |
| 6280 | } | 6276 | } |
| 6281 | 6277 | ||
| 6282 | handler = &mgmt_handlers[opcode]; | 6278 | handler = &chan->handlers[opcode]; |
| 6283 | 6279 | ||
| 6284 | if ((handler->var_len && len < handler->data_len) || | 6280 | if ((handler->var_len && len < handler->data_len) || |
| 6285 | (!handler->var_len && len != handler->data_len)) { | 6281 | (!handler->var_len && len != handler->data_len)) { |
| @@ -7470,3 +7466,19 @@ void mgmt_reenable_advertising(struct hci_dev *hdev) | |||
| 7470 | enable_advertising(&req); | 7466 | enable_advertising(&req); |
| 7471 | hci_req_run(&req, adv_enable_complete); | 7467 | hci_req_run(&req, adv_enable_complete); |
| 7472 | } | 7468 | |
