|
@@ -594,6 +594,99 @@ done:
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
+static u8 create_ad(struct hci_dev *hdev, u8 *ptr)
|
|
|
+{
|
|
|
+ u8 ad_len = 0, flags = 0;
|
|
|
+ size_t name_len;
|
|
|
+
|
|
|
+ if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags))
|
|
|
+ flags |= LE_AD_GENERAL;
|
|
|
+
|
|
|
+ if (!lmp_bredr_capable(hdev))
|
|
|
+ flags |= LE_AD_NO_BREDR;
|
|
|
+
|
|
|
+ if (lmp_le_br_capable(hdev))
|
|
|
+ flags |= LE_AD_SIM_LE_BREDR_CTRL;
|
|
|
+
|
|
|
+ if (lmp_host_le_br_capable(hdev))
|
|
|
+ flags |= LE_AD_SIM_LE_BREDR_HOST;
|
|
|
+
|
|
|
+ if (flags) {
|
|
|
+ BT_DBG("adv flags 0x%02x", flags);
|
|
|
+
|
|
|
+ ptr[0] = 2;
|
|
|
+ ptr[1] = EIR_FLAGS;
|
|
|
+ ptr[2] = flags;
|
|
|
+
|
|
|
+ ad_len += 3;
|
|
|
+ ptr += 3;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
|
|
|
+ ptr[0] = 2;
|
|
|
+ ptr[1] = EIR_TX_POWER;
|
|
|
+ ptr[2] = (u8) hdev->adv_tx_power;
|
|
|
+
|
|
|
+ ad_len += 3;
|
|
|
+ ptr += 3;
|
|
|
+ }
|
|
|
+
|
|
|
+ name_len = strlen(hdev->dev_name);
|
|
|
+ if (name_len > 0) {
|
|
|
+ size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
|
|
|
+
|
|
|
+ if (name_len > max_len) {
|
|
|
+ name_len = max_len;
|
|
|
+ ptr[1] = EIR_NAME_SHORT;
|
|
|
+ } else
|
|
|
+ ptr[1] = EIR_NAME_COMPLETE;
|
|
|
+
|
|
|
+ ptr[0] = name_len + 1;
|
|
|
+
|
|
|
+ memcpy(ptr + 2, hdev->dev_name, name_len);
|
|
|
+
|
|
|
+ ad_len += (name_len + 2);
|
|
|
+ ptr += (name_len + 2);
|
|
|
+ }
|
|
|
+
|
|
|
+ return ad_len;
|
|
|
+}
|
|
|
+
|
|
|
+int hci_update_ad(struct hci_dev *hdev)
|
|
|
+{
|
|
|
+ struct hci_cp_le_set_adv_data cp;
|
|
|
+ u8 len;
|
|
|
+ int err;
|
|
|
+
|
|
|
+ hci_dev_lock(hdev);
|
|
|
+
|
|
|
+ if (!lmp_le_capable(hdev)) {
|
|
|
+ err = -EINVAL;
|
|
|
+ goto unlock;
|
|
|
+ }
|
|
|
+
|
|
|
+ memset(&cp, 0, sizeof(cp));
|
|
|
+
|
|
|
+ len = create_ad(hdev, cp.data);
|
|
|
+
|
|
|
+ if (hdev->adv_data_len == len &&
|
|
|
+ memcmp(cp.data, hdev->adv_data, len) == 0) {
|
|
|
+ err = 0;
|
|
|
+ goto unlock;
|
|
|
+ }
|
|
|
+
|
|
|
+ memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
|
|
|
+ hdev->adv_data_len = len;
|
|
|
+
|
|
|
+ cp.length = len;
|
|
|
+ err = hci_send_cmd(hdev, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
|
|
|
+
|
|
|
+unlock:
|
|
|
+ hci_dev_unlock(hdev);
|
|
|
+
|
|
|
+ return err;
|
|
|
+}
|
|
|
+
|
|
|
/* ---- HCI ioctl helpers ---- */
|
|
|
|
|
|
int hci_dev_open(__u16 dev)
|
|
@@ -651,6 +744,7 @@ int hci_dev_open(__u16 dev)
|
|
|
hci_dev_hold(hdev);
|
|
|
set_bit(HCI_UP, &hdev->flags);
|
|
|
hci_notify(hdev, HCI_DEV_UP);
|
|
|
+ hci_update_ad(hdev);
|
|
|
if (!test_bit(HCI_SETUP, &hdev->dev_flags) &&
|
|
|
mgmt_valid_hdev(hdev)) {
|
|
|
hci_dev_lock(hdev);
|