]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Bluetooth: Add mgmt events for blacklisting
authorAntti Julku <antti.julku@nokia.com>
Thu, 25 Aug 2011 13:48:02 +0000 (16:48 +0300)
committerGustavo F. Padovan <padovan@profusion.mobi>
Thu, 25 Aug 2011 13:02:01 +0000 (10:02 -0300)
Add management interface events for blocking/unblocking a device.
Sender of the block device command gets cmd complete and other
mgmt sockets get the event. Event is also sent to mgmt sockets when
blocking is done with ioctl, e.g when blocking a device with
hciconfig. This makes it possible for bluetoothd to track status
of blocked devices when a third party block or unblocks a device.

Event sending is handled in mgmt_device_blocked function which gets
called from hci_blacklist_add in hci_core.c. A pending command is
added in mgmt_block_device, so that it can found when sending the
event - the event is not sent to the socket from which the pending
command came. Locks were moved out from hci_core.c to hci_sock.c
and mgmt.c, because locking is needed also for mgmt_pending_add in
mgmt.c.

Signed-off-by: Antti Julku <antti.julku@nokia.com>
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
include/net/bluetooth/hci_core.h
include/net/bluetooth/mgmt.h
net/bluetooth/hci_core.c
net/bluetooth/hci_sock.c
net/bluetooth/mgmt.c

index 4b17cd7fb1648b98d0bcfc0a28521ce14b463082..9ffd27e2e9a92f9ce7698907d2be1c658ff937ae 100644 (file)
@@ -875,6 +875,8 @@ int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi,
                                                                u8 *eir);
 int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name);
 int mgmt_discovering(u16 index, u8 discovering);
+int mgmt_device_blocked(u16 index, bdaddr_t *bdaddr);
+int mgmt_device_unblocked(u16 index, bdaddr_t *bdaddr);
 
 /* HCI info for socket */
 #define hci_pi(sk) ((struct hci_pinfo *) sk)
index 1c914ddc6d7a668ccf9f4aaaad2a73d6742d79fc..4ecf4a5277ac9b1007f7c66f5f85afff64f206d6 100644 (file)
@@ -302,3 +302,13 @@ struct mgmt_ev_remote_name {
 } __packed;
 
 #define MGMT_EV_DISCOVERING            0x0014
+
+#define MGMT_EV_DEVICE_BLOCKED         0x0015
+struct mgmt_ev_device_blocked {
+       bdaddr_t bdaddr;
+} __packed;
+
+#define MGMT_EV_DEVICE_UNBLOCKED       0x0016
+struct mgmt_ev_device_unblocked {
+       bdaddr_t bdaddr;
+} __packed;
index 1d2068322728a92a4c1b4735d895fc2891c1b773..446bfdb4e28173bba648aee931075fa7dc929c04 100644 (file)
@@ -1312,59 +1312,43 @@ int hci_blacklist_clear(struct hci_dev *hdev)
 int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr)
 {
        struct bdaddr_list *entry;
-       int err;
 
        if (bacmp(bdaddr, BDADDR_ANY) == 0)
                return -EBADF;
 
-       hci_dev_lock_bh(hdev);
-
        if (hci_blacklist_lookup(hdev, bdaddr)) {
-               err = -EEXIST;
-               goto err;
+               return -EEXIST;
        }
 
        entry = kzalloc(sizeof(struct bdaddr_list), GFP_KERNEL);
        if (!entry) {
-               err = -ENOMEM;
-               goto err;
+               return -ENOMEM;
        }
 
        bacpy(&entry->bdaddr, bdaddr);
 
        list_add(&entry->list, &hdev->blacklist);
 
-       err = 0;
-
-err:
-       hci_dev_unlock_bh(hdev);
-       return err;
+       return mgmt_device_blocked(hdev->id, bdaddr);
 }
 
 int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr)
 {
        struct bdaddr_list *entry;
-       int err = 0;
-
-       hci_dev_lock_bh(hdev);
 
        if (bacmp(bdaddr, BDADDR_ANY) == 0) {
-               hci_blacklist_clear(hdev);
-               goto done;
+               return hci_blacklist_clear(hdev);
        }
 
        entry = hci_blacklist_lookup(hdev, bdaddr);
        if (!entry) {
-               err = -ENOENT;
-               goto done;
+               return -ENOENT;
        }
 
        list_del(&entry->list);
        kfree(entry);
 
-done:
-       hci_dev_unlock_bh(hdev);
-       return err;
+       return mgmt_device_unblocked(hdev->id, bdaddr);
 }
 
 static void hci_clear_adv_cache(unsigned long arg)
index ff02cf5e77ccdd576d2f42f78f2c4715e3a47d5e..f6afe3d76a668154a3131fe55f78bf3de34ed636 100644 (file)
@@ -183,21 +183,35 @@ static int hci_sock_release(struct socket *sock)
 static int hci_sock_blacklist_add(struct hci_dev *hdev, void __user *arg)
 {
        bdaddr_t bdaddr;
+       int err;
 
        if (copy_from_user(&bdaddr, arg, sizeof(bdaddr)))
                return -EFAULT;
 
-       return hci_blacklist_add(hdev, &bdaddr);
+       hci_dev_lock_bh(hdev);
+
+       err = hci_blacklist_add(hdev, &bdaddr);
+
+       hci_dev_unlock_bh(hdev);
+
+       return err;
 }
 
 static int hci_sock_blacklist_del(struct hci_dev *hdev, void __user *arg)
 {
        bdaddr_t bdaddr;
+       int err;
 
        if (copy_from_user(&bdaddr, arg, sizeof(bdaddr)))
                return -EFAULT;
 
-       return hci_blacklist_del(hdev, &bdaddr);
+       hci_dev_lock_bh(hdev);
+
+       err = hci_blacklist_del(hdev, &bdaddr);
+
+       hci_dev_unlock_bh(hdev);
+
+       return err;
 }
 
 /* Ioctls that require bound socket */
index dac7d39b810b90c8af539cab8f7fe4fb04ae74cd..4f91a00db2716c72220f0ddaf317a6119d332479 100644 (file)
@@ -1700,13 +1700,12 @@ static int block_device(struct sock *sk, u16 index, unsigned char *data,
                                                                u16 len)
 {
        struct hci_dev *hdev;
-       struct mgmt_cp_block_device *cp;
+       struct pending_cmd *cmd;
+       struct mgmt_cp_block_device *cp = (void *) data;
        int err;
 
        BT_DBG("hci%u", index);
 
-       cp = (void *) data;
-
        if (len != sizeof(*cp))
                return cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE,
                                                        EINVAL);
@@ -1716,6 +1715,14 @@ static int block_device(struct sock *sk, u16 index, unsigned char *data,
                return cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE,
                                                        ENODEV);
 
+       hci_dev_lock_bh(hdev);
+
+       cmd = mgmt_pending_add(sk, MGMT_OP_BLOCK_DEVICE, index, NULL, 0);
+       if (!cmd) {
+               err = -ENOMEM;
+               goto failed;
+       }
+
        err = hci_blacklist_add(hdev, &cp->bdaddr);
 
        if (err < 0)
@@ -1723,6 +1730,11 @@ static int block_device(struct sock *sk, u16 index, unsigned char *data,
        else
                err = cmd_complete(sk, index, MGMT_OP_BLOCK_DEVICE,
                                                        NULL, 0);
+
+       mgmt_pending_remove(cmd);
+
+failed:
+       hci_dev_unlock_bh(hdev);
        hci_dev_put(hdev);
 
        return err;
@@ -1732,13 +1744,12 @@ static int unblock_device(struct sock *sk, u16 index, unsigned char *data,
                                                                u16 len)
 {
        struct hci_dev *hdev;
-       struct mgmt_cp_unblock_device *cp;
+       struct pending_cmd *cmd;
+       struct mgmt_cp_unblock_device *cp = (void *) data;
        int err;
 
        BT_DBG("hci%u", index);
 
-       cp = (void *) data;
-
        if (len != sizeof(*cp))
                return cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE,
                                                                EINVAL);
@@ -1748,6 +1759,14 @@ static int unblock_device(struct sock *sk, u16 index, unsigned char *data,
                return cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE,
                                                                ENODEV);
 
+       hci_dev_lock_bh(hdev);
+
+       cmd = mgmt_pending_add(sk, MGMT_OP_UNBLOCK_DEVICE, index, NULL, 0);
+       if (!cmd) {
+               err = -ENOMEM;
+               goto failed;
+       }
+
        err = hci_blacklist_del(hdev, &cp->bdaddr);
 
        if (err < 0)
@@ -1755,6 +1774,11 @@ static int unblock_device(struct sock *sk, u16 index, unsigned char *data,
        else
                err = cmd_complete(sk, index, MGMT_OP_UNBLOCK_DEVICE,
                                                                NULL, 0);
+
+       mgmt_pending_remove(cmd);
+
+failed:
+       hci_dev_unlock_bh(hdev);
        hci_dev_put(hdev);
 
        return err;
@@ -2298,3 +2322,29 @@ int mgmt_discovering(u16 index, u8 discovering)
        return mgmt_event(MGMT_EV_DISCOVERING, index, &discovering,
                                                sizeof(discovering), NULL);
 }
+
+int mgmt_device_blocked(u16 index, bdaddr_t *bdaddr)
+{
+       struct pending_cmd *cmd;
+       struct mgmt_ev_device_blocked ev;
+
+       cmd = mgmt_pending_find(MGMT_OP_BLOCK_DEVICE, index);
+
+       bacpy(&ev.bdaddr, bdaddr);
+
+       return mgmt_event(MGMT_EV_DEVICE_BLOCKED, index, &ev, sizeof(ev),
+                                               cmd ? cmd->sk : NULL);
+}
+
+int mgmt_device_unblocked(u16 index, bdaddr_t *bdaddr)
+{
+       struct pending_cmd *cmd;
+       struct mgmt_ev_device_unblocked ev;
+
+       cmd = mgmt_pending_find(MGMT_OP_UNBLOCK_DEVICE, index);
+
+       bacpy(&ev.bdaddr, bdaddr);
+
+       return mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, index, &ev, sizeof(ev),
+                                               cmd ? cmd->sk : NULL);
+}