gattlib: Change gattlib_read_char_by_uuid() to return an allocated buffer that fits GATT value size

pull/106/head
Olivier Martin 2019-05-27 17:21:59 +02:00 committed by Olivier Martin
parent 683efaaca4
commit ceaa8a17e4
5 changed files with 74 additions and 32 deletions

View File

@ -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;

View File

@ -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;

View File

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

View File

@ -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];

View File

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