Add support to retrieve all manufacturer data from GATT advertisement packets

pull/277/head
Olivier Martin 2024-04-10 10:33:10 +02:00
parent 8a108495a1
commit 880f1d2cd0
7 changed files with 77 additions and 64 deletions

View File

@ -303,15 +303,14 @@ int gattlib_discover_desc(gattlib_connection_t* connection, gattlib_descriptor_t
* @param mac_address is the MAC address of the device to get the RSSI * @param mac_address is the MAC address of the device to get the RSSI
* @param advertisement_data is an array of Service UUID and their respective data * @param advertisement_data is an array of Service UUID and their respective data
* @param advertisement_data_count is the number of elements in the advertisement_data array * @param advertisement_data_count is the number of elements in the advertisement_data array
* @param manufacturer_id is the ID of the Manufacturer ID * @param manufacturer_data is an array of `gattlib_manufacturer_data_t`
* @param manufacturer_data is the data following Manufacturer ID * @param manufacturer_data_count is the number of entry in `gattlib_manufacturer_data_t` array
* @param manufacturer_data_size is the size of manufacturer_data
* *
* @return GATTLIB_SUCCESS on success or GATTLIB_* error code * @return GATTLIB_SUCCESS on success or GATTLIB_* error code
*/ */
int gattlib_get_advertisement_data(gattlib_connection_t *connection, int gattlib_get_advertisement_data(gattlib_connection_t *connection,
gattlib_advertisement_data_t **advertisement_data, size_t *advertisement_data_count, gattlib_advertisement_data_t **advertisement_data, size_t *advertisement_data_count,
uint16_t *manufacturer_id, uint8_t **manufacturer_data, size_t *manufacturer_data_size) gattlib_manufacturer_data_t** manufacturer_data, size_t* manufacturer_data_count)
{ {
return GATTLIB_NOT_SUPPORTED; return GATTLIB_NOT_SUPPORTED;
} }
@ -323,15 +322,14 @@ int gattlib_get_advertisement_data(gattlib_connection_t *connection,
* @param mac_address is the MAC address of the device to get the RSSI * @param mac_address is the MAC address of the device to get the RSSI
* @param advertisement_data is an array of Service UUID and their respective data * @param advertisement_data is an array of Service UUID and their respective data
* @param advertisement_data_count is the number of elements in the advertisement_data array * @param advertisement_data_count is the number of elements in the advertisement_data array
* @param manufacturer_id is the ID of the Manufacturer ID * @param manufacturer_data is an array of `gattlib_manufacturer_data_t`
* @param manufacturer_data is the data following Manufacturer ID * @param manufacturer_data_count is the number of entry in `gattlib_manufacturer_data_t` array
* @param manufacturer_data_size is the size of manufacturer_data
* *
* @return GATTLIB_SUCCESS on success or GATTLIB_* error code * @return GATTLIB_SUCCESS on success or GATTLIB_* error code
*/ */
int gattlib_get_advertisement_data_from_mac(gattlib_adapter_t* adapter, const char *mac_address, int gattlib_get_advertisement_data_from_mac(gattlib_adapter_t* adapter, const char *mac_address,
gattlib_advertisement_data_t **advertisement_data, size_t *advertisement_data_count, gattlib_advertisement_data_t **advertisement_data, size_t *advertisement_data_count,
uint16_t *manufacturer_id, uint8_t **manufacturer_data, size_t *manufacturer_data_size) gattlib_manufacturer_data_t** manufacturer_data, size_t* manufacturer_data_count)
{ {
return GATTLIB_NOT_SUPPORTED; return GATTLIB_NOT_SUPPORTED;
} }

View File

@ -30,27 +30,29 @@ static void on_eddystone_discovered_device(gattlib_adapter_t* adapter, const cha
struct on_eddystone_discovered_device_arg *callback_data = user_data; struct on_eddystone_discovered_device_arg *callback_data = user_data;
gattlib_advertisement_data_t *advertisement_data = NULL; gattlib_advertisement_data_t *advertisement_data = NULL;
size_t advertisement_data_count; size_t advertisement_data_count;
uint16_t manufacturer_id; gattlib_manufacturer_data_t* manufacturer_data = NULL;
uint8_t *manufacturer_data = NULL; size_t manufacturer_data_count = 0;
size_t manufacturer_data_size;
int ret; int ret;
ret = gattlib_get_advertisement_data_from_mac(adapter, addr, ret = gattlib_get_advertisement_data_from_mac(adapter, addr,
&advertisement_data, &advertisement_data_count, &advertisement_data, &advertisement_data_count,
&manufacturer_id, &manufacturer_data, &manufacturer_data_size); &manufacturer_data, &manufacturer_data_count);
if (ret != 0) { if (ret != 0) {
return; return;
} }
callback_data->discovered_device_cb(adapter, addr, name, callback_data->discovered_device_cb(adapter, addr, name,
advertisement_data, advertisement_data_count, advertisement_data, advertisement_data_count,
manufacturer_id, manufacturer_data, manufacturer_data_size, manufacturer_data, manufacturer_data_count,
callback_data->user_data); callback_data->user_data);
if (advertisement_data != NULL) { if (advertisement_data != NULL) {
free(advertisement_data); free(advertisement_data);
} }
if (manufacturer_data != NULL) { if (manufacturer_data != NULL) {
for (uintptr_t i = 0; i < manufacturer_data_count; i++) {
free(manufacturer_data[i].data);
}
free(manufacturer_data); free(manufacturer_data);
} }
} }

View File

@ -10,14 +10,14 @@
int gattlib_get_advertisement_data(gattlib_connection_t *connection, int gattlib_get_advertisement_data(gattlib_connection_t *connection,
gattlib_advertisement_data_t **advertisement_data, size_t *advertisement_data_count, gattlib_advertisement_data_t **advertisement_data, size_t *advertisement_data_count,
uint16_t *manufacturer_id, uint8_t **manufacturer_data, size_t *manufacturer_data_size) gattlib_manufacturer_data_t** manufacturer_data, size_t* manufacturer_data_count)
{ {
return GATTLIB_NOT_SUPPORTED; return GATTLIB_NOT_SUPPORTED;
} }
int gattlib_get_advertisement_data_from_mac(gattlib_adapter_t* adapter, const char *mac_address, int gattlib_get_advertisement_data_from_mac(gattlib_adapter_t* adapter, const char *mac_address,
gattlib_advertisement_data_t **advertisement_data, size_t *advertisement_data_count, gattlib_advertisement_data_t **advertisement_data, size_t *advertisement_data_count,
uint16_t *manufacturer_id, uint8_t **manufacturer_data, size_t *manufacturer_data_size) gattlib_manufacturer_data_t** manufacturer_data, size_t* manufacturer_data_count)
{ {
return GATTLIB_NOT_SUPPORTED; return GATTLIB_NOT_SUPPORTED;
} }
@ -26,7 +26,7 @@ int gattlib_get_advertisement_data_from_mac(gattlib_adapter_t* adapter, const ch
int get_advertisement_data_from_device(OrgBluezDevice1 *bluez_device1, int get_advertisement_data_from_device(OrgBluezDevice1 *bluez_device1,
gattlib_advertisement_data_t **advertisement_data, size_t *advertisement_data_count, gattlib_advertisement_data_t **advertisement_data, size_t *advertisement_data_count,
uint16_t *manufacturer_id, uint8_t **manufacturer_data, size_t *manufacturer_data_size) gattlib_manufacturer_data_t** manufacturer_data, size_t* manufacturer_data_count)
{ {
GVariant *manufacturer_data_variant; GVariant *manufacturer_data_variant;
GVariant *service_data_variant; GVariant *service_data_variant;
@ -35,36 +35,41 @@ int get_advertisement_data_from_device(OrgBluezDevice1 *bluez_device1,
return GATTLIB_INVALID_PARAMETER; return GATTLIB_INVALID_PARAMETER;
} }
*manufacturer_id = 0; *manufacturer_data_count = 0;
*manufacturer_data_size = 0; *manufacturer_data = NULL;
manufacturer_data_variant = org_bluez_device1_get_manufacturer_data(bluez_device1); manufacturer_data_variant = org_bluez_device1_get_manufacturer_data(bluez_device1);
if (manufacturer_data_variant != NULL) { if (manufacturer_data_variant != NULL) {
if (g_variant_n_children(manufacturer_data_variant) != 1) { *manufacturer_data_count = g_variant_n_children(manufacturer_data_variant);
GATTLIB_LOG(GATTLIB_WARNING, "Manufacturer Data with multiple children: %s", *manufacturer_data = malloc(sizeof(gattlib_manufacturer_data_t) * (*manufacturer_data_count));
g_variant_print(manufacturer_data_variant, TRUE));
return GATTLIB_NOT_SUPPORTED;
}
GVariant* manufacturer_data_dict = g_variant_get_child_value(manufacturer_data_variant, 0);
GVariantIter *iter;
GVariant* values;
g_variant_get(manufacturer_data_dict, "{qv}", manufacturer_id, &values);
*manufacturer_data_size = g_variant_n_children(values);
*manufacturer_data = calloc(*manufacturer_data_size, sizeof(guchar));
if (*manufacturer_data == NULL) { if (*manufacturer_data == NULL) {
return GATTLIB_OUT_OF_MEMORY; return GATTLIB_OUT_OF_MEMORY;
} }
GVariant* value; for (uintptr_t i = 0; i < *manufacturer_data_count; i++) {
g_variant_get(values, "ay", &iter); GVariant* manufacturer_data_dict = g_variant_get_child_value(manufacturer_data_variant, i);
size_t index = 0; GVariantIter *iter;
GVariant* values;
uint16_t manufacturer_id = 0;
while ((value = g_variant_iter_next_value(iter)) != NULL) { g_variant_get(manufacturer_data_dict, "{qv}", &manufacturer_id, &values);
g_variant_get(value, "y", &(*manufacturer_data)[index++]); (*manufacturer_data)[i].manufacturer_id = manufacturer_id;
g_variant_unref(value); (*manufacturer_data)[i].data_size = g_variant_n_children(values);
(*manufacturer_data)[i].data = calloc((*manufacturer_data)[i].data_size, sizeof(guchar));
if ((*manufacturer_data)[i].data == NULL) {
return GATTLIB_OUT_OF_MEMORY;
}
// Copy manufacturer data to structure
GVariant* value;
g_variant_get(values, "ay", &iter);
size_t index = 0;
while ((value = g_variant_iter_next_value(iter)) != NULL) {
g_variant_get(value, "y", (*manufacturer_data)[i].data[index++]);
g_variant_unref(value);
}
g_variant_iter_free(iter);
} }
g_variant_iter_free(iter);
} }
service_data_variant = org_bluez_device1_get_service_data(bluez_device1); service_data_variant = org_bluez_device1_get_service_data(bluez_device1);
@ -114,7 +119,7 @@ int get_advertisement_data_from_device(OrgBluezDevice1 *bluez_device1,
int gattlib_get_advertisement_data(gattlib_connection_t *connection, int gattlib_get_advertisement_data(gattlib_connection_t *connection,
gattlib_advertisement_data_t **advertisement_data, size_t *advertisement_data_count, gattlib_advertisement_data_t **advertisement_data, size_t *advertisement_data_count,
uint16_t *manufacturer_id, uint8_t **manufacturer_data, size_t *manufacturer_data_size) gattlib_manufacturer_data_t** manufacturer_data, size_t* manufacturer_data_count)
{ {
int ret; int ret;
@ -138,7 +143,7 @@ int gattlib_get_advertisement_data(gattlib_connection_t *connection,
ret = get_advertisement_data_from_device(dbus_device, ret = get_advertisement_data_from_device(dbus_device,
advertisement_data, advertisement_data_count, advertisement_data, advertisement_data_count,
manufacturer_id, manufacturer_data, manufacturer_data_size); manufacturer_data, manufacturer_data_count);
g_object_unref(dbus_device); g_object_unref(dbus_device);
@ -147,7 +152,7 @@ int gattlib_get_advertisement_data(gattlib_connection_t *connection,
int gattlib_get_advertisement_data_from_mac(gattlib_adapter_t* adapter, const char *mac_address, int gattlib_get_advertisement_data_from_mac(gattlib_adapter_t* adapter, const char *mac_address,
gattlib_advertisement_data_t **advertisement_data, size_t *advertisement_data_count, gattlib_advertisement_data_t **advertisement_data, size_t *advertisement_data_count,
uint16_t *manufacturer_id, uint8_t **manufacturer_data, size_t *manufacturer_data_size) gattlib_manufacturer_data_t** manufacturer_data, size_t* manufacturer_data_count)
{ {
OrgBluezDevice1 *bluez_device1; OrgBluezDevice1 *bluez_device1;
int ret; int ret;
@ -164,7 +169,7 @@ int gattlib_get_advertisement_data_from_mac(gattlib_adapter_t* adapter, const ch
ret = get_advertisement_data_from_device(bluez_device1, ret = get_advertisement_data_from_device(bluez_device1,
advertisement_data, advertisement_data_count, advertisement_data, advertisement_data_count,
manufacturer_id, manufacturer_data, manufacturer_data_size); manufacturer_data, manufacturer_data_count);
g_object_unref(bluez_device1); g_object_unref(bluez_device1);

View File

@ -38,14 +38,13 @@ static const char* adapter_name;
static void ble_advertising_device(gattlib_adapter_t* adapter, const char* addr, const char* name, void *user_data) { static void ble_advertising_device(gattlib_adapter_t* adapter, const char* addr, const char* name, void *user_data) {
gattlib_advertisement_data_t *advertisement_data; gattlib_advertisement_data_t *advertisement_data;
size_t advertisement_data_count; size_t advertisement_data_count;
uint16_t manufacturer_id; gattlib_manufacturer_data_t* manufacturer_data = NULL;
uint8_t *manufacturer_data; size_t manufacturer_data_count = 0;
size_t manufacturer_data_size;
int ret; int ret;
ret = gattlib_get_advertisement_data_from_mac(adapter, addr, ret = gattlib_get_advertisement_data_from_mac(adapter, addr,
&advertisement_data, &advertisement_data_count, &advertisement_data, &advertisement_data_count,
&manufacturer_id, &manufacturer_data, &manufacturer_data_size); &manufacturer_data, &manufacturer_data_count);
if (ret != 0) { if (ret != 0) {
return; return;
} }
@ -56,10 +55,13 @@ static void ble_advertising_device(gattlib_adapter_t* adapter, const char* addr,
printf("Device %s: ", addr); printf("Device %s: ", addr);
} }
for (size_t i = 0; i < manufacturer_data_size; i++) { for (size_t i = 0; i < manufacturer_data_count; i++) {
printf("%02x ", manufacturer_data[i]); printf("- Manufacturer data for id 0x%x: ", manufacturer_data[i].manufacturer_id);
for (size_t j = 0; j < manufacturer_data[i].data_size; j++) {
printf("%02x ", manufacturer_data[i].data[j]);
}
printf("\n");
} }
printf("\n");
} }
static void* ble_task(void *arg) { static void* ble_task(void *arg) {

View File

@ -45,7 +45,7 @@ const char* m_adapter_name;
*/ */
void on_eddystone_found(gattlib_adapter_t* adapter, const char* addr, const char* name, void on_eddystone_found(gattlib_adapter_t* adapter, const char* addr, const char* name,
gattlib_advertisement_data_t *advertisement_data, size_t advertisement_data_count, gattlib_advertisement_data_t *advertisement_data, size_t advertisement_data_count,
uint16_t manufacturer_id, uint8_t *manufacturer_data, size_t manufacturer_data_size, gattlib_manufacturer_data_t* manufacturer_data, size_t manufacturer_data_count,
void *user_data) void *user_data)
{ {
puts("Found Eddystone device"); puts("Found Eddystone device");

View File

@ -210,13 +210,13 @@ gattlib_get_rssi_from_mac.argtypes = [c_void_p, c_char_p, POINTER(c_int16)]
# int gattlib_get_advertisement_data(gattlib_connection_t *connection, # int gattlib_get_advertisement_data(gattlib_connection_t *connection,
# gattlib_advertisement_data_t **advertisement_data, size_t *advertisement_data_count, # gattlib_advertisement_data_t **advertisement_data, size_t *advertisement_data_count,
# uint16_t *manufacturer_id, uint8_t **manufacturer_data, size_t *manufacturer_data_size) # gattlib_manufacturer_data_t** manufacturer_data, size_t* manufacturer_data_count)
gattlib_get_advertisement_data = gattlib.gattlib_get_advertisement_data gattlib_get_advertisement_data = gattlib.gattlib_get_advertisement_data
gattlib_get_advertisement_data.argtypes = [c_void_p, POINTER(POINTER(GattlibAdvertisementData)), POINTER(c_size_t), POINTER(c_uint16), POINTER(c_void_p), POINTER(c_size_t)] gattlib_get_advertisement_data.argtypes = [c_void_p, POINTER(POINTER(GattlibAdvertisementData)), POINTER(c_size_t), POINTER(c_uint16), POINTER(c_void_p), POINTER(c_size_t)]
# int gattlib_get_advertisement_data_from_mac(gattlib_adapter_t* adapter, const char *mac_address, # int gattlib_get_advertisement_data_from_mac(gattlib_adapter_t* adapter, const char *mac_address,
# gattlib_advertisement_data_t **advertisement_data, size_t *advertisement_data_length, # gattlib_advertisement_data_t **advertisement_data, size_t *advertisement_data_length,
# uint16_t *manufacturer_id, uint8_t **manufacturer_data, size_t *manufacturer_data_size) # gattlib_manufacturer_data_t** manufacturer_data, size_t* manufacturer_data_count)
gattlib_get_advertisement_data_from_mac = gattlib.gattlib_get_advertisement_data_from_mac gattlib_get_advertisement_data_from_mac = gattlib.gattlib_get_advertisement_data_from_mac
gattlib_get_advertisement_data_from_mac.argtypes = [c_void_p, c_char_p, POINTER(POINTER(GattlibAdvertisementData)), POINTER(c_size_t), POINTER(c_uint16), POINTER(c_void_p), POINTER(c_size_t)] gattlib_get_advertisement_data_from_mac.argtypes = [c_void_p, c_char_p, POINTER(POINTER(GattlibAdvertisementData)), POINTER(c_size_t), POINTER(c_uint16), POINTER(c_void_p), POINTER(c_size_t)]

View File

@ -164,6 +164,15 @@ typedef struct {
size_t data_length; /**< Length of data attached to the GATT Service */ size_t data_length; /**< Length of data attached to the GATT Service */
} gattlib_advertisement_data_t; } gattlib_advertisement_data_t;
/**
* Structure to represent manufacturer data from GATT advertisement packet
*/
typedef struct {
uint16_t manufacturer_id;
uint8_t* data;
size_t data_size;
} gattlib_manufacturer_data_t;
typedef void (*gattlib_event_handler_t)(const uuid_t* uuid, const uint8_t* data, size_t data_length, void* user_data); typedef void (*gattlib_event_handler_t)(const uuid_t* uuid, const uint8_t* data, size_t data_length, void* user_data);
/** /**
@ -192,14 +201,13 @@ typedef void (*gattlib_discovered_device_t)(gattlib_adapter_t* adapter, const ch
* @param name is the name of BLE device if advertised * @param name is the name of BLE device if advertised
* @param advertisement_data is an array of Service UUID and their respective data * @param advertisement_data is an array of Service UUID and their respective data
* @param advertisement_data_count is the number of elements in the advertisement_data array * @param advertisement_data_count is the number of elements in the advertisement_data array
* @param manufacturer_id is the ID of the Manufacturer ID * @param manufacturer_data is an array of `gattlib_manufacturer_data_t`
* @param manufacturer_data is the data following Manufacturer ID * @param manufacturer_data_count is the number of entry in `gattlib_manufacturer_data_t` array
* @param manufacturer_data_size is the size of manufacturer_data
* @param user_data Data defined when calling `gattlib_register_on_disconnect()` * @param user_data Data defined when calling `gattlib_register_on_disconnect()`
*/ */
typedef void (*gattlib_discovered_device_with_data_t)(gattlib_adapter_t* adapter, const char* addr, const char* name, typedef void (*gattlib_discovered_device_with_data_t)(gattlib_adapter_t* adapter, const char* addr, const char* name,
gattlib_advertisement_data_t *advertisement_data, size_t advertisement_data_count, gattlib_advertisement_data_t *advertisement_data, size_t advertisement_data_count,
uint16_t manufacturer_id, uint8_t *manufacturer_data, size_t manufacturer_data_size, gattlib_manufacturer_data_t* manufacturer_data, size_t manufacturer_data_count,
void *user_data); void *user_data);
/** /**
@ -688,15 +696,14 @@ int gattlib_get_rssi_from_mac(gattlib_adapter_t* adapter, const char *mac_addres
* @param connection Active GATT connection * @param connection Active GATT connection
* @param advertisement_data is an array of Service UUID and their respective data * @param advertisement_data is an array of Service UUID and their respective data
* @param advertisement_data_count is the number of elements in the advertisement_data array * @param advertisement_data_count is the number of elements in the advertisement_data array
* @param manufacturer_id is the ID of the Manufacturer ID * @param manufacturer_data is an array of `gattlib_manufacturer_data_t`
* @param manufacturer_data is the data following Manufacturer ID * @param manufacturer_data_count is the number of entry in `gattlib_manufacturer_data_t` array
* @param manufacturer_data_size is the size of manufacturer_data
* *
* @return GATTLIB_SUCCESS on success or GATTLIB_* error code * @return GATTLIB_SUCCESS on success or GATTLIB_* error code
*/ */
int gattlib_get_advertisement_data(gattlib_connection_t *connection, int gattlib_get_advertisement_data(gattlib_connection_t *connection,
gattlib_advertisement_data_t **advertisement_data, size_t *advertisement_data_count, gattlib_advertisement_data_t **advertisement_data, size_t *advertisement_data_count,
uint16_t *manufacturer_id, uint8_t **manufacturer_data, size_t *manufacturer_data_size); gattlib_manufacturer_data_t** manufacturer_data, size_t* manufacturer_data_count);
/** /**
* @brief Function to retrieve Advertisement Data from a MAC Address * @brief Function to retrieve Advertisement Data from a MAC Address
@ -705,15 +712,14 @@ int gattlib_get_advertisement_data(gattlib_connection_t *connection,
* @param mac_address is the MAC address of the device to get the RSSI * @param mac_address is the MAC address of the device to get the RSSI
* @param advertisement_data is an array of Service UUID and their respective data * @param advertisement_data is an array of Service UUID and their respective data
* @param advertisement_data_count is the number of elements in the advertisement_data array * @param advertisement_data_count is the number of elements in the advertisement_data array
* @param manufacturer_id is the ID of the Manufacturer ID * @param manufacturer_data is an array of `gattlib_manufacturer_data_t`
* @param manufacturer_data is the data following Manufacturer ID * @param manufacturer_data_count is the number of entry in `gattlib_manufacturer_data_t` array
* @param manufacturer_data_size is the size of manufacturer_data
* *
* @return GATTLIB_SUCCESS on success or GATTLIB_* error code * @return GATTLIB_SUCCESS on success or GATTLIB_* error code
*/ */
int gattlib_get_advertisement_data_from_mac(gattlib_adapter_t* adapter, const char *mac_address, int gattlib_get_advertisement_data_from_mac(gattlib_adapter_t* adapter, const char *mac_address,
gattlib_advertisement_data_t **advertisement_data, size_t *advertisement_data_count, gattlib_advertisement_data_t **advertisement_data, size_t *advertisement_data_count,
uint16_t *manufacturer_id, uint8_t **manufacturer_data, size_t *manufacturer_data_size); gattlib_manufacturer_data_t** manufacturer_data, size_t* manufacturer_data_count);
/** /**
* @brief Convert a UUID into a string * @brief Convert a UUID into a string