diff --git a/dbus/gattlib_adapter.c b/dbus/gattlib_adapter.c index 28a8c4e1..6ff5d6c3 100644 --- a/dbus/gattlib_adapter.c +++ b/dbus/gattlib_adapter.c @@ -203,24 +203,48 @@ on_interface_proxy_properties_changed (GDBusObjectManagerClient *device_manager, return; } - // It is a 'org.bluez.Device1' - device_manager_on_device1_signal(g_dbus_proxy_get_object_path(interface_proxy), user_data); + +static gboolean _stop_scan_func(gpointer data) { + struct gattlib_adapter *gattlib_adapter = data; + + g_mutex_lock(&gattlib_adapter->ble_scan.scan_loop_mutex); + + gattlib_adapter->ble_scan.is_scanning = false; + g_cond_signal(&gattlib_adapter->ble_scan.scan_loop_cond); + + // Unset timeout ID to not try removing it + gattlib_adapter->ble_scan.ble_scan_timeout_id = 0; + + g_mutex_unlock(&gattlib_adapter->ble_scan.scan_loop_mutex); + + GATTLIB_LOG(GATTLIB_DEBUG, "BLE scan is stopped after sacnning time has expired."); + return FALSE; +} } static void* _ble_scan_loop(void* args) { struct gattlib_adapter *gattlib_adapter = args; - // Run Glib loop for 'timeout' seconds - gattlib_adapter->ble_scan.scan_loop = g_main_loop_new(NULL, 0); + if (gattlib_adapter->ble_scan.ble_scan_timeout_id > 0) { + GATTLIB_LOG(GATTLIB_WARNING, "A BLE scan seems to already be in progress."); + } + + gattlib_adapter->ble_scan.is_scanning = true; + if (gattlib_adapter->ble_scan.ble_scan_timeout > 0) { + GATTLIB_LOG(GATTLIB_DEBUG, "Scan for BLE devices for %ld seconds", gattlib_adapter->ble_scan.ble_scan_timeout); + gattlib_adapter->ble_scan.ble_scan_timeout_id = g_timeout_add_seconds(gattlib_adapter->ble_scan.ble_scan_timeout, - stop_scan_func, gattlib_adapter->ble_scan.scan_loop); + _stop_scan_func, gattlib_adapter); } - // And start the loop... - g_main_loop_run(gattlib_adapter->ble_scan.scan_loop); - // At this point, either the timeout expired (and automatically was removed) or scan_disable was called, removing the timer. - gattlib_adapter->ble_scan.ble_scan_timeout_id = 0; + // Wait for the BLE scan to be explicitely stopped by 'gattlib_adapter_scan_disable()' or timeout. + + g_mutex_lock(&gattlib_adapter->ble_scan.scan_loop_mutex); + while (gattlib_adapter->ble_scan.is_scanning) { + g_cond_wait(&gattlib_adapter->ble_scan.scan_loop_cond, &gattlib_adapter->ble_scan.scan_loop_mutex); + } + g_mutex_unlock(&gattlib_adapter->ble_scan.scan_loop_mutex); // Note: The function only resumes when loop timeout as expired or g_main_loop_quit has been called. @@ -402,9 +426,3 @@ int gattlib_adapter_close(void* adapter) return GATTLIB_SUCCESS; } - -gboolean stop_scan_func(gpointer data) -{ - g_main_loop_quit(data); - return FALSE; -} diff --git a/dbus/gattlib_internal.h b/dbus/gattlib_internal.h index 8104402d..3c12756c 100644 --- a/dbus/gattlib_internal.h +++ b/dbus/gattlib_internal.h @@ -75,8 +75,10 @@ struct gattlib_adapter { size_t ble_scan_timeout; guint ble_scan_timeout_id; - pthread_t thread; // Thread used to run the scan_loop - GMainLoop *scan_loop; + GThread *thread; // Thread used to run the '_scan_loop()' when non-blocking + bool is_scanning; + GMutex scan_loop_mutex; + GCond scan_loop_cond; uint32_t enabled_filters; gattlib_discovered_device_t discovered_device_callback;