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>
This commit is contained in:
parent
801c1e8da5
commit
6d785aa345
@ -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);
|
|||||||
#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)
|
|||||||
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)
|
|||||||
|
|
||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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 {
|
|||||||
{ 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)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user