aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2015-03-06 14:08:51 -0500
committerMarcel Holtmann <marcel@holtmann.org>2015-03-06 14:15:21 -0500
commit6d785aa345f525e1fdf098b7c590168f0b00f3f1 (patch)
tree90aa79cca35cabed308ca3719bef5b516867b490
parent801c1e8da57499a9922223ee1882b2b59debd47c (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.h3
-rw-r--r--include/net/bluetooth/hci_core.h4
-rw-r--r--net/bluetooth/af_bluetooth.c9
-rw-r--r--net/bluetooth/hci_sock.c19
-rw-r--r--net/bluetooth/mgmt.c34
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);
354int sco_init(void); 354int sco_init(void);
355void sco_exit(void); 355void sco_exit(void);
356 356
357int mgmt_init(void);
358void mgmt_exit(void);
359
357void bt_sock_reclassify_lock(struct sock *sk, int proto); 360void 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
1312int mgmt_control(struct sock *sk, struct msghdr *msg, size_t len); 1312int mgmt_control(struct hci_mgmt_chan *chan, struct sock *sk,
1313 struct msghdr *msg, size_t msglen);
1314
1313int mgmt_new_settings(struct hci_dev *hdev); 1315int mgmt_new_settings(struct hci_dev *hdev);
1314void mgmt_index_added(struct hci_dev *hdev); 1316void mgmt_index_added(struct hci_dev *hdev);
1315void mgmt_index_removed(struct hci_dev *hdev); 1317void 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
754sock_err: 761sock_err:
@@ -763,6 +770,8 @@ error:
763 770
764static void __exit bt_exit(void) 771static 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
6133static const struct mgmt_handler { 6133static 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
6200int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) 6195int 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