diff --git a/client/main.c b/client/main.c
index 1ceddb0..9ba5a40 100644
--- a/client/main.c
+++ b/client/main.c
#include <readline/history.h>
#include <glib.h>
+#include "src/shared/util.h"
#include "gdbus/gdbus.h"
#include "monitor/uuid.h"
#include "agent.h"
static GDBusProxy *agent_manager;
static char *auto_register_agent = NULL;
-static GDBusProxy *ad_manager;
+struct adapter {
+ GDBusProxy *proxy;
+ GList *devices;
+};
-static GDBusProxy *default_ctrl;
+static struct adapter *default_ctrl;
static GDBusProxy *default_dev;
static GDBusProxy *default_attr;
+static GDBusProxy *ad_manager;
static GList *ctrl_list;
-static GList *dev_list;
static guint input = 0;
rl_on_new_line();
rl_redisplay();
- g_list_free(ctrl_list);
+ g_list_free_full(ctrl_list, proxy_leak);
ctrl_list = NULL;
default_ctrl = NULL;
-
- g_list_free(dev_list);
- dev_list = NULL;
}
static void print_adapter(GDBusProxy *proxy, const char *description)
description ? : "",
description ? "] " : "",
address, name,
- default_ctrl == proxy ? "[default]" : "");
+ default_ctrl &&
+ default_ctrl->proxy == proxy ?
+ "[default]" : "");
}
dbus_message_iter_get_basic(&iter, &device);
- for (l = dev_list; l; l = g_list_next(l)) {
- GDBusProxy *proxy = l->data;
+ if (!default_ctrl)
+ return FALSE;
+
+ for (l = default_ctrl->devices; l; l = g_list_next(l)) {
+ struct GDBusProxy *proxy = l->data;
path = g_dbus_proxy_get_path(proxy);
return FALSE;
}
+static struct adapter *find_parent(GDBusProxy *device)
+{
+ GList *list;
+
+ for (list = g_list_first(ctrl_list); list; list = g_list_next(list)) {
+ struct adapter *adapter = list->data;
+
+ if (device_is_child(device, adapter->proxy) == TRUE)
+ return adapter;
+ }
+ return NULL;
+}
+
static void set_default_device(GDBusProxy *proxy, const char *attribute)
{
char *desc = NULL;
static void device_added(GDBusProxy *proxy)
{
DBusMessageIter iter;
+ struct adapter *adapter = find_parent(proxy);
- dev_list = g_list_append(dev_list, proxy);
+ if (!adapter) {
+ /* TODO: Error */
+ return;
+ }
+ adapter->devices = g_list_append(adapter->devices, proxy);
print_device(proxy, COLORED_NEW);
if (default_dev)
}
}
+static void adapter_added(GDBusProxy *proxy)
+{
+ struct adapter *adapter = g_malloc0(sizeof(struct adapter));
+
+ adapter->proxy = proxy;
+ ctrl_list = g_list_append(ctrl_list, adapter);
+
+ if (!default_ctrl)
+ default_ctrl = adapter;
+
+ print_adapter(proxy, COLORED_NEW);
+}
+
static void proxy_added(GDBusProxy *proxy, void *user_data)
{
const char *interface;
interface = g_dbus_proxy_get_interface(proxy);
if (!strcmp(interface, "org.bluez.Device1")) {
- if (device_is_child(proxy, default_ctrl) == TRUE)
- device_added(proxy);
-
+ device_added(proxy);
} else if (!strcmp(interface, "org.bluez.Adapter1")) {
- ctrl_list = g_list_append(ctrl_list, proxy);
-
- if (!default_ctrl)
- default_ctrl = proxy;
-
- print_adapter(proxy, COLORED_NEW);
+ adapter_added(proxy);
} else if (!strcmp(interface, "org.bluez.AgentManager1")) {
if (!agent_manager) {
agent_manager = proxy;
set_default_device(default_dev, path);
}
-static void proxy_removed(GDBusProxy *proxy, void *user_data)
+static void device_removed(GDBusProxy *proxy)
{
- const char *interface;
+ struct adapter *adapter = find_parent(proxy);
+ if (!adapter) {
+ /* TODO: Error */
+ return;
+ }
- interface = g_dbus_proxy_get_interface(proxy);
+ adapter->devices = g_list_remove(adapter->devices, proxy);
- if (!strcmp(interface, "org.bluez.Device1")) {
- if (device_is_child(proxy, default_ctrl) == TRUE) {
- dev_list = g_list_remove(dev_list, proxy);
+ print_device(proxy, COLORED_DEL);
+
+ if (default_dev == proxy)
+ set_default_device(NULL, NULL);
+}
+
+static void adapter_removed(GDBusProxy *proxy)
+{
+ GList *ll;
- print_device(proxy, COLORED_DEL);
+ for (ll = g_list_first(ctrl_list); ll; ll = g_list_next(ll)) {
+ struct adapter *adapter = ll->data;
- if (default_dev == proxy)
+ if (adapter->proxy == proxy) {
+ print_adapter(proxy, COLORED_DEL);
+
+ if (default_ctrl && default_ctrl->proxy == proxy) {
+ default_ctrl = NULL;
set_default_device(NULL, NULL);
+ }
+
+ ctrl_list = g_list_remove_link(ctrl_list, ll);
+ g_list_free(adapter->devices);
+ g_free(adapter);
+ g_list_free(ll);
+ return;
}
- } else if (!strcmp(interface, "org.bluez.Adapter1")) {
- ctrl_list = g_list_remove(ctrl_list, proxy);
+ }
+}
- print_adapter(proxy, COLORED_DEL);
+static void proxy_removed(GDBusProxy *proxy, void *user_data)
+{
+ const char *interface;
- if (default_ctrl == proxy) {
- default_ctrl = NULL;
- set_default_device(NULL, NULL);
+ interface = g_dbus_proxy_get_interface(proxy);
- g_list_free(dev_list);
- dev_list = NULL;
- }
+ if (!strcmp(interface, "org.bluez.Device1")) {
+ device_removed(proxy);
+ } else if (!strcmp(interface, "org.bluez.Adapter1")) {
+ adapter_removed(proxy);
} else if (!strcmp(interface, "org.bluez.AgentManager1")) {
if (agent_manager == proxy) {
agent_manager = NULL;
interface = g_dbus_proxy_get_interface(proxy);
if (!strcmp(interface, "org.bluez.Device1")) {
- if (device_is_child(proxy, default_ctrl) == TRUE) {
+ if (default_ctrl && device_is_child(proxy,
+ default_ctrl->proxy) == TRUE) {
DBusMessageIter addr_iter;
char *str;
dbus_message_get_member(message));
}
+static struct adapter *find_ctrl_by_address(GList *source, const char *address)
+{
+ GList *list;
+
+ for (list = g_list_first(source); list; list = g_list_next(list)) {
+ struct adapter *adapter = list->data;
+ DBusMessageIter iter;
+ const char *str;
+
+ if (g_dbus_proxy_get_property(adapter->proxy,
+ "Address", &iter) == FALSE)
+ continue;
+
+ dbus_message_iter_get_basic(&iter, &str);
+
+ if (!strcmp(str, address))
+ return adapter;
+ }
+
+ return NULL;
+}
+
static GDBusProxy *find_proxy_by_address(GList *source, const char *address)
{
GList *list;
GList *list;
for (list = g_list_first(ctrl_list); list; list = g_list_next(list)) {
- GDBusProxy *proxy = list->data;
- print_adapter(proxy, NULL);
+ struct adapter *adapter = list->data;
+ print_adapter(adapter->proxy, NULL);
}
}
static void cmd_show(const char *arg)
{
+ struct adapter *adapter;
GDBusProxy *proxy;
DBusMessageIter iter;
const char *address;
if (check_default_ctrl() == FALSE)
return;
- proxy = default_ctrl;
+ proxy = default_ctrl->proxy;
} else {
- proxy = find_proxy_by_address(ctrl_list, arg);
- if (!proxy) {
+ adapter = find_ctrl_by_address(ctrl_list, arg);
+ if (!adapter) {
rl_printf("Controller %s not available\n", arg);
return;
}
+ proxy = adapter->proxy;
}
if (g_dbus_proxy_get_property(proxy, "Address", &iter) == FALSE)
static void cmd_select(const char *arg)
{
- GDBusProxy *proxy;
+ struct adapter *adapter;
if (!arg || !strlen(arg)) {
rl_printf("Missing controller address argument\n");
return;
}
- proxy = find_proxy_by_address(ctrl_list, arg);
- if (!proxy) {
+ adapter = find_ctrl_by_address(ctrl_list, arg);
+ if (!adapter) {
rl_printf("Controller %s not available\n", arg);
return;
}
- if (default_ctrl == proxy)
+ if (default_ctrl && default_ctrl->proxy == adapter->proxy)
return;
- default_ctrl = proxy;
- print_adapter(proxy, NULL);
-
- g_list_free(dev_list);
- dev_list = NULL;
+ default_ctrl = adapter;
+ print_adapter(adapter->proxy, NULL);
}
static void cmd_devices(const char *arg)
{
- GList *list;
+ GList *ll;
- for (list = g_list_first(dev_list); list; list = g_list_next(list)) {
- GDBusProxy *proxy = list->data;
+ if (check_default_ctrl() == FALSE)
+ return;
+
+ for (ll = g_list_first(default_ctrl->devices);
+ ll; ll = g_list_next(ll)) {
+ GDBusProxy *proxy = ll->data;
print_device(proxy, NULL);
}
}
static void cmd_paired_devices(const char *arg)
{
- GList *list;
+ GList *ll;
- for (list = g_list_first(dev_list); list; list = g_list_next(list)) {
- GDBusProxy *proxy = list->data;
+ if (check_default_ctrl() == FALSE)
+ return;
+
+ for (ll = g_list_first(default_ctrl->devices);
+ ll; ll = g_list_next(ll)) {
+ GDBusProxy *proxy = ll->data;
DBusMessageIter iter;
dbus_bool_t paired;
name = g_strdup(arg);
- if (g_dbus_proxy_set_property_basic(default_ctrl, "Alias",
+ if (g_dbus_proxy_set_property_basic(default_ctrl->proxy, "Alias",
DBUS_TYPE_STRING, &name,
generic_callback, name, g_free) == TRUE)
return;
name = g_strdup("");
- if (g_dbus_proxy_set_property_basic(default_ctrl, "Alias",
+ if (g_dbus_proxy_set_property_basic(default_ctrl->proxy, "Alias",
DBUS_TYPE_STRING, &name,
generic_callback, name, g_free) == TRUE)
return;
str = g_strdup_printf("power %s", powered == TRUE ? "on" : "off");
- if (g_dbus_proxy_set_property_basic(default_ctrl, "Powered",
+ if (g_dbus_proxy_set_property_basic(default_ctrl->proxy, "Powered",
DBUS_TYPE_BOOLEAN, &powered,
generic_callback, str, g_free) == TRUE)
return;
str = g_strdup_printf("pairable %s", pairable == TRUE ? "on" : "off");
- if (g_dbus_proxy_set_property_basic(default_ctrl, "Pairable",
+ if (g_dbus_proxy_set_property_basic(default_ctrl->proxy, "Pairable",
DBUS_TYPE_BOOLEAN, &pairable,
generic_callback, str, g_free) == TRUE)
return;
str = g_strdup_printf("discoverable %s",
discoverable == TRUE ? "on" : "off");
- if (g_dbus_proxy_set_property_basic(default_ctrl, "Discoverable",
+ if (g_dbus_proxy_set_property_basic(default_ctrl->proxy, "Discoverable",
DBUS_TYPE_BOOLEAN, &discoverable,
generic_callback, str, g_free) == TRUE)
return;
else
method = "StopDiscovery";
- if (g_dbus_proxy_method_call(default_ctrl, method,
+ if (g_dbus_proxy_method_call(default_ctrl->proxy, method,
NULL, start_discovery_reply,
GUINT_TO_POINTER(enable), NULL) == FALSE) {
rl_printf("Failed to %s discovery\n",
if (check_default_ctrl() == FALSE)
return;
- if (g_dbus_proxy_method_call(default_ctrl, "SetDiscoveryFilter",
+ if (g_dbus_proxy_method_call(default_ctrl->proxy, "SetDiscoveryFilter",
set_discovery_filter_setup, set_discovery_filter_reply,
&args, NULL) == FALSE) {
rl_printf("Failed to set discovery filter\n");
g_free(filtered_scan_transport);
filtered_scan_transport = NULL;
- if (g_dbus_proxy_method_call(default_ctrl, "SetDiscoveryFilter",
+ if (check_default_ctrl() == FALSE)
+ return;
+
+ if (g_dbus_proxy_method_call(default_ctrl->proxy, "SetDiscoveryFilter",
clear_discovery_filter_setup, set_discovery_filter_reply,
NULL, NULL) == FALSE) {
rl_printf("Failed to clear discovery filter\n");
return NULL;
}
- proxy = find_proxy_by_address(dev_list, arg);
+ if (check_default_ctrl() == FALSE)
+ return NULL;
+
+ proxy = find_proxy_by_address(default_ctrl->devices, arg);
if (!proxy) {
rl_printf("Device %s not available\n", arg);
return NULL;
path = g_strdup(g_dbus_proxy_get_path(proxy));
- if (g_dbus_proxy_method_call(default_ctrl, "RemoveDevice",
+ if (!default_ctrl)
+ return;
+
+ if (g_dbus_proxy_method_call(default_ctrl->proxy, "RemoveDevice",
remove_device_setup,
remove_device_reply,
path, g_free) == FALSE) {
if (strcmp(arg, "*") == 0) {
GList *list;
- for (list = g_list_first(dev_list); list; list = g_list_next(list)) {
+ for (list = default_ctrl->devices; list;
+ list = g_list_next(list)) {
GDBusProxy *proxy = list->data;
remove_device(proxy);
}
-
return;
}
- proxy = find_proxy_by_address(dev_list, arg);
+ proxy = find_proxy_by_address(default_ctrl->devices, arg);
if (!proxy) {
rl_printf("Device %s not available\n", arg);
return;
return;
}
- proxy = find_proxy_by_address(dev_list, arg);
+ if (check_default_ctrl() == FALSE)
+ return;
+
+ proxy = find_proxy_by_address(default_ctrl->devices, arg);
if (!proxy) {
rl_printf("Device %s not available\n", arg);
return;
return;
}
- gatt_register_profile(dbus_conn, default_ctrl, &w);
+ gatt_register_profile(dbus_conn, default_ctrl->proxy, &w);
wordfree(&w);
}
if (check_default_ctrl() == FALSE)
return;
- gatt_unregister_profile(dbus_conn, default_ctrl);
+ gatt_unregister_profile(dbus_conn, default_ctrl->proxy);
}
static void cmd_version(const char *arg)
static char *ctrl_generator(const char *text, int state)
{
- return generic_generator(text, state, ctrl_list, "Address");
+ static int index = 0;
+ static int len = 0;
+ GList *list;
+
+ if (!state) {
+ index = 0;
+ len = strlen(text);
+ }
+
+ for (list = g_list_nth(ctrl_list, index); list;
+ list = g_list_next(list)) {
+ struct adapter *adapter = list->data;
+ DBusMessageIter iter;
+ const char *str;
+
+ index++;
+
+ if (g_dbus_proxy_get_property(adapter->proxy,
+ "Address", &iter) == FALSE)
+ continue;
+
+ dbus_message_iter_get_basic(&iter, &str);
+
+ if (!strncmp(str, text, len))
+ return strdup(str);
+ }
+
+ return NULL;
}
static char *dev_generator(const char *text, int state)
{
- return generic_generator(text, state, dev_list, "Address");
+ return generic_generator(text, state,
+ default_ctrl ? default_ctrl->devices : NULL, "Address");
}
static char *attribute_generator(const char *text, int state)
g_main_loop_unref(main_loop);
g_list_free_full(ctrl_list, proxy_leak);
- g_list_free_full(dev_list, proxy_leak);
g_free(auto_register_agent);