Skip to content

Commit

Permalink
Add support to retrieve all manufacturer data from GATT advertisement…
Browse files Browse the repository at this point in the history
… packets
  • Loading branch information
oliviermartin committed Apr 10, 2024
1 parent 8a10849 commit 880f1d2
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 64 deletions.
14 changes: 6 additions & 8 deletions bluez/gattlib_discover.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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;
}
12 changes: 7 additions & 5 deletions common/gattlib_eddystone.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Expand Down
63 changes: 34 additions & 29 deletions dbus/gattlib_advertisement.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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;
Expand All @@ -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;

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)[index++]);
g_variant_unref(value);
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);
Expand Down Expand Up @@ -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;

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

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

Expand Down
16 changes: 9 additions & 7 deletions examples/advertisement_data/advertisement_data.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion examples/find_eddystone/find_eddystone.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
4 changes: 2 additions & 2 deletions gattlib-py/gattlib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,13 +210,13 @@ class GattlibAdvertisementData(Structure):

# 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)]

Expand Down
30 changes: 18 additions & 12 deletions include/gattlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

/**
Expand Down Expand Up @@ -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);

/**
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down

0 comments on commit 880f1d2

Please sign in to comment.