diff options
author | Johan Hedberg <johan.hedberg@nokia.com> | 2010-12-08 00:21:06 +0200 |
---|---|---|
committer | Gustavo F. Padovan <padovan@profusion.mobi> | 2010-12-07 23:03:38 -0200 |
commit | 0381101fd6a73c7d6b545044dc1472d019fc64e3 (patch) | |
tree | 8b7ec25d3e97e3bd7918135fa3fe3b29941e0db4 /net/bluetooth/hci_sock.c | |
parent | c02178d22b3ef2d18c38c96151600ee1c7ed94f0 (diff) |
Bluetooth: Add initial Bluetooth Management interface callbacks
Add initial code for handling Bluetooth Management interface messages.
Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
Acked-by: Andrei Emeltchenko <andrei.emeltchenko@nokia.com>
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net/bluetooth/hci_sock.c')
-rw-r--r-- | net/bluetooth/hci_sock.c | 39 |
1 files changed, 33 insertions, 6 deletions
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index b3753bad2a5..207be7abda9 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -49,6 +49,8 @@ #include <net/bluetooth/bluetooth.h> #include <net/bluetooth/hci_core.h> +static int enable_mgmt; + /* ----- HCI socket interface ----- */ static inline int hci_test_bit(int nr, void *addr) @@ -353,25 +355,35 @@ static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long a static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_len) { - struct sockaddr_hci *haddr = (struct sockaddr_hci *) addr; + struct sockaddr_hci haddr; struct sock *sk = sock->sk; struct hci_dev *hdev = NULL; - int err = 0; + int len, err = 0; BT_DBG("sock %p sk %p", sock, sk); - if (!haddr || haddr->hci_family != AF_BLUETOOTH) + if (!addr) + return -EINVAL; + + memset(&haddr, 0, sizeof(haddr)); + len = min_t(unsigned int, sizeof(haddr), addr_len); + memcpy(&haddr, addr, len); + + if (haddr.hci_family != AF_BLUETOOTH) + return -EINVAL; + + if (haddr.hci_channel != HCI_CHANNEL_RAW && !enable_mgmt) return -EINVAL; lock_sock(sk); - if (hci_pi(sk)->hdev) { + if (sk->sk_state == BT_BOUND || hci_pi(sk)->hdev) { err = -EALREADY; goto done; } - if (haddr->hci_dev != HCI_DEV_NONE) { - hdev = hci_dev_get(haddr->hci_dev); + if (haddr.hci_dev != HCI_DEV_NONE) { + hdev = hci_dev_get(haddr.hci_dev); if (!hdev) { err = -ENODEV; goto done; @@ -380,6 +392,7 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_le atomic_inc(&hdev->promisc); } + hci_pi(sk)->channel = haddr.hci_channel; hci_pi(sk)->hdev = hdev; sk->sk_state = BT_BOUND; @@ -502,6 +515,17 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock, lock_sock(sk); + switch (hci_pi(sk)->channel) { + case HCI_CHANNEL_RAW: + break; + case HCI_CHANNEL_CONTROL: + err = mgmt_control(sk, msg, len); + goto done; + default: + err = -EINVAL; + goto done; + } + hdev = hci_pi(sk)->hdev; if (!hdev) { err = -EBADFD; @@ -831,3 +855,6 @@ void __exit hci_sock_cleanup(void) proto_unregister(&hci_sk_proto); } + +module_param(enable_mgmt, bool, 0644); +MODULE_PARM_DESC(enable_mgmt, "Enable Management interface"); |