Added WPS-PBC support without ssid. 16/81716/1
authorNiraj Kumar Goit <niraj.g@samsung.com>
Fri, 24 Jun 2016 12:40:34 +0000 (18:10 +0530)
committerNiraj Kumar Goit <niraj.g@samsung.com>
Thu, 28 Jul 2016 04:40:39 +0000 (10:10 +0530)
desc: Added support to connect wifi AP using WPS-PBC
without ssid and cancel ongoing WPS provisioning.

Change-Id: If6fd071959734dd1a1e5ad5b38c518d36591d2da
Signed-off-by: Niraj Kumar Goit <niraj.g@samsung.com>
include/wifi-wps.h
interfaces/netconfig-iface-wifi.xml
src/signal-handler.c
src/wifi-wps.c
src/wifi.c

index 7628ea9df3a70d60d3af6796fe31e2ae58b8b4e4..e520220f394994d7962c5f3a6880d99c797e6077 100755 (executable)
@@ -26,13 +26,30 @@ extern "C" {
 
 #include "wifi.h"
 
+/* WPS Errors */
+#define WPS_CFG_NO_ERROR 0
+#define WPS_CFG_MSG_TIMEOUT 16
+#define WPS_EI_NO_ERROR 0
+#define WPS_EI_OPERATION_FAILED 1
+
 gboolean netconfig_wifi_is_wps_enabled(void);
 
 void netconfig_wifi_wps_signal_scandone(void);
 void netconfig_wifi_wps_signal_scanaborted(void);
 
 gboolean handle_request_wps_scan(Wifi *wifi, GDBusMethodInvocation *context);
-gboolean netconfig_iface_wifi_request_wps_cancel(Wifi *wifi, GDBusMethodInvocation **context);
+gboolean handle_request_wps_connect(Tv_profile *tv_profile,
+                               GDBusMethodInvocation *context, gchar *param);
+gboolean handle_request_wps_cancel(Tv_profile *tv_profile,
+                               GDBusMethodInvocation *context);
+void netconfig_wifi_notify_wps_completed(const char *ssid);
+void netconfig_wifi_notify_wps_fail_event(int config_error, int error_indication);
+void netconfig_wifi_notify_wps_credentials(const char *ssid, const char *wps_key);
+gboolean netconfig_get_wps_field();
+
+#if defined TIZEN_TV
+gboolean netconfig_wifi_wps_connect();
+#endif
 
 #ifdef __cplusplus
 }
index e9c6aa6d7bdd60f7b0b45b40317005a13a2147f4..0470fffa7684eab464d3d228da21c994fb4cd520 100755 (executable)
        <interface name="net.netconfig.tv_profile">
                <method name="RequestWpsCancel">
                </method>
+               <method name="RequestWpsConnect">
+                       <arg type="s" name="param" direction="in"/>
+               </method>
        </interface>
 </node>
index 34cb6f42fcce9d7dc7a50ffefb52f4a7b50a7bc5..cf33519e9092016036821e664f0f1be2470bfa77 100755 (executable)
 #define SIGNAL_TDLS_CONNECTED                          "TDLSConnected"
 #define SIGNAL_TDLS_DISCONNECTED                       "TDLSDisconnected"
 #define SIGNAL_TDLS_PEER_FOUND                         "TDLSPeerFound"
+
+#define SIGNAL_WPS_CONNECTED                           "WPSConnected"
+#define SIGNAL_WPS_EVENT                                       "Event"
+#define SIGNAL_WPS_CREDENTIALS                         "Credentials"
+
 #define CONNMAN_SIGNAL_SERVICES_CHANGED                "ServicesChanged"
 #define CONNMAN_SIGNAL_PROPERTY_CHANGED                "PropertyChanged"
 #define CONNMAN_SIGNAL_NAME_CHANGED            "NameOwnerChanged"
 
 #define MAX_SIG_LEN 64
-#define TOTAL_CONN_SIGNALS 4
+#define TOTAL_CONN_SIGNALS 5
 
 typedef enum {
        SIG_INTERFACE_REMOVED = 0,
@@ -565,6 +570,199 @@ static void _supplicant_tdls_peer_found(GDBusConnection *conn,
        return;
 }
 
+static void _supplicant_wifi_wps_connected(GVariant *param)
+{
+       gchar *key;
+       char ssid[32] = {0, };
+       gchar *name;
+       GVariantIter *iter;
+       GVariant *variant;
+       int config_error = 0;
+       int error_indication = 0;
+       gsize ssid_len;
+
+       if (param == NULL) {
+               ERR("Param is NULL");
+               return;
+       }
+
+       g_variant_get(param, "(sa{sv})", &name, &iter);
+       ERR("wps Result: %s", name);
+       while (g_variant_iter_loop(iter, "{sv}", &key, &variant)) {
+               INFO("wps Key is %s",key);
+               if (g_strcmp0(key, "SSID") == 0) {
+                       const char *t_key = NULL;
+                       ssid_len = g_variant_get_size(variant);
+                       INFO("wps ssid_len is %d ", ssid_len);
+                       t_key = g_variant_get_fixed_array(variant, &ssid_len,
+                                                         sizeof(guchar));
+                       if (t_key == NULL) {
+                               g_free(key);
+                               g_variant_unref(variant);
+                               ERR("WPS PBC Connection Failed");
+                               goto error;
+                       } else {
+                               strncpy(ssid, t_key, ssid_len);
+                               ssid[ssid_len] = '\0';
+                               ERR("WPS PBC Connection completed with AP %s",
+                                       ssid);
+                               netconfig_wifi_notify_wps_completed(ssid);
+                       }
+               }
+       }
+
+       g_variant_iter_free(iter);
+       g_free(name);
+       return;
+
+error:
+       g_variant_iter_free(iter);
+       g_free(name);
+       error_indication = WPS_EI_OPERATION_FAILED;
+       config_error = WPS_CFG_NO_ERROR;
+       ERR("Error Occured! Notifying Fail Event");
+       netconfig_wifi_notify_wps_fail_event(config_error, error_indication);
+
+}
+
+static void _supplicant_wifi_wps_event(GVariant *param)
+{
+       gchar *key;
+       gchar *name;
+       GVariantIter *iter;
+       GVariant *variant;
+       gint32 config_error = 0;
+       gint32 error_indication = 0;
+
+       if (param == NULL) {
+               ERR("Param is NULL");
+               return;
+       }
+
+       g_variant_get(param, "(sa{sv})", &name, &iter);
+       ERR("Event Result: %s", name);
+       if (g_strcmp0(name, "failed") == 0) {
+               while (g_variant_iter_loop(iter, "{sv}", &key, &variant)) {
+                       if (key == NULL)
+                               goto error;
+                       ERR("Key is %s",key);
+                       if (g_strcmp0(key, "config_error") == 0) {
+                               config_error = g_variant_get_int32(variant);
+                               ERR("Config Error %d", config_error);
+                       } else if (g_strcmp0(key, "error_indication") == 0) {
+                               error_indication = g_variant_get_int32(variant);
+                               ERR("Error Indication %d", error_indication);
+                       }
+               }
+               netconfig_wifi_notify_wps_fail_event(config_error,
+                                                       error_indication);
+       }
+
+       g_variant_iter_free(iter);
+       g_free(name);
+       return;
+
+error:
+       g_variant_iter_free(iter);
+       g_free(name);
+       error_indication = WPS_EI_OPERATION_FAILED;
+       config_error = WPS_CFG_NO_ERROR;
+       ERR("Error Occured! Notifying Fail Event");
+       netconfig_wifi_notify_wps_fail_event(config_error, error_indication);
+}
+
+static void _supplicant_wifi_wps_credentials(GVariant *param)
+{
+       gchar *key;
+       char ssid[32];
+       char wps_key[100];
+       GVariantIter *iter;
+       GVariant *variant;
+       int config_error = 0;
+       int error_indication = 0;
+
+       if (param == NULL) {
+               ERR("Param is NULL");
+               return;
+       }
+
+       g_variant_get(param, "(a{sv})", &iter);
+       while (g_variant_iter_loop(iter, "{sv}", &key, &variant)) {
+               if (key == NULL)
+                       goto error;
+               ERR("wps Key is %s",key);
+               if (g_strcmp0(key, "Key") == 0) {
+                       gsize key_len =0;
+                       const char *t_key = NULL;
+                       key_len = g_variant_get_size(variant);
+
+                       ERR("wps password len %d ", key_len);
+                       if (key_len > 0){
+                               t_key = g_variant_get_fixed_array(variant,
+                                               &key_len, sizeof(guchar));
+                               if (!t_key) {
+                                       g_free(key);
+                                       g_variant_unref(variant);
+                                       goto error;
+                               }
+                               strncpy(wps_key, t_key, key_len);
+                               wps_key[key_len] = '\0';
+                               ERR("WPS Key in process credentials %s",
+                                       wps_key);
+                       } else
+                               SLOGI("WPS AP Security ->Open");
+               } else if (g_strcmp0(key, "SSID") == 0) {
+                       const char *t_key = NULL;
+                       gsize ssid_len = g_variant_get_size(variant);
+                       ERR("wps ssid_len is %d ", ssid_len);
+                       t_key = g_variant_get_fixed_array(variant, &ssid_len,
+                                                       sizeof(guchar));
+                       if (!t_key) {
+                               g_free(key);
+                               g_variant_unref(variant);
+                               goto error;
+                       }
+                       strncpy(ssid, t_key, ssid_len);
+                       ssid[ssid_len] = '\0';
+                       ERR("SSID in process credentials %s", ssid);
+               }
+       }
+
+       g_variant_iter_free(iter);
+       /*
+        * Notify WPS Credentials only when requested through WPS PBC
+        * In case of WPS PIN connman will take care of notification
+        */
+       if (netconfig_get_wps_field() == TRUE)
+               netconfig_wifi_notify_wps_credentials(ssid, wps_key);
+       return;
+
+error:
+       g_variant_iter_free(iter);
+       error_indication = WPS_EI_OPERATION_FAILED;
+       config_error = WPS_CFG_NO_ERROR;
+       ERR("Error Occured! Notifying Fail Event");
+       netconfig_wifi_notify_wps_fail_event(config_error, error_indication);
+}
+
+static void __netconfig_wps_signal_filter_handler(GDBusConnection *conn,
+               const gchar *name, const gchar *path, const gchar *interface,
+               const gchar *sig, GVariant *param, gpointer user_data)
+{
+       if (g_strcmp0(sig, SIGNAL_WPS_CREDENTIALS) == 0) {
+               ERR("Received wps CREDENTIALS Signal from Supplicant");
+               _supplicant_wifi_wps_credentials(param);
+       } else if (g_strcmp0(sig, SIGNAL_WPS_EVENT) == 0) {
+               ERR("Received wps EVENT Signal from Supplicant");
+               _supplicant_wifi_wps_event(param);
+       } else if (g_strcmp0(sig, SIGNAL_WPS_CONNECTED) == 0) {
+               ERR("Received WPSConnected Signal from Supplicant");
+               _supplicant_wifi_wps_connected(param);
+       }
+
+       return;
+}
+
 static supplicant_signal_cb supplicant_cbs[SIG_MAX] = {
                _supplicant_interface_removed,
                _supplicant_properties_changed,
@@ -662,6 +860,20 @@ void register_gdbus_signal(void)
 
        INFO("Successfully register connman DBus signal filters");
 
+       conn_subscription_ids[4] = g_dbus_connection_signal_subscribe(
+                       connection,
+                       SUPPLICANT_SERVICE,
+                       SUPPLICANT_INTERFACE ".Interface.WPS",
+                       NULL,
+                       NULL,
+                       NULL,
+                       G_DBUS_SIGNAL_FLAGS_NONE,
+                       __netconfig_wps_signal_filter_handler,
+                       NULL,
+                       NULL);
+
+       INFO("Successfully register Supplicant WPS DBus signal filters");
+
        for (sig = SIG_INTERFACE_REMOVED; sig < SIG_MAX; sig++) {
                /*
                 * For SIG_INTERFACE_REMOVED INTERFACE_ADDED
index 618a2c6ce4d5ffe5f186e7bfab19e4f88dda081c..500d1f052c39d237b5e7973421460d7899687a86 100755 (executable)
@@ -51,6 +51,15 @@ struct wps_bss_info_t {
        int mode;
 };
 
+#if defined TIZEN_TV
+struct netconfig_wifi_wps {
+       char *pin;
+       gboolean pbc;
+};
+
+static struct netconfig_wifi_wps wifi_wps;
+#endif
+
 static GSList *wps_bss_info_list = NULL;
 
 static void __netconfig_wps_set_mode(gboolean enable)
@@ -66,6 +75,82 @@ gboolean netconfig_wifi_is_wps_enabled(void)
        return netconfig_is_wps_enabled;
 }
 
+
+void netconfig_wifi_notify_wps_credentials(const char *ssid, const char *wps_key)
+{
+       GVariantBuilder *builder;
+       GVariant *params;
+       const char *sig_name = "WpsCredentials";
+       const char *prop_ssid = "ssid";
+       const char *prop_key = "key";
+
+       builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+       g_variant_builder_add(builder, "{sv}", prop_ssid, g_variant_new_string(ssid));
+       g_variant_builder_add(builder, "{sv}", prop_key, g_variant_new_string(wps_key));
+
+       params = g_variant_new("(@a{sv})", g_variant_builder_end(builder));
+       g_variant_builder_unref(builder);
+
+       netconfig_dbus_emit_signal(NULL,
+                               NETCONFIG_WIFI_PATH,
+                               NETCONFIG_WIFI_INTERFACE,
+                               sig_name,
+                               params);
+
+       INFO("Sent signal (%s)", sig_name);
+       return;
+}
+
+void netconfig_wifi_notify_wps_completed(const char *ssid)
+{
+       GVariantBuilder *builder;
+       GVariant *params;
+       const char *sig_name = "WpsCompleted";
+       const char *prop_ssid = "ssid";
+
+       builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+       g_variant_builder_add(builder, "{sv}", prop_ssid, g_variant_new_string(ssid));
+
+       params = g_variant_new("(@a{sv})", g_variant_builder_end(builder));
+       g_variant_builder_unref(builder);
+
+       netconfig_dbus_emit_signal(NULL,
+                               NETCONFIG_WIFI_PATH,
+                               NETCONFIG_WIFI_INTERFACE,
+                               sig_name,
+                               params);
+
+       INFO("Sent signal (%s)", sig_name);
+       return;
+}
+
+void netconfig_wifi_notify_wps_fail_event(int config_error, int error_indication)
+{
+       GVariantBuilder *builder;
+       GVariant *params;
+       const char *sig_name = "WpsFailEvent";
+       const char *prop_config_error = "config_error";
+       const char *prop_error_indication = "error_indication";
+
+       builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+       g_variant_builder_add(builder, "{sv}", prop_config_error,
+                               g_variant_new_int32(config_error));
+       g_variant_builder_add(builder, "{sv}", prop_error_indication,
+                               g_variant_new_int32(error_indication));
+
+       params = g_variant_new("(@a{sv})", g_variant_builder_end(builder));
+       g_variant_builder_unref(builder);
+
+       netconfig_dbus_emit_signal(NULL,
+                               NETCONFIG_WIFI_PATH,
+                               NETCONFIG_WIFI_INTERFACE,
+                               sig_name,
+                               params);
+
+       INFO("Sent signal (%s)", sig_name);
+       return;
+}
+
 static void __netconfig_wifi_wps_notify_scan_done(void)
 {
        GVariantBuilder *builder = NULL;
@@ -540,6 +625,126 @@ gboolean handle_request_wps_scan(Wifi *wifi, GDBusMethodInvocation *context)
 }
 
 #if defined TIZEN_TV
+
+static void interface_wps_start_result(GObject *source_object,
+                       GAsyncResult *res, gpointer user_data)
+{
+       GVariant *reply;
+       GDBusConnection *conn = NULL;
+       GError *error = NULL;
+
+       conn = G_DBUS_CONNECTION (source_object);
+       reply = g_dbus_connection_call_finish(conn, res, &error);
+
+       if (reply == NULL) {
+               if (error != NULL) {
+                       ERR("Fail to request status [%d: %s]",
+                                       error->code, error->message);
+                       g_error_free(error);
+               } else
+                       ERR("Fail to request status");
+       } else
+               DBG("Successfully M/W--->WPAS: Interface.WPS.Start Method");
+
+       g_variant_unref(reply);
+       netconfig_gdbus_pending_call_unref();
+}
+
+static void __netconfig_wifi_invoke_wps_connect(GObject *source_object,
+                       GAsyncResult *res, gpointer user_data)
+{
+       GVariant *message = NULL;
+       GVariantBuilder *builder = NULL;
+       const char *role = "enrollee", *type, *key;
+       const char *if_path = NULL;
+       gboolean reply = FALSE;
+
+       if (if_path == NULL)
+               if_path = netconfig_wifi_get_supplicant_interface();
+
+       if (if_path == NULL) {
+               DBG("Fail to get wpa_supplicant DBus path");
+               return;
+       }
+
+       builder = g_variant_builder_new(G_VARIANT_TYPE ("a{sv}"));
+
+       key = "Role";
+       g_variant_builder_add(builder, "{sv}", key, g_variant_new_string(role));
+
+       key = "Type";
+       if (wifi_wps.pbc == TRUE)
+               type = "pbc";
+       else
+               type = "pin";
+       g_variant_builder_add(builder, "{sv}", key, g_variant_new_string(type));
+
+       if (wifi_wps.pin != NULL) {
+               key="Pin";
+               g_variant_builder_add(builder, "{sv}", key,
+                                       g_variant_new_string(wifi_wps.pin));
+       }
+       message = g_variant_new("(@a{sv})", g_variant_builder_end(builder));
+       g_variant_builder_unref(builder);
+
+       DBG("[net-config]: TizenMW-->WPAS: .Interface.WPS.Start");
+        reply = netconfig_supplicant_invoke_dbus_method_nonblock(
+                       SUPPLICANT_SERVICE,
+                        if_path,
+                       SUPPLICANT_IFACE_WPS,
+                       "Start",
+                        message,
+                       (GAsyncReadyCallback) interface_wps_start_result);
+
+       if (reply != TRUE)
+               ERR("Fail to Scan");
+
+       return;
+}
+
+static gboolean __netconfig_wifi_invoke_wps_process_credentials(
+                                                       const char *object_path)
+{
+       gboolean reply = FALSE;
+       GVariant *params = NULL;
+       const char *interface = SUPPLICANT_IFACE_WPS;
+       const char *key = "ProcessCredentials";
+       gboolean credentials = TRUE;
+       GVariant *var = NULL;
+
+        var = g_variant_new_boolean(credentials);
+       params = g_variant_new("(ssv)", interface, key, var);
+
+       ERR("[net-config]: TizenMW-->WPAS: .Set");
+       reply = netconfig_invoke_dbus_method_nonblock(SUPPLICANT_SERVICE,
+                       object_path, DBUS_INTERFACE_PROPERTIES,
+                       "Set", params, __netconfig_wifi_invoke_wps_connect);
+
+       if (reply != TRUE)
+               ERR("M/W--->WPAS: Interface.WPS.Set Method Failed");
+
+       return reply;
+}
+
+gboolean netconfig_wifi_wps_connect()
+{
+       const char *if_path = NULL;
+
+       if_path = netconfig_wifi_get_supplicant_interface();
+       if (if_path == NULL) {
+               DBG("Fail to get wpa_supplicant DBus path");
+                return FALSE;
+       }
+
+       if (__netconfig_wifi_invoke_wps_process_credentials(if_path) == TRUE) {
+               ERR("Wi-Fi WPS Connect started");
+
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
 static void __interface_wps_cancel_result(GObject *source_object,
                        GAsyncResult *res, gpointer user_data)
 {
@@ -547,7 +752,7 @@ static void __interface_wps_cancel_result(GObject *source_object,
        GDBusConnection *conn = NULL;
        GError *error = NULL;
 
-       conn = G_DBUS_CONNECTION(source_object);
+       conn = G_DBUS_CONNECTION (source_object);
        reply = g_dbus_connection_call_finish(conn, res, &error);
 
        if (reply == NULL) {
@@ -588,16 +793,59 @@ static gboolean __netconfig_wifi_invoke_wps_cancel()
 
        return reply;
 }
+
+gboolean netconfig_get_wps_field()
+{
+       return wifi_wps.pbc;
+}
 #endif
 
-gboolean netconfig_iface_wifi_request_wps_cancel(Wifi *wifi, GDBusMethodInvocation **context)
+gboolean handle_request_wps_cancel(Tv_profile *tv_profile,
+                                  GDBusMethodInvocation *context)
 {
 #if defined TIZEN_TV
-       DBG("Received WPS PBC Cancel Request");
-       g_return_val_if_fail(wifi != NULL, FALSE);
-       return __netconfig_wifi_invoke_wps_cancel();
+       ERR("Received WPS PBC Cancel Request");
+       g_return_val_if_fail(tv_profile != NULL, FALSE);
+       __netconfig_wifi_invoke_wps_cancel();
+
+       tv_profile_complete_request_wps_connect(tv_profile, context);
+       return TRUE;
 #else
        /*Not supported for mobile and Wearable profile*/
+       tv_profile_complete_request_wps_connect(tv_profile, context);
+       return FALSE;
+#endif
+}
+
+gboolean handle_request_wps_connect(Tv_profile *tv_profile,
+                                   GDBusMethodInvocation *context,
+                                       gchar *param)
+{
+#if defined TIZEN_TV
+
+       ERR("Received WPS PBC/PIN Connection Request");
+
+       g_return_val_if_fail(tv_profile != NULL, FALSE);
+
+       /* Checking the value of pin if param have a string "PBC"
+        * in that scenario PBC will trigger otherwise PIN Connection */
+
+       if (g_strcmp0(param, "PBC") == 0){
+               wifi_wps.pbc = TRUE;
+               wifi_wps.pin = NULL;
+       } else {
+               wifi_wps.pin = g_strdup(param);
+               wifi_wps.pbc = FALSE;
+       }
+
+       netconfig_wifi_wps_connect();
+
+       tv_profile_complete_request_wps_connect(tv_profile, context);
+       return TRUE;
+#else
+       /*Tizen Mobile & Wearable Profile does not support
+               this feature*/
+       tv_profile_complete_request_wps_connect(tv_profile, context);
        return FALSE;
 #endif
 }
index bf1f8363c711562965e73b2c13f238a1bc08259e..0cdfd2aaf54da8faa0551833b1169b62555890fb 100755 (executable)
@@ -48,6 +48,7 @@ static int is_wifi_firmware_downloaded = FALSE;
 static Wifi *wifi_object = NULL;
 static NetConnmanAgent *connman_agent_object = NULL;
 static WifiFirmware *wififirmware_object = NULL;
+static Tv_profile *tv_profile_object = NULL;
 
 Wifi *get_wifi_object(void){
        return wifi_object;
@@ -128,6 +129,7 @@ void wifi_object_create_and_init(void)
        GDBusInterfaceSkeleton *interface_wifi = NULL;
        GDBusInterfaceSkeleton *interface_connman_agent = NULL;
        GDBusInterfaceSkeleton *interface_wifi_firmware = NULL;
+       GDBusInterfaceSkeleton *interface_tv_profile = NULL;
        GDBusConnection *connection = NULL;
        GDBusObjectManagerServer *server = netdbus_get_wifi_manager();
        if (server == NULL)
@@ -262,6 +264,20 @@ void wifi_object_create_and_init(void)
                ERR("Export WIFI_PATH for firmware failed");
        }
 
+       /* Interface netconfig.tv_profile */
+       tv_profile_object = tv_profile_skeleton_new();
+       interface_tv_profile = G_DBUS_INTERFACE_SKELETON(tv_profile_object);
+
+       /* WPS Connect */
+       g_signal_connect(tv_profile_object, "handle-request-wps-connect",
+                       G_CALLBACK(handle_request_wps_connect), NULL);
+       g_signal_connect(tv_profile_object, "handle-request-wps-cancel",
+                       G_CALLBACK(handle_request_wps_cancel), NULL);
+
+       if (!g_dbus_interface_skeleton_export(interface_tv_profile, connection,
+                       NETCONFIG_WIFI_PATH, NULL))
+               ERR("Export WIFI_PATH for tv_profile failed");
+
        _set_wifi_mac_address();
 
        wifi_power_initialize();