shared/ad: Add support for arbritary type
Luiz Augusto von Dentz
maintainerRFC 1/7 shared/ad: Add support for arbritary type
From: Luiz Augusto von Dentz <[email protected]>
This adds APIs to include data of any type.
--- src/shared/ad.c | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/shared/ad.h | 16 ++++++ 2 files changed, 172 insertions(+)
src/shared/ad.c +156 -0
@@ -37,6 +37,7 @@ struct bt_ad {struct queue *manufacturer_data;struct queue *solicit_uuids;struct queue *service_data; +struct queue *data; };struct bt_ad *bt_ad_new (void )
@@ -48,6 +49,7 @@ struct bt_ad *bt_ad_new(void) ad->manufacturer_data =queue_new (); ad->solicit_uuids =queue_new (); ad->service_data =queue_new (); + ad->data =queue_new (); ad->appearance =UINT16_MAX ;return bt_ad_ref (ad);
@@ -94,6 +96,14 @@ static bool manuf_match(const void *data, const void *elem)return manuf->manufacturer_id == manuf_id; } +static void data_destroy (void *data) +{ +struct bt_ad_data *ad = data; + +free (ad->data); +free (ad); +} +void bt_ad_unref (struct bt_ad *ad) {if (!ad)
@@ -110,6 +120,8 @@ void bt_ad_unref(struct bt_ad *ad)queue_destroy (ad->service_data, uuid_destroy); +queue_destroy (ad->data, data_destroy); +free (ad->name);free (ad);
@@ -203,6 +215,24 @@ static size_t name_length(const char *name, size_t *pos)return len; } +static size_t data_length (struct queue *queue) +{ +size_t length =0 ; +const struct queue_entry *entry; + + entry =queue_get_entries (queue); + +while (entry) { +struct bt_ad_data *data = entry->data; + + length +=1 +1 + data->len; + + entry = entry->next; + } + +return length; +} +static size_t calculate_length (struct bt_ad *ad) {size_t length =0 ;
@@ -219,6 +249,8 @@ static size_t calculate_length(struct bt_ad *ad) length += ad->appearance !=UINT16_MAX ?4 :0 ; + length +=data_length (ad->data); +return length; }
@@ -370,6 +402,24 @@ static void serialize_appearance(uint16_t value, uint8_t *buf, uint8_t *pos) *pos +=2 ; } +static void serialize_data (struct queue *queue,uint8_t *buf,uint8_t *pos) +{ +const struct queue_entry *entry =queue_get_entries (queue); + +while (entry) { +struct bt_ad_data *data = entry->data; + + buf[(*pos)++] = data->len +1 ; + buf[(*pos)++] = data->type; + +memcpy (buf + *pos, data->data, data->len); + + *pos += data->len; + + entry = entry->next; + } +} +uint8_t *bt_ad_generate (struct bt_ad *ad,size_t *length) {uint8_t *adv_data;
@@ -399,6 +449,8 @@ uint8_t *bt_ad_generate(struct bt_ad *ad, size_t *length)serialize_appearance (ad->appearance, adv_data, &pos); +serialize_data (ad->data, adv_data, &pos); +return adv_data; }
@@ -756,3 +808,107 @@ void bt_ad_clear_appearance(struct bt_ad *ad) ad->appearance =UINT16_MAX ; } + +static bool data_type_match (const void *data,const void *user_data) +{ +const struct bt_ad_data *a = data; +const uint8_t type =PTR_TO_UINT (user_data); + +return a->type == type; +} + +bool bt_ad_add_data (struct bt_ad *ad,uint8_t type,void *data,size_t len) +{ +struct bt_ad_data *new_data; + +if (!ad) +return false; + +if (len > (MAX_ADV_DATA_LEN -2 )) +return false; + + new_data =queue_find (ad->data, data_type_match,UINT_TO_PTR (type)); +if (new_data) { +if (new_data->len == len && !memcmp (new_data->data, data, len)) +return false; + new_data->data =realloc (new_data->data, len); +memcpy (new_data->data, data, len); + new_data->len = len; +return true; + } + + new_data = new0(struct bt_ad_data, 1); + new_data->type = type; + new_data->data =malloc (len); +if (!new_data->data) { +free (new_data); +return false; + } + +memcpy (new_data->data, data, len); + new_data->len = len; + +if (queue_push_tail (ad->data, new_data)) +return true; + +data_destroy (new_data); + +return false; +} + +static bool data_match (const void *data,const void *user_data) +{ +const struct bt_ad_data *d1 = data; +const struct bt_ad_data *d2 = user_data; + +if (d1->type != d2->type) +return false; + +if (d1->len != d2->len) +return false; + +return !memcmp (d1->data, d2->data, d1->len); +} + +bool bt_ad_has_data (struct bt_ad *ad,const struct bt_ad_data *data) +{ +if (!ad) +return false; + +if (!data) +return !queue_isempty (ad->data); + +return queue_find (ad->data, data_match, data); +} + +void bt_ad_foreach_data (struct bt_ad *ad,bt_ad_func_t func,void *user_data) +{ +if (!ad) +return ; + +queue_foreach (ad->data, func, user_data); +} + +bool bt_ad_remove_data (struct bt_ad *ad,uint8_t type) +{ +struct bt_ad_data *data; + +if (!ad) +return false; + + data =queue_remove_if (ad->data, data_type_match,UINT_TO_PTR (type)); +if (!data) +return false; + +data_destroy (data); + +return true; +} + +void bt_ad_clear_data (struct bt_ad *ad) +{ +if (!ad) +return ; + +queue_remove_all (ad->data,NULL ,NULL , data_destroy); +}
src/shared/ad.h +16 -0
@@ -39,6 +39,12 @@ struct bt_ad_manufacturer_data {struct bt_ad_service_data {bt_uuid_t uuid; +size_t len; +void *data; +}; + +struct bt_ad_data { +uint8_t type;uint8_t *data;size_t len; };
@@ -96,3 +102,13 @@ void bt_ad_clear_name(struct bt_ad *ad);bool bt_ad_add_appearance (struct bt_ad *ad,uint16_t appearance);void bt_ad_clear_appearance (struct bt_ad *ad); + +bool bt_ad_add_data (struct bt_ad *ad,uint8_t type,void *data,size_t len); + +bool bt_ad_has_data (struct bt_ad *ad,const struct bt_ad_data *data); + +void bt_ad_foreach_data (struct bt_ad *ad,bt_ad_func_t func,void *user_data); + +bool bt_ad_remove_data (struct bt_ad *ad,uint8_t type); + +void bt_ad_clear_data (struct bt_ad *ad);
Signature · 1 line
2.14.3
Luiz Augusto von Dentz
maintainerRFC 2/7 doc/device-api: Add AdvertisingData property
From: Luiz Augusto von Dentz <[email protected]>
This adds AdvertisingData which exposes data being advertised which is may be useful for profiles not handled by bluetoothd.
--- doc/device-api.txt | 5 +++++ 1 file changed, 5 insertions(+)
doc/device-api.txt +5 -0
@@ -251,3 +251,8 @@ Properties string Address [readonly] array{byte} AdvertisingFlags [readonly, experimental] The Advertising Data Flags of the remote device. + + dict AdvertisingData [readonly, experimental] + + The Advertising Data of the remote device. Keys are + are 8 bits AD Type followed by data as byte array.
Signature · 1 line
2.14.3
Marcel Holtmann
maintainerRe: [RFC 2/7] doc/device-api: Add AdvertisingData property
Hi Luiz,
Quoted 11 lines
This adds AdvertisingData which exposes data being advertised which is may be useful for profiles not handled by bluetoothd.
---doc/device-api.txt| 5 +++++1 file changed, 5 insertions(+)doc/device-api.txt +0
-0
doc/device-api.txt Properties string Address [readonly] · line 258
Quoted 8 lines
doc/device-api.txt +5
-0@@ -251,3 +251,8 @@ Properties string Address [readonly] array{byte} AdvertisingFlags [readonly, experimental] The Advertising Data Flags of the remote device. + + dict AdvertisingData [readonly, experimental] + + The Advertising Data of the remote device. Keys are + are 8 bits AD Type followed by data as byte array.
this somehow needs to be explained on how a dict like that would look like. And also which AD types are _not_ valid here. Or at least not valid in conjunction with using other properties.
Regards
Marcel
Luiz Augusto von Dentz
maintainerRe: [RFC 2/7] doc/device-api: Add AdvertisingData property
Hi Marcel,
Quoted 15 lines · Marcel Holtmann
Hi Luiz,
Quoted 13 lines
This adds AdvertisingData which exposes data being advertised which is may be useful for profiles not handled by bluetoothd.
---doc/device-api.txt| 5 +++++1 file changed, 5 insertions(+)doc/device-api.txt +0
-0@@ -251,3 +251,8 @@ Properties string Address [readonly] array{byte} AdvertisingFlags [readonly, experimental]
Quoted 8 lines
doc/device-api.txt Properties string Address [readonly] · line 258
Quoted 6 lines
doc/device-api.txt +5
-0The Advertising Data Flags of the remote device. + + dict AdvertisingData [readonly, experimental] + + The Advertising Data of the remote device. Keys are + are 8 bits AD Type followed by data as byte array.this somehow needs to be explained on how a dict like that would look like. And also which AD types are _not_ valid here. Or at least not valid in conjunction with using other properties.
Sure, I can add a couple of examples for the existing profiles like Transport Discovery Data. For the peripheral we could limit the available type to just AD types available in the assigned number, like a whitelist, or blacklist the types that either kernel or bluetooothd are managing, I guess either way would work but maintaining the first option might be more troublesome since there are new profile being adopted all the time which was the reason why I haven't bother adding profile specific properties since we would end up with too many. There is also the option to use Advertising1 interface instead of Device1 that way central and peripheral APIs would be symmetric.
Btw, I don't know what went wrong with Service Data type, afaik that was meant for the profile to use instead of each creating its own AD type, now types can be profile specific without the use of the UUIDs which makes it hard to correlate with the actual profile.
Quoted 4 lines
Regards
Marcel
Signature · 1 line
Luiz Augusto von Dentz
Marcel Holtmann
maintainerRe: [RFC 2/7] doc/device-api: Add AdvertisingData property
Hi Luiz,
Quoted 22 lines
Quoted 13 lines
Quoted 13 lines
This adds AdvertisingData which exposes data being advertised which is may be useful for profiles not handled by bluetoothd.
---doc/device-api.txt| 5 +++++1 file changed, 5 insertions(+)doc/device-api.txt +0
-0@@ -251,3 +251,8 @@ Properties string Address [readonly] array{byte} AdvertisingFlags [readonly, experimental]Quoted 8 lines
doc/device-api.txt Properties string Address [readonly] · line 258
Quoted 6 lines
doc/device-api.txt +5
-0The Advertising Data Flags of the remote device. + + dict AdvertisingData [readonly, experimental] + + The Advertising Data of the remote device. Keys are + are 8 bits AD Type followed by data as byte array.this somehow needs to be explained on how a dict like that would look like. And also which AD types are _not_ valid here. Or at least not valid in conjunction with using other properties.
Quoted 10 lines
Sure, I can add a couple of examples for the existing profiles like Transport Discovery Data. For the peripheral we could limit the available type to just AD types available in the assigned number, like a whitelist, or blacklist the types that either kernel or bluetooothd are managing, I guess either way would work but maintaining the first option might be more troublesome since there are new profile being adopted all the time which was the reason why I haven't bother adding profile specific properties since we would end up with too many. There is also the option to use Advertising1 interface instead of Device1 that way central and peripheral APIs would be symmetric.
actually I am fine with allowing any AD type, but not allowing conflicting AD type here with other properties. So if you want all freeform, then do it and only use AdvertisingData, but if you want a combination, then certain AD types are not allowed.
Now I just saw that this is Device API, so all AD fields that are not covered by the exposed properties are fair game. My comment about not conflicting data is for the Advertising API.
Quoted 4 lines
Btw, I don't know what went wrong with Service Data type, afaik that was meant for the profile to use instead of each creating its own AD type, now types can be profile specific without the use of the UUIDs which makes it hard to correlate with the actual profile.
Most likely size or some how stupid things that it is not a real service. This reminds me, I would actually also blacklist the Mesh AD Types since they should not be processed via D-Bus. So lets just say which ones are blacklisted.
Regards
Marcel
Luiz Augusto von Dentz
maintainerRFC 3/7 device: Add implementation of AdvertisingData
In reply to Luiz Augusto von DentzFrom: Luiz Augusto von Dentz <[email protected]>
This adds the implementation of AdvertisingData property.
--- src/adapter.c | 3 +++ src/device.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- src/device.h | 2 ++ src/eir.c | 26 +++++++++++++++++++++++ src/eir.h | 8 +++++++ 5 files changed, 105 insertions(+), 1 deletion(-)
src/adapter.c +3 -0
@@ -6093,6 +6093,9 @@ static void update_found_devices(struct btd_adapter *adapter,if (eir_data.sd_list)device_set_service_data (dev, eir_data.sd_list, duplicate); +if (eir_data.data_list) +device_set_data (dev, eir_data.data_list, duplicate); +if (bdaddr_type !=BDADDR_BREDR )device_set_flags (dev, eir_data.flags);
src/device.c +66 -1
85 lines not on this page · raw message
src/device.h +2 -0
@@ -83,6 +83,8 @@ void device_set_manufacturer_data(struct btd_device *dev, GSList *list, bool duplicate);void device_set_service_data (struct btd_device *dev,GSList *list,bool duplicate); +void device_set_data (struct btd_device *dev,GSList *list, +bool duplicate);void device_probe_profile (gpointer a,gpointer b);void device_remove_profile (gpointer a,gpointer b);struct btd_adapter *device_get_adapter (struct btd_device *device);
src/eir.c +26 -0
@@ -51,6 +51,14 @@ static void sd_free(void *data)g_free (sd); } +static void data_free (void *data) +{ +struct eir_ad *ad = data; + +g_free (ad->data); +g_free (ad); +} +void eir_data_free (struct eir_data *eir) {g_slist_free_full (eir->services, free);
@@ -65,6 +73,8 @@ void eir_data_free(struct eir_data *eir) eir->msd_list =NULL ;g_slist_free_full (eir->sd_list, sd_free); eir->sd_list =NULL ; +g_slist_free_full (eir->data_list, data_free); + eir->data_list =NULL ; } static void eir_parse_uuid16(struct eir_data *eir, const void *data,
@@ -226,6 +236,19 @@ static void eir_parse_uuid128_data(struct eir_data *eir, const uint8_t *data,eir_parse_sd (eir, &service, data +16 , len -16 ); } +static void eir_parse_data (struct eir_data *eir,uint8_t type, +const uint8_t *data,uint8_t len) +{ +struct eir_ad *ad; + + ad =g_malloc (sizeof (*ad)); + ad->len = len; + ad->data =g_malloc (len); +memcpy (ad->data, data, len); + + eir->data_list =g_slist_append (eir->data_list, ad); +} +void eir_parse (struct eir_data *eir,const uint8_t *eir_data,uint8_t eir_len) {uint16_t len =0 ;
@@ -346,6 +369,9 @@ void eir_parse(struct eir_data *eir, const uint8_t *eir_data, uint8_t eir_len)eir_parse_msd (eir, data, data_len);break ; +default : +eir_parse_data (eir, eir_data[1 ], data, data_len); +break ; } eir_data += field_len +1 ;
src/eir.h +8 -0
@@ -49,6 +49,7 @@#define EIR_SOLICIT32 0x1F/* LE: Solicit UUIDs, 32-bit */ #define EIR_SVC_DATA32 0x20/* LE: Service data, 32-bit UUID */ #define EIR_SVC_DATA128 0x21/* LE: Service data, 128-bit UUID */ +#define EIR_TRANSPORT_DISCOVERY 0x26/* Transport Discovery Service */ #define EIR_MANUFACTURER_DATA 0xFF/* Manufacturer Specific Data */ /* Flags Descriptions */
@@ -75,6 +76,12 @@ struct eir_sd {uint8_t data_len; }; +struct eir_ad { +uint8_t type; +uint8_t len; +void *data; +}; +struct eir_data {GSList *services;unsigned int flags;
@@ -92,6 +99,7 @@ struct eir_data {uint16_t did_source;GSList *msd_list;GSList *sd_list; +GSList *data_list; };void eir_data_free (struct eir_data *eir);
Signature · 1 line
2.14.3
Luiz Augusto von Dentz
maintainerRFC 4/7 doc/advertising-api: Add Data property
In reply to Luiz Augusto von DentzFrom: Luiz Augusto von Dentz <[email protected]>
Data property can be used to add advertising data with arbitrary/profile specific type.
--- doc/advertising-api.txt | 6 ++++++ 1 file changed, 6 insertions(+)
doc/advertising-api.txt +6 -0
@@ -61,6 +61,12 @@ Properties string Type Service Data elements to include. The keys are the UUID to associate with the data. + dict Data [Experimental] + + Advertising Type to include in the Advertising + Data. Key is the advertising type and value is the + data as byte array. + array{string} Includes List of features to be included in the advertising
Signature · 1 line
2.14.3
Luiz Augusto von Dentz
maintainerRFC 5/7 advertising: Add Data implementation
In reply to Luiz Augusto von DentzFrom: Luiz Augusto von Dentz <[email protected]>
This adds the support for Data property.
--- src/advertising.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+)
src/advertising.c +59 -0
@@ -583,6 +583,64 @@ static bool parse_timeout(DBusMessageIter *iter,return true; } +static bool parse_data (DBusMessageIter *iter,struct btd_adv_client *client) +{ +DBusMessageIter entries; + +if (!iter) { +bt_ad_clear_data (client->data); +return true; + } + +if (dbus_message_iter_get_arg_type (iter) !=DBUS_TYPE_ARRAY ) +return false; + +dbus_message_iter_recurse (iter, &entries); + +bt_ad_clear_data (client->data); + +while (dbus_message_iter_get_arg_type (&entries) + ==DBUS_TYPE_DICT_ENTRY ) { +DBusMessageIter value, entry, array; +uint8_t type; +uint8_t *data; +int len; + +dbus_message_iter_recurse (&entries, &entry); +dbus_message_iter_get_basic (&entry, &type); + +dbus_message_iter_next (&entry); + +if (dbus_message_iter_get_arg_type (&entry) !=DBUS_TYPE_VARIANT ) + goto fail; + +dbus_message_iter_recurse (&entry, &value); + +if (dbus_message_iter_get_arg_type (&value) !=DBUS_TYPE_ARRAY ) + goto fail; + +dbus_message_iter_recurse (&value, &array); + +if (dbus_message_iter_get_arg_type (&array) !=DBUS_TYPE_BYTE ) + goto fail; + +dbus_message_iter_get_fixed_array (&array, &data, &len); + +DBG ("Adding Data for type 0x%02x len %u" , type, len); + +if (!bt_ad_add_data (client->data, type, data, len)) + goto fail; + +dbus_message_iter_next (&entries); + } + +return true; + +fail: +bt_ad_clear_data (client->data); +return false; +} + static struct adv_parser { const char *name; bool (*func)(DBusMessageIter *iter, struct btd_adv_client *client);
@@ -597,6 +655,7 @@ static struct adv_parser { { "Appearance", parse_appearance }, { "Duration", parse_duration }, { "Timeout", parse_timeout }, + { "Data", parse_data }, { }, };
Signature · 1 line
2.14.3
Luiz Augusto von Dentz
maintainerRFC 6/7 monitor: Add support for Transport Discovery AD
In reply to Luiz Augusto von DentzFrom: Luiz Augusto von Dentz <[email protected]>
This adds support for decoding Transport Discovery Data:
@ MGMT Command: Add Advertising (0x003e) plen 16
Instance: 1
Flags: 0x00000001
Switch into Connectable mode
Duration: 0
Timeout: 0
Advertising data length: 5
Transport Discovery Data
Organization: Bluetooth SIG (0x01)
Flags: 0x01
Role: 0x01
Seeker Only
Transport Data Incomplete: False (0x00)
Transport State: 0x00
Off
Length: 0
Data:
Scan response length: 0
---
monitor/packet.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 55 insertions(+)monitor/packet.c +55 -0
@@ -3545,6 +3545,57 @@ static void print_mesh_data(const uint8_t *data, uint8_t len)packet_hexdump (data +1 , len -1 ); } +static void print_transport_data (const uint8_t *data,uint8_t len) +{ +print_field ("Transport Discovery Data" ); + +if (len <3 ) +return ; + +print_field (" Organization: %s (0x%02x)" , + data[0 ] ==0x01 ?"Bluetooth SIG" :"RFU" , data[0 ]); +print_field (" Flags: 0x%2.2x" , data[1 ]); +print_field (" Role: 0x%2.2x" , data[1 ] &0x03 ); + +switch (data[1 ] &0x03 ) { +case 0x00 : +print_field (" Not Specified" ); +break ; +case 0x01 : +print_field (" Seeker Only" ); +break ; +case 0x02 : +print_field (" Provider Only" ); +break ; +case 0x03 : +print_field (" Both Seeker an Provider" ); +break ; + } + +print_field (" Transport Data Incomplete: %s (0x%2.2x)" , + data[1 ] &0x04 ?"True" :"False" , data[1 ] &0x04 ); + +print_field (" Transport State: 0x%2.2x" , data[1 ] &0x18 ); + +switch (data[1 ] &0x18 ) { +case 0x00 : +print_field (" Off" ); +break ; +case 0x08 : +print_field (" On" ); +break ; +case 0x10 : +print_field (" Temporary Unavailable" ); +break ; +case 0x18 : +print_field (" RFU" ); +break ; + } + +print_field (" Length: %u" , data[2 ]); +print_hex_field (" Data" , data +3 , len -3 ); +} +static void print_eir (const uint8_t *eir,uint8_t eir_len,bool le) {uint16_t len =0 ;
@@ -3744,6 +3795,10 @@ static void print_eir(const uint8_t *eir, uint8_t eir_len, bool le)print_randomizer_p256 (data);break ; +case BT_EIR_TRANSPORT_DISCOVERY : +print_transport_data (data, data_len); +break ; +case BT_EIR_3D_INFO_DATA :print_hex_field ("3D Information Data" , data, data_len);if (data_len <2 )
Signature · 1 line
2.14.3
Luiz Augusto von Dentz
maintainerRFC 7/7 client: Add support for setting advertising Data property
In reply to Luiz Augusto von DentzFrom: Luiz Augusto von Dentz <[email protected]>
This adds data command to advertise menu which can be used to set an arbitrary/profile specific advertising type and data:
[bluetooth]# data 0x26 0x01 0x01 0x00
--- client/advertising.c | 158 +++++++++++++++++++++++++++++++++++++-------------- client/advertising.h | 2 + client/main.c | 13 +++++ 3 files changed, 130 insertions(+), 43 deletions(-)
client/advertising.c +115 -43
@@ -54,6 +54,11 @@ struct manufacturer_data {struct ad_data data; }; +struct data { +uint8_t type; +struct ad_data data; +}; + static struct ad { bool registered; char *type;
@@ -65,6 +70,7 @@ static struct ad {size_t uuids_len;struct service_data service;struct manufacturer_data manufacturer; +struct data data;bool tx_power;bool name;bool appearance;
@@ -373,12 +379,35 @@ static gboolean get_timeout(const GDBusPropertyTable *property,return TRUE; } +static gboolean data_exists (const GDBusPropertyTable *property,void *data) +{ +return ad.data.type !=0 ; +} + +static gboolean get_data (const GDBusPropertyTable *property, +DBusMessageIter *iter,void *user_data) +{ +DBusMessageIter dict; +struct ad_data *data = &ad.data.data; +uint8_t *val = data->data; + +dbus_message_iter_open_container (iter,DBUS_TYPE_ARRAY ,"{yv}" , &dict); + +g_dbus_dict_append_basic_array (&dict,DBUS_TYPE_BYTE , &ad.data.type, +DBUS_TYPE_BYTE , &val, data->len); + +dbus_message_iter_close_container (iter, &dict); + +return TRUE; +} +static const GDBusPropertyTable ad_props[] = { {"Type" ,"s" , get_type }, {"ServiceUUIDs" ,"as" , get_uuids,NULL , uuids_exists }, {"ServiceData" ,"a{sv}" , get_service_data,NULL , service_data_exists }, {"ManufacturerData" ,"a{qv}" , get_manufacturer_data,NULL , manufacturer_data_exists }, + {"Data" ,"a{yv}" , get_data,NULL , data_exists }, {"Includes" ,"as" , get_includes,NULL , includes_exists }, {"LocalName" ,"s" , get_local_name,NULL , local_name_exits }, {"Appearance" ,"q" , get_appearance,NULL , appearance_exits },
@@ -508,46 +537,55 @@ static void ad_clear_service(void)return bt_shell_noninteractive_quit (EXIT_SUCCESS ); } -void ad_advertise_service (DBusConnection *conn,int argc,char *argv[]) +static bool ad_add_data (struct ad_data *data,int argc,char *argv[]) {unsigned int i; -struct ad_data *data; -if (argc <2 || !strlen (argv[1 ])) { -if (ad.service.uuid) { -print_uuid (ad.service.uuid); -bt_shell_hexdump (ad.service.data.data, - ad.service.data.len); - } -return bt_shell_noninteractive_quit (EXIT_SUCCESS ); - } +memset (data,0 ,sizeof (*data)); -ad_clear_service (); - - ad.service.uuid =g_strdup (argv[1 ]); - data = &ad.service.data; - -for (i =2 ; i < (unsigned int ) argc; i++) { +for (i =0 ; i < (unsigned int ) argc; i++) {long int val;char *endptr =NULL ;if (i >=G_N_ELEMENTS (data->data)) {bt_shell_printf ("Too much data\n" ); -ad_clear_service (); -return ; +return false; } val =strtol (argv[i], &endptr,0 );if (!endptr || *endptr !='\0' || val >UINT8_MAX ) {bt_shell_printf ("Invalid value at index %d\n" , i); -ad_clear_service (); -return ; +return false; } data->data[data->len] = val; data->len++; } +return true; +} + +void ad_advertise_service (DBusConnection *conn,int argc,char *argv[]) +{ +struct ad_data data; + +if (argc <2 || !strlen (argv[1 ])) { +if (ad.service.uuid) { +print_uuid (ad.service.uuid); +bt_shell_hexdump (ad.service.data.data, + ad.service.data.len); + } +return bt_shell_noninteractive_quit (EXIT_SUCCESS ); + } + +if (!ad_add_data (&data, argc -2 , argv +2 )) +return bt_shell_noninteractive_quit (EXIT_FAILURE ); + +ad_clear_service (); + + ad.service.uuid =g_strdup (argv[1 ]); + ad.service.data = data; +g_dbus_emit_property_changed (conn,AD_PATH ,AD_IFACE ,"ServiceData" );return bt_shell_noninteractive_quit (EXIT_SUCCESS );
@@ -573,10 +611,9 @@ static void ad_clear_manufacturer(void)void ad_advertise_manufacturer (DBusConnection *conn,int argc,char *argv[]) { -unsigned int i;char *endptr =NULL ;long int val; -struct ad_data *data; +struct ad_data data;if (argc <2 || !strlen (argv[1 ])) {if (ad.manufacturer.data.len) {
@@ -589,34 +626,18 @@ void ad_advertise_manufacturer(DBusConnection *conn, int argc, char *argv[])return bt_shell_noninteractive_quit (EXIT_SUCCESS ); } -ad_clear_manufacturer (); - val =strtol (argv[1 ], &endptr,0 );if (!endptr || *endptr !='\0' || val >UINT16_MAX ) {bt_shell_printf ("Invalid manufacture id\n" );return bt_shell_noninteractive_quit (EXIT_FAILURE ); } - ad.manufacturer.id = val; - data = &ad.manufacturer.data; - -for (i =2 ; i < (unsigned int ) argc; i++) { -if (i >=G_N_ELEMENTS (data->data)) { -bt_shell_printf ("Too much data\n" ); -ad_clear_manufacturer (); -return bt_shell_noninteractive_quit (EXIT_FAILURE ); - } - - val =strtol (argv[i], &endptr,0 ); -if (!endptr || *endptr !='\0' || val >UINT8_MAX ) { -bt_shell_printf ("Invalid value at index %d\n" , i); -ad_clear_manufacturer (); -return bt_shell_noninteractive_quit (EXIT_FAILURE ); - } +if (!ad_add_data (&data, argc -2 , argv +2 )) +return bt_shell_noninteractive_quit (EXIT_FAILURE ); - data->data[data->len] = val; - data->len++; - } +ad_clear_manufacturer (); + ad.manufacturer.id = val; + ad.manufacturer.data = data;g_dbus_emit_property_changed (conn,AD_PATH ,AD_IFACE ,"ManufacturerData" );
@@ -636,6 +657,57 @@ void ad_disable_manufacturer(DBusConnection *conn)return bt_shell_noninteractive_quit (EXIT_SUCCESS ); } +static void ad_clear_data (void ) +{ +memset (&ad.manufacturer,0 ,sizeof (ad.manufacturer)); + +return bt_shell_noninteractive_quit (EXIT_SUCCESS ); +} + +void ad_advertise_data (DBusConnection *conn,int argc,char *argv[]) +{ +char *endptr =NULL ; +long int val; +struct ad_data data; + +if (argc <2 || !strlen (argv[1 ])) { +if (ad.manufacturer.data.len) { +bt_shell_printf ("Type: 0x%02x\n" , ad.data.type); +bt_shell_hexdump (ad.data.data.data, ad.data.data.len); + } + +return bt_shell_noninteractive_quit (EXIT_SUCCESS ); + } + + val =strtol (argv[1 ], &endptr,0 ); +if (!endptr || *endptr !='\0' || val >UINT8_MAX ) { +bt_shell_printf ("Invalid type\n" ); +return bt_shell_noninteractive_quit (EXIT_FAILURE ); + } + +if (!ad_add_data (&data, argc -2 , argv +2 )) +return bt_shell_noninteractive_quit (EXIT_FAILURE ); + +ad_clear_data (); + ad.data.type = val; + ad.data.data = data; + +g_dbus_emit_property_changed (conn,AD_PATH ,AD_IFACE ,"Data" ); + +return bt_shell_noninteractive_quit (EXIT_SUCCESS ); +} + +void ad_disable_data (DBusConnection *conn) +{ +if (!ad.data.type && !ad.data.data.len) +return bt_shell_noninteractive_quit (EXIT_SUCCESS ); + +ad_clear_data (); +g_dbus_emit_property_changed (conn,AD_PATH ,AD_IFACE ,"Data" ); + +return bt_shell_noninteractive_quit (EXIT_SUCCESS ); +} +void ad_advertise_tx_power (DBusConnection *conn,dbus_bool_t *value) {if (!value) {
client/advertising.h +2 -0
@@ -37,3 +37,5 @@ void ad_advertise_local_name(DBusConnection *conn, const char *name);void ad_advertise_local_appearance (DBusConnection *conn,long int *value);void ad_advertise_duration (DBusConnection *conn,long int *value);void ad_advertise_timeout (DBusConnection *conn,long int *value); +void ad_advertise_data (DBusConnection *conn,int argc,char *argv[]); +void ad_disable_data (DBusConnection *conn);
client/main.c +13 -0
@@ -2185,6 +2185,11 @@ static void cmd_advertise_manufacturer(int argc, char *argv[])ad_advertise_manufacturer (dbus_conn, argc, argv); } +static void cmd_advertise_data (int argc,char *argv[]) +{ +ad_advertise_data (dbus_conn, argc, argv); +} +static void cmd_advertise_tx_power (int argc,char *argv[]) {dbus_bool_t powered;
@@ -2302,6 +2307,11 @@ static void ad_clear_manufacturer(void)ad_disable_manufacturer (dbus_conn); } +static void ad_clear_data (void ) +{ +ad_disable_data (dbus_conn); +} +static void ad_clear_tx_power (void ) {dbus_bool_t powered = false;
@@ -2337,6 +2347,7 @@ static const struct clear_entry ad_clear[] = { { "uuids", ad_clear_uuids }, { "service", ad_clear_service }, { "manufacturer", ad_clear_manufacturer }, + { "data", ad_clear_data }, { "tx-power", ad_clear_tx_power }, { "name", ad_clear_name }, { "appearance", ad_clear_appearance },
@@ -2367,6 +2378,8 @@ static const struct bt_shell_menu advertise_menu = { {"manufacturer" ,"[id] [data=xx xx ...]" , cmd_advertise_manufacturer, "Set/Get advertise manufacturer data" }, + { "data", "[type] [data=xx xx ...]", cmd_advertise_data, + "Set/Get advertise data" }, { "tx-power", "[on/off]", cmd_advertise_tx_power,"Show/Enable/Disable TX power to be advertised" , NULL },
Signature · 1 line
2.14.3