Skip to content

Commit

Permalink
Fix gattlib and examples
Browse files Browse the repository at this point in the history
  • Loading branch information
oliviermartin committed Mar 17, 2024
1 parent b2c4094 commit 2a46780
Show file tree
Hide file tree
Showing 12 changed files with 197 additions and 107 deletions.
2 changes: 2 additions & 0 deletions bluez/gattlib_connect.c
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,7 @@ static gatt_connection_t *gattlib_connect_with_options(const char *src, const ch
if (conn == NULL) {
if (io_connect_arg.error) {
fprintf(stderr, "Error: gattlib_connect - initialization error:%s\n", io_connect_arg.error->message);
g_error_free(io_connect_arg.error);
} else {
fprintf(stderr, "Error: gattlib_connect - initialization\n");
}
Expand All @@ -428,6 +429,7 @@ static gatt_connection_t *gattlib_connect_with_options(const char *src, const ch

if (io_connect_arg.error) {
fprintf(stderr, "gattlib_connect - connection error:%s\n", io_connect_arg.error->message);
g_error_free(io_connect_arg.error);
return NULL;
} else {
return conn;
Expand Down
1 change: 1 addition & 0 deletions common/gattlib_callback_notification_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,5 +98,6 @@ void gattlib_on_gatt_notification(gatt_connection_t* connection, const uuid_t* u
g_thread_pool_push(connection->notification.thread_pool, arg, &error);
if (error != NULL) {
GATTLIB_LOG(GATTLIB_ERROR, "gattlib_on_gatt_notification: Failed to push thread in pool: %s", error->message);
g_error_free(error);
}
}
3 changes: 3 additions & 0 deletions common/gattlib_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ int gattlib_register_notification(gatt_connection_t* connection, gattlib_event_h
1 /* max_threads */, FALSE /* exclusive */, &error);
if (error != NULL) {
GATTLIB_LOG(GATTLIB_ERROR, "gattlib_register_notification: Failed to create thread pool: %s", error->message);
g_error_free(error);
return GATTLIB_ERROR_INTERNAL;
} else {
assert(connection->notification.thread_pool != NULL);
Expand All @@ -46,6 +47,7 @@ int gattlib_register_indication(gatt_connection_t* connection, gattlib_event_han
1 /* max_threads */, FALSE /* exclusive */, &error);
if (error != NULL) {
GATTLIB_LOG(GATTLIB_ERROR, "gattlib_register_indication: Failed to create thread pool: %s", error->message);
g_error_free(error);
return GATTLIB_ERROR_INTERNAL;
} else {
return GATTLIB_SUCCESS;
Expand Down Expand Up @@ -188,6 +190,7 @@ void gattlib_handler_dispatch_to_thread(struct gattlib_handler* handler, void (*
handler->thread = g_thread_try_new(thread_name, thread_func, thread_args, &error);
if (handler->thread == NULL) {
GATTLIB_LOG(GATTLIB_ERROR, "Failed to create thread '%s': %s", thread_name, error->message);
g_error_free(error);
return;
}
}
Expand Down
28 changes: 27 additions & 1 deletion common/mainloop/gattlib_glib_mainloop.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,42 @@
// We make this variable global to be able to exit the main loop
static GMainLoop *m_main_loop;

struct _execute_task_arg {
void* (*task)(void* arg);
void* arg;
};

static void* _execute_task(void* arg) {
struct _execute_task_arg *execute_task_arg = arg;
execute_task_arg->task(execute_task_arg->arg);
g_main_loop_quit(m_main_loop);
return NULL;
}

int gattlib_mainloop(void* (*task)(void* arg), void *arg) {
GThread *task_thread = g_thread_new("gattlib_task", task, arg);
struct _execute_task_arg execute_task_arg = {
.task = task,
.arg = arg
};
GError* error;

GThread *task_thread = g_thread_try_new("gattlib_task", _execute_task, &execute_task_arg, &error);

if (m_main_loop != NULL) {
GATTLIB_LOG(GATTLIB_ERROR, "Main loop is already running: %s", error->message);
g_error_free(error);
return GATTLIB_BUSY;
}

m_main_loop = g_main_loop_new(NULL, FALSE);

g_main_loop_run(m_main_loop);
g_main_loop_unref(m_main_loop);

g_thread_join(task_thread);
g_thread_unref(task_thread);

m_main_loop = NULL;
return GATTLIB_SUCCESS;
}

Expand Down
15 changes: 12 additions & 3 deletions dbus/gattlib_adapter.c
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,11 @@ static int _gattlib_adapter_scan_enable_with_filter(void *adapter, uuid_t **uuid
char uuid_str[MAX_LEN_UUID_STR + 1];
GVariantBuilder list_uuid_builder;

if (uuid_list == NULL) {
GATTLIB_LOG(GATTLIB_ERROR, "Could not start BLE scan. Missing list of UUIDs");
return GATTLIB_INVALID_PARAMETER;
}

GATTLIB_LOG(GATTLIB_DEBUG, "Configure bluetooth scan with UUID");

g_variant_builder_init(&list_uuid_builder, G_VARIANT_TYPE ("as"));
Expand Down Expand Up @@ -434,18 +439,22 @@ int gattlib_adapter_scan_enable_with_filter(void *adapter, uuid_t **uuid_list, i
return ret;
}

gattlib_adapter->ble_scan.is_scanning = true;

gattlib_adapter->ble_scan.scan_loop_thread = g_thread_try_new("gattlib_ble_scan", _ble_scan_loop, gattlib_adapter, &error);
if (gattlib_adapter->ble_scan.scan_loop_thread == NULL) {
GATTLIB_LOG(GATTLIB_ERROR, "Failed to create BLE scan thread: %s", error->message);
g_error_free(error);
return GATTLIB_ERROR_INTERNAL;
}

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);
}

// Free thread
g_object_unref(gattlib_adapter->ble_scan.scan_loop_thread);
g_thread_unref(gattlib_adapter->ble_scan.scan_loop_thread);
gattlib_adapter->ble_scan.scan_loop_thread = NULL;
g_mutex_unlock(&gattlib_adapter->ble_scan.scan_loop_mutex);

Expand All @@ -468,6 +477,7 @@ int gattlib_adapter_scan_enable_with_filter_non_blocking(void *adapter, uuid_t *
gattlib_adapter->ble_scan.scan_loop_thread = g_thread_try_new("gattlib_ble_scan", _ble_scan_loop, gattlib_adapter, &error);
if (gattlib_adapter->ble_scan.scan_loop_thread == NULL) {
GATTLIB_LOG(GATTLIB_ERROR, "Failed to create BLE scan thread: %s", error->message);
g_error_free(error);
return GATTLIB_ERROR_INTERNAL;
}

Expand Down Expand Up @@ -559,8 +569,7 @@ int gattlib_adapter_close(void* adapter)

// Ensure the thread is freed on adapter closing
if (gattlib_adapter->ble_scan.scan_loop_thread) {
//TODO: Fix memory leak here
//g_object_unref(gattlib_adapter->ble_scan.scan_loop_thread);
g_thread_unref(gattlib_adapter->ble_scan.scan_loop_thread);
gattlib_adapter->ble_scan.scan_loop_thread = NULL;
}

Expand Down
46 changes: 29 additions & 17 deletions examples/advertisement_data/advertisement_data.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@

#define BLE_SCAN_TIMEOUT 60

static const char* adapter_name;

static void ble_advertising_device(void *adapter, const char* addr, const char* name, void *user_data) {
gattlib_advertisement_data_t *advertisement_data;
size_t advertisement_data_count;
Expand Down Expand Up @@ -60,29 +62,14 @@ static void ble_advertising_device(void *adapter, const char* addr, const char*
printf("\n");
}

int main(int argc, const char *argv[]) {
const char* adapter_name;
static void* ble_task(void *arg) {
void* adapter;
int ret;

if (argc == 1) {
adapter_name = NULL;
} else if (argc == 2) {
adapter_name = argv[1];
} else {
GATTLIB_LOG(GATTLIB_ERROR, "%s [<bluetooth-adapter>]", argv[0]);
return 1;
}

#ifdef GATTLIB_LOG_BACKEND_SYSLOG
openlog("gattlib_advertisement_dat", LOG_CONS | LOG_NDELAY | LOG_PERROR, LOG_USER);
setlogmask(LOG_UPTO(LOG_INFO));
#endif

ret = gattlib_adapter_open(adapter_name, &adapter);
if (ret) {
GATTLIB_LOG(GATTLIB_ERROR, "Failed to open adapter.");
return 1;
return NULL;
}

ret = gattlib_adapter_scan_enable_with_filter(adapter,
Expand All @@ -103,5 +90,30 @@ int main(int argc, const char *argv[]) {

EXIT:
gattlib_adapter_close(adapter);
return NULL;
}

int main(int argc, const char *argv[]) {
int ret;

if (argc == 1) {
adapter_name = NULL;
} else if (argc == 2) {
adapter_name = argv[1];
} else {
GATTLIB_LOG(GATTLIB_ERROR, "%s [<bluetooth-adapter>]", argv[0]);
return 1;
}

#ifdef GATTLIB_LOG_BACKEND_SYSLOG
openlog("gattlib_advertisement_dat", LOG_CONS | LOG_NDELAY | LOG_PERROR, LOG_USER);
setlogmask(LOG_UPTO(LOG_INFO));
#endif

ret = gattlib_mainloop(ble_task, NULL);
if (ret != GATTLIB_SUCCESS) {
GATTLIB_LOG(GATTLIB_ERROR, "Failed to create gattlib mainloop");
}

return ret;
}
95 changes: 53 additions & 42 deletions examples/ble_scan/ble_scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
*
* GattLib - GATT Library
*
* Copyright (C) 2021 Olivier Martin <[email protected]>
*
* Copyright (C) 2021-2024 Olivier Martin <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -33,7 +32,9 @@

#include "gattlib.h"

#define BLE_SCAN_TIMEOUT 4
#define BLE_SCAN_TIMEOUT 10

static const char* adapter_name;

typedef void (*ble_discovered_device_t)(const char* addr, const char* name);

Expand All @@ -43,33 +44,19 @@ static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
LIST_HEAD(listhead, connection_t) g_ble_connections;
struct connection_t {
pthread_t thread;
void *adapter;
char* addr;
LIST_ENTRY(connection_t) entries;
};

static void *ble_connect_device(void *arg) {
struct connection_t *connection = arg;
char* addr = connection->addr;
gatt_connection_t* gatt_connection;
static void on_device_connect(void *adapter, const char *dst, gatt_connection_t* connection, int error, void* user_data) {
gattlib_primary_service_t* services;
gattlib_characteristic_t* characteristics;
int services_count, characteristics_count;
char uuid_str[MAX_LEN_UUID_STR + 1];
int ret, i;

pthread_mutex_lock(&g_mutex);

printf("------------START %s ---------------\n", addr);

gatt_connection = gattlib_connect(NULL, addr, GATTLIB_CONNECTION_OPTIONS_LEGACY_DEFAULT);
if (gatt_connection == NULL) {
GATTLIB_LOG(GATTLIB_ERROR, "Fail to connect to the bluetooth device.");
goto connection_exit;
} else {
puts("Succeeded to connect to the bluetooth device.");
}

ret = gattlib_discover_primary(gatt_connection, &services, &services_count);
ret = gattlib_discover_primary(connection, &services, &services_count);
if (ret != 0) {
GATTLIB_LOG(GATTLIB_ERROR, "Fail to discover primary services.");
goto disconnect_exit;
Expand All @@ -84,7 +71,7 @@ static void *ble_connect_device(void *arg) {
}
free(services);

ret = gattlib_discover_char(gatt_connection, &characteristics, &characteristics_count);
ret = gattlib_discover_char(connection, &characteristics, &characteristics_count);
if (ret != 0) {
GATTLIB_LOG(GATTLIB_ERROR, "Fail to discover characteristics.");
goto disconnect_exit;
Expand All @@ -99,9 +86,22 @@ static void *ble_connect_device(void *arg) {
free(characteristics);

disconnect_exit:
gattlib_disconnect(gatt_connection);
gattlib_disconnect(connection);
}

static void *ble_connect_device(void *arg) {
struct connection_t *connection = arg;
char* addr = connection->addr;
int ret;

pthread_mutex_lock(&g_mutex);
printf("------------START %s ---------------\n", addr);

ret = gattlib_connect(connection->adapter, connection->addr, GATTLIB_CONNECTION_OPTIONS_NONE, on_device_connect, NULL);
if (ret != GATTLIB_SUCCESS) {
GATTLIB_LOG(GATTLIB_ERROR, "Failed to connect to the bluetooth device '%s'", connection->addr);
}

connection_exit:
printf("------------DONE %s ---------------\n", addr);
pthread_mutex_unlock(&g_mutex);
return NULL;
Expand All @@ -123,6 +123,7 @@ static void ble_discovered_device(void *adapter, const char* addr, const char* n
return;
}
connection->addr = strdup(addr);
connection->adapter = adapter;

ret = pthread_create(&connection->thread, NULL, ble_connect_device, connection);
if (ret != 0) {
Expand All @@ -133,31 +134,14 @@ static void ble_discovered_device(void *adapter, const char* addr, const char* n
LIST_INSERT_HEAD(&g_ble_connections, connection, entries);
}

int main(int argc, const char *argv[]) {
const char* adapter_name;
static void* ble_task(void* arg) {
void* adapter;
int ret;

if (argc == 1) {
adapter_name = NULL;
} else if (argc == 2) {
adapter_name = argv[1];
} else {
printf("%s [<bluetooth-adapter>]\n", argv[0]);
return 1;
}

#ifdef GATTLIB_LOG_BACKEND_SYSLOG
openlog("gattlib_ble_scan", LOG_CONS | LOG_NDELAY | LOG_PERROR, LOG_USER);
setlogmask(LOG_UPTO(LOG_INFO));
#endif

LIST_INIT(&g_ble_connections);

ret = gattlib_adapter_open(adapter_name, &adapter);
if (ret) {
GATTLIB_LOG(GATTLIB_ERROR, "Failed to open adapter.");
return 1;
return NULL;
}

pthread_mutex_lock(&g_mutex);
Expand All @@ -183,5 +167,32 @@ int main(int argc, const char *argv[]) {

EXIT:
gattlib_adapter_close(adapter);
return NULL;
}

int main(int argc, const char *argv[]) {
int ret;

if (argc == 1) {
adapter_name = NULL;
} else if (argc == 2) {
adapter_name = argv[1];
} else {
printf("%s [<bluetooth-adapter>]\n", argv[0]);
return 1;
}

#ifdef GATTLIB_LOG_BACKEND_SYSLOG
openlog("gattlib_ble_scan", LOG_CONS | LOG_NDELAY | LOG_PERROR, LOG_USER);
setlogmask(LOG_UPTO(LOG_INFO));
#endif

LIST_INIT(&g_ble_connections);

ret = gattlib_mainloop(ble_task, NULL);
if (ret != GATTLIB_SUCCESS) {
GATTLIB_LOG(GATTLIB_ERROR, "Failed to create gattlib mainloop");
}

return ret;
}
Loading

0 comments on commit 2a46780

Please sign in to comment.