Bluetooth: Fix setting HCI_CONNECTABLE from ioctl code
authorJohan Hedberg <johan.hedberg@intel.com>
Wed, 9 Jul 2014 10:28:26 +0000 (13:28 +0300)
committerMarcel Holtmann <marcel@holtmann.org>
Wed, 9 Jul 2014 10:30:18 +0000 (12:30 +0200)
When the white list is in use the code would not update the
HCI_CONNECTABLE flag if it gets changed through the ioctl code (e.g.
hciconfig hci0 pscan). Since the flag is important for properly
accepting incoming connections add code to fix it up if necessary and
emit a New Settings mgmt event.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
include/net/bluetooth/hci_core.h
net/bluetooth/hci_core.c
net/bluetooth/mgmt.c

index cba4837dcaa5f3befb420e65fd9e3a9086281286..e69c2b08c0c6194aa898ad820cfc6e746f61c9c0 100644 (file)
@@ -1281,6 +1281,7 @@ void hci_sock_dev_event(struct hci_dev *hdev, int event);
 #define DISCOV_BREDR_INQUIRY_LEN       0x08
 
 int mgmt_control(struct sock *sk, struct msghdr *msg, size_t len);
+int mgmt_new_settings(struct hci_dev *hdev);
 void mgmt_index_added(struct hci_dev *hdev);
 void mgmt_index_removed(struct hci_dev *hdev);
 void mgmt_set_powered_failed(struct hci_dev *hdev, int err);
index 728a6ee471eac45255b011739aef8873a6ba88ad..84431b86af963d423dd19d2ffcf957508aa3a1f0 100644 (file)
@@ -2715,6 +2715,23 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg)
        case HCISETSCAN:
                err = hci_req_sync(hdev, hci_scan_req, dr.dev_opt,
                                   HCI_INIT_TIMEOUT);
+
+               /* Ensure that the connectable state gets correctly
+                * notified if the whitelist is in use.
+                */
+               if (!err && !list_empty(&hdev->whitelist)) {
+                       bool changed;
+
+                       if ((dr.dev_opt & SCAN_PAGE))
+                               changed = !test_and_set_bit(HCI_CONNECTABLE,
+                                                           &hdev->dev_flags);
+                       else
+                               changed = test_and_set_bit(HCI_CONNECTABLE,
+                                                          &hdev->dev_flags);
+
+                       if (changed)
+                               mgmt_new_settings(hdev);
+               }
                break;
 
        case HCISETLINKPOL:
index 98392d61b78fd3b76bf707cd28efd6a1b73f91d8..91b1f92c681e0372ab1276d99b7e89750b2e0076 100644 (file)
@@ -1427,6 +1427,11 @@ static int new_settings(struct hci_dev *hdev, struct sock *skip)
        return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
 }
 
+int mgmt_new_settings(struct hci_dev *hdev)
+{
+       return new_settings(hdev, NULL);
+}
+
 struct cmd_lookup {
        struct sock *sk;
        struct hci_dev *hdev;