Re: [PATCH BlueZ] src/adapter: add timeout for missing discovery

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Luiz,

On 9/12/25 16:15, Luiz Augusto von Dentz wrote:
Hi Andreas,

On Fri, Sep 12, 2025 at 6:36 AM Andreas Glinserer
<andreas.glinserer@xxxxxxxxxxxxx> wrote:

Add a timeout to detect when the controller stops sending discovery
events. Without this, the system silently discovering new devices
and the scan list gradually empties due to DEFAULT_TEMPORARY_TIMEOUT.

When the timeout triggers, issue MGMT_OP_STOP_DISCOVERY to restart the
event loop and resume discovery.

I'm not really sure how sending stop would make any difference?
The correct technical reason I also do not understand. Sending the stop gets the controller out of the (presumably) faulty state and correctly starts rediscovering. To get to the bottom of this, I am missing more fundamental knowledge. My first assumption was, that just sending another start discovery would work, but this returned a busy. From this I concluded, that the controller is doing something and stuck at doing it. The next logical thing for me was stopping it by sending stop which is working and getting the controller back into a working event loop.

From my testing I can see it is not a hardware specific issue. I had this issue on the following devices/bluetooth controller on different pcs:
- Intel Bluetooth 9460/9560 Jefferson Peak
- Mediatek 7925
- Intel BE200 usb device


Link: https://github.com/bluez/bluez/issues/1554

The bug mentioned BlueZ version 1.72?, well I guess that is 4.72 which
is very old, have you tried with something more recent?
I am terribly sorry, version is 5.72 (Ubuntu 24.04). I also corrected it in the GH issue. I see this issue with 5.79 (Ubuntu 25.04) as well.

---
  src/adapter.c | 35 +++++++++++++++++++++++++++++++++++
  1 file changed, 35 insertions(+)

diff --git a/src/adapter.c b/src/adapter.c
index dc5ba65d7..1ec665c73 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -342,6 +342,7 @@ struct btd_adapter {

         struct queue *exp_pending;
         struct queue *exps;
+       unsigned int last_discovery_timeout_id;         /* Timeout for discovery stop if no cb is coming */
  };

  static char *adapter_power_state_str(uint32_t power_state)
@@ -1727,6 +1728,11 @@ static void discovery_cleanup(struct btd_adapter *adapter, int timeout)
                 adapter->discovery_idle_timeout = 0;
         }

+       if (adapter->last_discovery_timeout_id > 0) {
+               timeout_remove(adapter->last_discovery_timeout_id);
+               adapter->last_discovery_timeout_id = 0;
+       }
+
         g_slist_free_full(adapter->discovery_found,
                                                 invalidate_rssi_and_tx_power);
         adapter->discovery_found = NULL;
@@ -1833,6 +1839,8 @@ static struct discovery_client *discovery_complete(struct btd_adapter *adapter,
         return client;
  }

+static bool time_since_last_discovery_cb(gpointer user_data);
+
  static void start_discovery_complete(uint8_t status, uint16_t length,
                                         const void *param, void *user_data)
  {
@@ -1900,6 +1908,20 @@ static void start_discovery_complete(uint8_t status, uint16_t length,
         trigger_start_discovery(adapter, IDLE_DISCOV_TIMEOUT * 2);
  }

+static bool time_since_last_discovery_cb(gpointer user_data)
+{
+       struct btd_adapter *adapter = user_data;
+       struct mgmt_cp_start_discovery cp;
+       DBG("");
+       cp.type =  get_scan_type(adapter);
+
+       mgmt_send(adapter->mgmt, MGMT_OP_STOP_DISCOVERY,
+               adapter->dev_id, sizeof(cp), &cp,
+               NULL, NULL, NULL);
+
+       return FALSE;
+}
+
  static bool start_discovery_timeout(gpointer user_data)
  {
         struct btd_adapter *adapter = user_data;
@@ -1909,6 +1931,9 @@ static bool start_discovery_timeout(gpointer user_data)
         DBG("");

         adapter->discovery_idle_timeout = 0;
+       adapter->last_discovery_timeout_id = timeout_add_seconds(
+               IDLE_DISCOV_TIMEOUT * 3, time_since_last_discovery_cb,
+               adapter, NULL);

         /* If we're doing filtered discovery, it must be quickly restarted */
         adapter->no_scan_restart_delay = !!adapter->current_discovery_filter;
@@ -2009,6 +2034,11 @@ static void trigger_start_discovery(struct btd_adapter *adapter, guint delay)
         if (!btd_adapter_get_powered(adapter))
                 return;

+       if (adapter->last_discovery_timeout_id > 0) {
+               timeout_remove(adapter->last_discovery_timeout_id);
+               adapter->last_discovery_timeout_id = 0;
+       }
+
         adapter->discovery_idle_timeout = timeout_add_seconds(delay,
                                         start_discovery_timeout, adapter, NULL);
  }
@@ -2053,6 +2083,11 @@ static void suspend_discovery(struct btd_adapter *adapter)
                 adapter->discovery_idle_timeout = 0;
         }

+       if (adapter->last_discovery_timeout_id > 0) {
+               timeout_remove(adapter->last_discovery_timeout_id);
+               adapter->last_discovery_timeout_id = 0;
+       }
+
         if (adapter->discovery_enable == 0x00)
                 return;

--
2.43.0









[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux