2024-04-03 15:16:38 +02:00
|
|
|
/*
|
|
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
*
|
|
|
|
* Copyright (c) 2024, Olivier Martin <olivier@labapart.org>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "gattlib_internal.h"
|
|
|
|
|
|
|
|
const char* device_state_str[] = {
|
|
|
|
"NOT_FOUND",
|
2024-04-05 13:25:51 +02:00
|
|
|
"CONNECTING",
|
|
|
|
"CONNECTED",
|
|
|
|
"DISCONNECTING",
|
|
|
|
"DISCONNECTED"
|
2024-04-03 15:16:38 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
static gint _compare_device_with_device_id(gconstpointer a, gconstpointer b) {
|
2024-04-05 11:43:21 +02:00
|
|
|
const gattlib_device_t* device = a;
|
2024-04-03 15:16:38 +02:00
|
|
|
const char* device_id = b;
|
|
|
|
|
|
|
|
return g_ascii_strcasecmp(device->device_id, device_id);
|
|
|
|
}
|
|
|
|
|
2024-04-05 11:43:21 +02:00
|
|
|
static GSList* _find_device_with_device_id(gattlib_adapter_t* adapter, const char* device_id) {
|
2024-04-03 15:16:38 +02:00
|
|
|
return g_slist_find_custom(adapter->devices, device_id, _compare_device_with_device_id);
|
|
|
|
}
|
|
|
|
|
2024-04-05 11:43:21 +02:00
|
|
|
gattlib_device_t* gattlib_device_get_device(gattlib_adapter_t* adapter, const char* device_id) {
|
|
|
|
GSList *item = _find_device_with_device_id(adapter, device_id);
|
2024-04-03 15:16:38 +02:00
|
|
|
if (item == NULL) {
|
2024-04-05 13:25:51 +02:00
|
|
|
return NULL;
|
2024-04-03 15:16:38 +02:00
|
|
|
}
|
|
|
|
|
2024-04-05 13:25:51 +02:00
|
|
|
return (gattlib_device_t*)item->data;
|
2024-04-03 15:16:38 +02:00
|
|
|
}
|
|
|
|
|
2024-04-05 11:43:21 +02:00
|
|
|
enum _gattlib_device_state gattlib_device_get_state(gattlib_adapter_t* adapter, const char* device_id) {
|
|
|
|
gattlib_device_t* device = gattlib_device_get_device(adapter, device_id);
|
2024-04-05 13:25:51 +02:00
|
|
|
if (device == NULL) {
|
|
|
|
return NOT_FOUND;
|
2024-04-03 15:16:38 +02:00
|
|
|
}
|
|
|
|
|
2024-04-05 13:25:51 +02:00
|
|
|
return device->state;
|
2024-04-03 15:16:38 +02:00
|
|
|
}
|
|
|
|
|
2024-04-05 11:43:21 +02:00
|
|
|
int gattlib_device_set_state(gattlib_adapter_t* adapter, const char* device_id, enum _gattlib_device_state new_state) {
|
2024-04-03 15:16:38 +02:00
|
|
|
enum _gattlib_device_state old_state;
|
|
|
|
int ret = GATTLIB_SUCCESS;
|
|
|
|
|
2024-04-05 13:25:51 +02:00
|
|
|
g_rec_mutex_lock(&m_gattlib_mutex);
|
|
|
|
|
|
|
|
if (!gattlib_adapter_is_valid(adapter)) {
|
2024-04-08 10:08:57 +02:00
|
|
|
ret = GATTLIB_ADAPTER_CLOSE;
|
2024-04-05 13:25:51 +02:00
|
|
|
goto EXIT;
|
|
|
|
}
|
2024-04-03 15:16:38 +02:00
|
|
|
|
|
|
|
old_state = gattlib_device_get_state(adapter, device_id);
|
|
|
|
if (old_state == NOT_FOUND) {
|
|
|
|
//
|
|
|
|
// The device does not exist yet
|
|
|
|
//
|
|
|
|
if (new_state != NOT_FOUND) {
|
2024-04-05 11:43:21 +02:00
|
|
|
gattlib_device_t* device = calloc(sizeof(gattlib_device_t), 1);
|
2024-04-03 15:16:38 +02:00
|
|
|
if (device == NULL) {
|
|
|
|
GATTLIB_LOG(GATTLIB_ERROR, "gattlib_device_set_state: Cannot allocate device");
|
|
|
|
ret = GATTLIB_OUT_OF_MEMORY;
|
|
|
|
goto EXIT;
|
|
|
|
}
|
|
|
|
|
|
|
|
GATTLIB_LOG(GATTLIB_DEBUG, "gattlib_device_set_state:%s: Set initial state %s", device_id, device_state_str[new_state]);
|
|
|
|
|
2024-04-05 13:25:51 +02:00
|
|
|
device->reference_counter = 1;
|
2024-04-03 15:16:38 +02:00
|
|
|
device->adapter = adapter;
|
|
|
|
device->device_id = g_strdup(device_id);
|
|
|
|
device->state = new_state;
|
2024-04-05 11:43:21 +02:00
|
|
|
device->connection.device = device;
|
2024-04-03 15:16:38 +02:00
|
|
|
|
2024-04-05 11:43:21 +02:00
|
|
|
adapter->devices = g_slist_append(adapter->devices, device);
|
2024-04-03 15:16:38 +02:00
|
|
|
} else {
|
|
|
|
GATTLIB_LOG(GATTLIB_DEBUG, "gattlib_device_set_state:%s: No state to set", device_id);
|
|
|
|
}
|
|
|
|
} else if (new_state == NOT_FOUND) {
|
|
|
|
//
|
|
|
|
// The device needs to be remove and free
|
|
|
|
//
|
2024-04-05 11:43:21 +02:00
|
|
|
GSList *item = _find_device_with_device_id(adapter, device_id);
|
2024-04-03 15:16:38 +02:00
|
|
|
if (item == NULL) {
|
|
|
|
GATTLIB_LOG(GATTLIB_ERROR, "gattlib_device_set_state: The device is not present. It is not expected");
|
|
|
|
ret = GATTLIB_UNEXPECTED;
|
|
|
|
goto EXIT;
|
|
|
|
}
|
|
|
|
|
2024-04-05 11:43:21 +02:00
|
|
|
gattlib_device_t* device = item->data;
|
2024-04-03 15:16:38 +02:00
|
|
|
|
|
|
|
switch (device->state) {
|
|
|
|
case DISCONNECTED:
|
|
|
|
GATTLIB_LOG(GATTLIB_DEBUG, "gattlib_device_set_state: Free device %p", device);
|
2024-04-05 11:43:21 +02:00
|
|
|
adapter->devices = g_slist_remove(adapter->devices, device);
|
2024-04-05 13:25:51 +02:00
|
|
|
gattlib_device_unref(device);
|
2024-04-03 15:16:38 +02:00
|
|
|
break;
|
|
|
|
case CONNECTING:
|
|
|
|
GATTLIB_LOG(GATTLIB_DEBUG, "gattlib_device_set_state: Connecting device needs to be removed - ignore it");
|
|
|
|
ret = GATTLIB_UNEXPECTED;
|
|
|
|
break;
|
|
|
|
case CONNECTED:
|
|
|
|
GATTLIB_LOG(GATTLIB_DEBUG, "gattlib_device_set_state: Connecting device needs to be removed - ignore it");
|
|
|
|
ret = GATTLIB_UNEXPECTED;
|
|
|
|
break;
|
|
|
|
case DISCONNECTING:
|
|
|
|
GATTLIB_LOG(GATTLIB_DEBUG, "gattlib_device_set_state: Connecting device needs to be removed - ignore it");
|
|
|
|
ret = GATTLIB_UNEXPECTED;
|
|
|
|
break;
|
|
|
|
case NOT_FOUND:
|
|
|
|
GATTLIB_LOG(GATTLIB_DEBUG, "gattlib_device_set_state: Not found device needs to be removed - ignore it");
|
|
|
|
ret = GATTLIB_UNEXPECTED;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
GATTLIB_LOG(GATTLIB_DEBUG, "gattlib_device_set_state:%s: Set state %s", device_id, device_state_str[new_state]);
|
|
|
|
|
2024-04-05 11:43:21 +02:00
|
|
|
gattlib_device_t* device = gattlib_device_get_device(adapter, device_id);
|
2024-04-03 15:16:38 +02:00
|
|
|
device->state = new_state;
|
|
|
|
}
|
|
|
|
|
|
|
|
EXIT:
|
2024-04-05 13:25:51 +02:00
|
|
|
g_rec_mutex_unlock(&m_gattlib_mutex);
|
2024-04-03 15:16:38 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void _gattlib_device_free(gpointer data) {
|
2024-04-05 11:43:21 +02:00
|
|
|
gattlib_device_t* device = data;
|
2024-04-03 15:16:38 +02:00
|
|
|
|
|
|
|
switch (device->state) {
|
|
|
|
case DISCONNECTED:
|
2024-04-05 13:25:51 +02:00
|
|
|
gattlib_device_unref(device);
|
2024-04-03 15:16:38 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
GATTLIB_LOG(GATTLIB_WARNING, "Memory of the BLE device '%s' has not been freed because in state %s",
|
|
|
|
device->device_id, device_state_str[device->state]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-05 11:43:21 +02:00
|
|
|
int gattlib_devices_free(gattlib_adapter_t* adapter) {
|
|
|
|
g_slist_free_full(adapter->devices, _gattlib_device_free);
|
2024-04-03 15:16:38 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2024-04-05 13:25:51 +02:00
|
|
|
int gattlib_device_unref(gattlib_device_t* device) {
|
|
|
|
g_rec_mutex_lock(&m_gattlib_mutex);
|
|
|
|
device->reference_counter--;
|
|
|
|
if (device->reference_counter > 0) {
|
|
|
|
goto EXIT;
|
|
|
|
}
|
|
|
|
|
|
|
|
free(device);
|
|
|
|
|
|
|
|
EXIT:
|
|
|
|
g_rec_mutex_unlock(&m_gattlib_mutex);
|
|
|
|
return GATTLIB_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2024-04-03 15:16:38 +02:00
|
|
|
static void _gattlib_device_is_disconnected(gpointer data, gpointer user_data) {
|
2024-04-05 11:43:21 +02:00
|
|
|
gattlib_device_t* device = data;
|
2024-04-03 15:16:38 +02:00
|
|
|
bool* devices_are_disconnected_ptr = user_data;
|
|
|
|
|
|
|
|
if (device->state != DISCONNECTED) {
|
|
|
|
*devices_are_disconnected_ptr = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-05 11:43:21 +02:00
|
|
|
int gattlib_devices_are_disconnected(gattlib_adapter_t* adapter) {
|
2024-04-03 15:16:38 +02:00
|
|
|
bool devices_are_disconnected = true;
|
|
|
|
|
2024-04-05 11:43:21 +02:00
|
|
|
g_slist_foreach(adapter->devices, _gattlib_device_is_disconnected, &devices_are_disconnected);
|
2024-04-03 15:16:38 +02:00
|
|
|
|
|
|
|
return devices_are_disconnected;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
|
|
|
static void _gattlib_device_dump_state(gpointer data, gpointer user_data) {
|
2024-04-05 11:43:21 +02:00
|
|
|
gattlib_device_t* device = data;
|
2024-04-03 15:16:38 +02:00
|
|
|
GATTLIB_LOG(GATTLIB_DEBUG, "\t%s: %s", device->device_id, device_state_str[device->state]);
|
|
|
|
}
|
|
|
|
|
2024-04-05 11:43:21 +02:00
|
|
|
void gattlib_devices_dump_state(gattlib_adapter_t* adapter) {
|
2024-04-05 13:25:51 +02:00
|
|
|
g_rec_mutex_lock(&m_gattlib_mutex);
|
|
|
|
|
|
|
|
if (!gattlib_adapter_is_valid(adapter)) {
|
|
|
|
goto EXIT;
|
|
|
|
}
|
|
|
|
|
2024-04-03 15:16:38 +02:00
|
|
|
GATTLIB_LOG(GATTLIB_DEBUG, "Device list:");
|
2024-04-05 11:43:21 +02:00
|
|
|
g_slist_foreach(adapter->devices, _gattlib_device_dump_state, NULL);
|
2024-04-05 13:25:51 +02:00
|
|
|
|
|
|
|
EXIT:
|
|
|
|
g_rec_mutex_unlock(&m_gattlib_mutex);
|
2024-04-03 15:16:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|