};
struct adv_info {
- struct delayed_work timeout_exp;
struct list_head list;
__u8 instance;
__u32 flags;
__u16 timeout;
+ __u16 remaining_time;
__u16 duration;
__u16 adv_data_len;
__u8 adv_data[HCI_MAX_AD_LENGTH];
struct list_head adv_instances;
unsigned int adv_instance_cnt;
__u8 cur_adv_instance;
+ __u16 adv_instance_timeout;
+ struct delayed_work adv_instance_expire;
__u8 irk[16];
__u32 rpa_timeout;
int mgmt_powered(struct hci_dev *hdev, u8 powered);
int mgmt_update_adv_data(struct hci_dev *hdev);
void mgmt_discoverable_timeout(struct hci_dev *hdev);
+void mgmt_adv_timeout_expired(struct hci_dev *hdev);
void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
bool persistent);
void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
if (hci_dev_test_flag(hdev, HCI_MGMT))
cancel_delayed_work_sync(&hdev->rpa_expired);
+ if (hdev->adv_instance_timeout) {
+ cancel_delayed_work_sync(&hdev->adv_instance_expire);
+ hdev->adv_instance_timeout = 0;
+ }
+
/* Avoid potential lockdep warnings from the *_flush() calls by
* ensuring the workqueue is empty up front.
*/
mgmt_discoverable_timeout(hdev);
}
+static void hci_adv_timeout_expire(struct work_struct *work)
+{
+ struct hci_dev *hdev;
+
+ hdev = container_of(work, struct hci_dev, adv_instance_expire.work);
+
+ BT_DBG("%s", hdev->name);
+
+ mgmt_adv_timeout_expired(hdev);
+}
+
void hci_uuids_clear(struct hci_dev *hdev)
{
struct bt_uuid *uuid, *tmp;
BT_DBG("%s removing %dMR", hdev->name, instance);
+ if (hdev->cur_adv_instance == instance && hdev->adv_instance_timeout) {
+ cancel_delayed_work(&hdev->adv_instance_expire);
+ hdev->adv_instance_timeout = 0;
+ }
+
list_del(&adv_instance->list);
kfree(adv_instance);
{
struct adv_info *adv_instance, *n;
+ if (hdev->adv_instance_timeout) {
+ cancel_delayed_work(&hdev->adv_instance_expire);
+ hdev->adv_instance_timeout = 0;
+ }
+
list_for_each_entry_safe(adv_instance, n, &hdev->adv_instances, list) {
list_del(&adv_instance->list);
kfree(adv_instance);
scan_rsp_data, scan_rsp_len);
adv_instance->timeout = timeout;
+ adv_instance->remaining_time = timeout;
if (duration == 0)
adv_instance->duration = HCI_DEFAULT_ADV_DURATION;
hdev->adv_tx_power = HCI_TX_POWER_INVALID;
hdev->adv_instance_cnt = 0;
hdev->cur_adv_instance = 0x00;
+ hdev->adv_instance_timeout = 0;
hdev->sniff_max_interval = 800;
hdev->sniff_min_interval = 80;
INIT_DELAYED_WORK(&hdev->discov_off, hci_discov_off);
INIT_DELAYED_WORK(&hdev->le_scan_disable, le_scan_disable_work);
INIT_DELAYED_WORK(&hdev->le_scan_restart, le_scan_restart_work);
+ INIT_DELAYED_WORK(&hdev->adv_instance_expire, hci_adv_timeout_expire);
skb_queue_head_init(&hdev->rx_q);
skb_queue_head_init(&hdev->cmd_q);
if (!hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
return;
- if (hdev->adv_instance.timeout)
- cancel_delayed_work(&hdev->adv_instance.timeout_exp);
+ if (hdev->adv_instance_timeout)
+ cancel_delayed_work(&hdev->adv_instance_expire);
memset(&hdev->adv_instance, 0, sizeof(hdev->adv_instance));
advertising_removed(NULL, hdev, 1);
hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
}
- if (hdev->adv_instance.timeout)
+ if (hdev->adv_instance_timeout)
clear_adv_instance(hdev);
if (hci_dev_test_flag(hdev, HCI_LE_ADV))
hci_dev_unlock(hdev);
}
-static void adv_timeout_expired(struct work_struct *work)
+void mgmt_adv_timeout_expired(struct hci_dev *hdev)
{
- struct hci_dev *hdev = container_of(work, struct hci_dev,
- adv_instance.timeout_exp.work);
-
- hdev->adv_instance.timeout = 0;
+ hdev->adv_instance_timeout = 0;
hci_dev_lock(hdev);
clear_adv_instance(hdev);
goto unlock;
}
- INIT_DELAYED_WORK(&hdev->adv_instance.timeout_exp, adv_timeout_expired);
-
hdev->adv_instance.flags = flags;
hdev->adv_instance.adv_data_len = cp->adv_data_len;
hdev->adv_instance.scan_rsp_len = cp->scan_rsp_len;
memcpy(hdev->adv_instance.scan_rsp_data,
cp->data + cp->adv_data_len, cp->scan_rsp_len);
- if (hdev->adv_instance.timeout)
- cancel_delayed_work(&hdev->adv_instance.timeout_exp);
+ if (hdev->adv_instance_timeout)
+ cancel_delayed_work(&hdev->adv_instance_expire);
- hdev->adv_instance.timeout = timeout;
+ hdev->adv_instance_timeout = timeout;
if (timeout)
queue_delayed_work(hdev->workqueue,
- &hdev->adv_instance.timeout_exp,
+ &hdev->adv_instance_expire,
msecs_to_jiffies(timeout * 1000));
if (!hci_dev_test_and_set_flag(hdev, HCI_ADVERTISING_INSTANCE))
goto unlock;
}
- if (hdev->adv_instance.timeout)
- cancel_delayed_work(&hdev->adv_instance.timeout_exp);
+ if (hdev->adv_instance_timeout)
+ cancel_delayed_work(&hdev->adv_instance_expire);
memset(&hdev->adv_instance, 0, sizeof(hdev->adv_instance));