error: Introduce error module to catch DBUS error details

pull/266/head
Olivier Martin 2024-02-15 21:44:34 +01:00 committed by Olivier Martin
parent ad7aa1899e
commit 4c5f35f15f
9 changed files with 131 additions and 60 deletions

View File

@ -85,7 +85,7 @@ int gattlib_discover_primary(gatt_connection_t* connection, gattlib_primary_serv
ret = gatt_discover_primary(conn_context->attrib, NULL, primary_all_cb, &user_data);
if (ret == 0) {
GATTLIB_LOG(GATTLIB_ERROR, "Fail to discover primary services.");
return GATTLIB_ERROR_BLUEZ;
return GATTLIB_ERROR_BLUEZ_WITH_ERROR(ret);
}
// Wait for completion
@ -157,11 +157,11 @@ int gattlib_discover_char_range(gatt_connection_t* connection, int start, int en
ret = gatt_discover_char(conn_context->attrib, start, end, NULL, characteristic_cb, &user_data);
if (ret == 0) {
GATTLIB_LOG(GATTLIB_ERROR, "Fail to discover characteristics.");
return GATTLIB_ERROR_BLUEZ;
return GATTLIB_ERROR_BLUEZ_WITH_ERROR(ret);
}
// Wait for completion
while(user_data.discovered == FALSE) {
while(user_data.discovered == FALSE) {
g_main_context_iteration(g_gattlib_thread.loop_context, FALSE);
}
*characteristics = user_data.characteristics;
@ -278,7 +278,7 @@ int gattlib_discover_desc_range(gatt_connection_t* connection, int start, int en
#endif
if (ret == 0) {
fprintf(stderr, "Fail to discover descriptors.\n");
return GATTLIB_ERROR_BLUEZ;
return GATTLIB_ERROR_BLUEZ_WITH_ERROR(ret);
}
// Wait for completion

View File

@ -24,6 +24,7 @@ static void* glib_event_thread(void* main_loop_p) {
static void _on_device_connect(gatt_connection_t* connection) {
gattlib_context_t* conn_context = connection->context;
GDBusObjectManager *device_manager;
GError *error = NULL;
// Stop the timeout for connection
if (conn_context->connection_timeout) {
@ -32,10 +33,14 @@ static void _on_device_connect(gatt_connection_t* connection) {
}
// Get list of objects belonging to Device Manager
device_manager = get_device_manager_from_adapter(conn_context->adapter);
device_manager = get_device_manager_from_adapter(conn_context->adapter, &error);
if (device_manager == NULL) {
GATTLIB_LOG(GATTLIB_DEBUG, "gattlib_connect: Failed to get device manager from adapter");
if (error != NULL) {
GATTLIB_LOG(GATTLIB_ERROR, "gattlib_connect: Failed to get device manager from adapter (%d, %d).", error->domain, error->code);
g_error_free(error);
} else {
GATTLIB_LOG(GATTLIB_ERROR, "gattlib_connect: Failed to get device manager from adapter");
}
//TODO: Free device
return;
}
@ -237,9 +242,14 @@ gatt_connection_t *gattlib_connect(void* adapter, const char *dst, unsigned long
conn_context->connection_loop = NULL;
// Get list of objects belonging to Device Manager
device_manager = get_device_manager_from_adapter(conn_context->adapter);
device_manager = get_device_manager_from_adapter(conn_context->adapter, &error);
if (device_manager == NULL) {
GATTLIB_LOG(GATTLIB_DEBUG, "gattlib_connect: Failed to get device manager from adapter");
if (error != NULL) {
GATTLIB_LOG(GATTLIB_ERROR, "gattlib_connect: Failed to get device manager from adapter (%d, %d).", error->domain, error->code);
g_error_free(error);
} else {
GATTLIB_LOG(GATTLIB_ERROR, "gattlib_connect: Failed to get device manager from adapter.");
}
goto FREE_DEVICE;
}
conn_context->dbus_objects = g_dbus_object_manager_get_objects(device_manager);
@ -417,17 +427,24 @@ int gattlib_discover_primary(gatt_connection_t* connection, gattlib_primary_serv
}
gattlib_context_t* conn_context = connection->context;
GDBusObjectManager *device_manager = get_device_manager_from_adapter(conn_context->adapter);
GError *error = NULL;
GDBusObjectManager *device_manager = get_device_manager_from_adapter(conn_context->adapter, &error);
OrgBluezDevice1* device = conn_context->device;
const gchar* const* service_str;
GError *error = NULL;
int ret = GATTLIB_SUCCESS;
const gchar* const* service_strs = org_bluez_device1_get_uuids(device);
if (device_manager == NULL) {
GATTLIB_LOG(GATTLIB_ERROR, "Gattlib context not initialized.");
return GATTLIB_INVALID_PARAMETER;
if (error != NULL) {
ret = GATTLIB_ERROR_DBUS_WITH_ERROR(error);
GATTLIB_LOG(GATTLIB_ERROR, "Gattlib Context not initialized (%d, %d).", error->domain, error->code);
g_error_free(error);
} else {
ret = GATTLIB_ERROR_DBUS;
GATTLIB_LOG(GATTLIB_ERROR, "Gattlib Context not initialized.");
}
return ret;
}
if (service_strs == NULL) {
@ -802,13 +819,21 @@ static void add_characteristics_from_service(gattlib_context_t* conn_context, GD
int gattlib_discover_char_range(gatt_connection_t* connection, int start, int end, gattlib_characteristic_t** characteristics, int* characteristics_count) {
gattlib_context_t* conn_context = connection->context;
GDBusObjectManager *device_manager = get_device_manager_from_adapter(conn_context->adapter);
GError *error = NULL;
GDBusObjectManager *device_manager = get_device_manager_from_adapter(conn_context->adapter, &error);
GList *l;
int ret;
if (device_manager == NULL) {
GATTLIB_LOG(GATTLIB_ERROR, "Gattlib context not initialized.");
return GATTLIB_INVALID_PARAMETER;
if (error != NULL) {
ret = GATTLIB_ERROR_DBUS_WITH_ERROR(error);
GATTLIB_LOG(GATTLIB_ERROR, "Gattlib Context not initialized (%d, %d).", error->domain, error->code);
g_error_free(error);
} else {
ret = GATTLIB_ERROR_DBUS;
GATTLIB_LOG(GATTLIB_ERROR, "Gattlib Context not initialized.");
}
return ret;
}
// Count the maximum number of characteristic to allocate the array (we count all the characterstic for all devices)
@ -917,6 +942,7 @@ int get_bluez_device_from_mac(struct gattlib_adapter *adapter, const char *mac_a
{
GError *error = NULL;
char object_path[100];
int ret;
if (adapter != NULL) {
get_device_path_from_mac_with_adapter(adapter->adapter_proxy, mac_address, object_path, sizeof(object_path));
@ -932,9 +958,10 @@ int get_bluez_device_from_mac(struct gattlib_adapter *adapter, const char *mac_a
NULL,
&error);
if (error) {
ret = GATTLIB_ERROR_DBUS_WITH_ERROR(error);
GATTLIB_LOG(GATTLIB_ERROR, "Failed to connection to new DBus Bluez Device: %s", error->message);
g_error_free(error);
return GATTLIB_ERROR_DBUS;
return ret;
}
return GATTLIB_SUCCESS;

View File

@ -29,13 +29,15 @@ int gattlib_adapter_open(const char* adapter_name, void** adapter) {
object_path,
NULL, &error);
if (adapter_proxy == NULL) {
int ret = GATTLIB_ERROR_DBUS;
if (error) {
GATTLIB_LOG(GATTLIB_ERROR, "Failed to get adapter %s: %s", object_path, error->message);
ret = GATTLIB_ERROR_DBUS_WITH_ERROR(error);
g_error_free(error);
} else {
GATTLIB_LOG(GATTLIB_ERROR, "Failed to get adapter %s", object_path);
}
return GATTLIB_ERROR_DBUS;
return ret;
}
// Ensure the adapter is powered on
@ -71,9 +73,7 @@ struct gattlib_adapter *init_default_adapter(void) {
}
}
GDBusObjectManager *get_device_manager_from_adapter(struct gattlib_adapter *gattlib_adapter) {
GError *error = NULL;
GDBusObjectManager *get_device_manager_from_adapter(struct gattlib_adapter *gattlib_adapter, GError **error) {
if (gattlib_adapter->device_manager) {
return gattlib_adapter->device_manager;
}
@ -89,14 +89,8 @@ GDBusObjectManager *get_device_manager_from_adapter(struct gattlib_adapter *gatt
"org.bluez",
"/",
NULL, NULL, NULL, NULL,
&error);
error);
if (gattlib_adapter->device_manager == NULL) {
if (error) {
GATTLIB_LOG(GATTLIB_ERROR, "Failed to get Bluez Device Manager: %s", error->message);
g_error_free(error);
} else {
GATTLIB_LOG(GATTLIB_ERROR, "Failed to get Bluez Device Manager.");
}
return NULL;
}
@ -266,6 +260,7 @@ static int _gattlib_adapter_scan_enable_with_filter(void *adapter, uuid_t **uuid
GError *error = NULL;
GVariantBuilder arg_properties_builder;
GVariant *rssi_variant = NULL;
int ret;
g_variant_builder_init(&arg_properties_builder, G_VARIANT_TYPE("a{sv}"));
@ -296,10 +291,11 @@ static int _gattlib_adapter_scan_enable_with_filter(void *adapter, uuid_t **uuid
}
if (error) {
ret = GATTLIB_ERROR_DBUS_WITH_ERROR(error);
GATTLIB_LOG(GATTLIB_ERROR, "Failed to set discovery filter: %s (%d.%d)",
error->message, error->domain, error->code);
g_error_free(error);
return GATTLIB_ERROR_DBUS;
return ret;
}
//
@ -307,9 +303,15 @@ static int _gattlib_adapter_scan_enable_with_filter(void *adapter, uuid_t **uuid
// We should get notified when the connection is lost with the target to allow
// us to advertise us again
//
device_manager = get_device_manager_from_adapter(gattlib_adapter);
device_manager = get_device_manager_from_adapter(gattlib_adapter, &error);
if (device_manager == NULL) {
return GATTLIB_ERROR_DBUS;
if (error != NULL) {
ret = GATTLIB_ERROR_DBUS_WITH_ERROR(error);
g_error_free(error);
} else {
ret = GATTLIB_ERROR_DBUS;
}
return ret;
}
// Clear BLE scan structure
@ -333,9 +335,10 @@ static int _gattlib_adapter_scan_enable_with_filter(void *adapter, uuid_t **uuid
// Now, start BLE discovery
org_bluez_adapter1_call_start_discovery_sync(gattlib_adapter->adapter_proxy, NULL, &error);
if (error) {
ret = GATTLIB_ERROR_DBUS_WITH_ERROR(error);
GATTLIB_LOG(GATTLIB_ERROR, "Failed to start discovery: %s", error->message);
g_error_free(error);
return GATTLIB_ERROR_DBUS;
return ret;
}
return GATTLIB_SUCCESS;

View File

@ -103,8 +103,8 @@ static bool handle_dbus_battery_from_uuid(gattlib_context_t* conn_context, const
struct dbus_characteristic get_characteristic_from_uuid(gatt_connection_t* connection, const uuid_t* uuid) {
gattlib_context_t* conn_context = connection->context;
GDBusObjectManager *device_manager = get_device_manager_from_adapter(conn_context->adapter);
GError *error = NULL;
GDBusObjectManager *device_manager = get_device_manager_from_adapter(conn_context->adapter, &error);
bool is_battery_level_uuid = false;
struct dbus_characteristic dbus_characteristic = {
@ -112,7 +112,12 @@ struct dbus_characteristic get_characteristic_from_uuid(gatt_connection_t* conne
};
if (device_manager == NULL) {
GATTLIB_LOG(GATTLIB_ERROR, "Gattlib Context not initialized.");
if (error != NULL) {
GATTLIB_LOG(GATTLIB_ERROR, "Gattlib Context not initialized (%d, %d).", error->domain, error->code);
g_error_free(error);
} else {
GATTLIB_LOG(GATTLIB_ERROR, "Gattlib Context not initialized.");
}
return dbus_characteristic; // Return characteristic of type TYPE_NONE
}
@ -163,8 +168,8 @@ struct dbus_characteristic get_characteristic_from_uuid(gatt_connection_t* conne
static struct dbus_characteristic get_characteristic_from_handle(gatt_connection_t* connection, int handle) {
gattlib_context_t* conn_context = connection->context;
GDBusObjectManager *device_manager = get_device_manager_from_adapter(conn_context->adapter);
GError *error = NULL;
GDBusObjectManager *device_manager = get_device_manager_from_adapter(conn_context->adapter, &error);
int char_handle;
struct dbus_characteristic dbus_characteristic = {
@ -172,7 +177,12 @@ static struct dbus_characteristic get_characteristic_from_handle(gatt_connection
};
if (device_manager == NULL) {
GATTLIB_LOG(GATTLIB_ERROR, "Gattlib context not initialized.");
if (error != NULL) {
GATTLIB_LOG(GATTLIB_ERROR, "Gattlib Context not initialized (%d, %d).", error->domain, error->code);
g_error_free(error);
} else {
GATTLIB_LOG(GATTLIB_ERROR, "Gattlib Context not initialized.");
}
return dbus_characteristic;
}
@ -219,9 +229,10 @@ static int read_gatt_characteristic(struct dbus_characteristic *dbus_characteris
g_variant_builder_unref(options);
#endif
if (error != NULL) {
ret = GATTLIB_ERROR_DBUS_WITH_ERROR(error);
GATTLIB_LOG(GATTLIB_ERROR, "Failed to read DBus GATT characteristic: %s", error->message);
g_error_free(error);
return GATTLIB_ERROR_DBUS;
return ret;
}
gsize n_elements = 0;
@ -320,9 +331,9 @@ int gattlib_read_char_by_uuid_async(gatt_connection_t* connection, uuid_t* uuid,
g_variant_builder_unref(options);
#endif
if (error != NULL) {
ret = GATTLIB_ERROR_DBUS_WITH_ERROR(error);
GATTLIB_LOG(GATTLIB_ERROR, "Failed to read DBus GATT characteristic: %s", error->message);
g_error_free(error);
ret = GATTLIB_ERROR_DBUS;
goto EXIT;
}
@ -359,9 +370,15 @@ static int write_char(struct dbus_characteristic *dbus_characteristic, const voi
#endif
if (error != NULL) {
GATTLIB_LOG(GATTLIB_ERROR, "Failed to write DBus GATT characteristic: %s", error->message);
if ((error->domain == 238) && (error->code == 36)) {
ret = GATTLIB_DEVICE_NOT_CONNECTED;
} else {
GATTLIB_LOG(GATTLIB_ERROR, "Failed to write DBus GATT characteristic: %s (%d,%d)",
error->message, error->domain, error->code);
ret = GATTLIB_ERROR_DBUS_WITH_ERROR(error);
}
g_error_free(error);
return GATTLIB_ERROR_DBUS;
return ret;
}
//

View File

@ -103,7 +103,7 @@ struct dbus_characteristic {
extern const uuid_t m_battery_level_uuid;
struct gattlib_adapter *init_default_adapter(void);
GDBusObjectManager *get_device_manager_from_adapter(struct gattlib_adapter *gattlib_adapter);
GDBusObjectManager *get_device_manager_from_adapter(struct gattlib_adapter *gattlib_adapter, GError **error);
void get_device_path_from_mac_with_adapter(OrgBluezAdapter1* adapter, const char *mac_address, char *object_path, size_t object_path_len);
void get_device_path_from_mac(const char *adapter_name, const char *mac_address, char *object_path, size_t object_path_len);

View File

@ -148,6 +148,7 @@ static gboolean on_handle_characteristic_indication(
static int connect_signal_to_characteristic_uuid(gatt_connection_t* connection, const uuid_t* uuid, void *callback) {
gattlib_context_t* conn_context = connection->context;
int ret;
assert(callback != NULL);
@ -197,9 +198,10 @@ static int connect_signal_to_characteristic_uuid(gatt_connection_t* connection,
GError *error = NULL;
org_bluez_gatt_characteristic1_call_start_notify_sync(dbus_characteristic.gatt, NULL, &error);
if (error) {
ret = GATTLIB_ERROR_DBUS_WITH_ERROR(error);
GATTLIB_LOG(GATTLIB_ERROR, "Failed to start DBus GATT notification: %s", error->message);
g_error_free(error);
return GATTLIB_ERROR_DBUS;
return ret;
} else {
return GATTLIB_SUCCESS;
}

View File

@ -33,6 +33,7 @@ int gattlib_write_char_by_uuid_stream_open(gatt_connection_t* connection, uuid_t
GError *error = NULL;
GUnixFDList *fd_list;
GVariant *out_fd;
int ret;
int fd;
GVariantBuilder *variant_options = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
@ -48,17 +49,19 @@ int gattlib_write_char_by_uuid_stream_open(gatt_connection_t* connection, uuid_t
g_variant_builder_unref(variant_options);
if (error != NULL) {
ret = GATTLIB_ERROR_DBUS_WITH_ERROR(error);
GATTLIB_LOG(GATTLIB_ERROR, "Failed to acquired write DBus GATT characteristic: %s", error->message);
g_error_free(error);
return GATTLIB_ERROR_DBUS;
return ret;
}
error = NULL;
fd = g_unix_fd_list_get(fd_list, g_variant_get_handle(out_fd), &error);
if (error != NULL) {
ret = GATTLIB_ERROR_DBUS_WITH_ERROR(error);
GATTLIB_LOG(GATTLIB_ERROR, "Failed to retrieve Unix File Descriptor: %s", error->message);
g_error_free(error);
return GATTLIB_ERROR_DBUS;
return ret;
}
// We abuse the pointer 'stream' to pass the 'File Descriptor'

View File

@ -11,9 +11,12 @@ GATTLIB_ERROR_TIMEOUT = 3
GATTLIB_OUT_OF_MEMORY = 4
GATTLIB_NOT_SUPPORTED = 5
GATTLIB_DEVICE_ERROR = 6
GATTLIB_ERROR_DBUS = 7
GATTLIB_ERROR_BLUEZ = 8
GATTLIB_ERROR_INTERNAL = 9
GATTLIB_DEVICE_NOT_CONNECTED = 7
GATTLIB_ERROR_MODULE_MASK = 0xF0000000
GATTLIB_ERROR_DBUS = 0x10000000
GATTLIB_ERROR_BLUEZ = 0x20000000
GATTLIB_ERROR_INTERNAL = 0x80000000
class GattlibException(Exception):
@ -39,6 +42,8 @@ class OutOfMemory(GattlibException):
class NotSupported(GattlibException):
pass
class NotConnected(GattlibException):
pass
class DeviceError(GattlibException):
def __init__(self, adapter: str = None, mac_address: str = None) -> None:
@ -49,7 +54,12 @@ class DeviceError(GattlibException):
return f"Error with device {self.mac_address} on adapter {self.adapter}"
class DBusError(GattlibException):
pass
def __init__(self, domain: int, code: int) -> None:
self.domain = domain
self.code = code
def __str__(self) -> str:
return f"DBus Error domain={self.domain},code={self.code}"
def handle_return(ret):
@ -65,8 +75,10 @@ def handle_return(ret):
raise NotSupported()
elif ret == GATTLIB_DEVICE_ERROR:
raise DeviceError()
elif ret == GATTLIB_ERROR_DBUS:
raise DBusError()
elif ret == GATTLIB_DEVICE_NOT_CONNECTED:
raise NotConnected()
elif (ret & GATTLIB_ERROR_MODULE_MASK) == GATTLIB_ERROR_DBUS:
raise DBusError((ret >> 8) & 0xFFF, ret & 0xFFFF)
elif ret == -22: # From '-EINVAL'
raise ValueError("Gattlib value error")
elif ret != 0:

View File

@ -35,16 +35,23 @@ extern "C" {
* @name Gattlib errors
*/
//@{
#define GATTLIB_SUCCESS 0
#define GATTLIB_INVALID_PARAMETER 1
#define GATTLIB_NOT_FOUND 2
#define GATTLIB_ERROR_TIMEOUT 3
#define GATTLIB_OUT_OF_MEMORY 4
#define GATTLIB_NOT_SUPPORTED 5
#define GATTLIB_DEVICE_ERROR 6
#define GATTLIB_ERROR_DBUS 7
#define GATTLIB_ERROR_BLUEZ 8
#define GATTLIB_ERROR_INTERNAL 9
#define GATTLIB_SUCCESS 0
#define GATTLIB_INVALID_PARAMETER 1
#define GATTLIB_NOT_FOUND 2
#define GATTLIB_ERROR_TIMEOUT 3
#define GATTLIB_OUT_OF_MEMORY 4
#define GATTLIB_NOT_SUPPORTED 5
#define GATTLIB_DEVICE_ERROR 6
#define GATTLIB_DEVICE_NOT_CONNECTED 7
#define GATTLIB_ERROR_MODULE_MASK 0xF0000000
#define GATTLIB_ERROR_DBUS 0x10000000
#define GATTLIB_ERROR_BLUEZ 0x20000000
#define GATTLIB_ERROR_INTERNAL 0x80000000
#define GATTLIB_ERROR_DBUS_WITH_ERROR(error) \
(GATTLIB_ERROR_DBUS | (error->domain << 8) | (error->code))
#define GATTLIB_ERROR_BLUEZ_WITH_ERROR(ret) \
(GATTLIB_ERROR_BLUEZ | (ret))
//@}
/**