Bluetooth: Convert mgmt to use HCI chan registration API
authorJohan Hedberg <johan.hedberg@intel.com>
Fri, 6 Mar 2015 19:08:51 +0000 (21:08 +0200)
committerMarcel Holtmann <marcel@holtmann.org>
Fri, 6 Mar 2015 19:15:21 +0000 (20:15 +0100)
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>
include/net/bluetooth/bluetooth.h
include/net/bluetooth/hci_core.h
net/bluetooth/af_bluetooth.c
net/bluetooth/hci_sock.c
net/bluetooth/mgmt.c

index 6bb97df16d2deb5016768ee2a5e57d698d5337c2..e598ca096ec9990eba529703ad57d5047ee96d35 100644 (file)
@@ -354,6 +354,9 @@ void l2cap_exit(void);
 int sco_init(void);
 void sco_exit(void);
 
+int mgmt_init(void);
+void mgmt_exit(void);
+
 void bt_sock_reclassify_lock(struct sock *sk, int proto);
 
 #endif /* __BLUETOOTH_H */
index 0c84d48e5517654afc930c7fb7c09ac6cf65ed3b..b2a183d201b7f112ebf1c87b28298778ec4c2b8f 100644 (file)
@@ -1309,7 +1309,9 @@ void hci_mgmt_chan_unregister(struct hci_mgmt_chan *c);
 #define DISCOV_BREDR_INQUIRY_LEN       0x08
 #define DISCOV_LE_RESTART_DELAY                msecs_to_jiffies(200)   /* msec */
 
-int mgmt_control(struct sock *sk, struct msghdr *msg, size_t len);
+int mgmt_control(struct hci_mgmt_chan *chan, struct sock *sk,
+                struct msghdr *msg, size_t msglen);
+
 int mgmt_new_settings(struct hci_dev *hdev);
 void mgmt_index_added(struct hci_dev *hdev);
 void mgmt_index_removed(struct hci_dev *hdev);
index 20a4698e2255fc051b29833187ae1c3e58106480..70f9d945faf7b439ce7a5283e94bc9687e8e67af 100644 (file)
@@ -749,6 +749,13 @@ static int __init bt_init(void)
                goto sock_err;
        }
 
+       err = mgmt_init();
+       if (err < 0) {
+               sco_exit();
+               l2cap_exit();
+               goto sock_err;
+       }
+
        return 0;
 
 sock_err:
@@ -763,6 +770,8 @@ error:
 
 static void __exit bt_exit(void)
 {
+       mgmt_exit();
+
        sco_exit();
 
        l2cap_exit();
index 0d5ace8922b1785744156ee53b7bfd03e1e8c422..aa9ffcb9481f4cb9ac54222f0f00279e0f36cd34 100644 (file)
@@ -741,19 +741,6 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr,
                hci_pi(sk)->hdev = hdev;
                break;
 
-       case HCI_CHANNEL_CONTROL:
-               if (haddr.hci_dev != HCI_DEV_NONE) {
-                       err = -EINVAL;
-                       goto done;
-               }
-
-               if (!capable(CAP_NET_ADMIN)) {
-                       err = -EPERM;
-                       goto done;
-               }
-
-               break;
-
        case HCI_CHANNEL_MONITOR:
                if (haddr.hci_dev != HCI_DEV_NONE) {
                        err = -EINVAL;
@@ -900,7 +887,6 @@ static int hci_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
                hci_sock_cmsg(sk, msg, skb);
                break;
        case HCI_CHANNEL_USER:
-       case HCI_CHANNEL_CONTROL:
        case HCI_CHANNEL_MONITOR:
                sock_recv_timestamp(msg, sk, skb);
                break;
@@ -941,9 +927,6 @@ static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg,
        case HCI_CHANNEL_RAW:
        case HCI_CHANNEL_USER:
                break;
-       case HCI_CHANNEL_CONTROL:
-               err = mgmt_control(sk, msg, len);
-               goto done;
        case HCI_CHANNEL_MONITOR:
                err = -EOPNOTSUPP;
                goto done;
@@ -951,7 +934,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 = -ENOSYS; /* FIXME: call handler */
+                       err = mgmt_control(chan, sk, msg, len);
                else
                        err = -EINVAL;
 
index d185a980098336de121fadb8964a15d6143b1531..bb02dd1b82bfdf7f739ba2bff165897f9e890ee1 100644 (file)
@@ -6130,12 +6130,7 @@ unlock:
        return err;
 }
 
-static const struct mgmt_handler {
-       int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
-                    u16 data_len);
-       bool var_len;
-       size_t data_len;
-} mgmt_handlers[] = {
+static const struct hci_mgmt_handler mgmt_handlers[] = {
        { NULL }, /* 0x0000 (no command) */
        { read_version,           false, MGMT_READ_VERSION_SIZE },
        { read_commands,          false, MGMT_READ_COMMANDS_SIZE },
@@ -6197,14 +6192,15 @@ static const struct mgmt_handler {
        { start_service_discovery,true,  MGMT_START_SERVICE_DISCOVERY_SIZE },
 };
 
-int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
+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 mgmt_handler *handler;
+       const struct hci_mgmt_handler *handler;
        int err;
 
        BT_DBG("got %zu bytes", msglen);
@@ -6257,8 +6253,8 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
                }
        }
 
-       if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
-           mgmt_handlers[opcode].func == NULL) {
+       if (opcode >= chan->handler_count ||
+           chan->handlers[opcode].func == NULL) {
                BT_DBG("Unknown op %u", opcode);
                err = cmd_status(sk, index, opcode,
                                 MGMT_STATUS_UNKNOWN_COMMAND);
@@ -6279,7 +6275,7 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
                goto done;
        }
 
-       handler = &mgmt_handlers[opcode];
+       handler = &chan->handlers[opcode];
 
        if ((handler->var_len && len < handler->data_len) ||
            (!handler->var_len && len != handler->data_len)) {
@@ -7470,3 +7466,19 @@ void mgmt_reenable_advertising(struct hci_dev *hdev)
        enable_advertising(&req);
        hci_req_run(&req, adv_enable_complete);
 }
+
+static struct hci_mgmt_chan chan = {
+       .channel        = HCI_CHANNEL_CONTROL,
+       .handler_count  = ARRAY_SIZE(mgmt_handlers),
+       .handlers       = mgmt_handlers,
+};
+
+int mgmt_init(void)
+{
+       return hci_mgmt_chan_register(&chan);
+}
+
+void mgmt_exit(void)
+{
+       hci_mgmt_chan_unregister(&chan);
+}