diff --git a/client/gatt.c b/client/gatt.c
index 7c44a9f..8fb3f62 100644
--- a/client/gatt.c
+++ b/client/gatt.c
{
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)
+{
+ static GList *list = NULL;
+
+ if (!state) {
+ GList *list1;
+
+ if (list) {
+ g_list_free(list);
+ list = NULL;
+ }
+
+ list1 = g_list_copy(characteristics);
+ list1 = g_list_concat(list1, g_list_copy(descriptors));
+
+ list = g_list_copy(services);
+ list = g_list_concat(list, list1);
+ }
+
+ return attribute_generator(text, state, list);
+}
diff --git a/client/gatt.h b/client/gatt.h
index 5785073..bb7cb1c 100644
--- a/client/gatt.h
+++ b/client/gatt.h
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
static GDBusProxy *default_ctrl;
static GDBusProxy *default_dev;
+static GDBusProxy *default_attr;
static GList *ctrl_list;
static GList *dev_list;
}
}
-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);
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;
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);
if (default_ctrl == proxy) {
default_ctrl = NULL;
- set_default_device(NULL);
+ set_default_device(NULL, NULL);
g_list_free(dev_list);
dev_list = NULL;
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);
}
}
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);
rl_printf("Connection successful\n");
- set_default_device(proxy);
+ set_default_device(proxy, NULL);
}
static void cmd_connect(const char *arg)
if (proxy != default_dev)
return;
- set_default_device(NULL);
+ set_default_device(NULL, NULL);
}
static void cmd_disconn(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);
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;
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 },