Unlike Scan, SignalPoll is not supposed to disturb active connections
or affect throughput in any way. The primary use case is querying the
signal strength of the AP we are currently connected to.
---
 gsupplicant/gsupplicant.h |  14 ++++++
 gsupplicant/supplicant.c  | 121 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 135 insertions(+)
 mode change 100755 => 100644 gsupplicant/supplicant.c

diff --git a/gsupplicant/gsupplicant.h b/gsupplicant/gsupplicant.h
index 2a87f2f..161c8a2 100644
--- a/gsupplicant/gsupplicant.h
+++ b/gsupplicant/gsupplicant.h
@@ -168,6 +168,13 @@ struct _GSupplicantScanParams {
        uint16_t *freqs;
 };
 
+typedef struct _GSupplicantSignalPoll {
+       int rssi;
+       int linkspeed;
+       int noise;
+       unsigned int frequency;
+} GSupplicantSignalPoll;
+
 typedef struct _GSupplicantScanParams GSupplicantScanParams;
 
 struct _GSupplicantPeerParams {
@@ -211,6 +218,10 @@ typedef void (*GSupplicantInterfaceCallback) (int result,
                                        GSupplicantInterface *interface,
                                                        void *user_data);
 
+typedef void (*GSupplicantSignalPollCallback) (int result,
+                                               const GSupplicantSignalPoll 
*data,
+                                                       void *user_data);
+
 void g_supplicant_interface_cancel(GSupplicantInterface *interface);
 
 int g_supplicant_interface_create(const char *ifname, const char *driver,
@@ -287,6 +298,9 @@ int g_supplicant_interface_set_country(GSupplicantInterface 
*interface,
                                        GSupplicantCountryCallback callback,
                                                        const char *alpha2,
                                                        void *user_data);
+int g_supplicant_interface_signal_poll(GSupplicantInterface *interface,
+                                       GSupplicantSignalPollCallback callback,
+                                                       void *user_data);
 bool g_supplicant_interface_has_p2p(GSupplicantInterface *interface);
 int g_supplicant_interface_set_p2p_device_config(GSupplicantInterface 
*interface,
                                                const char *device_name,
diff --git a/gsupplicant/supplicant.c b/gsupplicant/supplicant.c
old mode 100755
new mode 100644
index fb62a97..2e9b640
--- a/gsupplicant/supplicant.c
+++ b/gsupplicant/supplicant.c
@@ -3322,6 +3322,127 @@ int 
g_supplicant_interface_set_country(GSupplicantInterface *interface,
        return ret;
 }
 
+static bool signal_poll_get_data(DBusMessageIter *iter,
+                                               GSupplicantSignalPoll *data)
+{
+       DBusMessageIter array, dict;
+
+       memset(data, 0, sizeof(*data));
+       if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_VARIANT)
+               return false;
+
+       dbus_message_iter_recurse(iter, &array);
+       if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
+               return false;
+
+       dbus_message_iter_recurse(&array, &dict);
+       while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
+               DBusMessageIter entry, value;
+               DBusBasicValue basic;
+               const char *key = NULL;
+
+               dbus_message_iter_recurse(&dict, &entry);
+                if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
+                    return false;
+
+               dbus_message_iter_get_basic(&entry, &key);
+               dbus_message_iter_next(&entry);
+                if (dbus_message_iter_get_arg_type(&entry) != 
DBUS_TYPE_VARIANT)
+                    return false;
+
+               dbus_message_iter_recurse(&entry, &value);
+               if (g_str_equal(key, "rssi")) {
+                       if (dbus_message_iter_get_arg_type(&value) !=
+                                                       DBUS_TYPE_INT32)
+                               return false;
+
+                       dbus_message_iter_get_basic(&value, &basic);
+                       data->rssi = basic.i32;
+               } else if (g_str_equal(key, "linkspeed")) {
+                       if (dbus_message_iter_get_arg_type(&value) !=
+                                                       DBUS_TYPE_INT32)
+                               return false;
+
+                       dbus_message_iter_get_basic(&value, &basic);
+                       data->linkspeed = basic.i32;
+               } else if (g_str_equal(key, "noise")) {
+                       if (dbus_message_iter_get_arg_type(&value) !=
+                                                       DBUS_TYPE_INT32)
+                               return false;
+
+                       dbus_message_iter_get_basic(&value, &basic);
+                       data->noise = basic.i32;
+               } else if (g_str_equal(key, "frequency")) {
+                       if (dbus_message_iter_get_arg_type(&value) !=
+                                                       DBUS_TYPE_UINT32)
+                               return false;
+
+                       dbus_message_iter_get_basic(&value, &basic);
+                       data->frequency = basic.u32;
+               }
+
+               dbus_message_iter_next(&dict);
+       }
+
+       return true;
+}
+
+struct signal_poll_call {
+       GSupplicantSignalPollCallback callback;
+       void *user_data;
+};
+
+static void signal_poll_result(const char *error, DBusMessageIter *iter,
+                                                       void *user_data)
+{
+       struct signal_poll_call *call = user_data;
+       const GSupplicantSignalPoll *data = NULL;
+       GSupplicantSignalPoll parsed_data;
+       int result;
+
+       if (error) {
+               SUPPLICANT_DBG("SignalPoll failure %s", error);
+               result = -EFAULT;
+       } else if (!signal_poll_get_data(iter, &parsed_data)) {
+               SUPPLICANT_DBG("failed to parse SignalPoll result");
+               result = -EINVAL;
+       } else {
+               SUPPLICANT_DBG("SignalPoll OK");
+               data = &parsed_data;
+               result = 0;
+       }
+
+       call->callback(result, data, call->user_data);
+       g_free(call);
+}
+
+int g_supplicant_interface_signal_poll(GSupplicantInterface *interface,
+                                       GSupplicantSignalPollCallback callback,
+                                                       void *user_data)
+{
+       struct signal_poll_call *call;
+       int ret;
+
+       /* This call makes no sense without the callback */
+       if (!callback)
+               return -EINVAL;
+
+       call = dbus_new0(struct signal_poll_call, 1);
+       if (!call)
+               return -ENOMEM;
+
+       call->callback = callback;
+       call->user_data = user_data;
+       ret = supplicant_dbus_method_call(interface->path,
+                       SUPPLICANT_INTERFACE ".Interface", "SignalPoll", NULL,
+                                       signal_poll_result, call, interface);
+
+       if (ret < 0)
+               dbus_free(call);
+
+       return ret;
+}
+
 bool g_supplicant_interface_has_p2p(GSupplicantInterface *interface)
 {
        if (!interface)
-- 
1.8.3.2

_______________________________________________
connman mailing list
[email protected]
https://lists.connman.net/mailman/listinfo/connman

Reply via email to