summaryrefslogtreecommitdiffstats
path: root/net/bluetooth/hci_sock.c
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2012-02-20 14:50:35 +0100
committerJohan Hedberg <johan.hedberg@intel.com>2012-02-20 15:58:59 +0200
commit7cc2ade2cbc6f71090f0f8d0e11cb68886ddc65e (patch)
tree7ba106e3e172853d1bcc7af8c60a6c1c9766b1c7 /net/bluetooth/hci_sock.c
parent3a208627f3ac83d3b749608770f7eb631db31a77 (diff)
downloadlinux-7cc2ade2cbc6f71090f0f8d0e11cb68886ddc65e.tar.gz
linux-7cc2ade2cbc6f71090f0f8d0e11cb68886ddc65e.tar.bz2
linux-7cc2ade2cbc6f71090f0f8d0e11cb68886ddc65e.zip
Bluetooth: Simplify HCI socket bind handling
The HCI socket bind handling checks a few too many times the channel we are binding. So centralize this and make the function easier to read. Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Diffstat (limited to 'net/bluetooth/hci_sock.c')
-rw-r--r--net/bluetooth/hci_sock.c47
1 files changed, 31 insertions, 16 deletions
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 71a02adbaa77..4dda4574db3e 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -367,34 +367,49 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_le
if (haddr.hci_family != AF_BLUETOOTH)
return -EINVAL;
- if (haddr.hci_channel > HCI_CHANNEL_CONTROL)
- return -EINVAL;
-
- if (haddr.hci_channel == HCI_CHANNEL_CONTROL) {
- if (!enable_mgmt)
- return -EINVAL;
- set_bit(HCI_PI_MGMT_INIT, &hci_pi(sk)->flags);
- }
-
lock_sock(sk);
- if (sk->sk_state == BT_BOUND || hci_pi(sk)->hdev) {
+ if (sk->sk_state == BT_BOUND) {
err = -EALREADY;
goto done;
}
- if (haddr.hci_dev != HCI_DEV_NONE) {
- hdev = hci_dev_get(haddr.hci_dev);
- if (!hdev) {
- err = -ENODEV;
+ switch (haddr.hci_channel) {
+ case HCI_CHANNEL_RAW:
+ if (hci_pi(sk)->hdev) {
+ err = -EALREADY;
goto done;
}
- atomic_inc(&hdev->promisc);
+ if (haddr.hci_dev != HCI_DEV_NONE) {
+ hdev = hci_dev_get(haddr.hci_dev);
+ if (!hdev) {
+ err = -ENODEV;
+ goto done;
+ }
+
+ atomic_inc(&hdev->promisc);
+ }
+
+ hci_pi(sk)->hdev = hdev;
+ break;
+
+ case HCI_CHANNEL_CONTROL:
+ if (haddr.hci_dev != HCI_DEV_NONE || !enable_mgmt) {
+ err = -EINVAL;
+ goto done;
+ }
+
+ set_bit(HCI_PI_MGMT_INIT, &hci_pi(sk)->flags);
+ break;
+
+ default:
+ err = -EINVAL;
+ goto done;
}
+
hci_pi(sk)->channel = haddr.hci_channel;
- hci_pi(sk)->hdev = hdev;
sk->sk_state = BT_BOUND;
done: