From: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx> Command select-attribute can be used to select a service attribute. --- client/gatt.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----- client/gatt.h | 2 ++ client/main.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 144 insertions(+), 15 deletions(-) diff --git a/client/gatt.c b/client/gatt.c index 723b6d6..f2830a3 100644 --- a/client/gatt.c +++ b/client/gatt.c @@ -234,15 +234,14 @@ static void list_attributes(const char *path, GList *source) if (!g_str_has_prefix(proxy_path, path)) continue; - if (source == services) + if (source == services) { print_service(proxy, NULL); - else if (source == characteristics) + list_attributes(proxy_path, characteristics); + } else if (source == characteristics) { print_characteristic(proxy, NULL); - else if (source == descriptors) + list_attributes(proxy_path, descriptors); + } else if (source == descriptors) print_descriptor(proxy, NULL); - - list_attributes(proxy_path, source == services ? characteristics - : descriptors); } } @@ -250,3 +249,73 @@ void gatt_list_attributes(const char *path) { list_attributes(path, services); } + +static GDBusProxy *select_proxy(const char *path, GList *source) +{ + GList *l; + + for (l = source; l; l = g_list_next(l)) { + GDBusProxy *proxy = l->data; + + if (strcmp(path, g_dbus_proxy_get_path(proxy)) == 0) + return proxy; + } + + return NULL; +} + +GDBusProxy *gatt_select_attribute(const char *path) +{ + GDBusProxy *proxy; + + proxy = select_proxy(path, services); + if (proxy) + return proxy; + + proxy = select_proxy(path, characteristics); + if (proxy) + return proxy; + + return select_proxy(path, descriptors); +} + +static char *attribute_generator(const char *text, int state, GList *source) +{ + static int index, len; + GList *list; + + if (!state) { + index = 0; + len = strlen(text); + } + + for (list = g_list_nth(source, index); list; + list = g_list_next(list)) { + GDBusProxy *proxy = list->data; + const char *path; + + index++; + + path = g_dbus_proxy_get_path(proxy); + + if (!strncmp(path, text, len)) + return strdup(path); + } + + return NULL; +} + +char *gatt_attribute_generator(const char *text, int state) +{ + char *ret; + + ret = attribute_generator(text, state, services); + if (ret) + return ret; + + ret = attribute_generator(text, state, characteristics); + if (ret) + return ret; + + return attribute_generator(text, state, descriptors); +} diff --git a/client/gatt.h b/client/gatt.h index 5785073..bb7cb1c 100644 --- a/client/gatt.h +++ b/client/gatt.h @@ -31,3 +31,5 @@ void gatt_add_descriptor(GDBusProxy *proxy); void gatt_remove_descriptor(GDBusProxy *proxy); void gatt_list_attributes(const char *device); +GDBusProxy *gatt_select_attribute(const char *path); +char *gatt_attribute_generator(const char *text, int state); diff --git a/client/main.c b/client/main.c index 7cdb19a..1481694 100644 --- a/client/main.c +++ b/client/main.c @@ -59,6 +59,7 @@ static char *auto_register_agent = NULL; static GDBusProxy *default_ctrl; static GDBusProxy *default_dev; +static GDBusProxy *default_attr; static GList *ctrl_list; static GList *dev_list; @@ -346,20 +347,30 @@ static void proxy_added(GDBusProxy *proxy, void *user_data) } } -static void set_default_device(GDBusProxy *proxy) +static void set_default_device(GDBusProxy *proxy, const char *attribute) { char *desc = NULL; DBusMessageIter iter; + const char *path; default_dev = proxy; + if (proxy == NULL) { + default_attr = NULL; + goto done; + } + if (!g_dbus_proxy_get_property(proxy, "Alias", &iter)) { if (!g_dbus_proxy_get_property(proxy, "Address", &iter)) goto done; } + path = g_dbus_proxy_get_path(proxy); + dbus_message_iter_get_basic(&iter, &desc); - desc = g_strdup_printf(COLOR_BLUE "[%s]" COLOR_OFF "# ", desc); + desc = g_strdup_printf(COLOR_BLUE "[%s%s%s]" COLOR_OFF "# ", desc, + attribute ? ":" : "", + attribute ? attribute + strlen(path) : ""); done: rl_set_prompt(desc ? desc : PROMPT_ON); @@ -367,6 +378,17 @@ done: g_free(desc); } +static void set_default_attribute(GDBusProxy *proxy) +{ + const char *path; + + default_attr = proxy; + + path = g_dbus_proxy_get_path(proxy); + + set_default_device(default_dev, path); +} + static void proxy_removed(GDBusProxy *proxy, void *user_data) { const char *interface; @@ -380,7 +402,7 @@ static void proxy_removed(GDBusProxy *proxy, void *user_data) print_device(proxy, COLORED_DEL); if (default_dev == proxy) - set_default_device(NULL); + set_default_device(NULL, NULL); } } else if (!strcmp(interface, "org.bluez.Adapter1")) { ctrl_list = g_list_remove(ctrl_list, proxy); @@ -389,7 +411,7 @@ static void proxy_removed(GDBusProxy *proxy, void *user_data) if (default_ctrl == proxy) { default_ctrl = NULL; - set_default_device(NULL); + set_default_device(NULL, NULL); g_list_free(dev_list); dev_list = NULL; @@ -401,12 +423,22 @@ static void proxy_removed(GDBusProxy *proxy, void *user_data) agent_unregister(dbus_conn, NULL); } } else if (!strcmp(interface, "org.bluez.GattService1")) { - if (service_is_child(proxy)) + if (service_is_child(proxy)) { gatt_remove_service(proxy); + + if (default_attr == proxy) + set_default_attribute(NULL); + } } else if (!strcmp(interface, "org.bluez.GattCharacteristic1")) { gatt_remove_characteristic(proxy); + + if (default_attr == proxy) + set_default_attribute(NULL); } else if (!strcmp(interface, "org.bluez.GattDescriptor1")) { gatt_remove_descriptor(proxy); + + if (default_attr == proxy) + set_default_attribute(NULL); } } @@ -439,9 +471,9 @@ static void property_changed(GDBusProxy *proxy, const char *name, dbus_message_iter_get_basic(iter, &connected); if (connected && default_dev == NULL) - set_default_device(proxy); + set_default_device(proxy, NULL); else if (!connected && default_dev == proxy) - set_default_device(NULL); + set_default_device(NULL, NULL); } print_iter(str, name, iter); @@ -1085,7 +1117,7 @@ static void connect_reply(DBusMessage *message, void *user_data) rl_printf("Connection successful\n"); - set_default_device(proxy); + set_default_device(proxy, NULL); } static void cmd_connect(const char *arg) @@ -1130,7 +1162,7 @@ static void disconn_reply(DBusMessage *message, void *user_data) if (proxy != default_dev) return; - set_default_device(NULL); + set_default_device(NULL, NULL); } static void cmd_disconn(const char *arg) @@ -1161,6 +1193,25 @@ static void cmd_list_attributes(const char *arg) gatt_list_attributes(g_dbus_proxy_get_path(proxy)); } +static void cmd_select_attribute(const char *arg) +{ + GDBusProxy *proxy; + + if (!arg || !strlen(arg)) { + rl_printf("Missing attribute argument\n"); + return; + } + + if (!default_dev) { + rl_printf("No device connected\n"); + return; + } + + proxy = gatt_select_attribute(arg); + if (proxy) + set_default_attribute(proxy); +} + static void cmd_version(const char *arg) { rl_printf("Version %s\n", VERSION); @@ -1212,6 +1263,11 @@ static char *dev_generator(const char *text, int state) return generic_generator(text, state, dev_list, "Address"); } +static char *attribute_generator(const char *text, int state) +{ + return gatt_attribute_generator(text, state); +} + static char *capability_generator(const char *text, int state) { static int index, len; @@ -1281,6 +1337,8 @@ static const struct { dev_generator }, { "list-attributes", "[dev]", cmd_list_attributes, "List attributes", dev_generator }, + { "select-attribute", "<attribute>", cmd_select_attribute, + "Select attribute", attribute_generator }, { "version", NULL, cmd_version, "Display version" }, { "quit", NULL, cmd_quit, "Quit program" }, { "exit", NULL, cmd_quit }, -- 2.1.0 -- To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html