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 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 manufacturer_id is the ID of the Manufacturer ID
* @param manufacturer_data is the data following Manufacturer ID
* @param manufacturer_data_size is the size of manufacturer_data
* @param manufacturer_data is an array of `gattlib_manufacturer_data_t`
* @param manufacturer_data_count is the number of entry in `gattlib_manufacturer_data_t` array
*
* @return GATTLIB_SUCCESS on success or GATTLIB_* error code
*/
int gattlib_get_advertisement_data(gattlib_connection_t *connection,
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;
}
@ -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 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 manufacturer_id is the ID of the Manufacturer ID
* @param manufacturer_data is the data following Manufacturer ID
* @param manufacturer_data_size is the size of manufacturer_data
* @param manufacturer_data is an array of `gattlib_manufacturer_data_t`
* @param manufacturer_data_count is the number of entry in `gattlib_manufacturer_data_t` array
*
* @return GATTLIB_SUCCESS on success or GATTLIB_* error code
*/
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,
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;
}

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;
gattlib_advertisement_data_t *advertisement_data = NULL;
size_t advertisement_data_count;
uint16_t manufacturer_id;
uint8_t *manufacturer_data = NULL;
size_t manufacturer_data_size;
gattlib_manufacturer_data_t* manufacturer_data = NULL;
size_t manufacturer_data_count = 0;
int ret;
ret = gattlib_get_advertisement_data_from_mac(adapter, addr,
&advertisement_data, &advertisement_data_count,
&manufacturer_id, &manufacturer_data, &manufacturer_data_size);
&manufacturer_data, &manufacturer_data_count);
if (ret != 0) {
return;
}
callback_data->discovered_device_cb(adapter, addr, name,
advertisement_data, advertisement_data_count,
manufacturer_id, manufacturer_data, manufacturer_data_size,
manufacturer_data, manufacturer_data_count,
callback_data->user_data);
if (advertisement_data != NULL) {
free(advertisement_data);
}
if (manufacturer_data != NULL) {
for (uintptr_t i = 0; i < manufacturer_data_count; i++) {
free(manufacturer_data[i].data);
}
free(manufacturer_data);
}
}

View File

@ -10,14 +10,14 @@
int gattlib_get_advertisement_data(gattlib_connection_t *connection,
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;
}
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,
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;
}
@ -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,
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 *service_data_variant;
@ -35,36 +35,41 @@ int get_advertisement_data_from_device(OrgBluezDevice1 *bluez_device1,
return GATTLIB_INVALID_PARAMETER;
}
*manufacturer_id = 0;
*manufacturer_data_size = 0;
*manufacturer_data_count = 0;
*manufacturer_data = NULL;
manufacturer_data_variant = org_bluez_device1_get_manufacturer_data(bluez_device1);
if (manufacturer_data_variant != NULL) {
if (g_variant_n_children(manufacturer_data_variant) != 1) {
GATTLIB_LOG(GATTLIB_WARNING, "Manufacturer Data with multiple children: %s",
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));
*manufacturer_data_count = g_variant_n_children(manufacturer_data_variant);
*manufacturer_data = malloc(sizeof(gattlib_manufacturer_data_t) * (*manufacturer_data_count));
if (*manufacturer_data == NULL) {
return GATTLIB_OUT_OF_MEMORY;
}
GVariant* value;
g_variant_get(values, "ay", &iter);
size_t index = 0;
for (uintptr_t i = 0; i < *manufacturer_data_count; i++) {
GVariant* manufacturer_data_dict = g_variant_get_child_value(manufacturer_data_variant, i);
GVariantIter *iter;
GVariant* values;
uint16_t manufacturer_id = 0;
while ((value = g_variant_iter_next_value(iter)) != NULL) {
g_variant_get(value, "y", &(*manufacturer_data)[index++]);
g_variant_unref(value);
g_variant_get(manufacturer_data_dict, "{qv}", &manufacturer_id, &values);
(*manufacturer_data)[i].manufacturer_id = manufacturer_id;
(*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);
@ -114,7 +119,7 @@ int get_advertisement_data_from_device(OrgBluezDevice1 *bluez_device1,
int gattlib_get_advertisement_data(gattlib_connection_t *connection,
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;
@ -138,7 +143,7 @@ int gattlib_get_advertisement_data(gattlib_connection_t *connection,
ret = get_advertisement_data_from_device(dbus_device,
advertisement_data, advertisement_data_count,
manufacturer_id, manufacturer_data, manufacturer_data_size);
manufacturer_data, manufacturer_data_count);
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,
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;
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,
advertisement_data, advertisement_data_count,
manufacturer_id, manufacturer_data, manufacturer_data_size);
manufacturer_data, manufacturer_data_count);
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) {
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 = NULL;
size_t manufacturer_data_count = 0;
int ret;
ret = gattlib_get_advertisement_data_from_mac(adapter, addr,
&advertisement_data, &advertisement_data_count,
&manufacturer_id, &manufacturer_data, &manufacturer_data_size);
&manufacturer_data, &manufacturer_data_count);
if (ret != 0) {
return;
}
@ -56,10 +55,13 @@ static void ble_advertising_device(gattlib_adapter_t* adapter, const char* addr,
printf("Device %s: ", addr);
}
for (size_t i = 0; i < manufacturer_data_size; i++) {
printf("%02x ", manufacturer_data[i]);
for (size_t i = 0; i < manufacturer_data_count; 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) {

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,
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)
{
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,
# 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.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,
# 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.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 */
} 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);
/**
@ -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 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 manufacturer_id is the ID of the Manufacturer ID
* @param manufacturer_data is the data following Manufacturer ID
* @param manufacturer_data_size is the size of manufacturer_data
* @param manufacturer_data is an array of `gattlib_manufacturer_data_t`
* @param manufacturer_data_count is the number of entry in `gattlib_manufacturer_data_t` array
* @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,
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);
/**
@ -688,15 +696,14 @@ int gattlib_get_rssi_from_mac(gattlib_adapter_t* adapter, const char *mac_addres
* @param connection Active GATT connection
* @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 manufacturer_id is the ID of the Manufacturer ID
* @param manufacturer_data is the data following Manufacturer ID
* @param manufacturer_data_size is the size of manufacturer_data
* @param manufacturer_data is an array of `gattlib_manufacturer_data_t`
* @param manufacturer_data_count is the number of entry in `gattlib_manufacturer_data_t` array
*
* @return GATTLIB_SUCCESS on success or GATTLIB_* error code
*/
int gattlib_get_advertisement_data(gattlib_connection_t *connection,
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
@ -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 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 manufacturer_id is the ID of the Manufacturer ID
* @param manufacturer_data is the data following Manufacturer ID
* @param manufacturer_data_size is the size of manufacturer_data
* @param manufacturer_data is an array of `gattlib_manufacturer_data_t`
* @param manufacturer_data_count is the number of entry in `gattlib_manufacturer_data_t` array
*
* @return GATTLIB_SUCCESS on success or GATTLIB_* error code
*/
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,
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