|
@@ -54,6 +54,15 @@ DEFINE_RWLOCK(hci_cb_list_lock);
|
|
|
/* HCI ID Numbering */
|
|
|
static DEFINE_IDA(hci_index_ida);
|
|
|
|
|
|
+/* ----- HCI requests ----- */
|
|
|
+
|
|
|
+#define HCI_REQ_DONE 0
|
|
|
+#define HCI_REQ_PEND 1
|
|
|
+#define HCI_REQ_CANCELED 2
|
|
|
+
|
|
|
+#define hci_req_lock(d) mutex_lock(&d->req_lock)
|
|
|
+#define hci_req_unlock(d) mutex_unlock(&d->req_lock)
|
|
|
+
|
|
|
/* ---- HCI notifications ---- */
|
|
|
|
|
|
static void hci_notify(struct hci_dev *hdev, int event)
|
|
@@ -1339,9 +1348,6 @@ static void le_setup(struct hci_request *req)
|
|
|
/* Read LE Supported States */
|
|
|
hci_req_add(req, HCI_OP_LE_READ_SUPPORTED_STATES, 0, NULL);
|
|
|
|
|
|
- /* Read LE Advertising Channel TX Power */
|
|
|
- hci_req_add(req, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL);
|
|
|
-
|
|
|
/* Read LE White List Size */
|
|
|
hci_req_add(req, HCI_OP_LE_READ_WHITE_LIST_SIZE, 0, NULL);
|
|
|
|
|
@@ -1416,14 +1422,17 @@ static void hci_setup_event_mask(struct hci_request *req)
|
|
|
/* Use a different default for LE-only devices */
|
|
|
memset(events, 0, sizeof(events));
|
|
|
events[0] |= 0x10; /* Disconnection Complete */
|
|
|
- events[0] |= 0x80; /* Encryption Change */
|
|
|
events[1] |= 0x08; /* Read Remote Version Information Complete */
|
|
|
events[1] |= 0x20; /* Command Complete */
|
|
|
events[1] |= 0x40; /* Command Status */
|
|
|
events[1] |= 0x80; /* Hardware Error */
|
|
|
events[2] |= 0x04; /* Number of Completed Packets */
|
|
|
events[3] |= 0x02; /* Data Buffer Overflow */
|
|
|
- events[5] |= 0x80; /* Encryption Key Refresh Complete */
|
|
|
+
|
|
|
+ if (hdev->le_features[0] & HCI_LE_ENCRYPTION) {
|
|
|
+ events[0] |= 0x80; /* Encryption Change */
|
|
|
+ events[5] |= 0x80; /* Encryption Key Refresh Complete */
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
if (lmp_inq_rssi_capable(hdev))
|
|
@@ -1476,8 +1485,6 @@ static void hci_init2_req(struct hci_request *req, unsigned long opt)
|
|
|
if (lmp_le_capable(hdev))
|
|
|
le_setup(req);
|
|
|
|
|
|
- hci_setup_event_mask(req);
|
|
|
-
|
|
|
/* AVM Berlin (31), aka "BlueFRITZ!", doesn't support the read
|
|
|
* local supported commands HCI command.
|
|
|
*/
|
|
@@ -1605,6 +1612,8 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt)
|
|
|
struct hci_dev *hdev = req->hdev;
|
|
|
u8 p;
|
|
|
|
|
|
+ hci_setup_event_mask(req);
|
|
|
+
|
|
|
/* Some Broadcom based Bluetooth controllers do not support the
|
|
|
* Delete Stored Link Key command. They are clearly indicating its
|
|
|
* absence in the bit mask of supported commands.
|
|
@@ -1635,7 +1644,10 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt)
|
|
|
u8 events[8];
|
|
|
|
|
|
memset(events, 0, sizeof(events));
|
|
|
- events[0] = 0x1f;
|
|
|
+ events[0] = 0x0f;
|
|
|
+
|
|
|
+ if (hdev->le_features[0] & HCI_LE_ENCRYPTION)
|
|
|
+ events[0] |= 0x10; /* LE Long Term Key Request */
|
|
|
|
|
|
/* If controller supports the Connection Parameters Request
|
|
|
* Link Layer Procedure, enable the corresponding event.
|
|
@@ -1648,6 +1660,11 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt)
|
|
|
hci_req_add(req, HCI_OP_LE_SET_EVENT_MASK, sizeof(events),
|
|
|
events);
|
|
|
|
|
|
+ if (hdev->commands[25] & 0x40) {
|
|
|
+ /* Read LE Advertising Channel TX Power */
|
|
|
+ hci_req_add(req, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL);
|
|
|
+ }
|
|
|
+
|
|
|
hci_set_le_support(req);
|
|
|
}
|
|
|
|
|
@@ -2071,7 +2088,7 @@ u32 hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data,
|
|
|
}
|
|
|
|
|
|
/* Entry not in the cache. Add new one. */
|
|
|
- ie = kzalloc(sizeof(struct inquiry_entry), GFP_ATOMIC);
|
|
|
+ ie = kzalloc(sizeof(struct inquiry_entry), GFP_KERNEL);
|
|
|
if (!ie) {
|
|
|
flags |= MGMT_DEV_FOUND_CONFIRM_NAME;
|
|
|
goto done;
|
|
@@ -2435,6 +2452,16 @@ int hci_dev_open(__u16 dev)
|
|
|
*/
|
|
|
flush_workqueue(hdev->req_workqueue);
|
|
|
|
|
|
+ /* For controllers not using the management interface and that
|
|
|
+ * are brought up using legacy ioctl, set the HCI_PAIRABLE bit
|
|
|
+ * so that pairing works for them. Once the management interface
|
|
|
+ * is in use this bit will be cleared again and userspace has
|
|
|
+ * to explicitly enable it.
|
|
|
+ */
|
|
|
+ if (!test_bit(HCI_USER_CHANNEL, &hdev->dev_flags) &&
|
|
|
+ !test_bit(HCI_MGMT, &hdev->dev_flags))
|
|
|
+ set_bit(HCI_PAIRABLE, &hdev->dev_flags);
|
|
|
+
|
|
|
err = hci_dev_do_open(hdev);
|
|
|
|
|
|
done:
|
|
@@ -2655,6 +2682,42 @@ done:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+static void hci_update_scan_state(struct hci_dev *hdev, u8 scan)
|
|
|
+{
|
|
|
+ bool conn_changed, discov_changed;
|
|
|
+
|
|
|
+ BT_DBG("%s scan 0x%02x", hdev->name, scan);
|
|
|
+
|
|
|
+ if ((scan & SCAN_PAGE))
|
|
|
+ conn_changed = !test_and_set_bit(HCI_CONNECTABLE,
|
|
|
+ &hdev->dev_flags);
|
|
|
+ else
|
|
|
+ conn_changed = test_and_clear_bit(HCI_CONNECTABLE,
|
|
|
+ &hdev->dev_flags);
|
|
|
+
|
|
|
+ if ((scan & SCAN_INQUIRY)) {
|
|
|
+ discov_changed = !test_and_set_bit(HCI_DISCOVERABLE,
|
|
|
+ &hdev->dev_flags);
|
|
|
+ } else {
|
|
|
+ clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
|
|
|
+ discov_changed = test_and_clear_bit(HCI_DISCOVERABLE,
|
|
|
+ &hdev->dev_flags);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!test_bit(HCI_MGMT, &hdev->dev_flags))
|
|
|
+ return;
|
|
|
+
|
|
|
+ if (conn_changed || discov_changed) {
|
|
|
+ /* In case this was disabled through mgmt */
|
|
|
+ set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
|
|
|
+
|
|
|
+ if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
|
|
|
+ mgmt_update_adv_data(hdev);
|
|
|
+
|
|
|
+ mgmt_new_settings(hdev);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
int hci_dev_cmd(unsigned int cmd, void __user *arg)
|
|
|
{
|
|
|
struct hci_dev *hdev;
|
|
@@ -2716,22 +2779,11 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg)
|
|
|
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.
|
|
|
+ /* Ensure that the connectable and discoverable states
|
|
|
+ * get correctly modified as this was a non-mgmt change.
|
|
|
*/
|
|
|
- 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);
|
|
|
- }
|
|
|
+ if (!err)
|
|
|
+ hci_update_scan_state(hdev, dr.dev_opt);
|
|
|
break;
|
|
|
|
|
|
case HCISETLINKPOL:
|
|
@@ -2792,14 +2844,17 @@ int hci_get_dev_list(void __user *arg)
|
|
|
|
|
|
read_lock(&hci_dev_list_lock);
|
|
|
list_for_each_entry(hdev, &hci_dev_list, list) {
|
|
|
- if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags))
|
|
|
- cancel_delayed_work(&hdev->power_off);
|
|
|
+ unsigned long flags = hdev->flags;
|
|
|
|
|
|
- if (!test_bit(HCI_MGMT, &hdev->dev_flags))
|
|
|
- set_bit(HCI_PAIRABLE, &hdev->dev_flags);
|
|
|
+ /* When the auto-off is configured it means the transport
|
|
|
+ * is running, but in that case still indicate that the
|
|
|
+ * device is actually down.
|
|
|
+ */
|
|
|
+ if (test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
|
|
|
+ flags &= ~BIT(HCI_UP);
|
|
|
|
|
|
(dr + n)->dev_id = hdev->id;
|
|
|
- (dr + n)->dev_opt = hdev->flags;
|
|
|
+ (dr + n)->dev_opt = flags;
|
|
|
|
|
|
if (++n >= dev_num)
|
|
|
break;
|
|
@@ -2819,6 +2874,7 @@ int hci_get_dev_info(void __user *arg)
|
|
|
{
|
|
|
struct hci_dev *hdev;
|
|
|
struct hci_dev_info di;
|
|
|
+ unsigned long flags;
|
|
|
int err = 0;
|
|
|
|
|
|
if (copy_from_user(&di, arg, sizeof(di)))
|
|
@@ -2828,16 +2884,19 @@ int hci_get_dev_info(void __user *arg)
|
|
|
if (!hdev)
|
|
|
return -ENODEV;
|
|
|
|
|
|
- if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags))
|
|
|
- cancel_delayed_work_sync(&hdev->power_off);
|
|
|
-
|
|
|
- if (!test_bit(HCI_MGMT, &hdev->dev_flags))
|
|
|
- set_bit(HCI_PAIRABLE, &hdev->dev_flags);
|
|
|
+ /* When the auto-off is configured it means the transport
|
|
|
+ * is running, but in that case still indicate that the
|
|
|
+ * device is actually down.
|
|
|
+ */
|
|
|
+ if (test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
|
|
|
+ flags = hdev->flags & ~BIT(HCI_UP);
|
|
|
+ else
|
|
|
+ flags = hdev->flags;
|
|
|
|
|
|
strcpy(di.name, hdev->name);
|
|
|
di.bdaddr = hdev->bdaddr;
|
|
|
di.type = (hdev->bus & 0x0f) | ((hdev->dev_type & 0x03) << 4);
|
|
|
- di.flags = hdev->flags;
|
|
|
+ di.flags = flags;
|
|
|
di.pkt_type = hdev->pkt_type;
|
|
|
if (lmp_bredr_capable(hdev)) {
|
|
|
di.acl_mtu = hdev->acl_mtu;
|
|
@@ -4390,6 +4449,11 @@ int hci_req_run(struct hci_request *req, hci_req_complete_t complete)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+bool hci_req_pending(struct hci_dev *hdev)
|
|
|
+{
|
|
|
+ return (hdev->req_status == HCI_REQ_PEND);
|
|
|
+}
|
|
|
+
|
|
|
static struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode,
|
|
|
u32 plen, const void *param)
|
|
|
{
|