Commit 6d785aa3 authored by Johan Hedberg's avatar Johan Hedberg Committed by Marcel Holtmann

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: default avatarJohan Hedberg <johan.hedberg@intel.com>
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent 801c1e8d
...@@ -354,6 +354,9 @@ void l2cap_exit(void); ...@@ -354,6 +354,9 @@ void l2cap_exit(void);
int sco_init(void); int sco_init(void);
void sco_exit(void); void sco_exit(void);
int mgmt_init(void);
void mgmt_exit(void);
void bt_sock_reclassify_lock(struct sock *sk, int proto); void bt_sock_reclassify_lock(struct sock *sk, int proto);
#endif /* __BLUETOOTH_H */ #endif /* __BLUETOOTH_H */
...@@ -1309,7 +1309,9 @@ void hci_mgmt_chan_unregister(struct hci_mgmt_chan *c); ...@@ -1309,7 +1309,9 @@ void hci_mgmt_chan_unregister(struct hci_mgmt_chan *c);
#define DISCOV_BREDR_INQUIRY_LEN 0x08 #define DISCOV_BREDR_INQUIRY_LEN 0x08
#define DISCOV_LE_RESTART_DELAY msecs_to_jiffies(200) /* msec */ #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); int mgmt_new_settings(struct hci_dev *hdev);
void mgmt_index_added(struct hci_dev *hdev); void mgmt_index_added(struct hci_dev *hdev);
void mgmt_index_removed(struct hci_dev *hdev); void mgmt_index_removed(struct hci_dev *hdev);
......
...@@ -749,6 +749,13 @@ static int __init bt_init(void) ...@@ -749,6 +749,13 @@ static int __init bt_init(void)
goto sock_err; goto sock_err;
} }
err = mgmt_init();
if (err < 0) {
sco_exit();
l2cap_exit();
goto sock_err;
}
return 0; return 0;
sock_err: sock_err:
...@@ -763,6 +770,8 @@ static int __init bt_init(void) ...@@ -763,6 +770,8 @@ static int __init bt_init(void)
static void __exit bt_exit(void) static void __exit bt_exit(void)
{ {
mgmt_exit();
sco_exit(); sco_exit();
l2cap_exit(); l2cap_exit();
......
...@@ -741,19 +741,6 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, ...@@ -741,19 +741,6 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr,
hci_pi(sk)->hdev = hdev; hci_pi(sk)->hdev = hdev;
break; 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: case HCI_CHANNEL_MONITOR:
if (haddr.hci_dev != HCI_DEV_NONE) { if (haddr.hci_dev != HCI_DEV_NONE) {
err = -EINVAL; err = -EINVAL;
...@@ -900,7 +887,6 @@ static int hci_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, ...@@ -900,7 +887,6 @@ static int hci_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
hci_sock_cmsg(sk, msg, skb); hci_sock_cmsg(sk, msg, skb);
break; break;
case HCI_CHANNEL_USER: case HCI_CHANNEL_USER:
case HCI_CHANNEL_CONTROL:
case HCI_CHANNEL_MONITOR: case HCI_CHANNEL_MONITOR:
sock_recv_timestamp(msg, sk, skb); sock_recv_timestamp(msg, sk, skb);
break; break;
...@@ -941,9 +927,6 @@ static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg, ...@@ -941,9 +927,6 @@ static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg,
case HCI_CHANNEL_RAW: case HCI_CHANNEL_RAW:
case HCI_CHANNEL_USER: case HCI_CHANNEL_USER:
break; break;
case HCI_CHANNEL_CONTROL:
err = mgmt_control(sk, msg, len);
goto done;
case HCI_CHANNEL_MONITOR: case HCI_CHANNEL_MONITOR:
err = -EOPNOTSUPP; err = -EOPNOTSUPP;
goto done; goto done;
...@@ -951,7 +934,7 @@ static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg, ...@@ -951,7 +934,7 @@ static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg,
mutex_lock(&mgmt_chan_list_lock); mutex_lock(&mgmt_chan_list_lock);
chan = __hci_mgmt_chan_find(hci_pi(sk)->channel); chan = __hci_mgmt_chan_find(hci_pi(sk)->channel);
if (chan) if (chan)
err = -ENOSYS; /* FIXME: call handler */ err = mgmt_control(chan, sk, msg, len);
else else
err = -EINVAL; err = -EINVAL;
......
...@@ -6130,12 +6130,7 @@ static int set_public_address(struct sock *sk, struct hci_dev *hdev, ...@@ -6130,12 +6130,7 @@ static int set_public_address(struct sock *sk, struct hci_dev *hdev,
return err; return err;
} }
static const struct mgmt_handler { static const struct hci_mgmt_handler mgmt_handlers[] = {
int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
u16 data_len);
bool var_len;
size_t data_len;
} mgmt_handlers[] = {
{ NULL }, /* 0x0000 (no command) */ { NULL }, /* 0x0000 (no command) */
{ read_version, false, MGMT_READ_VERSION_SIZE }, { read_version, false, MGMT_READ_VERSION_SIZE },
{ read_commands, false, MGMT_READ_COMMANDS_SIZE }, { read_commands, false, MGMT_READ_COMMANDS_SIZE },
...@@ -6197,14 +6192,15 @@ static const struct mgmt_handler { ...@@ -6197,14 +6192,15 @@ static const struct mgmt_handler {
{ start_service_discovery,true, MGMT_START_SERVICE_DISCOVERY_SIZE }, { 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; void *buf;
u8 *cp; u8 *cp;
struct mgmt_hdr *hdr; struct mgmt_hdr *hdr;
u16 opcode, index, len; u16 opcode, index, len;
struct hci_dev *hdev = NULL; struct hci_dev *hdev = NULL;
const struct mgmt_handler *handler; const struct hci_mgmt_handler *handler;
int err; int err;
BT_DBG("got %zu bytes", msglen); BT_DBG("got %zu bytes", msglen);
...@@ -6257,8 +6253,8 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) ...@@ -6257,8 +6253,8 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
} }
} }
if (opcode >= ARRAY_SIZE(mgmt_handlers) || if (opcode >= chan->handler_count ||
mgmt_handlers[opcode].func == NULL) { chan->handlers[opcode].func == NULL) {
BT_DBG("Unknown op %u", opcode); BT_DBG("Unknown op %u", opcode);
err = cmd_status(sk, index, opcode, err = cmd_status(sk, index, opcode,
MGMT_STATUS_UNKNOWN_COMMAND); MGMT_STATUS_UNKNOWN_COMMAND);
...@@ -6279,7 +6275,7 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) ...@@ -6279,7 +6275,7 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
goto done; goto done;
} }
handler = &mgmt_handlers[opcode]; handler = &chan->handlers[opcode];
if ((handler->var_len && len < handler->data_len) || if ((handler->var_len && len < handler->data_len) ||
(!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) ...@@ -7470,3 +7466,19 @@ void mgmt_reenable_advertising(struct hci_dev *hdev)
enable_advertising(&req); enable_advertising(&req);
hci_req_run(&req, adv_enable_complete); 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);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment