The information requested with GetDiagnostics will now appear in
the "station <iface> show" command. If IWD is not connected, or
there is no diagnostic interface (older IWD version) 'show' will
behave as it always has, only showing scanning/connected.
---
client/station.c | 106 +++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 102 insertions(+), 4 deletions(-)
diff --git a/client/station.c b/client/station.c
index b6b59239..93b1a4da 100644
--- a/client/station.c
+++ b/client/station.c
@@ -130,6 +130,10 @@ static struct proxy_interface_type station_interface_type = {
.ops = &station_ops,
};
+static struct proxy_interface_type station_diagnostic_interface = {
+ .interface = IWD_STATION_DIAGNOSTIC_INTERFACE,
+};
+
static void check_errors_method_callback(struct l_dbus_message *message,
void *user_data)
{
@@ -137,7 +141,8 @@ static void check_errors_method_callback(struct l_dbus_message
*message,
}
static void display_station(const char *device_name,
- const struct proxy_interface *proxy)
+ const struct proxy_interface *proxy,
+ bool *connected)
{
const struct station *station = proxy_interface_get_data(proxy);
char *caption = l_strdup_printf("%s: %s", "Station", device_name);
@@ -145,10 +150,15 @@ static void display_station(const char *device_name,
proxy_properties_display(proxy, caption, MARGIN, 20, 47);
l_free(caption);
- if (station->connected_network)
+ if (station->connected_network) {
display("%s%*s %-*s%-*s\n", MARGIN, 8, "", 20,
"Connected network", 47,
network_get_name(station->connected_network));
+ *connected = true;
+ return;
+ }
+
+ *connected = false;
display_table_footer();
}
@@ -583,20 +593,106 @@ static enum cmd_status cmd_scan(const char *device_name,
return CMD_STATUS_TRIGGERED;
}
+static void get_diagnostics_callback(struct l_dbus_message *message,
+ void *user_data)
+{
+ struct l_dbus_message_iter iter;
+ struct l_dbus_message_iter variant;
+ const char *key;
+
+ if (dbus_message_has_error(message))
+ return;
+
+ if (!l_dbus_message_get_arguments(message, "a{sv}", &iter)) {
+ l_error("Failed to parse GetDiagnostics message");
+ goto done;
+ }
+
+ while (l_dbus_message_iter_next_entry(&iter, &key, &variant)) {
+ const char *s_value;
+ uint32_t u_value;
+ int16_t i_value;
+ uint8_t y_value;
+
+ if (!strcmp(key, "ConnectedBss") || !strcmp(key, "RxMode") ||
+ !strcmp(key, "TxMode")) {
+ /* String variants with no special handling */
+
+ l_dbus_message_iter_get_variant(&variant, "s",
+ &s_value);
+
+ display("%s%*s %-*s%-*s\n", MARGIN, 8, "", 20,
+ key, 47, s_value);
+ } else if (!strcmp(key, "RxBitrate") ||
+ !strcmp(key, "TxBitrate")) {
+ /* Bitrates expressed in 100Kbit/s */
+
+ l_dbus_message_iter_get_variant(&variant, "u",
+ &u_value);
+ display("%s%*s %-*s%u Kbit/s\n", MARGIN, 8, "", 20,
+ key, u_value * 100);
+ } else if (!strcmp(key, "ExpectedThroughput")) {
+ /* ExpectedThroughput expressed in Kbit/s */
+
+ l_dbus_message_iter_get_variant(&variant, "u",
+ &u_value);
+ display("%s%*s %-*s%u Kbit/s\n", MARGIN, 8, "", 20,
+ key, u_value);
+ } else if (!strcmp(key, "RSSI")) {
+ /* RSSI expressed in dBm */
+
+ l_dbus_message_iter_get_variant(&variant, "n",
+ &i_value);
+ display("%s%*s %-*s%i dBm\n", MARGIN, 8, "", 20,
+ key, i_value);
+ } else if (!strcmp(key, "RxMCS") || !strcmp(key, "TxMCS")) {
+ /* MCS index's are single byte integers */
+
+ l_dbus_message_iter_get_variant(&variant, "y",
+ &y_value);
+ display("%s%*s %-*s%u\n", MARGIN, 8, "", 20,
+ key, y_value);
+ }
+ }
+
+done:
+ /* Finish the table started by cmd_show */
+ display_table_footer();
+ display_refresh_reset();
+}
+
static enum cmd_status cmd_show(const char *device_name,
char **argv, int argc)
{
const struct proxy_interface *station =
device_proxy_find(device_name, IWD_STATION_INTERFACE);
+ const struct proxy_interface *diagnostic =
+ device_proxy_find(device_name,
+ IWD_STATION_DIAGNOSTIC_INTERFACE);
+ bool connected;
if (!station) {
display("No station on device: '%s'\n", device_name);
return CMD_STATUS_INVALID_VALUE;
}
- display_station(device_name, station);
+ display_station(device_name, station, &connected);
- return CMD_STATUS_DONE;
+ /*
+ * No need to query additional diagnostic information if not connected,
+ * or IWD has no diagnostic interface.
+ */
+ if (!connected || !diagnostic) {
+ display_table_footer();
+ display_refresh_reset();
+ return CMD_STATUS_DONE;
+ }
+
+ proxy_interface_method_call(diagnostic, "GetDiagnostics", "",
+ get_diagnostics_callback);
+
+ /* Don't display table footer, this will be done in the callback */
+ return CMD_STATUS_TRIGGERED;
}
static const struct command station_commands[] = {
@@ -663,6 +759,7 @@ COMMAND_FAMILY(station_command_family, station_command_family_init,
static int station_interface_init(void)
{
proxy_interface_type_register(&station_interface_type);
+ proxy_interface_type_register(&station_diagnostic_interface);
return 0;
}
@@ -670,6 +767,7 @@ static int station_interface_init(void)
static void station_interface_exit(void)
{
proxy_interface_type_unregister(&station_interface_type);
+ proxy_interface_type_unregister(&station_diagnostic_interface);
}
INTERFACE_TYPE(station_interface_type,
--
2.26.2