diff options
author | Johan Hedberg <johan.hedberg@intel.com> | 2015-03-17 11:48:50 (GMT) |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2015-03-17 17:03:08 (GMT) |
commit | fa4335d71a1408d0112c15874538f3f4e153ba01 (patch) | |
tree | f67bac624e402bc5f0ce84936d3cf9c573849355 /net | |
parent | 88b94ce925cb103851f39bfa7e23e09823573d30 (diff) | |
download | linux-fa4335d71a1408d0112c15874538f3f4e153ba01.tar.xz |
Bluetooth: Move generic mgmt command dispatcher to hci_sock.c
The mgmt.c file should be reserved purely for HCI_CHANNEL_CONTROL. The
mgmt_control() function in it is already completely generic and has a
single user in hci_sock.c. This patch moves the function there and
renames it a bit more appropriately to hci_mgmt_cmd() (as it's a command
dispatcher).
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net')
-rw-r--r-- | net/bluetooth/hci_sock.c | 116 | ||||
-rw-r--r-- | net/bluetooth/mgmt.c | 111 |
2 files changed, 115 insertions, 112 deletions
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 9ba1a26..85a44a7 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -30,6 +30,9 @@ #include <net/bluetooth/bluetooth.h> #include <net/bluetooth/hci_core.h> #include <net/bluetooth/hci_mon.h> +#include <net/bluetooth/mgmt.h> + +#include "mgmt_util.h" static LIST_HEAD(mgmt_chan_list); static DEFINE_MUTEX(mgmt_chan_list_lock); @@ -951,6 +954,117 @@ static int hci_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, return err ? : copied; } +static int hci_mgmt_cmd(struct hci_mgmt_chan *chan, struct sock *sk, + struct msghdr *msg, size_t msglen) +{ + void *buf; + u8 *cp; + struct mgmt_hdr *hdr; + u16 opcode, index, len; + struct hci_dev *hdev = NULL; + const struct hci_mgmt_handler *handler; + bool var_len, no_hdev; + int err; + + BT_DBG("got %zu bytes", msglen); + + if (msglen < sizeof(*hdr)) + return -EINVAL; + + buf = kmalloc(msglen, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + if (memcpy_from_msg(buf, msg, msglen)) { + err = -EFAULT; + goto done; + } + + hdr = buf; + opcode = __le16_to_cpu(hdr->opcode); + index = __le16_to_cpu(hdr->index); + len = __le16_to_cpu(hdr->len); + + if (len != msglen - sizeof(*hdr)) { + err = -EINVAL; + goto done; + } + + if (opcode >= chan->handler_count || + chan->handlers[opcode].func == NULL) { + BT_DBG("Unknown op %u", opcode); + err = mgmt_cmd_status(sk, index, opcode, + MGMT_STATUS_UNKNOWN_COMMAND); + goto done; + } + + handler = &chan->handlers[opcode]; + + if (!hci_sock_test_flag(sk, HCI_SOCK_TRUSTED) && + !(handler->flags & HCI_MGMT_UNTRUSTED)) { + err = mgmt_cmd_status(sk, index, opcode, + MGMT_STATUS_PERMISSION_DENIED); + goto done; + } + + if (index != MGMT_INDEX_NONE) { + hdev = hci_dev_get(index); + if (!hdev) { + err = mgmt_cmd_status(sk, index, opcode, + MGMT_STATUS_INVALID_INDEX); + goto done; + } + + if (hci_dev_test_flag(hdev, HCI_SETUP) || + hci_dev_test_flag(hdev, HCI_CONFIG) || + hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) { + err = mgmt_cmd_status(sk, index, opcode, + MGMT_STATUS_INVALID_INDEX); + goto done; + } + + if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) && + !(handler->flags & HCI_MGMT_UNCONFIGURED)) { + err = mgmt_cmd_status(sk, index, opcode, + MGMT_STATUS_INVALID_INDEX); + goto done; + } + } + + no_hdev = (handler->flags & HCI_MGMT_NO_HDEV); + if (no_hdev != !hdev) { + err = mgmt_cmd_status(sk, index, opcode, + MGMT_STATUS_INVALID_INDEX); + goto done; + } + + var_len = (handler->flags & HCI_MGMT_VAR_LEN); + if ((var_len && len < handler->data_len) || + (!var_len && len != handler->data_len)) { + err = mgmt_cmd_status(sk, index, opcode, + MGMT_STATUS_INVALID_PARAMS); + goto done; + } + + if (hdev && chan->hdev_init) + chan->hdev_init(sk, hdev); + + cp = buf + sizeof(*hdr); + + err = handler->func(sk, hdev, cp, len); + if (err < 0) + goto done; + + err = msglen; + +done: + if (hdev) + hci_dev_put(hdev); + + kfree(buf); + return err; +} + static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) { @@ -984,7 +1098,7 @@ static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg, mutex_lock(&mgmt_chan_list_lock); chan = __hci_mgmt_chan_find(hci_pi(sk)->channel); if (chan) - err = mgmt_control(chan, sk, msg, len); + err = hci_mgmt_cmd(chan, sk, msg, len); else err = -EINVAL; diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index ac897e6..f3a9579 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -6401,117 +6401,6 @@ static const struct hci_mgmt_handler mgmt_handlers[] = { { read_adv_features, MGMT_READ_ADV_FEATURES_SIZE }, }; -int mgmt_control(struct hci_mgmt_chan *chan, struct sock *sk, - struct msghdr *msg, size_t msglen) -{ - void *buf; - u8 *cp; - struct mgmt_hdr *hdr; - u16 opcode, index, len; - struct hci_dev *hdev = NULL; - const struct hci_mgmt_handler *handler; - bool var_len, no_hdev; - int err; - - BT_DBG("got %zu bytes", msglen); - - if (msglen < sizeof(*hdr)) - return -EINVAL; - - buf = kmalloc(msglen, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - if (memcpy_from_msg(buf, msg, msglen)) { - err = -EFAULT; - goto done; - } - - hdr = buf; - opcode = __le16_to_cpu(hdr->opcode); - index = __le16_to_cpu(hdr->index); - len = __le16_to_cpu(hdr->len); - - if (len != msglen - sizeof(*hdr)) { - err = -EINVAL; - goto done; - } - - if (opcode >= chan->handler_count || - chan->handlers[opcode].func == NULL) { - BT_DBG("Unknown op %u", opcode); - err = mgmt_cmd_status(sk, index, opcode, - MGMT_STATUS_UNKNOWN_COMMAND); - goto done; - } - - handler = &chan->handlers[opcode]; - - if (!hci_sock_test_flag(sk, HCI_SOCK_TRUSTED) && - !(handler->flags & HCI_MGMT_UNTRUSTED)) { - err = mgmt_cmd_status(sk, index, opcode, - MGMT_STATUS_PERMISSION_DENIED); - goto done; - } - - if (index != MGMT_INDEX_NONE) { - hdev = hci_dev_get(index); - if (!hdev) { - err = mgmt_cmd_status(sk, index, opcode, - MGMT_STATUS_INVALID_INDEX); - goto done; - } - - if (hci_dev_test_flag(hdev, HCI_SETUP) || - hci_dev_test_flag(hdev, HCI_CONFIG) || - hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) { - err = mgmt_cmd_status(sk, index, opcode, - MGMT_STATUS_INVALID_INDEX); - goto done; - } - - if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) && - !(handler->flags & HCI_MGMT_UNCONFIGURED)) { - err = mgmt_cmd_status(sk, index, opcode, - MGMT_STATUS_INVALID_INDEX); - goto done; - } - } - - no_hdev = (handler->flags & HCI_MGMT_NO_HDEV); - if (no_hdev != !hdev) { - err = mgmt_cmd_status(sk, index, opcode, - MGMT_STATUS_INVALID_INDEX); - goto done; - } - - var_len = (handler->flags & HCI_MGMT_VAR_LEN); - if ((var_len && len < handler->data_len) || - (!var_len && len != handler->data_len)) { - err = mgmt_cmd_status(sk, index, opcode, - MGMT_STATUS_INVALID_PARAMS); - goto done; - } - - if (hdev && chan->hdev_init) - chan->hdev_init(sk, hdev); - - cp = buf + sizeof(*hdr); - - err = handler->func(sk, hdev, cp, len); - if (err < 0) - goto done; - - err = msglen; - -done: - if (hdev) - hci_dev_put(hdev); - - kfree(buf); - return err; -} - void mgmt_index_added(struct hci_dev *hdev) { struct mgmt_ev_ext_index ev; |