diff --git a/dbus/gattlib.c b/dbus/gattlib.c index 53d4238..d4ee3cc 100644 --- a/dbus/gattlib.c +++ b/dbus/gattlib.c @@ -40,6 +40,8 @@ static void _on_device_connect(gatt_connection_t* connection) { } conn_context->dbus_objects = g_dbus_object_manager_get_objects(device_manager); + gattlib_device_set_state(conn_context->adapter, connection->device_id, CONNECTED); + gattlib_on_connected_device(connection); } @@ -183,6 +185,16 @@ int gattlib_connect(void *adapter, const char *dst, get_device_path_from_mac(adapter_name, dst, object_path, sizeof(object_path)); + gatt_connection_t* connection = gattlib_device_get_device(adapter, object_path); + if (connection == NULL) { + GATTLIB_LOG(GATTLIB_DEBUG, "gattlib_connect: Cannot find connection %s", dst); + return GATTLIB_INVALID_PARAMETER; + } else if (connection->state != DISCONNECTED) { + GATTLIB_LOG(GATTLIB_DEBUG, "gattlib_connect: Cannot connect to '%s'. Device is in state %s", + dst, device_state_str[connection->state]); + return GATTLIB_BUSY; + } + gattlib_context_t* conn_context = calloc(sizeof(gattlib_context_t), 1); if (conn_context == NULL) { GATTLIB_LOG(GATTLIB_DEBUG, "gattlib_connect: Cannot allocate context"); @@ -190,18 +202,14 @@ int gattlib_connect(void *adapter, const char *dst, } conn_context->adapter = gattlib_adapter; - gatt_connection_t* connection = calloc(sizeof(gatt_connection_t), 1); - if (connection == NULL) { - GATTLIB_LOG(GATTLIB_DEBUG, "gattlib_connect: Cannot allocate connection"); - ret = GATTLIB_OUT_OF_MEMORY; - goto FREE_CONN_CONTEXT; - } - connection->context = conn_context; connection->on_connection.callback.connection_handler = connect_cb; connection->on_connection.user_data = user_data; - GATTLIB_LOG(GATTLIB_DEBUG, "Connect bluetooth device %s", dst); + GATTLIB_LOG(GATTLIB_DEBUG, "Connecting bluetooth device %s", dst); + + // Mark the device has disconnected + gattlib_device_set_state(connection->adapter, connection->device_id, CONNECTING); OrgBluezDevice1* device = org_bluez_device1_proxy_new_for_bus_sync( G_BUS_TYPE_SYSTEM, @@ -219,7 +227,7 @@ int gattlib_connect(void *adapter, const char *dst, } else { GATTLIB_LOG(GATTLIB_ERROR, "gattlib_connect: Failed to connect to DBus Bluez Device"); } - goto FREE_CONNECTION; + goto FREE_CONNECTION_CONTEXT; } else { conn_context->device = device; conn_context->device_object_path = strdup(object_path); @@ -263,10 +271,7 @@ FREE_DEVICE: free(conn_context->device_object_path); g_object_unref(conn_context->device); -FREE_CONNECTION: - free(connection); - -FREE_CONN_CONTEXT: +FREE_CONNECTION_CONTEXT: free(conn_context); // destroy default adapter @@ -289,9 +294,13 @@ FREE_CONN_CONTEXT: */ void gattlib_connection_free(gatt_connection_t* connection) { gattlib_context_t* conn_context; + void* adapter; + char* device_id; g_mutex_lock(&connection->device_mutex); conn_context = connection->context; + adapter = conn_context->adapter; + device_id = connection->device_id; // Remove signal if (conn_context->on_handle_device_property_change_id != 0) { @@ -326,10 +335,10 @@ void gattlib_connection_free(gatt_connection_t* connection) { free(connection->context); connection->context = NULL; - g_mutex_unlock(&connection->device_mutex); + // Mark the device has disconnected + gattlib_device_set_state(adapter, device_id, DISCONNECTED); - // And finally free the connection - free(connection); + g_mutex_unlock(&connection->device_mutex); } int gattlib_disconnect(gatt_connection_t* connection, bool wait_disconnection) { @@ -349,9 +358,14 @@ int gattlib_disconnect(gatt_connection_t* connection, bool wait_disconnection) { GATTLIB_LOG(GATTLIB_ERROR, "Cannot disconnect - connection context is not valid."); ret = GATTLIB_NOT_SUPPORTED; goto EXIT; + } else if (connection->state != CONNECTED) { + GATTLIB_LOG(GATTLIB_ERROR, "Cannot disconnect - connection is not in connected state (state=%s).", + device_state_str[connection->state]); + ret = GATTLIB_BUSY; + goto EXIT; } - GATTLIB_LOG(GATTLIB_DEBUG, "Disconnect bluetooth device %s", conn_context->device_object_path); + GATTLIB_LOG(GATTLIB_DEBUG, "Disconnecting bluetooth device %s", conn_context->device_object_path); org_bluez_device1_call_disconnect_sync(conn_context->device, NULL, &error); if (error) { @@ -359,6 +373,9 @@ int gattlib_disconnect(gatt_connection_t* connection, bool wait_disconnection) { g_error_free(error); } + // Mark the device has disconnected + gattlib_device_set_state(connection->adapter, connection->device_id, DISCONNECTING); + //Note: Signals and memory will be removed/clean on disconnction callback // See _gattlib_clean_on_disconnection() diff --git a/dbus/gattlib_adapter.c b/dbus/gattlib_adapter.c index fdd3050..dc87d88 100644 --- a/dbus/gattlib_adapter.c +++ b/dbus/gattlib_adapter.c @@ -143,12 +143,9 @@ static void device_manager_on_added_device1_signal(const char* device1_path, str //TODO: Add support for connected device with 'gboolean org_bluez_device1_get_connected (OrgBluezDevice1 *object);' // When the device is connected, we potentially need to initialize some attributes - ret = gattlib_device_set_state(gattlib_adapter, address, DISCONNECTED); - + ret = gattlib_device_set_state(gattlib_adapter, device1_path, DISCONNECTED); if (ret == GATTLIB_SUCCESS) { - if (gattlib_adapter->ble_scan.enabled_filters & GATTLIB_DISCOVER_FILTER_NOTIFY_CHANGE) { - gattlib_on_discovered_device(gattlib_adapter, device1); - } + gattlib_on_discovered_device(gattlib_adapter, device1); } g_rec_mutex_unlock(&gattlib_adapter->mutex); @@ -226,40 +223,28 @@ on_interface_proxy_properties_changed (GDBusObjectManagerClient *device_manager, return; } - const char* device_mac_address = org_bluez_device1_get_address(device1); - // Check if the device has been disconnected GVariantDict dict; g_variant_dict_init(&dict, changed_properties); - GVariant* connected = g_variant_dict_lookup_value(&dict, "Connected", NULL); - GVariant* rssi = g_variant_dict_lookup_value(&dict, "RSSI", NULL); + GVariant* has_rssi = g_variant_dict_lookup_value(&dict, "RSSI", NULL); + GVariant* has_manufacturer_data = g_variant_dict_lookup_value(&dict, "ManufacturerData", NULL); - g_mutex_lock(&gattlib_adapter->ble_scan.discovered_devices_mutex); + g_rec_mutex_lock(&gattlib_adapter->mutex); - // Check if the device is already part of the list - GSList *found_device = g_slist_find_custom(gattlib_adapter->ble_scan.discovered_devices, device_mac_address, (GCompareFunc)g_ascii_strcasecmp); + enum _gattlib_device_state old_device_state = gattlib_device_get_state(gattlib_adapter, proxy_object_path); - if (connected && !g_variant_get_boolean(connected)) { - // The device has been disconnected. We will remove it from the list of discovered device. - // In case the device has been found again, it will be seen as a new device - - GATTLIB_LOG(GATTLIB_INFO, "Device %s has been disconnected", device_mac_address); - - if (found_device) { - gattlib_adapter->ble_scan.discovered_devices = g_slist_remove(gattlib_adapter->ble_scan.discovered_devices, found_device); - } - } else if (rssi) { - // First time this device is in the list - if (found_device == NULL) { - // Add the device to the list - gattlib_adapter->ble_scan.discovered_devices = g_slist_append(gattlib_adapter->ble_scan.discovered_devices, g_strdup(device_mac_address)); - gattlib_on_discovered_device(gattlib_adapter, device1); + if (old_device_state == NOT_FOUND) { + if (has_rssi || has_manufacturer_data) { + int ret = gattlib_device_set_state(gattlib_adapter, proxy_object_path, DISCONNECTED); + if (ret == GATTLIB_SUCCESS) { + gattlib_on_discovered_device(gattlib_adapter, device1); + } } } - g_mutex_unlock(&gattlib_adapter->ble_scan.discovered_devices_mutex); + + g_rec_mutex_unlock(&gattlib_adapter->mutex); g_variant_dict_end(&dict); - g_object_unref(device1); } } @@ -549,9 +534,15 @@ EXIT: return GATTLIB_SUCCESS; } -int gattlib_adapter_close(void* adapter) -{ +int gattlib_adapter_close(void* adapter) { struct gattlib_adapter *gattlib_adapter = adapter; + bool are_devices_disconnected; + + are_devices_disconnected = gattlib_devices_are_disconnected(adapter); + if (!are_devices_disconnected) { + GATTLIB_LOG(GATTLIB_ERROR, "Adapter cannot be closed as some devices are not disconnected"); + return GATTLIB_BUSY; + } g_mutex_lock(&m_adapter_list_mutex); GSList *adapter_entry = g_slist_find(m_adapter_list, adapter);