diff --git a/Makefile.am b/Makefile.am index 224a0e0d..768853fc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -171,7 +171,7 @@ client_iwctl_SOURCES = client/main.c \ client/known-networks.c \ client/network.h client/network.c \ client/properties.h client/properties.c \ - client/wsc.c + client/wsc.c client/station.c client_iwctl_LDADD = ell/libell-internal.la -lreadline endif diff --git a/client/dbus-proxy.h b/client/dbus-proxy.h index cdd7423c..8772b64f 100644 --- a/client/dbus-proxy.h +++ b/client/dbus-proxy.h @@ -32,6 +32,7 @@ struct property_value_options; #define IWD_KNOWN_NETWORK_INTREFACE "net.connman.iwd.KnownNetwork" #define IWD_NETWORK_INTERFACE "net.connman.iwd.Network" #define IWD_WSC_INTERFACE "net.connman.iwd.WiFiSimpleConfiguration" +#define IWD_STATION_INTERFACE "net.connman.iwd.Station" typedef bool (*proxy_property_match_func_t) (const void *a, const void *b); diff --git a/client/device.c b/client/device.c index 9f8222ee..52e820ea 100644 --- a/client/device.c +++ b/client/device.c @@ -35,14 +35,11 @@ struct device { bool powered; - bool scanning; bool wds; char *address; char *name; - char *state; char *mode; const struct proxy_interface *adapter; - const struct proxy_interface *connected_network; }; static struct proxy_interface *default_device; @@ -56,13 +53,6 @@ static void display_device(const struct proxy_interface *proxy) l_free(caption); - if (device->connected_network) { - display("%s%*s %-*s%-*s\n", MARGIN, 8, "", - 20, "Connected network", - 47, proxy_interface_get_identity_str( - device->connected_network) ? : ""); - } - if (device->adapter) { display("%s%*s %-*s%-*s\n", MARGIN, 8, "", 20, "Adapter", 47, proxy_interface_get_identity_str( @@ -155,45 +145,6 @@ static void update_address(void *data, struct l_dbus_message_iter *variant) device->address = l_strdup(value); } -static const char *get_state(const void *data) -{ - const struct device *device = data; - - return device->state; -} - -static void update_state(void *data, struct l_dbus_message_iter *variant) -{ - struct device *device = data; - const char *value; - - l_free(device->state); - - if (!l_dbus_message_iter_get_variant(variant, "s", &value)) { - device->state = NULL; - - return; - } - - device->state = l_strdup(value); -} - -static void update_connected_network(void *data, - struct l_dbus_message_iter *variant) -{ - struct device *device = data; - const char *path; - - if (!l_dbus_message_iter_get_variant(variant, "o", &path)) { - device->connected_network = NULL; - - return; - } - - device->connected_network = proxy_interface_find(IWD_NETWORK_INTERFACE, - path); -} - static const char *get_powered_tostr(const void *data) { const struct device *device = data; @@ -236,27 +187,6 @@ static void update_wds(void *data, struct l_dbus_message_iter *variant) device->wds = value; } -static const char *get_scanning_tostr(const void *data) -{ - const struct device *device = data; - - return device->scanning ? "yes" : "no"; -} - -static void update_scanning(void *data, struct l_dbus_message_iter *variant) -{ - struct device *device = data; - bool value; - - if (!l_dbus_message_iter_get_variant(variant, "b", &value)) { - device->scanning = false; - - return; - } - - device->scanning = value; -} - static void update_adapter(void *data, struct l_dbus_message_iter *variant) { struct device *device = data; @@ -283,10 +213,6 @@ static const struct proxy_interface_property device_properties[] = { { "WDS", "b", update_wds, get_wds_tostr, true, properties_builder_append_on_off_variant, properties_on_off_opts }, - { "Scanning", "b", update_scanning, get_scanning_tostr }, - { "State", "s", update_state, get_state }, - { "ConnectedNetwork", - "o", update_connected_network }, { } }; @@ -432,11 +358,9 @@ static void device_destroy(void *data) l_free(device->address); l_free(device->name); - l_free(device->state); l_free(device->mode); device->adapter = NULL; - device->connected_network = NULL; l_free(device); } @@ -452,12 +376,10 @@ static void display_device_inline(const char *margin, const void *data) else adapter_str = "-"; - display("%s%-*s%-*s%-*s%-*s%-*s\n", margin, + display("%s%-*s%-*s%-*s\n", margin, 20, device->name ? : "", 20, device->address ? : "", - 15, device->state ? : "", - 10, adapter_str, - 8, device->scanning ? "scanning" : ""); + 10, adapter_str); } static const char *device_identity(void *data) @@ -831,6 +753,14 @@ char *device_ad_hoc_family_arg_completion(const char *text, int state) IWD_AD_HOC_INTERFACE); } +char *device_station_family_arg_completion(const char *text, int state) +{ + return proxy_property_str_completion(&device_interface_type, + match_by_partial_name, + "Name", text, state, + IWD_STATION_INTERFACE); +} + static char *family_arg_completion(const char *text, int state) { static bool first_pass; diff --git a/client/device.h b/client/device.h index e31bd409..5cfad5fd 100644 --- a/client/device.h +++ b/client/device.h @@ -23,9 +23,9 @@ struct proxy_interface; char *device_wsc_family_arg_completion(const char *text, int state); - char *device_ap_family_arg_completion(const char *text, int state); - char *device_ad_hoc_family_arg_completion(const char *text, int state); +char *device_station_family_arg_completion(const char *text, int state); + const struct proxy_interface *device_proxy_find(const char *device_name, const char *interface); diff --git a/client/station.c b/client/station.c new file mode 100644 index 00000000..af0d43f2 --- /dev/null +++ b/client/station.c @@ -0,0 +1,257 @@ +/* + * + * Wireless daemon for Linux + * + * Copyright (C) 2018 Intel Corporation. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "command.h" +#include "dbus-proxy.h" +#include "device.h" +#include "display.h" + +struct station { + bool scanning; + char *state; + const struct proxy_interface *connected_network; +}; + +static void *station_create(void) +{ + return l_new(struct station, 1); +} + +static void station_destroy(void *data) +{ + struct station *station = data; + + l_free(station->state); + station->connected_network = NULL; + + l_free(station); +} + +static const struct proxy_interface_type_ops station_ops = { + .create = station_create, + .destroy = station_destroy, +}; + +static const char *get_scanning_tostr(const void *data) +{ + const struct station *station = data; + + return station->scanning ? "yes" : "no"; +} + +static void update_scanning(void *data, struct l_dbus_message_iter *variant) +{ + struct station *station = data; + bool value; + + if (!l_dbus_message_iter_get_variant(variant, "b", &value)) { + station->scanning = false; + return; + } + + station->scanning = value; +} + +static const char *get_state(const void *data) +{ + const struct station *station = data; + + return station->state; +} + +static void update_state(void *data, struct l_dbus_message_iter *variant) +{ + struct station *station = data; + const char *value; + + l_free(station->state); + + if (!l_dbus_message_iter_get_variant(variant, "s", &value)) { + station->state = NULL; + return; + } + + station->state = l_strdup(value); +} + +static void update_connected_network(void *data, + struct l_dbus_message_iter *variant) +{ + struct station *station = data; + const char *path; + + if (!l_dbus_message_iter_get_variant(variant, "o", &path)) { + station->connected_network = NULL; + + return; + } + + station->connected_network = proxy_interface_find(IWD_NETWORK_INTERFACE, + path); +} + +static const struct proxy_interface_property station_properties[] = { + { "Scanning", "b", update_scanning, get_scanning_tostr }, + { "State", "s", update_state, get_state }, + { "ConnectedNetwork", + "o", update_connected_network }, + { } +}; + +static struct proxy_interface_type station_interface_type = { + .interface = IWD_STATION_INTERFACE, + .properties = station_properties, + .ops = &station_ops, +}; + +static void display_station_inline(const char *margin, const void *data) +{ + const struct proxy_interface *station_i = data; + const struct station *station = proxy_interface_get_data(station_i); + struct proxy_interface *device_i = + proxy_interface_find(IWD_DEVICE_INTERFACE, + proxy_interface_get_path(station_i)); + const char *identity; + + if (!device_i) + return; + + identity = proxy_interface_get_identity_str(device_i); + if (!identity) + return; + + display("%s%-*s%-*s%-*s\n", margin, + 20, identity, + 15, station->state ? : "", + 8, station->scanning ? "scanning" : ""); +} + +static enum cmd_status cmd_list(const char *device_name, char **argv, int argc) +{ + const struct l_queue_entry *entry; + struct l_queue *match = + proxy_interface_find_all(IWD_STATION_INTERFACE, NULL, NULL); + + display_table_header("Devices in Station Mode", MARGIN "%-*s%-*s%-*s", + 20, "Name", 15, "State", 8, "Scanning"); + + if (!match) { + display("No devices in Station mode available.\n"); + display_table_footer(); + + return CMD_STATUS_DONE; + } + + for (entry = l_queue_get_entries(match); entry; entry = entry->next) { + const struct proxy_interface *station = entry->data; + display_station_inline(MARGIN, station); + } + + display_table_footer(); + + l_queue_destroy(match, NULL); + + return CMD_STATUS_DONE; +} + +static const struct command station_commands[] = { + { NULL, "list", NULL, cmd_list, "List Ad-Hoc devices", true }, + { } +}; + +static char *family_arg_completion(const char *text, int state) +{ + static bool first_pass; + static size_t index; + static size_t len; + const char *cmd; + + if (!state) { + index = 0; + len = strlen(text); + first_pass = true; + } + + while ((cmd = station_commands[index].cmd)) { + if (station_commands[index++].entity) + continue; + + if (!strncmp(cmd, text, len)) + return l_strdup(cmd); + } + + if (first_pass) { + state = 0; + first_pass = false; + } + + return device_station_family_arg_completion(text, state); +} + +static char *entity_arg_completion(const char *text, int state) +{ + return command_entity_arg_completion(text, state, station_commands); +} + +static struct command_family station_command_family = { + .caption = "Station", + .name = "station", + .command_list = station_commands, + .family_arg_completion = family_arg_completion, + .entity_arg_completion = entity_arg_completion, +}; + +static int station_command_family_init(void) +{ + command_family_register(&station_command_family); + + return 0; +} + +static void station_command_family_exit(void) +{ + command_family_unregister(&station_command_family); +} + +COMMAND_FAMILY(station_command_family, station_command_family_init, + station_command_family_exit) + +static int station_interface_init(void) +{ + proxy_interface_type_register(&station_interface_type); + + return 0; +} + +static void station_interface_exit(void) +{ + proxy_interface_type_unregister(&station_interface_type); +} + +INTERFACE_TYPE(station_interface_type, + station_interface_init, station_interface_exit)