diff --git a/bluez/gattlib_read_write.c b/bluez/gattlib_read_write.c index b6ca530..8e71e08 100644 --- a/bluez/gattlib_read_write.c +++ b/bluez/gattlib_read_write.c @@ -31,9 +31,8 @@ #include "gatt.h" struct gattlib_result_read_uuid_t { - void* buffer; - size_t buffer_max_len; - size_t buffer_len; + void** buffer; + size_t* buffer_len; gatt_read_cb_t callback; int completed; }; @@ -59,15 +58,24 @@ static void gattlib_result_read_uuid_cb(guint8 status, const guint8 *pdu, guint1 for (i = 0; i < list->num; i++) { uint8_t *value = list->data[i]; + size_t buffer_len = list->len - 2; + // Move the value to the beginning of the data value += 2; - gattlib_result->buffer_len = list->len - 2; - if (gattlib_result->callback) { - gattlib_result->callback(value, gattlib_result->buffer_len); + gattlib_result->callback(value, buffer_len); } else { - memcpy(gattlib_result->buffer, value, MIN(gattlib_result->buffer_len, gattlib_result->buffer_max_len)); + void* buffer = malloc(buffer_len); + if (buffer == NULL) { + goto done; + } + + // Copy value into the buffer + memcpy(buffer, value, buffer_len); + + *gattlib_result->buffer_len = buffer_len; + *gattlib_result->buffer = buffer; } } @@ -95,7 +103,7 @@ void uuid_to_bt_uuid(uuid_t* uuid, bt_uuid_t* bt_uuid) { } int gattlib_read_char_by_uuid(gatt_connection_t* connection, uuid_t* uuid, - void* buffer, size_t* buffer_len) + void **buffer, size_t* buffer_len) { gattlib_context_t* conn_context = connection->context; struct gattlib_result_read_uuid_t* gattlib_result; @@ -108,29 +116,26 @@ int gattlib_read_char_by_uuid(gatt_connection_t* connection, uuid_t* uuid, return GATTLIB_OUT_OF_MEMORY; } gattlib_result->buffer = buffer; - gattlib_result->buffer_max_len = *buffer_len; - gattlib_result->buffer_len = 0; + gattlib_result->buffer_len = buffer_len; gattlib_result->callback = NULL; gattlib_result->completed = FALSE; uuid_to_bt_uuid(uuid, &bt_uuid); gatt_read_char_by_uuid(conn_context->attrib, start, end, &bt_uuid, - gattlib_result_read_uuid_cb, gattlib_result); + gattlib_result_read_uuid_cb, gattlib_result); // Wait for completion of the event while(gattlib_result->completed == FALSE) { g_main_context_iteration(g_gattlib_thread.loop_context, FALSE); } - *buffer_len = gattlib_result->buffer_len; - free(gattlib_result); return GATTLIB_SUCCESS; } int gattlib_read_char_by_uuid_async(gatt_connection_t* connection, uuid_t* uuid, - gatt_read_cb_t gatt_read_cb) + gatt_read_cb_t gatt_read_cb) { gattlib_context_t* conn_context = connection->context; struct gattlib_result_read_uuid_t* gattlib_result; @@ -143,7 +148,6 @@ int gattlib_read_char_by_uuid_async(gatt_connection_t* connection, uuid_t* uuid, return GATTLIB_OUT_OF_MEMORY; } gattlib_result->buffer = NULL; - gattlib_result->buffer_max_len = 0; gattlib_result->buffer_len = 0; gattlib_result->callback = gatt_read_cb; gattlib_result->completed = FALSE; @@ -151,7 +155,7 @@ int gattlib_read_char_by_uuid_async(gatt_connection_t* connection, uuid_t* uuid, uuid_to_bt_uuid(uuid, &bt_uuid); guint id = gatt_read_char_by_uuid(conn_context->attrib, start, end, &bt_uuid, - gattlib_result_read_uuid_cb, gattlib_result); + gattlib_result_read_uuid_cb, gattlib_result); if (id) { return GATTLIB_SUCCESS; diff --git a/dbus/gattlib.c b/dbus/gattlib.c index cb867e0..0c9baae 100644 --- a/dbus/gattlib.c +++ b/dbus/gattlib.c @@ -1048,7 +1048,7 @@ int gattlib_discover_desc(gatt_connection_t* connection, gattlib_descriptor_t** return GATTLIB_NOT_SUPPORTED; } -static int read_gatt_characteristic(struct dbus_characteristic *dbus_characteristic, void* buffer, size_t* buffer_len) { +static int read_gatt_characteristic(struct dbus_characteristic *dbus_characteristic, void **buffer, size_t* buffer_len) { GVariant *out_value; GError *error = NULL; @@ -1070,11 +1070,16 @@ static int read_gatt_characteristic(struct dbus_characteristic *dbus_characteris gsize n_elements = 0; gconstpointer const_buffer = g_variant_get_fixed_array(out_value, &n_elements, sizeof(guchar)); if (const_buffer) { - n_elements = MIN(n_elements, *buffer_len); - memcpy(buffer, const_buffer, n_elements); - } + *buffer = malloc(n_elements); + if (*buffer == NULL) { + return GATTLIB_OUT_OF_MEMORY; + } - *buffer_len = n_elements; + *buffer_len = n_elements; + memcpy(*buffer, const_buffer, n_elements); + } else { + *buffer_len = 0; + } g_object_unref(dbus_characteristic->gatt); @@ -1095,7 +1100,7 @@ static int read_battery_level(struct dbus_characteristic *dbus_characteristic, v } #endif -int gattlib_read_char_by_uuid(gatt_connection_t* connection, uuid_t* uuid, void* buffer, size_t* buffer_len) { +int gattlib_read_char_by_uuid(gatt_connection_t* connection, uuid_t* uuid, void **buffer, size_t *buffer_len) { struct dbus_characteristic dbus_characteristic = get_characteristic_from_uuid(connection, uuid); if (dbus_characteristic.type == TYPE_NONE) { return GATTLIB_NOT_FOUND; diff --git a/examples/gatttool/gatttool.c b/examples/gatttool/gatttool.c index 57eab4e..fad22ca 100644 --- a/examples/gatttool/gatttool.c +++ b/examples/gatttool/gatttool.c @@ -247,23 +247,24 @@ static gboolean characteristics_read(gpointer user_data) GAttrib *attrib = conn_context->attrib; if (opt_uuid != NULL) { - uint8_t buffer[0x100]; + uint8_t *buffer; uuid_t uuid; - size_t len = sizeof(buffer); + size_t buffer_len; int i, ret; bt_uuid_to_uuid(opt_uuid, &uuid); - ret = gattlib_read_char_by_uuid(connection, &uuid, buffer, &len); + ret = gattlib_read_char_by_uuid(connection, &uuid, &buffer, &buffer_len); if (ret) { return FALSE; } else { g_print("value: "); - for (i = 0; i < len; i++) { + for (i = 0; i < buffer_len; i++) { g_print("%02x ", buffer[i]); } g_print("\n"); + free(buffer); return TRUE; } } diff --git a/examples/read_write/read_write.c b/examples/read_write/read_write.c index cdaf659..f8d4624 100644 --- a/examples/read_write/read_write.c +++ b/examples/read_write/read_write.c @@ -38,7 +38,6 @@ static void usage(char *argv[]) { } int main(int argc, char *argv[]) { - uint8_t buffer[100]; int i, ret; size_t len; gatt_connection_t* connection; @@ -76,8 +75,9 @@ int main(int argc, char *argv[]) { } if (g_operation == READ) { - len = sizeof(buffer); - ret = gattlib_read_char_by_uuid(connection, &g_uuid, buffer, &len); + uint8_t *buffer; + + ret = gattlib_read_char_by_uuid(connection, &g_uuid, (void **)&buffer, &len); if (ret == -1) { char uuid_str[MAX_LEN_UUID_STR + 1]; @@ -92,8 +92,10 @@ int main(int argc, char *argv[]) { printf("%02x ", buffer[i]); } printf("\n"); + + free(buffer); } else { - ret = gattlib_write_char_by_uuid(connection, &g_uuid, buffer, sizeof(buffer)); + ret = gattlib_write_char_by_uuid(connection, &g_uuid, &value_data, sizeof(value_data)); if (ret == -1) { char uuid_str[MAX_LEN_UUID_STR + 1]; diff --git a/include/gattlib.h b/include/gattlib.h index 6ede0ec..6eaeb01 100644 --- a/include/gattlib.h +++ b/include/gattlib.h @@ -116,7 +116,15 @@ typedef struct _gatt_connection_t { typedef void (*gattlib_discovered_device_t)(const char* addr, const char* name); typedef void (*gatt_connect_cb_t)(gatt_connection_t* connection, void* user_data); -typedef void* (*gatt_read_cb_t)(const void* buffer, size_t buffer_len); + +/** + * @brief Callback called when GATT characteristic read value has been received + * + * @param buffer contains the value to read. + * @param buffer_len Length of the read data + * + */ +typedef void* (*gatt_read_cb_t)(const void *buffer, size_t buffer_len); /** * @brief Open Bluetooth adapter @@ -179,7 +187,29 @@ int gattlib_discover_char(gatt_connection_t* connection, gattlib_characteristic_ int gattlib_discover_desc_range(gatt_connection_t* connection, int start, int end, gattlib_descriptor_t** descriptors, int* descriptor_count); int gattlib_discover_desc(gatt_connection_t* connection, gattlib_descriptor_t** descriptors, int* descriptor_count); -int gattlib_read_char_by_uuid(gatt_connection_t* connection, uuid_t* uuid, void* buffer, size_t* buffer_len); +/** + * @brief Function to read GATT characteristic + * + * @note buffer is allocated by the function. It is the responsibility of the caller to free the buffer. + * + * @param connection Active GATT connection + * @param uuid UUID of the GATT characteristic to read + * @param buffer contains the value to read. It is allocated by the function. + * @param buffer_len Length of the read data + * + * @return GATTLIB_SUCCESS on success or GATTLIB_* error code + */ +int gattlib_read_char_by_uuid(gatt_connection_t* connection, uuid_t* uuid, void** buffer, size_t* buffer_len); + +/** + * @brief Function to asynchronously read GATT characteristic + * + * @param connection Active GATT connection + * @param uuid UUID of the GATT characteristic to read + * @param gatt_read_cb is the callback to read when the GATT characteristic is available + * + * @return GATTLIB_SUCCESS on success or GATTLIB_* error code + */ int gattlib_read_char_by_uuid_async(gatt_connection_t* connection, uuid_t* uuid, gatt_read_cb_t gatt_read_cb); int gattlib_write_char_by_uuid(gatt_connection_t* connection, uuid_t* uuid, const void* buffer, size_t buffer_len);