diff options
author | Johan Hedberg <johan.hedberg@intel.com> | 2015-03-17 07:48:50 -0400 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2015-03-17 13:03:08 -0400 |
commit | fa4335d71a1408d0112c15874538f3f4e153ba01 (patch) | |
tree | f67bac624e402bc5f0ce84936d3cf9c573849355 | |
parent | 88b94ce925cb103851f39bfa7e23e09823573d30 (diff) |
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>
-rw-r--r-- | include/net/bluetooth/hci_core.h | 3 | ||||
-rw-r--r-- | net/bluetooth/hci_sock.c | 116 | ||||
-rw-r--r-- | net/bluetooth/mgmt.c | 111 |
3 files changed, 115 insertions, 115 deletions
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 93e7b2b05a17..b65c53de6a69 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
@@ -1330,9 +1330,6 @@ void hci_mgmt_chan_unregister(struct hci_mgmt_chan *c); | |||
1330 | #define DISCOV_BREDR_INQUIRY_LEN 0x08 | 1330 | #define DISCOV_BREDR_INQUIRY_LEN 0x08 |
1331 | #define DISCOV_LE_RESTART_DELAY msecs_to_jiffies(200) /* msec */ | 1331 | #define DISCOV_LE_RESTART_DELAY msecs_to_jiffies(200) /* msec */ |
1332 | 1332 | ||
1333 | int mgmt_control(struct hci_mgmt_chan *chan, struct sock *sk, | ||
1334 | struct msghdr *msg, size_t msglen); | ||
1335 | |||
1336 | int mgmt_new_settings(struct hci_dev *hdev); | 1333 | int mgmt_new_settings(struct hci_dev *hdev); |
1337 | void mgmt_index_added(struct hci_dev *hdev); | 1334 | void mgmt_index_added(struct hci_dev *hdev); |
1338 | void mgmt_index_removed(struct hci_dev *hdev); | 1335 | void mgmt_index_removed(struct hci_dev *hdev); |
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 9ba1a2667eaa..85a44a7dc150 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c | |||
@@ -30,6 +30,9 @@ | |||
30 | #include <net/bluetooth/bluetooth.h> | 30 | #include <net/bluetooth/bluetooth.h> |
31 | #include <net/bluetooth/hci_core.h> | 31 | #include <net/bluetooth/hci_core.h> |
32 | #include <net/bluetooth/hci_mon.h> | 32 | #include <net/bluetooth/hci_mon.h> |
33 | #include <net/bluetooth/mgmt.h> | ||
34 | |||
35 | #include "mgmt_util.h" | ||
33 | 36 | ||
34 | static LIST_HEAD(mgmt_chan_list); | 37 | static LIST_HEAD(mgmt_chan_list); |
35 | static DEFINE_MUTEX(mgmt_chan_list_lock); | 38 | 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, | |||
951 | return err ? : copied; | 954 | return err ? : copied; |
952 | } | 955 | } |
953 | 956 | ||
957 | static int hci_mgmt_cmd(struct hci_mgmt_chan *chan, struct sock *sk, | ||
958 | struct msghdr *msg, size_t msglen) | ||
959 | { | ||
960 | void *buf; | ||
961 | u8 *cp; | ||
962 | struct mgmt_hdr *hdr; | ||
963 | u16 opcode, index, len; | ||
964 | struct hci_dev *hdev = NULL; | ||
965 | const struct hci_mgmt_handler *handler; | ||
966 | bool var_len, no_hdev; | ||
967 | int err; | ||
968 | |||
969 | BT_DBG("got %zu bytes", msglen); | ||
970 | |||
971 | if (msglen < sizeof(*hdr)) | ||
972 | return -EINVAL; | ||
973 | |||
974 | buf = kmalloc(msglen, GFP_KERNEL); | ||
975 | if (!buf) | ||
976 | return -ENOMEM; | ||
977 | |||
978 | if (memcpy_from_msg(buf, msg, msglen)) { | ||
979 | err = -EFAULT; | ||
980 | goto done; | ||
981 | } | ||
982 | |||
983 | hdr = buf; | ||
984 | opcode = __le16_to_cpu(hdr->opcode); | ||
985 | index = __le16_to_cpu(hdr->index); | ||
986 | len = __le16_to_cpu(hdr->len); | ||
987 | |||
988 | if (len != msglen - sizeof(*hdr)) { | ||
989 | err = -EINVAL; | ||
990 | goto done; | ||
991 | } | ||
992 | |||
993 | if (opcode >= chan->handler_count || | ||
994 | chan->handlers[opcode].func == NULL) { | ||
995 | BT_DBG("Unknown op %u", opcode); | ||
996 | err = mgmt_cmd_status(sk, index, opcode, | ||
997 | MGMT_STATUS_UNKNOWN_COMMAND); | ||
998 | goto done; | ||
999 | } | ||
1000 | |||
1001 | handler = &chan->handlers[opcode]; | ||
1002 | |||
1003 | if (!hci_sock_test_flag(sk, HCI_SOCK_TRUSTED) && | ||
1004 | !(handler->flags & HCI_MGMT_UNTRUSTED)) { | ||
1005 | err = mgmt_cmd_status(sk, index, opcode, | ||
1006 | MGMT_STATUS_PERMISSION_DENIED); | ||
1007 | goto done; | ||
1008 | } | ||
1009 | |||
1010 | if (index != MGMT_INDEX_NONE) { | ||
1011 | hdev = hci_dev_get(index); | ||
1012 | if (!hdev) { | ||
1013 | err = mgmt_cmd_status(sk, index, opcode, | ||
1014 | MGMT_STATUS_INVALID_INDEX); | ||
1015 | goto done; | ||
1016 | } | ||
1017 | |||
1018 | if (hci_dev_test_flag(hdev, HCI_SETUP) || | ||
1019 | hci_dev_test_flag(hdev, HCI_CONFIG) || | ||
1020 | hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) { | ||
1021 | err = mgmt_cmd_status(sk, index, opcode, | ||
1022 | MGMT_STATUS_INVALID_INDEX); | ||
1023 | goto done; | ||
1024 | } | ||
1025 | |||
1026 | if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) && | ||
1027 | !(handler->flags & HCI_MGMT_UNCONFIGURED)) { | ||
1028 | err = mgmt_cmd_status(sk, index, opcode, | ||
1029 | MGMT_STATUS_INVALID_INDEX); | ||
1030 | goto done; | ||
1031 | } | ||
1032 | } | ||
1033 | |||
1034 | no_hdev = (handler->flags & HCI_MGMT_NO_HDEV); | ||
1035 | if (no_hdev != !hdev) { | ||
1036 | err = mgmt_cmd_status(sk, index, opcode, | ||
1037 | MGMT_STATUS_INVALID_INDEX); | ||
1038 | goto done; | ||
1039 | } | ||
1040 | |||
1041 | var_len = (handler->flags & HCI_MGMT_VAR_LEN); | ||
1042 | if ((var_len && len < handler->data_len) || | ||
1043 | (!var_len && len != handler->data_len)) { | ||
1044 | err = mgmt_cmd_status(sk, index, opcode, | ||
1045 | MGMT_STATUS_INVALID_PARAMS); | ||
1046 | goto done; | ||
1047 | } | ||
1048 | |||
1049 | if (hdev && chan->hdev_init) | ||
1050 | chan->hdev_init(sk, hdev); | ||
1051 | |||
1052 | cp = buf + sizeof(*hdr); | ||
1053 | |||
1054 | err = handler->func(sk, hdev, cp, len); | ||
1055 | if (err < 0) | ||
1056 | goto done; | ||
1057 | |||
1058 | err = msglen; | ||
1059 | |||
1060 | done: | ||
1061 | if (hdev) | ||
1062 | hci_dev_put(hdev); | ||
1063 | |||
1064 | kfree(buf); | ||
1065 | return err; | ||
1066 | } | ||
1067 | |||
954 | static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg, | 1068 | static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg, |
955 | size_t len) | 1069 | size_t len) |
956 | { | 1070 | { |
@@ -984,7 +1098,7 @@ static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg, | |||
984 | mutex_lock(&mgmt_chan_list_lock); | 1098 | mutex_lock(&mgmt_chan_list_lock); |
985 | chan = __hci_mgmt_chan_find(hci_pi(sk)->channel); | 1099 | chan = __hci_mgmt_chan_find(hci_pi(sk)->channel); |
986 | if (chan) | 1100 | if (chan) |
987 | err = mgmt_control(chan, sk, msg, len); | 1101 | err = hci_mgmt_cmd(chan, sk, msg, len); |
988 | else | 1102 | else |
989 | err = -EINVAL; | 1103 | err = -EINVAL; |
990 | 1104 | ||
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index ac897e676d5e..f3a957905193 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -6401,117 +6401,6 @@ static const struct hci_mgmt_handler mgmt_handlers[] = { | |||
6401 | { read_adv_features, MGMT_READ_ADV_FEATURES_SIZE }, | 6401 | { read_adv_features, MGMT_READ_ADV_FEATURES_SIZE }, |
6402 | }; | 6402 | }; |
6403 | 6403 | ||
6404 | int mgmt_control(struct hci_mgmt_chan *chan, struct sock *sk, | ||
6405 | struct msghdr *msg, size_t msglen) | ||
6406 | { | ||
6407 | void *buf; | ||
6408 | u8 *cp; | ||
6409 | struct mgmt_hdr *hdr; | ||
6410 | u16 opcode, index, len; | ||
6411 | struct hci_dev *hdev = NULL; | ||
6412 | const struct hci_mgmt_handler *handler; | ||
6413 | bool var_len, no_hdev; | ||
6414 | int err; | ||
6415 | |||
6416 | BT_DBG("got %zu bytes", msglen); | ||
6417 | |||
6418 | if (msglen < sizeof(*hdr)) | ||
6419 | return -EINVAL; | ||
6420 | |||
6421 | buf = kmalloc(msglen, GFP_KERNEL); | ||
6422 | if (!buf) | ||
6423 | return -ENOMEM; | ||
6424 | |||
6425 | if (memcpy_from_msg(buf, msg, msglen)) { | ||
6426 | err = -EFAULT; | ||
6427 | goto done; | ||
6428 | } | ||
6429 | |||
6430 | hdr = buf; | ||
6431 | opcode = __le16_to_cpu(hdr->opcode); | ||
6432 | index = __le16_to_cpu(hdr->index); | ||
6433 | len = __le16_to_cpu(hdr->len); | ||
6434 | |||
6435 | if (len != msglen - sizeof(*hdr)) { | ||
6436 | err = -EINVAL; | ||
6437 | goto done; | ||
6438 | } | ||
6439 | |||
6440 | if (opcode >= chan->handler_count || | ||
6441 | chan->handlers[opcode].func == NULL) { | ||
6442 | BT_DBG("Unknown op %u", opcode); | ||
6443 | err = mgmt_cmd_status(sk, index, opcode, | ||
6444 | MGMT_STATUS_UNKNOWN_COMMAND); | ||
6445 | goto done; | ||
6446 | } | ||
6447 | |||
6448 | handler = &chan->handlers[opcode]; | ||
6449 | |||
6450 | if (!hci_sock_test_flag(sk, HCI_SOCK_TRUSTED) && | ||
6451 | !(handler->flags & HCI_MGMT_UNTRUSTED)) { | ||
6452 | err = mgmt_cmd_status(sk, index, opcode, | ||
6453 | MGMT_STATUS_PERMISSION_DENIED); | ||
6454 | goto done; | ||
6455 | } | ||
6456 | |||
6457 | if (index != MGMT_INDEX_NONE) { | ||
6458 | hdev = hci_dev_get(index); | ||
6459 | if (!hdev) { | ||
6460 | err = mgmt_cmd_status(sk, index, opcode, | ||
6461 | MGMT_STATUS_INVALID_INDEX); | ||
6462 | goto done; | ||
6463 | } | ||
6464 | |||
6465 | if (hci_dev_test_flag(hdev, HCI_SETUP) || | ||
6466 | hci_dev_test_flag(hdev, HCI_CONFIG) || | ||
6467 | hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) { | ||
6468 | err = mgmt_cmd_status(sk, index, opcode, | ||
6469 | MGMT_STATUS_INVALID_INDEX); | ||
6470 | goto done; | ||
6471 | } | ||
6472 | |||
6473 | if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) && | ||
6474 | !(handler->flags & HCI_MGMT_UNCONFIGURED)) { | ||
6475 | err = mgmt_cmd_status(sk, index, opcode, | ||
6476 | MGMT_STATUS_INVALID_INDEX); | ||
6477 | goto done; | ||
6478 | } | ||
6479 | } | ||
6480 | |||
6481 | no_hdev = (handler->flags & HCI_MGMT_NO_HDEV); | ||
6482 | if (no_hdev != !hdev) { | ||
6483 | err = mgmt_cmd_status(sk, index, opcode, | ||
6484 | MGMT_STATUS_INVALID_INDEX); | ||
6485 | goto done; | ||
6486 | } | ||
6487 | |||
6488 | var_len = (handler->flags & HCI_MGMT_VAR_LEN); | ||
6489 | if ((var_len && len < handler->data_len) || | ||
6490 | (!var_len && len != handler->data_len)) { | ||
6491 | err = mgmt_cmd_status(sk, index, opcode, | ||
6492 | MGMT_STATUS_INVALID_PARAMS); | ||
6493 | goto done; | ||
6494 | } | ||
6495 | |||
6496 | if (hdev && chan->hdev_init) | ||
6497 | chan->hdev_init(sk, hdev); | ||
6498 | |||
6499 | cp = buf + sizeof(*hdr); | ||
6500 | |||
6501 | err = handler->func(sk, hdev, cp, len); | ||
6502 | if (err < 0) | ||
6503 | goto done; | ||
6504 | |||
6505 | err = msglen; | ||
6506 | |||
6507 | done: | ||
6508 | if (hdev) | ||
6509 | hci_dev_put(hdev); | ||
6510 | |||
6511 | kfree(buf); | ||
6512 | return err; | ||
6513 | } | ||
6514 | |||
6515 | void mgmt_index_added(struct hci_dev *hdev) | 6404 | void mgmt_index_added(struct hci_dev *hdev) |
6516 | { | 6405 | { |
6517 | struct mgmt_ev_ext_index ev; | 6406 | struct mgmt_ev_ext_index ev; |