From c45eee86f5a3fb041df570f23b2b477c38af0cce Mon Sep 17 00:00:00 2001 From: Jaehyun Kim Date: Thu, 27 Aug 2020 23:32:34 +0900 Subject: Add support for handling multiple wifi interfaces Change-Id: I4762c8d3444167dce34498634de4948e822f865f Signed-off-by: Jaehyun Kim --- include/device.h | 14 + include/service.h | 3 + include/technology.h | 8 +- packaging/connman.spec | 2 +- plugins/wifi.c | 20 +- src/connman.conf | 5 + src/connman.h | 7 +- src/device.c | 193 +++++++++++- src/main.c | 21 +- src/main.conf | 4 + src/main_tv.conf | 4 + src/manager.c | 16 + src/service.c | 85 +++++- src/technology.c | 780 ++++++++++++++++++++++++++++++++++++++++++------- 14 files changed, 1038 insertions(+), 124 deletions(-) diff --git a/include/device.h b/include/device.h index 98c7bd87..67d7928c 100755 --- a/include/device.h +++ b/include/device.h @@ -106,6 +106,20 @@ int connman_device_add_network(struct connman_device *device, struct connman_network *network); struct connman_network *connman_device_get_network(struct connman_device *device, const char *identifier); +#if defined TIZEN_EXT +struct connman_network *connman_device_get_default_network( + struct connman_device *device); +void connman_device_set_pending_reply(struct connman_device *device, + DBusMessage *msg); +void connman_device_send_connected_signal(struct connman_device *device, + bool connected); +void connman_device_set_max_scan_ssids(struct connman_device *device, + int max_scan_ssids); +int connman_device_get_max_scan_ssids(struct connman_device *device); +void connman_device_set_wifi_5ghz_supported(struct connman_device *device, + bool is_5_0_ghz_supported); +bool connman_device_get_wifi_5ghz_supported(struct connman_device *device); +#endif int connman_device_remove_network(struct connman_device *device, struct connman_network *network); diff --git a/include/service.h b/include/service.h index 617735e0..1e4a6926 100755 --- a/include/service.h +++ b/include/service.h @@ -26,6 +26,7 @@ #if defined TIZEN_EXT #include +#include #endif #ifdef __cplusplus @@ -208,6 +209,8 @@ void connman_service_set_disconnection_requested(struct connman_service *service void connman_service_set_internet_connection(struct connman_service *service, bool internet_connection); bool connman_service_get_internet_connection(struct connman_service *service); +DBusMessage *connman_service_get_defaut_info(DBusMessage *msg, + struct connman_service *service); #endif #ifdef __cplusplus diff --git a/include/technology.h b/include/technology.h index 39de65d9..b449c8d8 100755 --- a/include/technology.h +++ b/include/technology.h @@ -46,6 +46,7 @@ typedef enum { CONNMAN_SCAN_TYPE_SPECIFIC_AP, CONNMAN_SCAN_TYPE_MULTI_AP, CONNMAN_SCAN_TYPE_WPA_SUPPLICANT, + CONNMAN_SCAN_TYPE_UNKNOWN, } connman_scan_type_e; typedef struct { @@ -89,11 +90,8 @@ struct connman_technology_driver { int connman_technology_driver_register(struct connman_technology_driver *driver); void connman_technology_driver_unregister(struct connman_technology_driver *driver); #if defined TIZEN_EXT -void connman_techonology_wifi_set_5ghz_supported(struct connman_technology *technology, - bool is_5_0_Ghz_supported); -void connman_techonology_set_max_scan_ssids(struct connman_technology *technology, - int max_scan_ssids); -void __connman_technology_notify_scan_done(int val); +const char *connman_techonology_get_path(enum connman_service_type type); +void __connman_technology_notify_scan_done(const char *ifname, int val); #endif #ifdef __cplusplus diff --git a/packaging/connman.spec b/packaging/connman.spec index ff83e103..a8904e24 100644 --- a/packaging/connman.spec +++ b/packaging/connman.spec @@ -5,7 +5,7 @@ Name: connman Version: 1.37 -Release: 43 +Release: 44 License: GPL-2.0+ Summary: Connection Manager Url: http://connman.net diff --git a/plugins/wifi.c b/plugins/wifi.c index d998967f..8fe2be3b 100755 --- a/plugins/wifi.c +++ b/plugins/wifi.c @@ -3397,7 +3397,8 @@ static void connect_callback(int result, GSupplicantInterface *interface, DBG("network %p result %d", network, result); #if defined TIZEN_EXT - set_connman_bssid(RESET_BSSID, NULL); + char *ifname = g_supplicant_interface_get_ifname(interface); + set_connman_bssid(RESET_BSSID, NULL, ifname); for (list = iface_list; list; list = list->next) { wifi = list->data; @@ -3550,9 +3551,11 @@ static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network) #endif #if defined TIZEN_EXT - if (set_connman_bssid(CHECK_BSSID, NULL) == 6) { + const char *ifname = connman_device_get_string( + connman_network_get_device(network), "Interface"); + if (set_connman_bssid(CHECK_BSSID, NULL, ifname) == 6) { ssid->bssid_for_connect_len = 6; - set_connman_bssid(GET_BSSID, (char *)ssid->bssid_for_connect); + set_connman_bssid(GET_BSSID, (char *)ssid->bssid_for_connect, ifname); DBG("BSSID : %02x:%02x:%02x:%02x:%02x:%02x", ssid->bssid_for_connect[0], ssid->bssid_for_connect[1], ssid->bssid_for_connect[2], ssid->bssid_for_connect[3], @@ -3568,8 +3571,8 @@ static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network) * the user-specified bssid is tried only once at the beginning. * After that, the bssids in the list are tried in order. */ - if (set_connman_bssid(CHECK_BSSID, NULL) == 6) { - set_connman_bssid(RESET_BSSID, NULL); + if (set_connman_bssid(CHECK_BSSID, NULL, ifname) == 6) { + set_connman_bssid(RESET_BSSID, NULL, ifname); goto done; } @@ -3961,10 +3964,10 @@ static void interface_added(GSupplicantInterface *interface) connman_device_set_powered(wifi->device, true); #if defined TIZEN_EXT - connman_techonology_wifi_set_5ghz_supported(wifi_technology, is_5_0_ghz_supported); + connman_device_set_wifi_5ghz_supported(wifi->device, is_5_0_ghz_supported); /* Max number of SSIDs supported by wlan chipset that can be scanned */ int max_scan_ssids = g_supplicant_interface_get_max_scan_ssids(interface); - connman_techonology_set_max_scan_ssids(wifi_technology, max_scan_ssids); + connman_device_set_max_scan_ssids(wifi->device, max_scan_ssids); #endif } @@ -5605,7 +5608,8 @@ static void scan_done(GSupplicantInterface *interface) scanning = connman_device_get_scanning(wifi->device, CONNMAN_SERVICE_TYPE_WIFI); if (!scanning) - __connman_technology_notify_scan_done(scan_type); + __connman_technology_notify_scan_done( + connman_device_get_string(wifi->device, "Interface"), scan_type); break; } } diff --git a/src/connman.conf b/src/connman.conf index c1417ebc..60e7e828 100644 --- a/src/connman.conf +++ b/src/connman.conf @@ -20,6 +20,7 @@ + @@ -33,6 +34,10 @@ + + + + diff --git a/src/connman.h b/src/connman.h index 2f2f5a8e..9e28ffea 100755 --- a/src/connman.h +++ b/src/connman.h @@ -597,7 +597,8 @@ enum bssid_type { RESET_BSSID = 3, }; -int set_connman_bssid(enum bssid_type mode, char *bssid); +int set_connman_bssid(enum bssid_type mode, char *bssid, const char *ifname); +void technology_save_device(struct connman_device *device); #endif #include @@ -618,7 +619,9 @@ int __connman_device_request_hidden_scan(struct connman_device *device, void __connman_device_stop_scan(enum connman_service_type type); #if defined TIZEN_EXT int __connman_device_request_specific_scan(enum connman_service_type type, - int scan_type, GSList *specific_scan_list); + const char *ifname, int scan_type, GSList *specific_scan_list); +int connman_device_request_device_scan(enum connman_service_type type, + const char * ifname, bool force_full_scan); #endif bool __connman_device_isfiltered(const char *devname); diff --git a/src/device.c b/src/device.c index 2029871e..78b01f77 100755 --- a/src/device.c +++ b/src/device.c @@ -38,6 +38,10 @@ static GSList *device_list = NULL; static gchar **device_filter = NULL; static gchar **nodevice_filter = NULL; +#if defined TIZEN_EXT +static DBusConnection *connection; +#endif + enum connman_pending_type { PENDING_NONE = 0, PENDING_ENABLE = 1, @@ -72,11 +76,20 @@ struct connman_device { time_t last_user_selection_time; char *last_user_selection_ident; char *last_connected_ident; + DBusMessage *pending_reply; + int max_scan_ssids; + bool is_5_0_ghz_supported; #endif }; static void clear_pending_trigger(struct connman_device *device) { +#if defined TIZEN_EXT + if (device->pending_reply) { + dbus_message_unref(device->pending_reply); + device->pending_reply = NULL; + } +#endif if (device->pending_timeout > 0) { g_source_remove(device->pending_timeout); device->pending_timeout = 0; @@ -190,6 +203,19 @@ static gboolean device_pending_reset(gpointer user_data) DBG("device %p", device); +#if defined TIZEN_EXT + DBusMessage *reply; + + /* Power request timed out, send ETIMEDOUT. */ + if (device->pending_reply) { + reply = __connman_error_failed(device->pending_reply, ETIMEDOUT); + if (reply) + g_dbus_send_message(connection, reply); + + dbus_message_unref(device->pending_reply); + device->pending_reply = NULL; + } +#endif /* Power request timedout, reset power pending state. */ device->pending_timeout = 0; device->powered_pending = PENDING_NONE; @@ -436,6 +462,51 @@ static void device_destruct(struct connman_device *device) g_free(device); } +#if defined TIZEN_EXT +static void device_send_changed(const char *ifname, enum connman_service_type type, + const char *key, bool state) +{ + DBusMessage *signal; + DBusMessageIter iter, dict; + dbus_bool_t value = state; + const char *tech_path = connman_techonology_get_path(type); + + if (!tech_path || !ifname) + return; + + DBG("%s %s %s", ifname, key, state ? "TRUE" : "FALSE"); + + signal = dbus_message_new_signal(tech_path, + CONNMAN_TECHNOLOGY_INTERFACE, "DeviceChanged"); + if (!signal) + return; + + dbus_message_iter_init_append(signal, &iter); + + connman_dbus_dict_open(&iter, &dict); + connman_dbus_dict_append_basic(&dict, "Ifname", + DBUS_TYPE_STRING, + &ifname); + connman_dbus_dict_append_basic(&dict, key, + DBUS_TYPE_BOOLEAN, + &value); + connman_dbus_dict_close(&iter, &dict); + + dbus_connection_send(connection, signal, NULL); + dbus_message_unref(signal); +} + +static void device_send_reply(struct connman_device *device) +{ + if (device->pending_reply) { + g_dbus_send_reply(connection, + device->pending_reply, DBUS_TYPE_INVALID); + dbus_message_unref(device->pending_reply); + device->pending_reply = NULL; + } +} +#endif + /** * connman_device_create: * @node: device node name (for example an address) @@ -611,6 +682,10 @@ int connman_device_set_powered(struct connman_device *device, if (device->powered == powered) return -EALREADY; +#if defined TIZEN_EXT + device_send_reply(device); +#endif + clear_pending_trigger(device); device->powered_pending = PENDING_NONE; @@ -619,6 +694,11 @@ int connman_device_set_powered(struct connman_device *device, type = __connman_device_get_service_type(device); +#if defined TIZEN_EXT + device_send_changed(device->interface, type, "Powered", powered); + technology_save_device(device); +#endif + if (!device->powered) { __connman_technology_disabled(type); return 0; @@ -1102,6 +1182,54 @@ struct connman_network *connman_device_get_network(struct connman_device *device return g_hash_table_lookup(device->networks, identifier); } +#if defined TIZEN_EXT +struct connman_network *connman_device_get_default_network( + struct connman_device *device) +{ + return device->network; +} + +void connman_device_set_pending_reply(struct connman_device *device, + DBusMessage *msg) +{ + device->pending_reply = dbus_message_ref(msg); +} + +void connman_device_send_connected_signal(struct connman_device *device, + bool connected) +{ + enum connman_service_type type; + + if (!device) + return; + + type = __connman_device_get_service_type(device); + device_send_changed(device->interface, type, "Connected", connected); +} + +void connman_device_set_max_scan_ssids(struct connman_device *device, + int max_scan_ssids) +{ + device->max_scan_ssids = max_scan_ssids; +} + +int connman_device_get_max_scan_ssids(struct connman_device *device) +{ + return device->max_scan_ssids; +} + +void connman_device_set_wifi_5ghz_supported(struct connman_device *device, + bool is_5_0_ghz_supported) +{ + device->is_5_0_ghz_supported = is_5_0_ghz_supported; +} + +bool connman_device_get_wifi_5ghz_supported(struct connman_device *device) +{ + return device->is_5_0_ghz_supported; +} +#endif + /** * connman_device_remove_network: * @device: device structure @@ -1314,7 +1442,7 @@ static int device_specific_scan(enum connman_service_type type, } int __connman_device_request_specific_scan(enum connman_service_type type, - int scan_type, GSList *specific_scan_list) + const char *ifname, int scan_type, GSList *specific_scan_list) { bool success = false; int last_err = -ENOSYS; @@ -1352,6 +1480,9 @@ int __connman_device_request_specific_scan(enum connman_service_type type, continue; } + if (ifname && g_strcmp0(device->interface, ifname) != 0) + continue; + err = device_specific_scan(type, device, scan_type, specific_scan_list); if (err == 0 || err == -EINPROGRESS) { success = true; @@ -1367,6 +1498,58 @@ int __connman_device_request_specific_scan(enum connman_service_type type, return last_err; } +int connman_device_request_device_scan(enum connman_service_type type, + const char * ifname, bool force_full_scan) +{ + bool success = false; + int last_err = -ENOSYS; + GSList *list; + int err; + + switch (type) { + case CONNMAN_SERVICE_TYPE_UNKNOWN: + case CONNMAN_SERVICE_TYPE_SYSTEM: + case CONNMAN_SERVICE_TYPE_ETHERNET: + case CONNMAN_SERVICE_TYPE_BLUETOOTH: + case CONNMAN_SERVICE_TYPE_CELLULAR: + case CONNMAN_SERVICE_TYPE_GPS: + case CONNMAN_SERVICE_TYPE_VPN: + case CONNMAN_SERVICE_TYPE_GADGET: + return -EOPNOTSUPP; + case CONNMAN_SERVICE_TYPE_WIFI: + case CONNMAN_SERVICE_TYPE_P2P: +#if defined TIZEN_EXT_WIFI_MESH + case CONNMAN_SERVICE_TYPE_MESH: +#endif + break; + } + + for (list = device_list; list; list = list->next) { + struct connman_device *device = list->data; + + if (!device_has_service_type(device, type)) + continue; + + if (g_strcmp0(device->interface, ifname) != 0) + continue; + + err = device_scan(type, device, force_full_scan); + + if (err == 0 || err == -EINPROGRESS) { + success = true; + } else { + last_err = err; + DBG("device %p err %d", device, err); + } + break; + } + + if (success) + return 0; + + return last_err; +} + #if defined TIZEN_EXT_WIFI_MESH static int device_abort_scan(enum connman_service_type type, struct connman_device *device) @@ -1882,6 +2065,10 @@ int __connman_device_init(const char *device, const char *nodevice) { DBG(""); +#if defined TIZEN_EXT + connection = connman_dbus_get_connection(); +#endif + if (device) device_filter = g_strsplit(device, ",", -1); @@ -1899,4 +2086,8 @@ void __connman_device_cleanup(void) g_strfreev(nodevice_filter); g_strfreev(device_filter); + +#if defined TIZEN_EXT + dbus_connection_unref(connection); +#endif } diff --git a/src/main.c b/src/main.c index 6dcdced6..0700304e 100755 --- a/src/main.c +++ b/src/main.c @@ -46,6 +46,10 @@ #define DEFAULT_INPUT_REQUEST_TIMEOUT (120 * 1000) #define DEFAULT_BROWSER_LAUNCH_TIMEOUT (300 * 1000) +#if defined TIZEN_EXT +#define DEFAULT_WIFI_INTERFACE "wlan0" +#endif + #define MAINFILE "main.conf" #define CONFIGMAINFILE CONFIGDIR "/" MAINFILE @@ -99,6 +103,7 @@ static struct { bool auto_ip; char *global_nameserver; bool supplicant_debug; + char *def_wifi_ifname; #endif } connman_settings = { .bg_scan = true, @@ -128,6 +133,7 @@ static struct { .auto_ip = true, .global_nameserver = NULL, .supplicant_debug = false, + .def_wifi_ifname = DEFAULT_WIFI_INTERFACE, #endif }; @@ -214,6 +220,7 @@ static struct { #define CONF_ENABLE_AUTO_IP "EnableAutoIp" #define CONF_GLOBAL_NAMESERVER "GlobalNameserver" #define CONF_CONNMAN_SUPPLICANT_DEBUG "ConnmanSupplicantDebug" +#define CONF_CONNMAN_WIFI_DEF_IFNAME "DefaultWifiInterface" #endif #if defined TIZEN_EXT @@ -271,6 +278,7 @@ static const char *supported_options[] = { CONF_ENABLE_AUTO_IP, CONF_GLOBAL_NAMESERVER, CONF_CONNMAN_SUPPLICANT_DEBUG, + CONF_CONNMAN_WIFI_DEF_IFNAME, #endif NULL }; @@ -611,6 +619,7 @@ static void check_Tizen_configuration(GKeyFile *config) GError *error = NULL; char **cellular_interfaces; char *global_nameserver; + char *default_wifi_ifname; bool boolean; gsize len; @@ -650,6 +659,13 @@ static void check_Tizen_configuration(GKeyFile *config) g_clear_error(&error); + default_wifi_ifname = __connman_config_get_string(config, "General", + CONF_CONNMAN_WIFI_DEF_IFNAME, &error); + if (!error) + connman_settings.def_wifi_ifname = default_wifi_ifname; + + g_clear_error(&error); + check_Tizen_INS_configuration(config); } @@ -1067,14 +1083,15 @@ const char *connman_option_get_string(const char *key) #if defined TIZEN_EXT if (g_str_equal(key, CONF_GLOBAL_NAMESERVER)) return connman_settings.global_nameserver; -#endif -#if defined TIZEN_EXT if (g_str_equal(key, CONF_INS_PREFERRED_FREQ_BSSID)) return connman_ins_settings.ins_preferred_freq_bssid; if (g_str_equal(key, CONF_INS_PREFERRED_FREQ)) return connman_ins_settings.ins_preferred_freq; + + if (g_str_equal(key, CONF_CONNMAN_WIFI_DEF_IFNAME)) + return connman_settings.def_wifi_ifname; #endif return NULL; } diff --git a/src/main.conf b/src/main.conf index 6e26464e..58bcfcb9 100755 --- a/src/main.conf +++ b/src/main.conf @@ -172,6 +172,10 @@ NetworkCellularInterfaceList = pdp,rmnet,seth_td,seth_w # Enable supplicant debugging log ConnmanSupplicantDebug = false +# This value specifies which will be the default when there are multiple wifi interfaces. +# Default value is wlan0. +DefaultWifiInterface = wlan0 + [INS] # INS(Intelligent Network Selection) configuration: BSSID Selection. INSPreferredFreqBSSID = 5GHz diff --git a/src/main_tv.conf b/src/main_tv.conf index 65dc7270..c7b8e112 100755 --- a/src/main_tv.conf +++ b/src/main_tv.conf @@ -116,6 +116,10 @@ NetworkCellularInterfaceList = pdp,rmnet,seth_td,seth_w # Enable Tizen TV Profile Features TizenTVExtension = true +# This value specifies which will be the default when there are multiple wifi interfaces. +# Default value is wlan0. +DefaultWifiInterface = wlan0 + [INS] # INS(Intelligent Network Selection) configuration: BSSID Selection. INSPreferredFreqBSSID = 5GHz diff --git a/src/manager.c b/src/manager.c index 0b232ecb..4b351e11 100755 --- a/src/manager.c +++ b/src/manager.c @@ -216,6 +216,17 @@ static DBusMessage *get_services(DBusConnection *conn, return reply; } +#if defined TIZEN_EXT +static DBusMessage *get_default_service(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + struct connman_service *service = connman_service_get_default_connection(); + DBG("service %p", service); + + return connman_service_get_defaut_info(msg, service); +} +#endif + #if defined TIZEN_EXT_INS static void append_ins_structs(DBusMessageIter *iter, void *user_data) { @@ -688,6 +699,11 @@ static const GDBusMethodTable manager_methods[] = { { GDBUS_METHOD("GetServices", NULL, GDBUS_ARGS({ "services", "a(oa{sv})" }), get_services) }, +#if defined TIZEN_EXT + { GDBUS_METHOD("GetDefaultService", + NULL, GDBUS_ARGS({ "service", "oa{sv}" }), + get_default_service) }, +#endif #if defined TIZEN_EXT_INS { GDBUS_METHOD("GetINS", NULL, GDBUS_ARGS({ "services", "a(oa{sv})" }), diff --git a/src/service.c b/src/service.c index fb780fbe..b130888b 100755 --- a/src/service.c +++ b/src/service.c @@ -4888,6 +4888,30 @@ bool connman_service_get_internet_connection(struct connman_service *service) return service->is_internet_connection; } + +DBusMessage *connman_service_get_defaut_info(DBusMessage *msg, + struct connman_service *service) +{ + DBusMessage *reply; + DBusMessageIter array, dict; + + reply = dbus_message_new_method_return(msg); + if (!reply) + return NULL; + + dbus_message_iter_init_append(reply, &array); + + if (service) + dbus_message_iter_append_basic(&array, DBUS_TYPE_OBJECT_PATH, + &service->path); + + connman_dbus_dict_open(&array, &dict); + if (service) + append_properties(&dict, FALSE, service); + connman_dbus_dict_close(&array, &dict); + + return reply; +} #endif void __connman_service_set_proxy_autoconfig(struct connman_service *service, @@ -6331,6 +6355,9 @@ static bool auto_connect_service(GList *services, bool ignore[MAX_CONNMAN_SERVICE_TYPES] = { }; bool autoconnecting = false; GList *list; +#if defined TIZEN_EXT + GList *wifi_ignore = NULL; +#endif DBG("preferred %d sessions %d reason %s", preferred, active_count, reason2string(reason)); @@ -6346,6 +6373,13 @@ static bool auto_connect_service(GList *services, for (list = services; list; list = list->next) { service = list->data; +#if defined TIZEN_EXT + if (service->type == CONNMAN_SERVICE_TYPE_WIFI) { + int index = connman_network_get_index(service->network); + if (g_slist_find(wifi_ignore, GINT_TO_POINTER(index)) != NULL) + continue; + } else +#endif if (ignore[service->type]) { DBG("service %p type %s ignore", service, __connman_service_type2string(service->type)); @@ -6369,9 +6403,18 @@ static bool auto_connect_service(GList *services, if (service->pending || is_connecting(service->state) || is_connected(service->state)) { +#if defined TIZEN_EXT + if (service->type == CONNMAN_SERVICE_TYPE_WIFI) { + int index = connman_network_get_index(service->network); + wifi_ignore = g_slist_prepend(wifi_ignore, GINT_TO_POINTER(index)); + + autoconnecting = true; + continue; + } +#else if (autoconnect_no_session_active(service)) return true; - +#endif ignore[service->type] = true; autoconnecting = true; @@ -6388,6 +6431,7 @@ static bool auto_connect_service(GList *services, #if defined TIZEN_EXT DBG("Service is not favorite, autoconnecting %d", autoconnecting); + g_slist_free(wifi_ignore); #endif return autoconnecting; } @@ -6403,7 +6447,9 @@ static bool auto_connect_service(GList *services, if (is_ignore(service) || service->state != CONNMAN_SERVICE_STATE_IDLE) continue; - +#if defined TIZEN_EXT + if (service->type != CONNMAN_SERVICE_TYPE_WIFI) +#endif if (autoconnect_already_connecting(service, autoconnecting)) { DBG("service %p type %s has no users", service, __connman_service_type2string(service->type)); @@ -6414,13 +6460,15 @@ static bool auto_connect_service(GList *services, (preferred) ? "preferred" : reason2string(reason)); __connman_service_connect(service, reason); - +#if !defined TIZEN_EXT if (autoconnect_no_session_active(service)) return true; - +#endif ignore[service->type] = true; } - +#if defined TIZEN_EXT + g_slist_free(wifi_ignore); +#endif return autoconnecting; } @@ -7731,6 +7779,25 @@ static gint service_compare(gconstpointer a, gconstpointer b) a_connected = is_connected(state_a); b_connected = is_connected(state_b); +#if defined TIZEN_EXT + if ((a_connected && b_connected) && + state_a == state_b && + service_a->type == CONNMAN_SERVICE_TYPE_WIFI && + service_b->type == CONNMAN_SERVICE_TYPE_WIFI) { + const char *default_interface = + connman_option_get_string("DefaultWifiInterface"); + const char *ifname_a = connman_device_get_string( + connman_network_get_device(service_a->network), "Interface"); + const char *ifname_b = connman_device_get_string( + connman_network_get_device(service_b->network), "Interface"); + + if (g_strcmp0(default_interface, ifname_a) == 0) + return -1; + else if (g_strcmp0(default_interface, ifname_b) == 0) + return 1; + } +#endif + if (a_connected && b_connected) { if (service_a->order > service_b->order) return -1; @@ -8764,6 +8831,10 @@ static int service_indicate_state(struct connman_service *service) #if defined TIZEN_EXT if (service->type == CONNMAN_SERVICE_TYPE_WIFI) set_priority_connected_service(); + + if (!is_connected(old_state)) + connman_device_send_connected_signal( + connman_network_get_device(service->network), true); #endif break; @@ -8855,6 +8926,10 @@ static int service_indicate_state(struct connman_service *service) (old_state == CONNMAN_SERVICE_STATE_READY && new_state != CONNMAN_SERVICE_STATE_ONLINE)) { __connman_notifier_disconnect(service->type); +#if defined TIZEN_EXT + connman_device_send_connected_signal( + connman_network_get_device(service->network), false); +#endif } if (new_state == CONNMAN_SERVICE_STATE_ONLINE) { diff --git a/src/technology.c b/src/technology.c index b00273e3..b3586001 100644 --- a/src/technology.c +++ b/src/technology.c @@ -28,6 +28,7 @@ #if defined TIZEN_EXT #include #include +#include #endif #include @@ -48,7 +49,16 @@ static GHashTable *rfkill_list; static bool global_offlinemode; #if defined TIZEN_EXT -static connman_scan_type_e g_scan_type = -1; +struct connman_scan_pending { + char *ifname; + connman_scan_type_e scan_type; + DBusMessage *msg; +}; + +struct connman_bssid_pending { + char *ifname; + unsigned char bssid[6]; +}; #endif struct connman_rfkill { @@ -88,13 +98,12 @@ struct connman_technology { bool softblocked; bool hardblocked; bool dbus_registered; +#if defined TIZEN_EXT + char **enabled_devices; +#endif #if defined TIZEN_EXT_WIFI_MESH DBusMessage *mesh_dbus_msg; #endif -#if defined TIZEN_EXT - bool is_5_0_ghz_supported; - int max_scan_ssids; -#endif }; static GSList *driver_list = NULL; @@ -397,12 +406,14 @@ bool connman_technology_get_wifi_tethering(const char **ssid, } #if defined TIZEN_EXT -void connman_techonology_wifi_set_5ghz_supported(struct connman_technology *wifi_technology, - bool is_5_0_ghz_supported) +const char *connman_techonology_get_path(enum connman_service_type type) { - DBG(""); + struct connman_technology *technology = technology_find(type); + + if (!technology) + return NULL; - wifi_technology->is_5_0_ghz_supported = is_5_0_ghz_supported; + return technology->path; } #endif @@ -437,6 +448,16 @@ static void technology_load(struct connman_technology *technology) if (!identifier) goto done; +#ifdef TIZEN_EXT + gsize length; + technology->enabled_devices = g_key_file_get_string_list(keyfile, + identifier, "Enable.Devices", &length, NULL); + if (technology->enabled_devices && length == 0) { + g_strfreev(technology->enabled_devices); + technology->enabled_devices = NULL; + } +#endif + enable = g_key_file_get_boolean(keyfile, identifier, "Enable", &error); if (!error) technology->enable_persistent = enable; @@ -533,6 +554,43 @@ static bool connman_technology_load_offlinemode(void) return offlinemode; } +#if defined TIZEN_EXT +static void append_devices(DBusMessageIter *iter, void *user_data) +{ + GSList *list; + dbus_bool_t val; + struct connman_technology *technology = user_data; + + for (list = technology->device_list; list; list = list->next) { + struct connman_device *device = list->data; + + const char *str = connman_device_get_string(device, "Interface"); + struct connman_network *network = connman_device_get_default_network(device); + struct connman_service *service = connman_service_lookup_from_network(network); + + connman_dbus_dict_append_basic(iter, "Ifname", + DBUS_TYPE_STRING, &str); + + val = connman_device_get_powered(device); + connman_dbus_dict_append_basic(iter, "Powered", + DBUS_TYPE_BOOLEAN, &val); + + if (__connman_service_is_connected_state(service, CONNMAN_IPCONFIG_TYPE_IPV4) || + __connman_service_is_connected_state(service, CONNMAN_IPCONFIG_TYPE_IPV6)) + val = TRUE; + else + val = FALSE; + + connman_dbus_dict_append_basic(iter, "Connected", + DBUS_TYPE_BOOLEAN, &val); + + str = connman_device_get_string(device, "Address"); + connman_dbus_dict_append_basic(iter, "MAC.Address", + DBUS_TYPE_STRING, &str); + } +} +#endif + static void append_properties(DBusMessageIter *iter, struct connman_technology *technology) { @@ -577,7 +635,11 @@ static void append_properties(DBusMessageIter *iter, connman_dbus_dict_append_basic(&dict, "TetheringPassphrase", DBUS_TYPE_STRING, &technology->tethering_passphrase); - +#if defined TIZEN_EXT + if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) + connman_dbus_dict_append_dict(&dict, "Device.List", + append_devices, technology); +#endif connman_dbus_dict_close(iter, &dict); } @@ -898,25 +960,52 @@ make_reply: } #if defined TIZEN_EXT -int set_connman_bssid(enum bssid_type mode, char *bssid) +int set_connman_bssid(enum bssid_type mode, char *bssid, const char *ifname) { - static unsigned char bssid_for_connect[6]; static int bssid_len; + static const char *def_ifname = "default"; + static GSList *bssid_list = NULL; + GSList *list; + const char *local_ifname = ifname; + bool found = false; + struct connman_bssid_pending *bssid_info; - DBG("mode : %d", mode); + DBG("mode: %d, ifname: %s", mode, ifname); + + if (!ifname) + local_ifname = def_ifname; + + for (list = bssid_list; list; list = list->next) { + bssid_info = list->data; + + if (g_strcmp0(bssid_info->ifname, local_ifname) == 0) { + found = true; + break; + } + } if (mode == CHECK_BSSID) { - return bssid_len; + if (found) + return 6; + + return 0; } if (mode == GET_BSSID && bssid) { - memcpy(bssid, bssid_for_connect, 6); - return bssid_len; + if (found) { + memcpy(bssid, bssid_info->bssid, 6); + return 6; + } + return 0; } if (mode == RESET_BSSID) { - bssid_len = 0; - return bssid_len; + if (found) { + bssid_list = g_slist_remove(bssid_list, bssid_info); + g_free(bssid_info->ifname); + g_free(bssid_info); + } + return 0; } if (mode != SET_BSSID || !bssid) { @@ -924,17 +1013,37 @@ int set_connman_bssid(enum bssid_type mode, char *bssid) return 0; } + if (found) { + bssid_list = g_slist_remove(bssid_list, bssid_info); + g_free(bssid_info->ifname); + g_free(bssid_info); + } + + bssid_info = g_try_malloc0(sizeof(struct connman_bssid_pending)); + if (!bssid_info) { + DBG("Failed to allocate memory"); + return 0; + } + + unsigned char *bssid_data = bssid_info->bssid; + bssid_len = sscanf(bssid, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", - &bssid_for_connect[0], &bssid_for_connect[1], &bssid_for_connect[2], - &bssid_for_connect[3], &bssid_for_connect[4], &bssid_for_connect[5]); + &bssid_data[0], &bssid_data[1], &bssid_data[2], + &bssid_data[3], &bssid_data[4], &bssid_data[5]); if (bssid_len != 6) { DBG("Incorrect BSSID format. bssid_len = %d", bssid_len); - bssid_len = 0; + g_free(bssid_info); + return 0; } - DBG("SET BSSID len : %d, BSSID : %02x:%02x:%02x:%02x:%02x:%02x", bssid_len, - bssid_for_connect[0], bssid_for_connect[1], bssid_for_connect[2], - bssid_for_connect[3], bssid_for_connect[4], bssid_for_connect[5]); + DBG("SET BSSID len: %d, BSSID: %02x:%02x:%02x:%02x:%02x:%02x ifname: %s", + bssid_len, + bssid_data[0], bssid_data[1], bssid_data[2], + bssid_data[3], bssid_data[4], bssid_data[5], + ifname); + + bssid_info->ifname = g_strdup(ifname); + bssid_list = g_slist_prepend(bssid_list, bssid_info); return bssid_len; } @@ -1062,7 +1171,7 @@ static DBusMessage *set_property(DBusConnection *conn, dbus_message_iter_get_basic(&value, &key); DBG("BSSID %s", key); - set_connman_bssid(SET_BSSID, key); + set_connman_bssid(SET_BSSID, key, NULL); #endif } else return __connman_error_invalid_property(msg); @@ -1077,8 +1186,12 @@ static void reply_scan_pending(struct connman_technology *technology, int err) DBG("technology %p err %d", technology, err); while (technology->scan_pending) { +#if defined TIZEN_EXT + struct connman_scan_pending *pending_data = technology->scan_pending->data; + DBusMessage *msg = pending_data->msg; +#else DBusMessage *msg = technology->scan_pending->data; - +#endif DBG("reply to %s", dbus_message_get_sender(msg)); if (err == 0) @@ -1091,6 +1204,10 @@ static void reply_scan_pending(struct connman_technology *technology, int err) technology->scan_pending = g_slist_delete_link(technology->scan_pending, technology->scan_pending); +#if defined TIZEN_EXT + g_free(pending_data->ifname); + g_free(pending_data); +#endif } } @@ -1108,7 +1225,10 @@ dbus_bool_t __connman_technology_notify_scan_changed(const char *key, void *val) return result; dbus_message_iter_init_append(signal, &iter); - connman_dbus_property_append_basic(&iter, key, DBUS_TYPE_BOOLEAN, val); + if (key) + connman_dbus_property_append_basic(&iter, key, DBUS_TYPE_BOOLEAN, val); + else + connman_dbus_property_append_basic(&iter, "", DBUS_TYPE_BOOLEAN, val); result = dbus_connection_send(connection, signal, NULL); dbus_message_unref(signal); @@ -1118,7 +1238,7 @@ dbus_bool_t __connman_technology_notify_scan_changed(const char *key, void *val) return result; } -void __connman_technology_notify_scan_done(int val) +void __connman_technology_notify_scan_done(const char *ifname, int val) { DBG(""); DBusMessage *signal; @@ -1130,13 +1250,88 @@ void __connman_technology_notify_scan_done(int val) return; dbus_message_iter_init_append(signal, &iter); - connman_dbus_property_append_basic(&iter, "Scantype", - DBUS_TYPE_INT32, &val); + if (ifname) + connman_dbus_property_append_basic(&iter, ifname, + DBUS_TYPE_INT32, &val); + else + connman_dbus_property_append_basic(&iter, "", + DBUS_TYPE_INT32, &val); dbus_connection_send(connection, signal, NULL); dbus_message_unref(signal); - DBG("Successfuly sent signal"); + DBG("Successfuly sent ScanDone signal"); +} + +static void reply_scan_pending_device( + struct connman_technology *technology, const char *ifname, int count) +{ + DBusMessage *reply; + GSList *list; + dbus_bool_t status = 0; + connman_scan_type_e scan_type = CONNMAN_SCAN_TYPE_UNKNOWN; + + DBG("technology %p ifname %d count %d", technology, ifname, count); + + list = technology->scan_pending; + + while (list) { + struct connman_scan_pending *pending_data = list->data; + DBusMessage *msg = pending_data->msg; + list = list->next; + + if (scan_type == CONNMAN_SCAN_TYPE_UNKNOWN) + scan_type = pending_data->scan_type; + + if (count != 0 && g_strcmp0(pending_data->ifname, ifname) != 0) + continue; + + scan_type = pending_data->scan_type; + + DBG("reply to %s", dbus_message_get_sender(msg)); + reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID); + + g_dbus_send_message(connection, reply); + dbus_message_unref(msg); + + technology->scan_pending = + g_slist_remove(technology->scan_pending, pending_data); + + g_free(pending_data->ifname); + g_free(pending_data); + } + + if (scan_type == CONNMAN_SCAN_TYPE_UNKNOWN) + scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL; + + __connman_technology_notify_scan_changed(ifname, &status); + __connman_technology_notify_scan_done(ifname, scan_type); +} + +static void __connman_technology_notify_device_detected( + struct connman_technology *technology, const char *ifname, bool val) +{ + DBG(""); + DBusMessage *signal; + DBusMessageIter iter; + dbus_bool_t detected = val; + + if (!ifname) + return; + + signal = dbus_message_new_signal(technology->path, + CONNMAN_TECHNOLOGY_INTERFACE, "DeviceDetected"); + if (!signal) + return; + + dbus_message_iter_init_append(signal, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &ifname); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &detected); + + dbus_connection_send(connection, signal, NULL); + dbus_message_unref(signal); + + DBG("Successfuly sent DeviceDetected signal"); } #endif @@ -1145,7 +1340,9 @@ void __connman_technology_scan_started(struct connman_device *device) DBG("device %p", device); #if defined TIZEN_EXT dbus_bool_t status = 1; - __connman_technology_notify_scan_changed("scan_started", &status); + const char *ifname = connman_device_get_string(device, "Interface"); + + __connman_technology_notify_scan_changed(ifname, &status); #endif } @@ -1174,19 +1371,13 @@ void __connman_technology_scan_stopped(struct connman_device *device, } #if defined TIZEN_EXT - if (count == 0) { - dbus_bool_t status = 0; - - __connman_technology_notify_scan_changed("scan_done", &status); - __connman_technology_notify_scan_done((int)g_scan_type); - reply_scan_pending(technology, 0); + const char *ifname = connman_device_get_string(device, "Interface"); + reply_scan_pending_device(technology, ifname, count); - DBG("Successfuly sent ScanDone signal"); - } -#else + return; +#endif if (count == 0) reply_scan_pending(technology, 0); -#endif } void __connman_technology_notify_regdom_by_device(struct connman_device *device, @@ -1237,8 +1428,8 @@ static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data) !technology->enabled) return __connman_error_permission_denied(msg); - dbus_message_ref(msg); #if !defined TIZEN_EXT + dbus_message_ref(msg); technology->scan_pending = g_slist_prepend(technology->scan_pending, msg); #endif @@ -1252,17 +1443,71 @@ static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data) #endif #if defined TIZEN_EXT - if (err == 0) { - g_scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL; - DBG("g_scan_type %d", g_scan_type); - } + struct connman_scan_pending *pending_data = + g_try_malloc0(sizeof(struct connman_scan_pending)); + if (!pending_data) + return __connman_error_failed(msg, ENOMEM); + + pending_data->scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL; + DBG("scan_type %d", pending_data->scan_type); + + pending_data->msg = dbus_message_ref(msg); + technology->scan_pending = - g_slist_prepend(technology->scan_pending, msg); + g_slist_prepend(technology->scan_pending, pending_data); #endif return NULL; } #if defined TIZEN_EXT +static DBusMessage *scan_device(DBusConnection *conn, DBusMessage *msg, void *data) +{ + struct connman_technology *technology = data; + DBusMessageIter iter; + const char *ifname; + int err; + + DBG("technology %p request from %s", technology, + dbus_message_get_sender(msg)); + + if (!dbus_message_iter_init(msg, &iter)) + return __connman_error_invalid_arguments(msg); + + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_get_basic(&iter, &ifname); + DBG("Interface name %s", ifname); + + if (!ifname || strlen(ifname) == 0) + return __connman_error_invalid_arguments(msg); + + err = connman_device_request_device_scan(technology->type, ifname, true); + if (err < 0) + return __connman_error_failed(msg, -err); + + struct connman_scan_pending *pending_data = + g_try_malloc0(sizeof(struct connman_scan_pending)); + if (!pending_data) + return __connman_error_failed(msg, ENOMEM); + + pending_data->ifname = g_strdup(ifname); + if (pending_data->ifname == NULL) { + g_free(pending_data); + return __connman_error_failed(msg, ENOMEM); + } + + pending_data->scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL; + DBG("scan_type %d", pending_data->scan_type); + + pending_data->msg = dbus_message_ref(msg); + + technology->scan_pending = + g_slist_prepend(technology->scan_pending, pending_data); + + return NULL; +} + static DBusMessage *specific_scan(DBusConnection *conn, DBusMessage *msg, void *data) { struct connman_technology *technology = data; @@ -1270,6 +1515,7 @@ static DBusMessage *specific_scan(DBusConnection *conn, DBusMessage *msg, void * int scan_type = 0; const char *name = NULL; const char *freq = NULL; + const char *ifname = NULL; DBusMessageIter iter, dict; int err; @@ -1304,7 +1550,11 @@ static DBusMessage *specific_scan(DBusConnection *conn, DBusMessage *msg, void * dbus_message_iter_recurse(&entry, &value2); type = dbus_message_iter_get_arg_type(&value2); - if (g_str_equal(key, "SSID")) { + if (g_str_equal(key, "Ifname") && type == DBUS_TYPE_STRING) { + + dbus_message_iter_get_basic(&value2, &ifname); + DBG("ifname %s", ifname); + } else if (g_str_equal(key, "SSID")) { if (type != DBUS_TYPE_STRING) { g_slist_free_full(specific_scan_list, g_free); return __connman_error_invalid_arguments(msg); @@ -1333,7 +1583,8 @@ static DBusMessage *specific_scan(DBusConnection *conn, DBusMessage *msg, void * scan_type = CONNMAN_MULTI_SCAN_SSID_FREQ; /* SSID & Frequency mixed scan */ dbus_message_iter_get_basic(&value2, &name); - connman_multi_scan_ap_s *ap = (connman_multi_scan_ap_s*)g_try_malloc0(sizeof(connman_multi_scan_ap_s)); + connman_multi_scan_ap_s *ap = + (connman_multi_scan_ap_s*)g_try_malloc0(sizeof(connman_multi_scan_ap_s)); if (ap) { g_strlcpy(ap->str, name, strlen(name) + 1); ap->flag = true; @@ -1350,7 +1601,8 @@ static DBusMessage *specific_scan(DBusConnection *conn, DBusMessage *msg, void * scan_type = CONNMAN_MULTI_SCAN_SSID_FREQ; /* SSID & Frequency mixed scan */ dbus_message_iter_get_basic(&value2, &freq); - connman_multi_scan_ap_s *ap = (connman_multi_scan_ap_s*)g_try_malloc0(sizeof(connman_multi_scan_ap_s)); + connman_multi_scan_ap_s *ap = + (connman_multi_scan_ap_s*)g_try_malloc0(sizeof(connman_multi_scan_ap_s)); if (ap) { g_strlcpy(ap->str, freq, strlen(freq) + 1); ap->flag = false; @@ -1361,38 +1613,51 @@ static DBusMessage *specific_scan(DBusConnection *conn, DBusMessage *msg, void * dbus_message_iter_next(&dict); } - dbus_message_ref(msg); - - err = __connman_device_request_specific_scan(technology->type, scan_type, specific_scan_list); + err = __connman_device_request_specific_scan(technology->type, ifname, scan_type, specific_scan_list); if (err < 0) return __connman_error_failed(msg, -err); - if (err == 0) { - guint list_size = g_slist_length(specific_scan_list); - if (list_size == 1) - g_scan_type = CONNMAN_SCAN_TYPE_SPECIFIC_AP; - else - g_scan_type = CONNMAN_SCAN_TYPE_MULTI_AP; - DBG("list_size %u g_scan_type %d", list_size, g_scan_type); - } - technology->scan_pending = - g_slist_prepend(technology->scan_pending, msg); + guint list_size = g_slist_length(specific_scan_list); if (scan_type == CONNMAN_MULTI_SCAN_SSID || - scan_type == CONNMAN_MULTI_SCAN_SSID_FREQ) { + scan_type == CONNMAN_MULTI_SCAN_SSID_FREQ) g_slist_free_full(specific_scan_list, g_free); - scan_type = 0; + + struct connman_scan_pending *pending_data = + g_try_malloc0(sizeof(struct connman_scan_pending)); + if (!pending_data) + return __connman_error_failed(msg, ENOMEM); + + if (ifname) { + pending_data->ifname = g_strdup(ifname); + if (pending_data->ifname == NULL) { + g_free(pending_data); + return __connman_error_failed(msg, ENOMEM); + } } + + if (list_size == 1) + pending_data->scan_type = CONNMAN_SCAN_TYPE_SPECIFIC_AP; + else + pending_data->scan_type = CONNMAN_SCAN_TYPE_MULTI_AP; + DBG("list_size %u scan_type %d", list_size, pending_data->scan_type); + + pending_data->msg = dbus_message_ref(msg); + + technology->scan_pending = + g_slist_prepend(technology->scan_pending, pending_data); + return NULL; } -#if defined TIZEN_EXT static DBusMessage *get_5ghz_supported(DBusConnection *conn, DBusMessage *msg, void *data) { DBusMessage *reply; DBusMessageIter iter, dict; + GSList *list; struct connman_technology *technology = data; - dbus_bool_t supported = technology->is_5_0_ghz_supported; + dbus_bool_t supported = false; + const char *ifname = NULL; DBG("technology %p", technology); @@ -1401,17 +1666,24 @@ static DBusMessage *get_5ghz_supported(DBusConnection *conn, DBusMessage *msg, v return NULL; dbus_message_iter_init_append(reply, &iter); - connman_dbus_dict_open(&iter, &dict); - connman_dbus_dict_append_basic(&dict, "Is5GhzSupported", - DBUS_TYPE_BOOLEAN, - &supported); + + for (list = technology->device_list; list; list = list->next) { + struct connman_device *device = list->data; + + supported = connman_device_get_wifi_5ghz_supported(device); + ifname = connman_device_get_string(device, "Interface"); + + DBG("ifname %s supported : %d", ifname, supported); + connman_dbus_dict_append_basic(&dict, ifname, + DBUS_TYPE_BOOLEAN, + &supported); + } connman_dbus_dict_close(&iter, &dict); return reply; } -#endif static DBusMessage *get_scan_state(DBusConnection *conn, DBusMessage *msg, void *data) { @@ -1420,47 +1692,76 @@ static DBusMessage *get_scan_state(DBusConnection *conn, DBusMessage *msg, void GSList *list; struct connman_technology *technology = data; dbus_bool_t scanning = false; + const char *ifname = NULL; DBG("technology %p", technology); + reply = dbus_message_new_method_return(msg); + if (!reply) + return NULL; + + dbus_message_iter_init_append(reply, &iter); + connman_dbus_dict_open(&iter, &dict); + for (list = technology->device_list; list; list = list->next) { struct connman_device *device = list->data; - scanning = connman_device_get_scanning(device, - connman_device_get_type(device)); - if(scanning) - break; + + scanning = connman_device_get_scanning(device, technology->type); + ifname = connman_device_get_string(device, "Interface"); + + DBG("ifname %s scanning : %d", ifname, scanning); + connman_dbus_dict_append_basic(&dict, ifname, + DBUS_TYPE_BOOLEAN, + &scanning); } - DBG("scanning : %d", scanning); + connman_dbus_dict_close(&iter, &dict); + + return reply; +} + +static DBusMessage *get_max_scan_ssid(DBusConnection *conn, DBusMessage *msg, void *data) +{ + DBusMessage *reply; + DBusMessageIter iter, dict; + GSList *list; + struct connman_technology *technology = data; + dbus_int32_t max_scan_ssids = 0; + const char *ifname = NULL; + + DBG("technology %p", technology); + reply = dbus_message_new_method_return(msg); if (!reply) return NULL; dbus_message_iter_init_append(reply, &iter); - connman_dbus_dict_open(&iter, &dict); - connman_dbus_dict_append_basic(&dict, "Scanstate", - DBUS_TYPE_BOOLEAN, - &scanning); + + for (list = technology->device_list; list; list = list->next) { + struct connman_device *device = list->data; + + max_scan_ssids = connman_device_get_max_scan_ssids(device); + ifname = connman_device_get_string(device, "Interface"); + + DBG("ifname %s max_scan_ssids : %d", ifname, max_scan_ssids); + connman_dbus_dict_append_basic(&dict, ifname, + DBUS_TYPE_INT32, + &max_scan_ssids); + } connman_dbus_dict_close(&iter, &dict); return reply; } -void connman_techonology_set_max_scan_ssids(struct connman_technology *technology, - int max_scan_ssids) -{ - DBG(""); - technology->max_scan_ssids = max_scan_ssids; -} - -static DBusMessage *get_max_scan_ssid(DBusConnection *conn, DBusMessage *msg, void *data) +static DBusMessage *get_interfaces(DBusConnection *conn, DBusMessage *msg, void *data) { DBusMessage *reply; - DBusMessageIter iter, dict; + DBusMessageIter iter, array; + GSList *list; struct connman_technology *technology = data; - dbus_int32_t max_scan_ssids = technology->max_scan_ssids; + const char *default_interface = connman_option_get_string("DefaultWifiInterface"); DBG("technology %p", technology); @@ -1468,17 +1769,242 @@ static DBusMessage *get_max_scan_ssid(DBusConnection *conn, DBusMessage *msg, vo if (!reply) return NULL; + if (technology->type != CONNMAN_SERVICE_TYPE_WIFI) + return NULL; + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, + DBUS_TYPE_STRING_AS_STRING, &array); - connman_dbus_dict_open(&iter, &dict); - connman_dbus_dict_append_basic(&dict, "MaxScanSSID", - DBUS_TYPE_INT32, - &max_scan_ssids); + dbus_message_iter_append_basic(&array, + DBUS_TYPE_STRING, &default_interface); - connman_dbus_dict_close(&iter, &dict); + for (list = technology->device_list; list; list = list->next) { + struct connman_device *device = list->data; + const char *str = connman_device_get_string(device, "Interface"); + if (g_strcmp0(default_interface, str) == 0) + continue; + + dbus_message_iter_append_basic(&array, + DBUS_TYPE_STRING, &str); + } + + dbus_message_iter_close_container(&iter, &array); return reply; } + +static int technology_enable_device(struct connman_technology *technology, + bool enable_device, const char *ifname, struct connman_device **device_out) +{ + int err = 0; + GSList *list; + + for (list = technology->device_list; list; list = list->next) { + struct connman_device *device = list->data; + const char *str = connman_device_get_string(device, "Interface"); + + if (g_strcmp0(str, ifname) != 0) + continue; + + if (enable_device) + err = __connman_device_enable(device); + else + err = __connman_device_disable(device); + + *device_out = device; + return err; + } + + return -ENXIO; +} + +static DBusMessage *technology_set_device_powered(struct connman_technology *technology, + DBusMessage *msg, bool powered, const char *ifname) +{ + DBusMessage *reply = NULL; + struct connman_device *device = NULL; + int err = 0; + + err = technology_enable_device(technology, powered, ifname, &device); + + if (err == -EINPROGRESS) { + if (device) + connman_device_set_pending_reply(device, msg); + return reply; + } else if (err == -EALREADY) { + if (powered) + reply = __connman_error_already_enabled(msg); + else + reply = __connman_error_already_disabled(msg); + } else if (err < 0) + reply = __connman_error_failed(msg, -err); + else + reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID); + + return reply; +} + +static DBusMessage *set_device_power(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + struct connman_technology *technology = data; + DBusMessageIter iter; + const char *name; + int len; + dbus_bool_t enable; + + DBG("conn %p", conn); + + if (!dbus_message_iter_init(msg, &iter)) + return __connman_error_invalid_arguments(msg); + + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_get_basic(&iter, &name); + dbus_message_iter_next(&iter); + + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN) + return __connman_error_invalid_arguments(msg); + + DBG("interface name %s", name); + + len = strlen(name); + + if (len + 1 > IFNAMSIZ) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_get_basic(&iter, &enable); + DBG("powered %s", enable ? "TRUE" : "FALSE"); + + return technology_set_device_powered(technology, msg, enable, name); +} + +static DBusMessage *set_bssid(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + DBusMessageIter iter; + char *name, *bssid; + int len; + + DBG("conn %p", conn); + + if (!dbus_message_iter_init(msg, &iter)) + return __connman_error_invalid_arguments(msg); + + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_get_basic(&iter, &name); + dbus_message_iter_next(&iter); + + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_get_basic(&iter, &bssid); + + DBG("interface name %s bssid %s", name, bssid); + + len = strlen(name); + + if (len + 1 > IFNAMSIZ) + return __connman_error_invalid_arguments(msg); + + set_connman_bssid(SET_BSSID, bssid, name); + + return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); +} +static struct connman_technology *technology_get(enum connman_service_type type); + +void technology_save_device(struct connman_device *device) +{ + struct connman_technology *technology; + enum connman_service_type type; + + type = __connman_device_get_service_type(device); + technology = technology_get(type); + if (!technology) + return; + + GKeyFile *keyfile; + gchar *identifier; + const char *name = get_name(technology->type); + + DBG("technology %p type %d name %s", technology, technology->type, + name); + if (!name) + return; + + keyfile = __connman_storage_load_global(); + if (!keyfile) + keyfile = g_key_file_new(); + + identifier = g_strdup_printf("%s", name); + if (!identifier) + goto done; + + GSList *list = NULL; + gchar **ifname_list = NULL; + guint dev_count = g_slist_length(technology->device_list); + + if (dev_count > 1) { + GString *ifname_str = g_string_new(NULL); + + if (ifname_str) { + for (list = technology->device_list; list; list = list->next) { + struct connman_device *device = list->data; + + if (connman_device_get_powered(device)) { + const char *ifname = connman_device_get_string(device, "Interface"); + + if (ifname_str->len > 0) + g_string_append_printf(ifname_str, " %s", ifname); + else + g_string_append(ifname_str, ifname); + } + } + + if (ifname_str->len > 0) { + ifname_list = g_strsplit_set(ifname_str->str, " ", 0); + dev_count = g_strv_length(ifname_list); + g_key_file_set_string_list(keyfile, identifier, "Enable.Devices", + (const gchar **) ifname_list, dev_count); + + technology->enable_persistent = true; + } else { + g_key_file_remove_key(keyfile, identifier, "Enable.Devices", NULL); + technology->enable_persistent = false; + } + + g_strfreev(ifname_list); + g_string_free(ifname_str, TRUE); + } + } + + g_key_file_set_boolean(keyfile, identifier, "Enable", + technology->enable_persistent); + + g_key_file_set_boolean(keyfile, identifier, "Tethering", + technology->tethering_persistent); + + if (technology->tethering_ident) + g_key_file_set_string(keyfile, identifier, + "Tethering.Identifier", + technology->tethering_ident); + + if (technology->tethering_passphrase) + g_key_file_set_string(keyfile, identifier, + "Tethering.Passphrase", + technology->tethering_passphrase); + +done: + g_free(identifier); + + __connman_storage_save_global(keyfile); + + g_key_file_free(keyfile); +} #endif #if defined TIZEN_EXT_WIFI_MESH @@ -1873,9 +2399,15 @@ static DBusMessage *mesh_commands(DBusConnection *conn, DBG("MeshID %s Frequency %d sender %s", name, freq, dbus_message_get_sender(msg)); - dbus_message_ref(msg); + struct connman_scan_pending *pending_data = + g_try_malloc0(sizeof(struct connman_scan_pending)); + if (!pending_data) + return __connman_error_failed(msg, ENOMEM); + + pending_data->msg = dbus_message_ref(msg); + technology->scan_pending = - g_slist_prepend(technology->scan_pending, msg); + g_slist_prepend(technology->scan_pending, pending_data); err = __connman_device_request_mesh_specific_scan(technology->type, name, freq); @@ -1955,6 +2487,8 @@ static const GDBusMethodTable technology_methods[] = { NULL, set_property) }, { GDBUS_ASYNC_METHOD("Scan", NULL, NULL, scan) }, #if defined TIZEN_EXT + { GDBUS_ASYNC_METHOD("ScanDevice", GDBUS_ARGS({ "interface_name", "s" }), + NULL, scan_device) }, { GDBUS_ASYNC_METHOD("SpecificScan", GDBUS_ARGS({ "specificscan", "a{sv}" }), NULL, specific_scan) }, { GDBUS_METHOD("GetScanState", NULL, GDBUS_ARGS({ "scan_state", "a{sv}" }), @@ -1963,6 +2497,14 @@ static const GDBusMethodTable technology_methods[] = { get_5ghz_supported) }, { GDBUS_METHOD("GetMaxScanSsid", NULL, GDBUS_ARGS({ "maxscanssid", "a{sv}" }), get_max_scan_ssid) }, + { GDBUS_METHOD("GetInterfaces", NULL, GDBUS_ARGS({ "interface_list", "as" }), + get_interfaces) }, + { GDBUS_ASYNC_METHOD("SetDevicePower", + GDBUS_ARGS({ "ifname", "s" }, { "value", "b" }), + NULL, set_device_power) }, + { GDBUS_ASYNC_METHOD("SetBSSID", + GDBUS_ARGS({ "ifname", "s" }, { "bssid", "s" }), + NULL, set_bssid) }, #endif #if defined TIZEN_EXT_WIFI_MESH { GDBUS_ASYNC_METHOD("MeshCommands", @@ -1975,6 +2517,12 @@ static const GDBusMethodTable technology_methods[] = { static const GDBusSignalTable technology_signals[] = { { GDBUS_SIGNAL("PropertyChanged", GDBUS_ARGS({ "name", "s" }, { "value", "v" })) }, +#if defined TIZEN_EXT + { GDBUS_SIGNAL("DeviceChanged", + GDBUS_ARGS({ "device_property", "a{sv}" })) }, + { GDBUS_SIGNAL("DeviceDetected", + GDBUS_ARGS({ "ifname", "s" }, { "detected", "b" })) }, +#endif { }, }; @@ -2045,7 +2593,9 @@ static void technology_put(struct connman_technology *technology) g_source_remove(technology->pending_timeout); technology->pending_timeout = 0; } - +#ifdef TIZEN_EXT + g_strfreev(technology->enabled_devices); +#endif g_free(technology->path); g_free(technology->regdom); g_free(technology->tethering_ident); @@ -2377,7 +2927,28 @@ int __connman_technology_add_device(struct connman_device *device) if (technology->enable_persistent && !global_offlinemode) { +#if defined TIZEN_EXT + bool found = true; + int err = 0; + if (technology->enabled_devices) { + int i = 0; + found = false; + const char *ifname = connman_device_get_string(device, "Interface"); + + while (technology->enabled_devices[i]) { + if (g_strcmp0(technology->enabled_devices[i], ifname) == 0) { + found = true; + break; + } + i++; + } + } + + if (found) + err = __connman_device_enable(device); +#else int err = __connman_device_enable(device); +#endif /* * connman_technology_add_device() calls __connman_device_enable() * but since the device is already enabled, the call does not @@ -2395,6 +2966,10 @@ done: technology->device_list = g_slist_prepend(technology->device_list, device); +#if defined TIZEN_EXT + const char *ifname = connman_device_get_string(device, "Interface"); + __connman_technology_notify_device_detected(technology, ifname, true); +#endif return 0; } @@ -2417,6 +2992,11 @@ int __connman_technology_remove_device(struct connman_device *device) technology->device_list = g_slist_remove(technology->device_list, device); +#if defined TIZEN_EXT + const char *ifname = connman_device_get_string(device, "Interface"); + __connman_technology_notify_device_detected(technology, ifname, false); +#endif + if (technology->tethering) set_tethering(technology, false); -- cgit v1.2.3