diff --git a/common/gattlib_common_adapter.c b/common/gattlib_common_adapter.c index 2a514cd..0c10a5f 100644 --- a/common/gattlib_common_adapter.c +++ b/common/gattlib_common_adapter.c @@ -10,6 +10,38 @@ // It could happen when using Python wrapper. GSList *m_adapter_list; +static int stricmp(char const *a, char const *b) { + for (;; a++, b++) { + int d = tolower((unsigned char)*a) - tolower((unsigned char)*b); + if (d != 0 || !*a) + return d; + } +} + +static gint _is_adapter_id(gconstpointer a, gconstpointer b) { + const gattlib_adapter_t* adapter = a; + const char* adapter_id = b; + + return stricmp(adapter->id, adapter_id); +} + +gattlib_adapter_t* gattlib_adapter_from_id(const char* adapter_id) { + gattlib_adapter_t* adapter = NULL; + + g_rec_mutex_lock(&m_gattlib_mutex); + + GSList *adapter_entry = g_slist_find_custom(m_adapter_list, adapter_id, _is_adapter_id); + if (adapter_entry == NULL) { + goto EXIT; + } + + adapter = adapter_entry->data; + +EXIT: + g_rec_mutex_unlock(&m_gattlib_mutex); + return adapter; +} + bool gattlib_adapter_is_valid(gattlib_adapter_t* adapter) { bool is_valid; diff --git a/common/gattlib_internal.h b/common/gattlib_internal.h index 61e3639..d834006 100644 --- a/common/gattlib_internal.h +++ b/common/gattlib_internal.h @@ -68,6 +68,9 @@ struct _gattlib_adapter { // Context specific to the backend implementation (eg: dbus backend) struct _gattlib_adapter_backend backend; + // BLE adapter id (could be its DBUS device path on Linux) + char* id; + // BLE adapter name char* name; @@ -121,6 +124,7 @@ extern GSList *m_adapter_list; // This structure is used for inter-thread communication extern struct gattlib_signal m_gattlib_signal; +gattlib_adapter_t* gattlib_adapter_from_id(const char* adapter_id); bool gattlib_adapter_is_valid(gattlib_adapter_t* adapter); bool gattlib_adapter_is_scanning(gattlib_adapter_t* adapter); int gattlib_adapter_ref(gattlib_adapter_t* adapter); diff --git a/dbus/gattlib_adapter.c b/dbus/gattlib_adapter.c index 7d1f11a..7ada4f2 100644 --- a/dbus/gattlib_adapter.c +++ b/dbus/gattlib_adapter.c @@ -28,10 +28,21 @@ int gattlib_adapter_open(const char* adapter_name, gattlib_adapter_t** adapter) adapter_name = GATTLIB_DEFAULT_ADAPTER; } - GATTLIB_LOG(GATTLIB_DEBUG, "Open bluetooth adapter %s", adapter_name); - snprintf(object_path, sizeof(object_path), "/org/bluez/%s", adapter_name); + // Check if adapter has already be loaded + g_rec_mutex_lock(&m_gattlib_mutex); + *adapter = gattlib_adapter_from_id(object_path); + if (*adapter != NULL) { + GATTLIB_LOG(GATTLIB_DEBUG, "Bluetooth adapter %s has already been opened. Re-use it", adapter_name); + gattlib_adapter_ref(*adapter); + g_rec_mutex_unlock(&m_gattlib_mutex); + return GATTLIB_SUCCESS; + } + g_rec_mutex_unlock(&m_gattlib_mutex); + + GATTLIB_LOG(GATTLIB_DEBUG, "Open bluetooth adapter %s", adapter_name); + adapter_proxy = org_bluez_adapter1_proxy_new_for_bus_sync( G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, "org.bluez", @@ -58,6 +69,7 @@ int gattlib_adapter_open(const char* adapter_name, gattlib_adapter_t** adapter) } // Initialize stucture + gattlib_adapter->id = strdup(object_path); gattlib_adapter->name = strdup(adapter_name); gattlib_adapter->reference_counter = 1; gattlib_adapter->backend.adapter_proxy = adapter_proxy; @@ -651,11 +663,6 @@ int gattlib_adapter_close(gattlib_adapter_t* adapter) { bool are_devices_disconnected; int ret = GATTLIB_SUCCESS; - // - // TODO: Should we use reference counting to be able to open multiple times an adapter - // without freeing it on the first gattlib_adapter_close() - // - g_rec_mutex_lock(&m_gattlib_mutex); if (!gattlib_adapter_is_valid(adapter)) { @@ -689,9 +696,6 @@ int gattlib_adapter_close(gattlib_adapter_t* adapter) { // Unref/Free the adapter gattlib_adapter_unref(adapter); - // Remove adapter from the global list - m_adapter_list = g_slist_remove(m_adapter_list, adapter); - EXIT: g_rec_mutex_unlock(&m_gattlib_mutex); return ret; @@ -730,6 +734,11 @@ int gattlib_adapter_unref(gattlib_adapter_t* adapter) { adapter->backend.adapter_proxy = NULL; } + if (adapter->id != NULL) { + free(adapter->id); + adapter->id = NULL; + } + if (adapter->name != NULL) { free(adapter->name); adapter->name = NULL; @@ -737,6 +746,9 @@ int gattlib_adapter_unref(gattlib_adapter_t* adapter) { gattlib_devices_free(adapter); + // Remove adapter from the global list + m_adapter_list = g_slist_remove(m_adapter_list, adapter); + free(adapter); EXIT: