diff options
author | Luiz Augusto von Dentz <luiz.von.dentz@intel.com> | 2017-08-09 11:34:12 +0300 |
---|---|---|
committer | Luiz Augusto von Dentz <luiz.von.dentz@intel.com> | 2017-08-10 16:31:42 +0300 |
commit | 172e68c59f8cff319e456ef3923d3834a89b5494 (patch) | |
tree | f0c75be494692366584c3bbd7faee18bc741a165 /client/advertising.c | |
parent | 9fb1f9ff694c387e7547b897ff1cd4c95d1063da (diff) | |
download | bluez-172e68c59f8cff319e456ef3923d3834a89b5494.tar.gz |
client: Add set-advertise-name and set-advertise-appearance
set-advertise-appearance enables the use of adapter's appearance in the
scan response:
[bluetooth]# set-advertise-appearance on
[bluetooth]# advertise on
@ MGMT Command: Add Advertising (0x003e) plen 11
Instance: 1
Flags: 0x00000023
Switch into Connectable mode
Advertise as Discoverable
Add Appearance field to Scan Response
Duration: 0
Timeout: 0
Advertising data length: 0
Scan response length: 0
set-advertise-name enables the use of adapter's name/alias in the
scan response:
[bluetooth]# set-advertise-name on
[bluetooth]# advertise on
@ MGMT Command: Add Advertising (0x003e) plen 11
Instance: 1
Flags: 0x00000043
Switch into Connectable mode
Advertise as Discoverable
Add Local Name in Scan Response
Duration: 0
Timeout: 0
Advertising data length: 0
Scan response length: 0
Diffstat (limited to 'client/advertising.c')
-rw-r--r-- | client/advertising.c | 166 |
1 files changed, 107 insertions, 59 deletions
diff --git a/client/advertising.c b/client/advertising.c index 81fa85118..35e582afc 100644 --- a/client/advertising.c +++ b/client/advertising.c @@ -28,6 +28,7 @@ #include <stdio.h> #include <stdlib.h> #include <stdint.h> +#include <stdbool.h> #include <readline/readline.h> #include <wordexp.h> @@ -38,21 +39,36 @@ #define AD_PATH "/org/bluez/advertising" #define AD_IFACE "org.bluez.LEAdvertisement1" -static gboolean registered = FALSE; -static char *ad_type = NULL; -static char **ad_uuids = NULL; -static size_t ad_uuids_len = 0; -static char *ad_service_uuid = NULL; -static uint8_t ad_service_data[25]; -static uint8_t ad_service_data_len = 0; -static uint16_t ad_manufacturer_id; -static uint8_t ad_manufacturer_data[25]; -static uint8_t ad_manufacturer_data_len = 0; -static gboolean ad_tx_power = FALSE; +struct ad_data { + uint8_t data[25]; + uint8_t len; +}; + +struct service_data { + char *uuid; + struct ad_data data; +}; + +struct manufacturer_data { + uint16_t id; + struct ad_data data; +}; + +static struct ad { + bool registered; + char *type; + char **uuids; + size_t uuids_len; + struct service_data service; + struct manufacturer_data manufacturer; + bool tx_power; + bool name; + bool appearance; +} ad; static void ad_release(DBusConnection *conn) { - registered = FALSE; + ad.registered = false; g_dbus_unregister_interface(conn, AD_PATH, AD_IFACE); } @@ -94,7 +110,7 @@ static void register_reply(DBusMessage *message, void *user_data) dbus_error_init(&error); if (dbus_set_error_from_message(&error, message) == FALSE) { - registered = TRUE; + ad.registered = true; rl_printf("Advertising object registered\n"); } else { rl_printf("Failed to register advertisement: %s\n", error.name); @@ -111,8 +127,8 @@ static gboolean get_type(const GDBusPropertyTable *property, { const char *type = "peripheral"; - if (!ad_type || strlen(ad_type) > 0) - type = ad_type; + if (!ad.type || strlen(ad.type) > 0) + type = ad.type; dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &type); @@ -121,7 +137,7 @@ static gboolean get_type(const GDBusPropertyTable *property, static gboolean uuids_exists(const GDBusPropertyTable *property, void *data) { - return ad_uuids_len != 0; + return ad.uuids_len != 0; } static gboolean get_uuids(const GDBusPropertyTable *property, @@ -132,9 +148,9 @@ static gboolean get_uuids(const GDBusPropertyTable *property, dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "as", &array); - for (i = 0; i < ad_uuids_len; i++) + for (i = 0; i < ad.uuids_len; i++) dbus_message_iter_append_basic(&array, DBUS_TYPE_STRING, - &ad_uuids[i]); + &ad.uuids[i]); dbus_message_iter_close_container(iter, &array); @@ -197,19 +213,19 @@ static void dict_append_array(DBusMessageIter *dict, const char *key, int type, static gboolean service_data_exists(const GDBusPropertyTable *property, void *data) { - return ad_service_uuid != NULL; + return ad.service.uuid != NULL; } static gboolean get_service_data(const GDBusPropertyTable *property, DBusMessageIter *iter, void *user_data) { DBusMessageIter dict; - const uint8_t *data = ad_service_data; + struct ad_data *data = &ad.service.data; dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "{sv}", &dict); - dict_append_array(&dict, ad_service_uuid, DBUS_TYPE_BYTE, &data, - ad_service_data_len); + dict_append_array(&dict, ad.service.uuid, DBUS_TYPE_BYTE, &data->data, + data->len); dbus_message_iter_close_container(iter, &dict); @@ -219,35 +235,57 @@ static gboolean get_service_data(const GDBusPropertyTable *property, static gboolean manufacturer_data_exists(const GDBusPropertyTable *property, void *data) { - return ad_manufacturer_id != 0; + return ad.manufacturer.id != 0; } static gboolean get_manufacturer_data(const GDBusPropertyTable *property, DBusMessageIter *iter, void *user_data) { DBusMessageIter dict; - const uint8_t *data = ad_manufacturer_data; + struct ad_data *data = &ad.manufacturer.data; dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "{qv}", &dict); - dict_append_basic_array(&dict, DBUS_TYPE_UINT16, &ad_manufacturer_id, - DBUS_TYPE_BYTE, &data, - ad_manufacturer_data_len); + dict_append_basic_array(&dict, DBUS_TYPE_UINT16, &ad.manufacturer.id, + DBUS_TYPE_BYTE, &data->data, data->len); dbus_message_iter_close_container(iter, &dict); return TRUE; } -static gboolean tx_power_exists(const GDBusPropertyTable *property, void *data) +static gboolean includes_exists(const GDBusPropertyTable *property, void *data) { - return ad_tx_power; + return ad.tx_power || ad.name || ad.appearance; } -static gboolean get_tx_power(const GDBusPropertyTable *property, +static gboolean get_includes(const GDBusPropertyTable *property, DBusMessageIter *iter, void *user_data) { - dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &ad_tx_power); + DBusMessageIter array; + + dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "as", &array); + + if (ad.tx_power) { + const char *str = "tx-power"; + + dbus_message_iter_append_basic(&array, DBUS_TYPE_STRING, &str); + } + + if (ad.name) { + const char *str = "local-name"; + + dbus_message_iter_append_basic(&array, DBUS_TYPE_STRING, &str); + } + + if (ad.appearance) { + const char *str = "appearance"; + + dbus_message_iter_append_basic(&array, DBUS_TYPE_STRING, &str); + } + + dbus_message_iter_close_container(iter, &array); + return TRUE; } @@ -258,18 +296,18 @@ static const GDBusPropertyTable ad_props[] = { { "ServiceData", "a{sv}", get_service_data, NULL, service_data_exists }, { "ManufacturerData", "a{qv}", get_manufacturer_data, NULL, manufacturer_data_exists }, - { "IncludeTxPower", "b", get_tx_power, NULL, tx_power_exists }, + { "Includes", "as", get_includes, NULL, includes_exists }, { } }; void ad_register(DBusConnection *conn, GDBusProxy *manager, const char *type) { - if (registered == TRUE) { + if (ad.registered) { rl_printf("Advertisement is already registered\n"); return; } - ad_type = g_strdup(type); + ad.type = g_strdup(type); if (g_dbus_register_interface(conn, AD_PATH, AD_IFACE, ad_methods, NULL, ad_props, NULL, NULL) == FALSE) { @@ -300,7 +338,7 @@ static void unregister_reply(DBusMessage *message, void *user_data) dbus_error_init(&error); if (dbus_set_error_from_message(&error, message) == FALSE) { - registered = FALSE; + ad.registered = false; rl_printf("Advertising object unregistered\n"); if (g_dbus_unregister_interface(conn, AD_PATH, AD_IFACE) == FALSE) @@ -317,7 +355,7 @@ void ad_unregister(DBusConnection *conn, GDBusProxy *manager) if (!manager) ad_release(conn); - if (!registered) + if (!ad.registered) return; if (g_dbus_proxy_method_call(manager, "UnregisterAdvertisement", @@ -330,34 +368,33 @@ void ad_unregister(DBusConnection *conn, GDBusProxy *manager) void ad_advertise_uuids(const char *arg) { - g_strfreev(ad_uuids); - ad_uuids = NULL; - ad_uuids_len = 0; + g_strfreev(ad.uuids); + ad.uuids = NULL; + ad.uuids_len = 0; if (!arg || !strlen(arg)) return; - ad_uuids = g_strsplit(arg, " ", -1); - if (!ad_uuids) { + ad.uuids = g_strsplit(arg, " ", -1); + if (!ad.uuids) { rl_printf("Failed to parse input\n"); return; } - ad_uuids_len = g_strv_length(ad_uuids); + ad.uuids_len = g_strv_length(ad.uuids); } static void ad_clear_service(void) { - g_free(ad_service_uuid); - ad_service_uuid = NULL; - memset(ad_service_data, 0, sizeof(ad_service_data)); - ad_service_data_len = 0; + g_free(ad.service.uuid); + memset(&ad.service, 0, sizeof(ad.service)); } void ad_advertise_service(const char *arg) { wordexp_t w; unsigned int i; + struct ad_data *data; if (wordexp(arg, &w, WRDE_NOCMD)) { rl_printf("Invalid argument\n"); @@ -369,13 +406,14 @@ void ad_advertise_service(const char *arg) if (w.we_wordc == 0) goto done; - ad_service_uuid = g_strdup(w.we_wordv[0]); + ad.service.uuid = g_strdup(w.we_wordv[0]); + data = &ad.service.data; for (i = 1; i < w.we_wordc; i++) { long int val; char *endptr = NULL; - if (i >= G_N_ELEMENTS(ad_service_data)) { + if (i >= G_N_ELEMENTS(data->data)) { rl_printf("Too much data\n"); goto done; } @@ -387,8 +425,8 @@ void ad_advertise_service(const char *arg) goto done; } - ad_service_data[ad_service_data_len] = val; - ad_service_data_len++; + data->data[data->len] = val; + data->len++; } done: @@ -397,9 +435,7 @@ done: static void ad_clear_manufacturer(void) { - ad_manufacturer_id = 0; - memset(ad_manufacturer_data, 0, sizeof(ad_manufacturer_data)); - ad_manufacturer_data_len = 0; + memset(&ad.manufacturer, 0, sizeof(ad.manufacturer)); } void ad_advertise_manufacturer(const char *arg) @@ -408,6 +444,7 @@ void ad_advertise_manufacturer(const char *arg) unsigned int i; char *endptr = NULL; long int val; + struct ad_data *data; if (wordexp(arg, &w, WRDE_NOCMD)) { rl_printf("Invalid argument\n"); @@ -425,10 +462,11 @@ void ad_advertise_manufacturer(const char *arg) goto done; } - ad_manufacturer_id = val; + ad.manufacturer.id = val; + data = &ad.manufacturer.data; for (i = 1; i < w.we_wordc; i++) { - if (i >= G_N_ELEMENTS(ad_service_data)) { + if (i >= G_N_ELEMENTS(data->data)) { rl_printf("Too much data\n"); goto done; } @@ -440,8 +478,8 @@ void ad_advertise_manufacturer(const char *arg) goto done; } - ad_manufacturer_data[ad_manufacturer_data_len] = val; - ad_manufacturer_data_len++; + data->data[data->len] = val; + data->len++; } done: @@ -449,7 +487,17 @@ done: } -void ad_advertise_tx_power(gboolean value) +void ad_advertise_tx_power(bool value) +{ + ad.tx_power = value; +} + +void ad_advertise_name(bool value) +{ + ad.name = value; +} + +void ad_advertise_appearance(bool value) { - ad_tx_power = value; + ad.appearance = value; } |