diff options
author | Tasuku Suzuki <tasuku.suzuki@qt.io> | 2016-12-14 18:10:54 +0900 |
---|---|---|
committer | Tasuku Suzuki <tasuku.suzuki@qt.io> | 2016-12-14 23:23:02 +0900 |
commit | f67d4105a572345d1fed1231e06b99bd9411d040 (patch) | |
tree | 134fef0892a481d9cbbd7633feb40ae5b2439650 |
merge the Settings in CES2017 and bindings from ALPS
Change-Id: I00a7a6c5dae1cd579f91d543b0f5fba4616a633b
Signed-off-by: Tasuku Suzuki <tasuku.suzuki@qt.io>
-rw-r--r-- | agent.c | 262 | ||||
-rw-r--r-- | binding-wifi.pro | 11 | ||||
-rw-r--r-- | binding.pri | 6 | ||||
-rw-r--r-- | export.map | 1 | ||||
-rw-r--r-- | wifi-api.c | 489 | ||||
-rw-r--r-- | wifi-api.h | 38 | ||||
-rw-r--r-- | wifi-connman.c | 354 | ||||
-rw-r--r-- | wifi-connman.h | 126 |
8 files changed, 1287 insertions, 0 deletions
@@ -0,0 +1,262 @@ +/* Copyright 2016 ALPS ELECTRIC CO., LTD. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <stdio.h> +#include <errno.h> + +#include <gio/gio.h> +#include "wifi-connman.h" + +static GMainLoop *loop = NULL; + +static GDBusNodeInfo *introspection_data = NULL; + +GDBusMethodInvocation *invocation_passkey = NULL; + +/* Introspection data for the agent service */ +static const gchar introspection_xml[] = "<node>" + " <interface name='net.connman.Agent'>" + " <method name='RequestInput'>" + " <arg type='o' name='service' direction='in'/>" + " <arg type='a{sv}' name='fields' direction='in'/>" + " <arg type='a{sv}' name='fields' direction='out'/>" + " </method>" + " <method name='ReportError'>" + " <arg type='o' name='service' direction='in'/>" + " <arg type='s' name='error' direction='in'/>" + " </method>" + " </interface>" + "</node>"; + +callback password_callback; + +static void handle_method_call(GDBusConnection *connection, const gchar *sender, + const gchar *object_path, const gchar *interface_name, + const gchar *method_name, GVariant *parameters, + GDBusMethodInvocation *invocation, gpointer user_data) { + //MyObject *myobj = user_data; + + if (g_strcmp0(method_name, "RequestInput") == 0) { + printf("Input requested\n"); + + invocation_passkey = invocation; + + //TODO: send the name of the network to callback + + (*password_callback)(0); + + GVariantIter *array; + gchar * object_path; + g_variant_get(parameters, "(oa{sv})", &object_path, &array); + //TODO: get only object path for now, complete parameters are + + /* + object path "/net/connman/service/wifi_d85d4c880b1a_4c656e6f766f204b3520506c7573_managed_psk" + array [ + dict entry( + string "Passphrase" + variant array [ + dict entry( + string "Type" + variant string "psk" + ) + dict entry( + string "Requirement" + variant string "mandatory" + ) + ] + ) + ] + */ + printf("Passphrase requested for network : %s\n", object_path); + + } + + if (g_strcmp0(method_name, "ReportError") == 0) { + printf("Error reported\n"); + + gchar *error_string; // = NULL; + + gchar * object_path; + g_variant_get(parameters, "(os)", &object_path, &error_string); + + printf("Error %s for %s\n", error_string, object_path); + + if (g_strcmp0(error_string, "invalid-key") == 0) { + + printf("Passkey is not correct.\n"); + (*password_callback)(1); + + } + + } +} + +GError* sendPasskey(gchar *passkey) { + + GVariantBuilder *builder; + GVariant *value = NULL; + + printf("Passkey to send: %s\n", passkey); + + builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}")); + + g_variant_builder_add(builder, "{sv}", "Passphrase", + g_variant_new_string(passkey)); + + value = g_variant_new("(a{sv})", builder); + + g_dbus_method_invocation_return_value(invocation_passkey, value); + + return NULL; + +} + +static const GDBusInterfaceVTable interface_vtable = { handle_method_call, NULL, + NULL }; + +static void on_bus_acquired(GDBusConnection *connection, const gchar *name, + gpointer user_data) { + //MyObject *myobj = user_data; + guint registration_id; + + registration_id = g_dbus_connection_register_object(connection, + "/net/connman/Agent", introspection_data->interfaces[0], + &interface_vtable, NULL, NULL, /* user_data_free_func */ + NULL); /* GError** */ + //TODO: make some proper error message rather than exiting + //g_assert(registration_id > 0); + + return NULL; +} + +void* register_agent(void *data) { + + //printf("Loop start\n"); + + guint owner_id; + //MyObject *myobj; + + introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, NULL); + g_assert(introspection_data != NULL); + + //myobj = g_object_new(my_object_get_type(), NULL); + +// owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM, "org.agent", +// G_BUS_NAME_OWNER_FLAGS_NONE, on_bus_acquired, on_name_acquired, +// on_name_lost, myobj, +// NULL); + +//FIXME: ALLOW_REPLACEMENT for now, make proper deinitialization + owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM, AGENT_SERVICE, + G_BUS_NAME_OWNER_FLAGS_REPLACE, on_bus_acquired, NULL, NULL, NULL, + NULL); + //G_BUS_NAME_OWNER_FLAGS_NONE G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT + + loop = g_main_loop_new(NULL, FALSE); + + //sleep(10); + g_main_loop_run(loop); + + printf("Loop running\n"); + + g_bus_unown_name(owner_id); + + g_dbus_node_info_unref(introspection_data); + + //g_object_unref(myobj); + + //printf("Loop end\n"); + + return NULL; + +} + +GError* create_agent(GDBusConnection *connection) { + + int err = -1; + pthread_t tid[1]; + + //struct callbackData *threadData; + + err = pthread_create((&tid[0]), NULL, register_agent, NULL); + + if (err != 0) { + printf("\ncan't create thread :[%d]", err); + printf("Fatal error!\n\n"); + return NULL; + } + + GVariant *message = NULL; + GError *error = NULL; + + GVariant *params = NULL; + + char *agent_path = AGENT_PATH; + + params = g_variant_new("(o)", agent_path); + + message = g_dbus_connection_call_sync(connection, CONNMAN_SERVICE, + CONNMAN_MANAGER_PATH, CONNMAN_MANAGER_INTERFACE, "RegisterAgent", params, + NULL, G_DBUS_CALL_FLAGS_NONE, + DBUS_REPLY_TIMEOUT, NULL, &error); + + if (error) { + printf("error: %d:%s\n", error->code, error->message); + + return error; + + } else { + printf("Agent registered\n"); + return NULL; + } + +} + +GError* stop_agent(GDBusConnection *connection) { + + GVariant *message = NULL; + GError *error = NULL; + + + GVariant *params = NULL; + + char *agent_path = AGENT_PATH; + + + params = g_variant_new("(o)", agent_path); + + message = g_dbus_connection_call_sync(connection, CONNMAN_SERVICE, + CONNMAN_MANAGER_PATH, CONNMAN_MANAGER_INTERFACE, "UnregisterAgent", params, + NULL, G_DBUS_CALL_FLAGS_NONE, + DBUS_REPLY_TIMEOUT, NULL, &error); + + if (error) { + printf("error: %d:%s\n", error->code, error->message); + return error; + + } else { + printf("Agent unregistered\n"); + return NULL; + } + +} + +void register_callback(callback callback_function) { + + password_callback = callback_function; + +} + diff --git a/binding-wifi.pro b/binding-wifi.pro new file mode 100644 index 0000000..09c54b4 --- /dev/null +++ b/binding-wifi.pro @@ -0,0 +1,11 @@ +TARGET = serttings-wifi-binding + +HEADERS = wifi-api.h wifi-connman.h +SOURCES = agent.c wifi-api.c wifi-connman.c + +LIBS += -Wl,--version-script=$$PWD/export.map + +CONFIG += link_pkgconfig +PKGCONFIG += json-c afb-daemon glib-2.0 gio-2.0 gobject-2.0 zlib + +include(binding.pri) diff --git a/binding.pri b/binding.pri new file mode 100644 index 0000000..3448a56 --- /dev/null +++ b/binding.pri @@ -0,0 +1,6 @@ +TEMPLATE = lib +CONFIG += plugin use_c_linker +CONFIG -= qt +QMAKE_CFLAGS += -Wextra -Wconversion -Wno-unused-parameter -Werror=maybe-uninitialized -Werror=implicit-function-declaration -ffunction-sections -fdata-sections -Wl,--as-needed -Wl,--gc-sections + +DESTDIR = $${OUT_PWD}/../package/root/lib diff --git a/export.map b/export.map new file mode 100644 index 0000000..0ef1ac7 --- /dev/null +++ b/export.map @@ -0,0 +1 @@ +{ global: afbBindingV1Register; local: *; }; diff --git a/wifi-api.c b/wifi-api.c new file mode 100644 index 0000000..2d9748f --- /dev/null +++ b/wifi-api.c @@ -0,0 +1,489 @@ +/* Copyright 2016 ALPS ELECTRIC CO., LTD. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +/** + * file + * + * \brief Implementation of WiFi Binder for AGL's App Framework + * + * \author ALPS Electric + */ + +#define _GNU_SOURCE +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <json-c/json.h> +#include <afb/afb-binding.h> + +#include "wifi-api.h" +#include "wifi-connman.h" + +/* + * the interface to afb-daemon + */ +const struct afb_binding_interface *afbitf; + +static int need_password_flag = 0; +static int password_not_correct_flag = 0; + +char *passkey; +callback ptr_my_callback; + +GSList *wifi_list = NULL; + +/** + * \brief Read out the passkey from the use and pass it to Agent + * + * \todo Since I do not know how to subscribe for the events from framework, + * it is necessary first to register the password http://IP_ADDRESS:PORT/api/wifi-manager/security?passkey=mypassword. + * Then this function is called automatically. + * + * + * */ +void passkey_inserted(void) { + + printf("Passkey inserted: %s\n", passkey); + + if (passkey != NULL) { + + registerPasskey(passkey); + } else { + printf("Please enter the password first\n"); + + } +} + +/** + * \brief Notify user that password is necessary + * + * This function is called from the registered agent on RequestInput() call. + * \todo Subscribe for this event from GUI. + * + * */ +void ask_for_passkey(int password_rejected_flag) { + //TODO: show network we are asking password for + printf("Insert passkey.\n"); + + if (!password_rejected_flag) { + need_password_flag = 1; + password_not_correct_flag = 0; + //sleep(1); + passkey_inserted(); + + } + + else if (password_rejected_flag) { + need_password_flag = 1; + printf("Password not correct!\n"); + + } + +} + +/** + * \brief Insert passkey that will be used for connections to secured AP. + * + * \TODO Only temporary, user should enter the password on ask_for_passkey() callback + * + * */ +void wifi_insertpasskey(struct afb_req request) { + + const char *passkey_from_user; + + /* retrieves the argument, expects password string */ + passkey_from_user = afb_req_value(request, "passkey"); + + if (passkey_from_user == NULL) { + //TODO:better error message + afb_req_fail(request, "failed", "specify a security key"); + + } else { + + passkey = g_try_malloc0(256); + strcpy(passkey, passkey_from_user); + printf("Passkey is %s\n", passkey); + + } + + afb_req_success(request, NULL, NULL); +} + +/** + * \brief initialize the binder and activates the WiFi HW, should be called first + * + * This will fail if + * - agent for handling password requests cannot be registered + * - some error is returned from connman + * + * + * \return result of the request, either "success" or "failed" with description + */ +static void wifi_activate(struct afb_req request) /*AFB_SESSION_CHECK*/ +{ + json_object *jresp; + GError *error = NULL; + + if (ptr_my_callback == NULL) { + + printf("Registering callback\n"); + + ptr_my_callback = ask_for_passkey; + register_callback(ptr_my_callback); + + } + + jresp = json_object_new_object(); + json_object_object_add(jresp, "activation", json_object_new_string("on")); + + error = do_wifiActivate(); + + if (error == NULL) { + + afb_req_success(request, jresp, "Wi-Fi - Activated"); + + } else + + afb_req_fail(request, "failed", error->message); + +} + +/** + * \brief deinitialize the binder and activates the WiFi HW + * + * This will fail if + * - agent for handling password requests cannot be unregistered + * - some error is returned from connman + * + * + * \return result of the request, either "success" or "failed" with description + */ +static void wifi_deactivate(struct afb_req request) /*AFB_SESSION_CHECK*/ +{ + + json_object *jresp; + GError *error = NULL; + + ptr_my_callback = NULL; + + jresp = json_object_new_object(); + json_object_object_add(jresp, "deactivation", json_object_new_string("on")); + + error = do_wifiDeactivate(); + + if (error == NULL) { + + afb_req_success(request, jresp, "Wi-Fi - Activated"); + + } else + + afb_req_fail(request, "failed", error->message); +} + +/** + * \brief starts scan + * + * \return result of the request, either "success" or "failed" with description + */ +void wifi_scan(struct afb_req request) /*AFB_SESSION_NONE*/ +{ + GError *error = NULL; + + error = do_wifiScan(); + + if (error == NULL) { + + afb_req_success(request, NULL, "Wi-Fi - Scan success"); + + } else + + afb_req_fail(request, "failed", error->message); + +} + +/** + * \brief return network list + * + * + * \return result of the request, either "success" or "failed" with description + */ +void wifi_scanResult(struct afb_req request) /*AFB_SESSION_CHECK*/ +{ + struct wifi_profile_info *wifiProfile = NULL; + GSList *list = NULL; + GSList *holdMe = NULL; + wifi_list = NULL; + char *essid = NULL; + char *address = NULL; + char *security = NULL; + char *state = NULL; + int strength = 0; + int number = 0; + GError *error = NULL; + + error = do_displayScan(&wifi_list); /*Get wifi scan list*/ + if (error == NULL) { + json_object *my_array = json_object_new_array(); + + for (list = wifi_list; list; list = list->next) { /*extract wifi scan result*/ + wifiProfile = (struct wifi_profile_info *) list->data; + security = wifiProfile->Security.sec_type; + strength = wifiProfile->Strength; + //if (essid == NULL || security == NULL) + // continue; + + essid = wifiProfile->ESSID == NULL ? + "HiddenSSID" : wifiProfile->ESSID; + address = + wifiProfile->wifiNetwork.IPaddress == NULL ? + "unsigned" : wifiProfile->wifiNetwork.IPaddress; + state = wifiProfile->state; + //TODO: is there a case when security is NULL? + + json_object *int1 = json_object_new_int(number); + json_object *int2 = json_object_new_int(strength); + json_object *jstring1 = json_object_new_string(essid); + json_object *jstring2 = json_object_new_string(security); + json_object *jstring3 = json_object_new_string(address); + json_object *jstring4 = json_object_new_string(state); + + json_object *jresp = json_object_new_object(); + json_object_object_add(jresp, "Number", int1); + json_object_object_add(jresp, "Strength", int2); + json_object_object_add(jresp, "ESSID", jstring1); + json_object_object_add(jresp, "Security", jstring2); + json_object_object_add(jresp, "IPAddress", jstring3); + json_object_object_add(jresp, "State", jstring4); + + printf("The object json: %s\n", json_object_to_json_string(jresp)); + /*input each scan result into my_array*/ + json_object_array_add(my_array, jresp); + number += 1; + } + while (list != NULL) { + printf("Should be freed"); + holdMe = list->next; + g_free(list); + list = holdMe; + } + afb_req_success(request, my_array, "Wi-Fi - Scan Result is Displayed"); + } else + afb_req_fail(request, "failed", error->message); +} + +/** + * \brief connects to network + * + * \param[in] request number of network to connect to + * + * specify number of network to connect to obtained by scan_result() like this, + * http://IP_ADDRESS:PORT/api/wifi-manager/connect?network=1 + */ +void wifi_connect(struct afb_req request) { + + struct wifi_profile_info *wifiProfileToConnect = NULL; + + const char *network; + int network_index = 0; + GError *error = NULL; + GSList *item = NULL; + + /* retrieves the argument, expects the network number */ + network = afb_req_value(request, "network"); + + if (network == NULL) + //TODO:better error message + afb_req_fail(request, "failed", + "specify a network number to connect to"); + + else { + network_index = atoi(network); + printf("Joining network number %d\n", network_index); + + } + + //get information about desired network + item = g_slist_nth_data(wifi_list, network_index); + + if (item == NULL) { + //Index starts from 1 + printf("Network with number %d not found.\n", network_index + 1); + //TODO:better error message + afb_req_fail(request, "failed", "bad arguments"); + } + + else { + wifiProfileToConnect = (struct wifi_profile_info *) item; + printf("Name: %s, strength: %d, %s\n", wifiProfileToConnect->ESSID, + wifiProfileToConnect->Strength, + wifiProfileToConnect->NetworkPath); + //printf ("Connecting to %s\n", wifiProfileToConnect->NetworkPath); + } + error = do_connectNetwork(wifiProfileToConnect->NetworkPath); + + if (error == NULL) + afb_req_success(request, NULL, NULL); + + else if (password_not_correct_flag) { + need_password_flag = 0; + password_not_correct_flag = 0; + afb_req_fail(request, "password-incorrect", NULL); + } else if (need_password_flag) { + need_password_flag = 0; + afb_req_fail(request, "need-password", NULL); + + } else + afb_req_fail(request, "failed", error->message); +} + +/** + * \brief disconnect from network + * + * \param[in] request number of network to disconnect from + * + * specify number of network to disconnect from obtained by scan_result() like this, + * http://IP_ADDRESS:PORT/api/wifi-manager/discnnect?network=1 + */ +void wifi_disconnect(struct afb_req request) { + + struct wifi_profile_info *wifiProfileToConnect = NULL; + + const char *network; + int network_index = 0; + GError *error = NULL; + GSList *item = NULL; + + /* retrieves the argument, expects the network number */ + network = afb_req_value(request, "network"); + + if (network == NULL) + //TODO:better error message + afb_req_fail(request, "failed", + "specify a network number to disconnect from"); + + else { + network_index = atoi(network); + printf("Joining network number %d\n", network_index); + + } + + //get information about desired network + item = g_slist_nth_data(wifi_list, network_index); + + if (item == NULL) { + //Index starts from 1 + printf("Network with number %d not found.\n", network_index + 1); + //TODO:better error message + afb_req_fail(request, "failed", "bad arguments"); + } + + else { + wifiProfileToConnect = (struct wifi_profile_info *) item; + printf("Name: %s, strength: %d, %s\n", wifiProfileToConnect->ESSID, + wifiProfileToConnect->Strength, + wifiProfileToConnect->NetworkPath); + //printf ("Connecting to %s\n", wifiProfileToConnect->NetworkPath); + } + error = do_disconnectNetwork(wifiProfileToConnect->NetworkPath); + + if (error == NULL) + afb_req_success(request, NULL, NULL); + else + afb_req_fail(request, "failed", error->message); +} + +/** + * \brief return current status of connection + * + * \return result of the request, either "success" or "failed" with description + */ +void wifi_status(struct afb_req request) { + int error = 0; + wifi_list = NULL; + struct wifiStatus *status; + json_object *jresp = json_object_new_object(); + + status = g_try_malloc0(sizeof(struct wifiStatus)); + error = wifi_state(status); /*get current status of power and connection*/ + if (!error) { + if (status->state == 0) {/*Wi-Fi is OFF*/ + json_object_object_add(jresp, "Power", + json_object_new_string("OFF")); + //json_object_object_add(jresp, "Connection", json_object_new_string("Disconnected")); + printf("Wi-Fi OFF\n"); + } else {/*Wi-Fi is ON*/ + json_object_object_add(jresp, "Power", + json_object_new_string("ON")); + if (status->connected == 0) {/*disconnected*/ + json_object_object_add(jresp, "Connection", + json_object_new_string("Disconnected")); + printf("Wi-Fi ON - Disconnected \n"); + } else {/*Connected*/ + json_object_object_add(jresp, "Connection", + json_object_new_string("Connected")); + printf("Wi-Fi ON - Connected \n"); + } + } + afb_req_success(request, jresp, "Wi-Fi - Connection Status Checked"); + } else { + afb_req_fail(request, "failed", "Wi-Fi - Connection Status unknown"); + } +} + +void wifi_reconnect() { + /*TBD*/ +} + + + +/* + * array of the verbs exported to afb-daemon + */ +static const struct afb_verb_desc_v1 binding_verbs[] = { +/* VERB'S NAME SESSION MANAGEMENT FUNCTION TO CALL SHORT DESCRIPTION */ +{ .name = "activate", .session = AFB_SESSION_NONE, .callback = wifi_activate, .info = "Activate Wi-Fi" }, +{ .name = "deactivate", .session = AFB_SESSION_NONE, .callback = wifi_deactivate, .info ="Deactivate Wi-Fi" }, +{ .name = "scan", .session = AFB_SESSION_NONE, .callback = wifi_scan, .info = "Scanning Wi-Fi" }, +{ .name = "scan_result",.session = AFB_SESSION_NONE, .callback = wifi_scanResult, .info = "Get scan result Wi-Fi" }, +{ .name = "connect", .session = AFB_SESSION_NONE, .callback = wifi_connect, .info ="Connecting to Access Point" }, +{ .name = "status", .session = AFB_SESSION_NONE, .callback = wifi_status, .info ="Check connection status" }, +{ .name = "disconnect", .session = AFB_SESSION_NONE, .callback = wifi_disconnect, .info ="Disconnecting connection" }, +{ .name = "reconnect", .session = AFB_SESSION_NONE, .callback = wifi_reconnect, .info ="Reconnecting to Access Point" }, +{ .name = "security", .session = AFB_SESSION_NONE, .callback = wifi_insertpasskey, .info ="Insert passkey" }, + +{ .name = NULL } /* marker for end of the array */ +}; + +/* + * description of the binding for afb-daemon + */ +static const struct afb_binding binding_description = { +/* description conforms to VERSION 1 */ +.type = AFB_BINDING_VERSION_1, .v1 = { /* fills the v1 field of the union when AFB_BINDING_VERSION_1 */ +.prefix = "wifi-manager", /* the API name (or binding name or prefix) */ +.info = "wifi API", /* short description of of the binding */ +.verbs = binding_verbs /* the array describing the verbs of the API */ +} }; + +/* + * activation function for registering the binding called by afb-daemon + */ +const struct afb_binding *afbBindingV1Register( + const struct afb_binding_interface *itf) { + afbitf = itf; // records the interface for accessing afb-daemon + return &binding_description; // returns the description of the binding +} + diff --git a/wifi-api.h b/wifi-api.h new file mode 100644 index 0000000..429211b --- /dev/null +++ b/wifi-api.h @@ -0,0 +1,38 @@ +/* Copyright 2016 ALPS ELECTRIC CO., LTD. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef WIFI_API_H +#define WIFI_API_H + +/* global plugin handle, should store everything we may need */ +typedef struct { + int devCount; +} pluginHandleT; + +/* private client context [will be destroyed when client leaves] */ +typedef struct { + unsigned char activate; + unsigned char connected; +} wifiCtxHandleT; + + +struct scan_list_info { + int number; + char *SSID; + char *Security; + int Strength; +}; + +#endif /* AUDIO_API_H */ diff --git a/wifi-connman.c b/wifi-connman.c new file mode 100644 index 0000000..74d2be7 --- /dev/null +++ b/wifi-connman.c @@ -0,0 +1,354 @@ +/* Copyright 2016 ALPS ELECTRIC CO., LTD. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <glib.h> +//#include <dbus/dbus.h> +#include <gio/gio.h> +#include <glib-object.h> + +#include "wifi-api.h" +#include "wifi-connman.h" + +static __thread struct security_profile Security = { NULL, NULL, NULL, NULL, 0, + 0 }; + +int extract_values(GVariantIter *content, struct wifi_profile_info* wifiProfile) { + GVariant *var = NULL; + GVariant *subvar = NULL; + GVariantIter *array; + const gchar *key = NULL; + const gchar *subkey = NULL; + const gchar *value_char = NULL; + GVariantIter *content_sub; + int value_int; + gsize length; + + while (g_variant_iter_loop(content, "{sv}", &key, &var)) { + if (g_strcmp0(key, "Name") == 0) { + value_char = g_variant_get_string(var, &length); + wifiProfile->ESSID = (char *) value_char; + } else if (g_strcmp0(key, "Security") == 0) { + g_variant_get(var, "as", &content_sub); + while (g_variant_iter_loop(content_sub, "s", &value_char)) { + if (g_strcmp0(value_char, "none") == 0) + wifiProfile->Security.sec_type = "Open"; + else if (g_strcmp0(value_char, "wep") == 0) + wifiProfile->Security.sec_type = "WEP"; + else if (g_strcmp0(value_char, "psk") == 0) + wifiProfile->Security.sec_type = "WPA-PSK"; + else if (g_strcmp0(value_char, "ieee8021x") == 0) + wifiProfile->Security.sec_type = "ieee8021x"; + else if (g_strcmp0(value_char, "wpa") == 0) + wifiProfile->Security.sec_type = "WPA-PSK"; + else if (g_strcmp0(value_char, "rsn") == 0) + wifiProfile->Security.sec_type = "WPA2-PSK"; + else if (g_strcmp0(value_char, "wps") == 0) + wifiProfile->Security.wps_support = 1; + else + Security.sec_type = "Open"; + } + } else if (g_strcmp0(key, "Strength") == 0) { + value_int = (unsigned int) g_variant_get_byte(var); + wifiProfile->Strength = value_int; + } else if (g_strcmp0(key, "State") == 0) { + value_char = g_variant_get_string(var, &length); + wifiProfile->state = (char *) value_char; + } else if (g_strcmp0(key, "IPv4") == 0) { + g_variant_get(var, "a{sv}", &array); + while (g_variant_iter_loop(array, "{sv}", &subkey, &subvar)) { + if (g_strcmp0(subkey, "Method") == 0) { + value_char = g_variant_get_string(subvar, &length); + if (g_strcmp0(value_char, "dhcp") == 0) + wifiProfile->wifiNetwork.method = "dhcp"; + else if (g_strcmp0(value_char, "manual") == 0) + wifiProfile->wifiNetwork.method = "manual"; + else if (g_strcmp0(value_char, "fixed") == 0) + wifiProfile->wifiNetwork.method = "fix"; + else if (g_strcmp0(value_char, "off") == 0) + wifiProfile->wifiNetwork.method = "off"; + } else if (g_strcmp0(subkey, "Address") == 0) { + value_char = g_variant_get_string(subvar, &length); + wifiProfile->wifiNetwork.IPaddress = (char *) value_char; + } else if (g_strcmp0(subkey, "Netmask") == 0) { + value_char = g_variant_get_string(subvar, &length); + wifiProfile->wifiNetwork.netmask = (char *) value_char; + } + } + } + } + //printf ("SSID= %s, security= %s, Strength= %d, wps support= %d\n", wifiProfile->ESSID, wifiProfile->Security.sec_type, wifiProfile->Strength, wifiProfile->Security.wps_support); + return 0; +} + +int wifi_state(struct wifiStatus *status) { + GError *error = NULL; + GVariant *message = NULL; + GVariantIter *array; + GDBusConnection *connection; + GVariant *var = NULL; + const gchar *key = NULL; + gboolean value_bool; + + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (connection == NULL) { + printf("GDBusconnection is NULL"); + return -1; + } + message = g_dbus_connection_call_sync(connection, CONNMAN_SERVICE, + CONNMAN_TECHNOLOGY_PATH, CONNMAN_TECHNOLOGY_INTERFACE, "GetProperties", + NULL, NULL, G_DBUS_CALL_FLAGS_NONE, + DBUS_REPLY_TIMEOUT, NULL, &error); + if (message == NULL) { + printf("message is NULL"); + return -1; + } + g_variant_get(message, "(a{sv})", &array); + while (g_variant_iter_loop(array, "{sv}", &key, &var)) { + if (g_strcmp0(key, "Powered") == 0) { + value_bool = g_variant_get_boolean(var); + if (value_bool) + status->state = 1; + else + status->state = 0; + } else if (g_strcmp0(key, "Connected") == 0) { + value_bool = g_variant_get_boolean(var); + if (value_bool) + status->connected = 1; + else + status->connected = 0; + } + } + g_variant_iter_free(array); + g_variant_unref(message); + + return 0; +} + +GError* do_wifiActivate() { + GVariant *params = NULL; + params = g_variant_new("(sv)", "Powered", g_variant_new_boolean(TRUE)); + GDBusConnection *connection; + GError *error = NULL; + + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + + if (connection == NULL) { + printf("GDBusconnection is NULL"); + return error; + } + + //create the agent to handle security + error = create_agent(connection); + + if (error) + //This is fatal error, without agent secured networks can not be handled + return error; + + g_dbus_connection_call(connection, CONNMAN_SERVICE, + CONNMAN_WIFI_TECHNOLOGY_PREFIX, CONNMAN_TECHNOLOGY_INTERFACE, "SetProperty", + params, NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, &error); + + if (error) { + printf("error: %d:%s\n", error->code, error->message); + + return error; + } + + else { + printf("Power ON succeeded\n"); + return NULL; + } + +} + +GError* do_wifiDeactivate() { + GVariant *params = NULL; + params = g_variant_new("(sv)", "Powered", g_variant_new_boolean(FALSE)); + GDBusConnection *connection; + GError *error = NULL; + + /*connection = gdbus_conn->connection;*/ + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (connection == NULL) { + printf("GDBusconnection is NULL"); + return error; + } + + //create the agent to handle security + error = stop_agent(connection); + + if (error) { + printf("Error while unregistering the agent, ignoring."); + + } + + g_dbus_connection_call(connection, CONNMAN_SERVICE, + CONNMAN_WIFI_TECHNOLOGY_PREFIX, CONNMAN_TECHNOLOGY_INTERFACE, "SetProperty", + params, NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, &error); + + if (error) { + printf("error: %d:%s\n", error->code, error->message); + + return error; + } + + else { + printf("Power OFF succeeded\n"); + return NULL; + } +} + +GError* do_wifiScan() { + GDBusConnection *connection; + GError *error = NULL; + + /*connection = gdbus_conn->connection;*/ + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (connection == NULL) { + printf("GDBusconnection is NULL"); + return error; + } + + g_dbus_connection_call(connection, CONNMAN_SERVICE, + CONNMAN_WIFI_TECHNOLOGY_PREFIX, CONNMAN_TECHNOLOGY_INTERFACE, "Scan", NULL, + NULL, G_DBUS_CALL_FLAGS_NONE, DBUS_REPLY_TIMEOUT, NULL, NULL, &error); + if (error) { + printf("error: %d:%s\n", error->code, error->message); + + return error; + } + + else { + printf("Scan succeeded\n"); + return NULL; + } +} + +GError* do_displayScan(GSList **wifi_list) { + GError *error = NULL; + GVariant *message = NULL; + GVariantIter *array; + gchar *object; + GVariantIter *content = NULL; + GDBusConnection *connection; + struct wifi_profile_info *wifiProfile = NULL; + + /*connection = gdbus_conn->connection;*/ + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (connection == NULL) { + printf("GDBusconnection is NULL"); + return error; + } + message = g_dbus_connection_call_sync(connection, CONNMAN_SERVICE, + CONNMAN_MANAGER_PATH, CONNMAN_MANAGER_INTERFACE, "GetServices", NULL, NULL, + G_DBUS_CALL_FLAGS_NONE, + DBUS_REPLY_TIMEOUT, NULL, &error); + if (message == NULL) { + printf("message is NULL"); + return error; + } + g_variant_get(message, "(a(oa{sv}))", &array); + while (g_variant_iter_loop(array, "(oa{sv})", &object, &content)) { + if (g_str_has_prefix(object, + CONNMAN_WIFI_SERVICE_PROFILE_PREFIX) == TRUE) { + wifiProfile = g_try_malloc0(sizeof(struct wifi_profile_info)); + + extract_values(content, wifiProfile); + wifiProfile->NetworkPath = g_try_malloc0(strlen(object)); + strcpy(wifiProfile->NetworkPath, object); + printf( + "SSID= %s, security= %s, path= %s, Strength= %d, wps support= %d\n", + wifiProfile->ESSID, wifiProfile->Security.sec_type, + wifiProfile->NetworkPath, wifiProfile->Strength, + wifiProfile->Security.wps_support); + printf("method= %s, ip address= %s, netmask= %s\n", + wifiProfile->wifiNetwork.method, + wifiProfile->wifiNetwork.IPaddress, + wifiProfile->wifiNetwork.netmask); + *wifi_list = g_slist_append(*wifi_list, + (struct wifi_profile_info *) wifiProfile); + } + } + g_variant_iter_free(array); + + return NULL; +} + +GError* do_connectNetwork(gchar *networkPath) { + + printf("Connecting to: %s\n", networkPath); + + GVariant *message = NULL; + GError *error = NULL; + GDBusConnection *connection; + + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + + message = g_dbus_connection_call_sync(connection, CONNMAN_SERVICE, + networkPath, CONNMAN_SERVICE_INTERFACE, "Connect", NULL, NULL, + G_DBUS_CALL_FLAGS_NONE, + DBUS_REPLY_TIMEOUT_SHORT, NULL, &error); + + //printf("message error %s\n", message); + //TODO: do we need retunrn value in message + + if (error) { + printf("do_connectNetwork error: %s\n", error->message); + return error; + } else { + printf("Connection succeeded\n"); + return NULL; + } + +} + +GError* do_disconnectNetwork(gchar *networkPath) { + + printf("Connecting to: %s\n", networkPath); + + GVariant *message = NULL; + GError *error = NULL; + GDBusConnection *connection; + + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + + message = g_dbus_connection_call_sync(connection, CONNMAN_SERVICE, + networkPath, CONNMAN_SERVICE_INTERFACE, "Disconnect", NULL, NULL, + G_DBUS_CALL_FLAGS_NONE, + DBUS_REPLY_TIMEOUT, NULL, &error); + + //TODO: do we need return value in message + + if (error) { + printf("error: %s\n", error->message); + return error; + } else { + printf("Disconnected\n"); + return NULL; + } + +} + +void registerPasskey(gchar *passkey) { + + printf("Passkey: %s\n", passkey); + sendPasskey(passkey); + +} + diff --git a/wifi-connman.h b/wifi-connman.h new file mode 100644 index 0000000..bd83821 --- /dev/null +++ b/wifi-connman.h @@ -0,0 +1,126 @@ +/* Copyright 2016 ALPS ELECTRIC CO., LTD. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +//#include <dlog.h> +#include <glib.h> +#include <stdlib.h> +#include <gio/gio.h> +#include <glib-object.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** Maximum Profile Count */ +#define CONNMAN_MAX_BUFLEN 512 + +#define CONNMAN_STATE_STRLEN 16 + +#define CONNMAN_SERVICE "net.connman" +#define CONNMAN_MANAGER_INTERFACE CONNMAN_SERVICE ".Manager" +#define CONNMAN_TECHNOLOGY_INTERFACE CONNMAN_SERVICE ".Technology" +#define CONNMAN_SERVICE_INTERFACE CONNMAN_SERVICE ".Service" +#define CONNMAN_PROFILE_INTERFACE CONNMAN_SERVICE ".Profile" +#define CONNMAN_COUNTER_INTERFACE CONNMAN_SERVICE ".Counter" +#define CONNMAN_ERROR_INTERFACE CONNMAN_SERVICE ".Error" +#define CONNMAN_AGENT_INTERFACE CONNMAN_SERVICE ".Agent" + +#define CONNMAN_MANAGER_PATH "/" +#define CONNMAN_PATH "/net/connman" +#define CONNMAN_TECHNOLOGY_PATH "/net/connman/technology/wifi" + +/** ConnMan technology and profile prefixes for ConnMan 0.78 */ + +#define CONNMAN_WIFI_TECHNOLOGY_PREFIX CONNMAN_PATH "/technology/wifi" +#define CONNMAN_WIFI_SERVICE_PROFILE_PREFIX CONNMAN_PATH "/service/wifi_" + +#define WIFI_ESSID_LEN 128 +#define WIFI_MAX_WPSPIN_LEN 8 +#define WIFI_BSSID_LEN 17 +#define WIFI_MAX_PSK_PASSPHRASE_LEN 65 +#define WIFI_MAX_WEP_KEY_LEN 26 + +#define AGENT_PATH "/net/connman/Agent" +#define AGENT_SERVICE "org.agent" + +#define DBUS_REPLY_TIMEOUT (120 * 1000) +#define DBUS_REPLY_TIMEOUT_SHORT (10 * 1000) + + +struct gdbus_connection_data_s{ + GDBusConnection *connection; + int conn_ref_count; + GCancellable *cancellable; + void *handle_libnetwork; +}; + + +struct wifiStatus { + unsigned int state; + unsigned int connected; +}; + +struct security_profile{ + char *sec_type; + char *enc_type; + char *wepKey; + char *pskKey; + unsigned int PassphraseRequired; + unsigned int wps_support; +}; + +struct wifi_net{ + char *method; + char *IPaddress; + char *netmask; +}; + +struct wifi_profile_info{ + char *ESSID; + char *NetworkPath; + char *state; + unsigned int Strength; + struct security_profile Security; + struct wifi_net wifiNetwork; +}; + +//typedef void(*callback)(void); +typedef void(*callback)(int password_rejected_flag); +void register_callback(callback ptr); + + +int extract_values(GVariantIter *content, struct wifi_profile_info* wifiProfile); +int wifi_state(struct wifiStatus *status); +GError* do_wifiActivate(); +GError* do_wifiDeactivate(); +GError* do_wifiScan(); +GError* do_displayScan(GSList **wifi_list); +GError* do_connectNetwork(gchar *object); +GError* do_disconnectNetwork(gchar *object); + +GError* create_agent(GDBusConnection *connection); +GError* stop_agent(GDBusConnection *connection); + + +void registerPasskey(gchar *object); +GError* sendPasskey(gchar *object); + +GError* do_initialize(); +GError* do_initialize(); + + + + + |