/*
* Network Configuration Module
*
- * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
*/
+#include <stdio.h>
#include <string.h>
+#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include "log.h"
#include "util.h"
#include "netdbus.h"
+#include "wifi-state.h"
+#include "network-state.h"
+#include "network-statistics.h"
#include "netsupplicant.h"
#include "wifi-indicator.h"
#define VCONFKEY_WIFI_SNR_MIN -89
-#define NETCONFIG_WIFI_INDICATOR_INTERVAL 3
+#if !defined TIZEN_WEARABLE
+#define WIFI_INDICATOR_INTERVAL 2
+#else
+#define WIFI_INDICATOR_INTERVAL 10
+#endif
+
+#if defined TIZEN_WEARABLE
+#define NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL1 (19200 * 1024)
+#define NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL2 (2560 * 1024)
+#define NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL3 (1536 * 1024)
+#else
+#define NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL1 (19200 * 1024)
+#define NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL2 (7680 * 1024)
+#define NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL3 (3840 * 1024)
+#endif
+#define NETCONFIG_PROCWIRELESS "/proc/net/wireless"
+
+typedef struct {
+ char *interface_name;
+ char *default_path;
+ int last_snr_level;
+} rssi_data_s;
-static guint netconfig_wifi_indicator_timer = 0;
+static GSList *g_rssi_list = NULL;
+static guint netconfig_wifi_statistics_timer = 0;
-#if defined NL80211
-static int __netconfig_wifi_get_signal(const char *object_path)
+static rssi_data_s *__create_rssi_data(const char *interface_name)
{
- DBusConnection *connection = NULL;
- DBusMessage *message = NULL;
- DBusMessageIter iter;
- int rssi_dbm = 0;
- int MessageType = 0;
-
- if (object_path == NULL) {
- ERR("Error!!! path is NULL");
- goto error;
+ rssi_data_s *rssi_data = g_try_malloc0(sizeof(rssi_data_s));
+ if (!rssi_data) {
+ ERR("Memory allocation failed");
+ return NULL;
}
- connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
- if (connection == NULL) {
- ERR("Error!!! Failed to get system DBus");
- goto error;
- }
+ rssi_data->interface_name = g_strdup(interface_name);
- message = netconfig_supplicant_invoke_dbus_method(
- SUPPLICANT_SERVICE, connection, object_path,
- SUPPLICANT_INTERFACE ".Interface", "GetLinkSignal",
- NULL);
+ g_rssi_list = g_slist_append(g_rssi_list, rssi_data);
- if (message == NULL) {
- ERR("Error!!! Failed to get service properties");
- goto error;
- }
+ return rssi_data;
+}
- MessageType = dbus_message_get_type(message);
+static rssi_data_s *__get_rssi_data(const char *interface_name)
+{
+ GSList *list;
+ rssi_data_s *rssi_data = NULL;
- if (MessageType == DBUS_MESSAGE_TYPE_ERROR) {
- const char *err_msg = dbus_message_get_error_name(message);
- ERR("Error!!! Error message received [%s]", err_msg);
- goto error;
+ for (list = g_rssi_list; list; list = list->next) {
+ rssi_data = list->data;
+ if (g_strcmp0(rssi_data->interface_name, interface_name) == 0)
+ return rssi_data;
}
- dbus_message_iter_init(message, &iter);
-
- if ((MessageType = dbus_message_iter_get_arg_type(&iter)) == DBUS_TYPE_INT32)
- dbus_message_iter_get_basic(&iter, &rssi_dbm);
- else
- goto error;
+ return rssi_data;
+}
- dbus_message_unref(message);
- dbus_connection_unref(connection);
+static void __set_rssi_data_default_path(const char *interface_name,
+ const char *path)
+{
+ rssi_data_s *rssi_data = __get_rssi_data(interface_name);
+ if (rssi_data == NULL)
+ return;
- return rssi_dbm;
+ rssi_data->default_path = g_strdup(path);
+}
-error:
- if (message != NULL)
- dbus_message_unref(message);
+static void __destroy_rssi_data(const char *interface_name)
+{
+ rssi_data_s *rssi_data = __get_rssi_data(interface_name);
- if (connection != NULL)
- dbus_connection_unref(connection);
+ if (!rssi_data)
+ return;
- return VCONFKEY_WIFI_SNR_MIN;
+ g_rssi_list = g_slist_remove(g_rssi_list, rssi_data);
+ g_free(rssi_data->interface_name);
+ g_free(rssi_data->default_path);
+ g_free(rssi_data);
}
-static int __netconfig_wifi_get_rssi_from_supplicant(void)
+static int __netconfig_wifi_convert_dbm_to_level_24(int rssi_dbm)
{
- int rssi_dbm =0;
+ int rssi_level = 0;
- char object_path[DBUS_PATH_MAX_BUFLEN] = { 0, };
- char *path_ptr = &object_path[0];
-
- if (netconfig_wifi_get_supplicant_interface(&path_ptr) != TRUE) {
- DBG("Fail to get wpa_supplicant DBus path");
- return VCONFKEY_WIFI_SNR_MIN;
- }
+ /* Wi-Fi Signal Strength Display (for 2.4G (dB))
+ *
+ * Excellent : ~ -63
+ * Good : -64 ~ -74
+ * Weak : -75 ~ -82
+ * Very weak : -83 ~ -88
+ * No signal : -89 ~
+ */
- rssi_dbm = __netconfig_wifi_get_signal((const char *)path_ptr);
+ if (rssi_dbm >= -63)
+ rssi_level = 4;
+ else if (rssi_dbm >= -74)
+ rssi_level = 3;
+ else if (rssi_dbm >= -82)
+ rssi_level = 2;
+ else if (rssi_dbm >= -88)
+ rssi_level = 1;
+ else
+ rssi_level = 0;
- return rssi_dbm;
+ return rssi_level;
}
-#endif /* #if defined NL80211 */
-#if !defined NL80211
-static int __netconfig_wifi_get_rssi_from_system(void)
+static int __netconfig_wifi_convert_dbm_to_level_50(int rssi_dbm)
{
- int rssi_dbm = 0;
- char ifname[16] = { 0, };
- char *ifname_ptr = &ifname[0];
-
- int fd = -1;
- struct iwreq wifi_req;
- struct iw_statistics stats;
- unsigned int iw_stats_len = sizeof(struct iw_statistics);
-
- if (netconfig_wifi_get_ifname(&ifname_ptr) != TRUE) {
- DBG("Fail to get Wi-Fi ifname from wpa_supplicant: %s", ifname_ptr);
- return VCONFKEY_WIFI_SNR_MIN;
- }
-
- /* Set device name */
- memset(wifi_req.ifr_name, 0, sizeof(wifi_req.ifr_name));
- strncpy(wifi_req.ifr_name, ifname, sizeof(wifi_req.ifr_name) - 1);
- wifi_req.ifr_name[sizeof(wifi_req.ifr_name) - 1] = '\0';
+ int rssi_level = 0;
- wifi_req.u.data.pointer = (caddr_t) &stats;
- wifi_req.u.data.length = iw_stats_len;
- wifi_req.u.data.flags = 1; /* Clear updated flag */
+ /* Wi-Fi Signal Strength Display (for 5G (dB))
+ *
+ * Excellent : ~ -67
+ * Good : -68 ~ -76
+ * Weak : -77 ~ -82
+ * Very weak : -83 ~ -88
+ * No signal : -89 ~
+ */
- if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0) {
- DBG("Fail to open socket to get rssi");
- return VCONFKEY_WIFI_SNR_MIN;
- }
+ if (rssi_dbm >= -67)
+ rssi_level = 4;
+ else if (rssi_dbm >= -76)
+ rssi_level = 3;
+ else if (rssi_dbm >= -82)
+ rssi_level = 2;
+ else if (rssi_dbm >= -88)
+ rssi_level = 1;
+ else
+ rssi_level = 0;
- memset(&stats, 0, iw_stats_len);
+ return rssi_level;
+}
- if (ioctl(fd, SIOCGIWSTATS, &wifi_req) < 0) {
- DBG("Fail to execute ioctl for SIOCGIWSTATS");
- close(fd);
+static int __netconfig_wifi_get_rssi_level(const int rssi_dbm)
+{
+ int snr_level = 0;
+ int freq = 0;
+ int ret = 0;
- return VCONFKEY_WIFI_SNR_MIN;
- }
- close(fd);
+ ret = netconfig_vconf_get_int("memory/private/wifi/frequency", &freq);
- rssi_dbm = stats.qual.level - 255; /** signed integer, so 255 */
+ if (!ret && freq > 4900)
+ snr_level = __netconfig_wifi_convert_dbm_to_level_50(rssi_dbm);
+ else
+ snr_level = __netconfig_wifi_convert_dbm_to_level_24(rssi_dbm);
- return rssi_dbm;
+ return snr_level;
}
-#endif /* #if !defined NL80211 */
-int netconfig_wifi_get_rssi(void)
+static void __netconfig_wifi_set_rssi_level(const char *interface_name,
+ const char *path, const int snr_level)
{
- int rssi_dbm = 0;
-
- /* There are two ways to get Wi-Fi RSSI:
- * - WEXT interface, get DBus path of wpa_supplicant,
- * and get Wi-Fi interface name e.g. wlan0 from wpa_supplicant.
- * IOCTL with ifname will return RSSI dB.
- * - NL80211 interface, get DBus path of wpa_supplicant,
- * and get RSSI from wpa_supplicant directly.
- * However, in this case wpa_supplicant needs some modification
- * to get RSSI from DBus interface. */
-
-#if defined NL80211
- rssi_dbm = __netconfig_wifi_get_rssi_from_supplicant();
-#else
- rssi_dbm = __netconfig_wifi_get_rssi_from_system();
-#endif
+ rssi_data_s *rssi_data = NULL;
+ const char *default_ifname = NULL;
+
+ rssi_data = __get_rssi_data(interface_name);
+ if (rssi_data == NULL)
+ return;
+
+ if (snr_level != rssi_data->last_snr_level) {
+ default_ifname = netconfig_get_default_ifname();
+ if (g_strcmp0(default_ifname, interface_name) == 0)
+ netconfig_set_vconf_int(VCONFKEY_WIFI_STRENGTH, snr_level, FALSE);
+
+ if (g_strcmp0(rssi_data->default_path, path) == 0) {
+ wifi_emit_rssi_changed((Wifi *)get_wifi_object(), interface_name, snr_level);
+
+ netconfig_battery_update_wifi_rssi(snr_level);
- return rssi_dbm;
+ rssi_data->last_snr_level = snr_level;
+ }
+ }
}
-static void __netconfig_wifi_set_rssi_level(int rssi_dbm)
+static void __netconfig_wifi_data_activity_booster(int level)
{
- int snr_level = 0;
- static int last_snr_level = 0;
+ gboolean reply = FALSE;
+ GVariant *params = NULL;
+ int level1 = 1;
+ int level2 = 2;
+ int level3 = 3;
+
+ int lock = 2000;
+ int unlock = 0;
+
+ static int old_level = 0;
+
+ if (level < 0)
+ return;
+
+ if (level > 0) {
+ /* enable booster */
+ switch (level) {
+ case 1:
+ params = g_variant_new("(ii)", level1, lock);
+ break;
+ case 2:
+ params = g_variant_new("(ii)", level2, lock);
+ break;
+ case 3:
+ params = g_variant_new("(ii)", level3, lock);
+ break;
+ default:
+ ERR("Invalid level");
+ return;
+ }
+
+ reply = netconfig_invoke_dbus_method_nonblock(
+ "org.tizen.system.deviced",
+ "/Org/Tizen/System/DeviceD/PmQos",
+ "org.tizen.system.deviced.PmQos",
+ "WifiThroughput",
+ params,
+ NULL,
+ NULL);
+ if (reply != TRUE)
+ return;
+ }
- /* Wi-Fi Signal Strength Display
- *
- * Excellent : -63 ~
- * Good: -74 ~ -64
- * Weak: -82 ~ -75
- * Very weak: ~ -83
- */
- if (rssi_dbm >= -63)
- snr_level = 4;
- else if (rssi_dbm >= -74)
- snr_level = 3;
- else if (rssi_dbm >= -82)
- snr_level = 2;
- else
- snr_level = 1;
+ /* disable previous booster */
+ if (old_level == 0 || old_level == level)
+ return;
+
+ switch (old_level) {
+ case 1:
+ params = g_variant_new("(ii)", level1, unlock);
+ break;
+ case 2:
+ params = g_variant_new("(ii)", level2, unlock);
+ break;
+ case 3:
+ params = g_variant_new("(ii)", level3, unlock);
+ break;
+ default:
+ ERR("Invalid level");
+ return;
+ }
- if (snr_level != last_snr_level) {
- INFO("Wi-Fi RSSI: %d dB, %d level", rssi_dbm, snr_level);
+ reply = netconfig_invoke_dbus_method_nonblock(
+ "org.tizen.system.deviced",
+ "/Org/Tizen/System/DeviceD/PmQos",
+ "org.tizen.system.deviced.PmQos",
+ "WifiThroughput",
+ params,
+ NULL,
+ NULL);
+ if (reply != TRUE)
+ return;
+
+ old_level = level;
+}
+
+static void __netconfig_wifi_get_statistics(void)
+{
+ static int last_transfer_state = 0;
+ static int booster_tic = 0;
+ static int old_level = 0;
+ int booster_level = 0;
+ guint64 tx, rx;
+ int transfer_state;
+
+ if (netconfig_wifi_get_bytes_statistics(&tx, &rx, TRUE))
+ netconfig_wifi_set_bytes_pkt_vconf(tx, rx, FALSE);
+
+ netconfig_wifi_get_bytes_default_iface(&tx, &rx);
+
+ if (tx > 0) {
+ if (rx > 0)
+ transfer_state = VCONFKEY_WIFI_TRANSFER_STATE_TXRX;
+ else
+ transfer_state = VCONFKEY_WIFI_TRANSFER_STATE_TX;
+ } else {
+ if (rx > 0)
+ transfer_state = VCONFKEY_WIFI_TRANSFER_STATE_RX;
+ else
+ transfer_state = VCONFKEY_WIFI_TRANSFER_STATE_NONE;
+ }
- vconf_set_int(VCONFKEY_WIFI_STRENGTH, snr_level);
+ if (transfer_state != last_transfer_state) {
+ netconfig_set_vconf_int(VCONFKEY_WIFI_TRANSFER_STATE, transfer_state, FALSE);
+ last_transfer_state = transfer_state;
+ }
- last_snr_level = snr_level;
+ /* NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER */
+ if (tx >= NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL1 ||
+ rx >= NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL1)
+ booster_level = 1;
+ else if (tx >= NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL2 ||
+ rx >= NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL2)
+ booster_level = 2;
+ else if (tx >= NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL3 ||
+ rx >= NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL3)
+ booster_level = 3;
+
+ if (old_level == booster_level) {
+ if (--booster_tic <= 0) {
+ __netconfig_wifi_data_activity_booster(booster_level);
+
+ booster_tic = 2;
+ }
+ } else {
+ __netconfig_wifi_data_activity_booster(booster_level);
+
+ if (booster_level > 0)
+ booster_tic = 2;
+ else
+ booster_tic = 0;
}
+
+ old_level = booster_level;
}
-static gboolean __netconfig_wifi_indicator_monitor(gpointer data)
+static gboolean __netconfig_wifi_update_statistics(gpointer data)
{
- int rssi_dbm = 0;
int pm_state = VCONFKEY_PM_STATE_NORMAL;
+ char *interface_name = data;
+
+ if (wifi_state_get_service_state(interface_name) != NETCONFIG_WIFI_CONNECTED) {
+ g_free(interface_name);
+ return FALSE;
+ }
/* In case of LCD off, we don't need to update Wi-Fi indicator */
- vconf_get_int(VCONFKEY_PM_STATE, &pm_state);
+ netconfig_vconf_get_int(VCONFKEY_PM_STATE, &pm_state);
if (pm_state >= VCONFKEY_PM_STATE_LCDOFF)
return TRUE;
- rssi_dbm = netconfig_wifi_get_rssi();
-
- __netconfig_wifi_set_rssi_level(rssi_dbm);
+ __netconfig_wifi_get_statistics();
return TRUE;
}
-void netconfig_wifi_indicator_start(void)
+void netconfig_wifi_indicator_update(const char *interface_name,
+ const char *path, int rssi_dbm)
{
+ int pm_state = VCONFKEY_PM_STATE_NORMAL;
+ int snr_level = 0;
+
+ /* In case of LCD off, we don't need to update Wi-Fi indicator */
+ netconfig_vconf_get_int(VCONFKEY_PM_STATE, &pm_state);
+ if (pm_state >= VCONFKEY_PM_STATE_LCDOFF)
+ return;
+
+ snr_level = __netconfig_wifi_get_rssi_level(rssi_dbm);
+ __netconfig_wifi_set_rssi_level(interface_name, path, snr_level);
+}
+
+void netconfig_wifi_indicator_start(const char *interface_name,
+ const char *profile_path)
+{
+ const char *default_ifname = NULL;
+
INFO("Start Wi-Fi indicator");
- vconf_set_int(VCONFKEY_WIFI_STRENGTH, VCONFKEY_WIFI_STRENGTH_MAX);
+ __create_rssi_data(interface_name);
- netconfig_start_timer_seconds(
- NETCONFIG_WIFI_INDICATOR_INTERVAL,
- __netconfig_wifi_indicator_monitor,
- NULL,
- &netconfig_wifi_indicator_timer);
+ if (profile_path)
+ __set_rssi_data_default_path(interface_name, profile_path);
+
+ default_ifname = netconfig_get_default_ifname();
+ if (g_strcmp0(default_ifname, interface_name) == 0)
+ netconfig_set_vconf_int(VCONFKEY_WIFI_STRENGTH, VCONFKEY_WIFI_STRENGTH_MAX, FALSE);
+
+ wifi_emit_rssi_changed((Wifi *)get_wifi_object(),
+ interface_name, VCONFKEY_WIFI_STRENGTH_MAX);
+
+ if (netconfig_wifi_statistics_timer == 0) {
+ netconfig_wifi_reset_last_bytes();
+ netconfig_start_timer_seconds(WIFI_INDICATOR_INTERVAL,
+ __netconfig_wifi_update_statistics, g_strdup(interface_name),
+ &netconfig_wifi_statistics_timer);
+ }
+
+ netconfig_battery_update_wifi_rssi(VCONFKEY_WIFI_STRENGTH_MAX);
}
-void netconfig_wifi_indicator_stop(void)
+void netconfig_wifi_indicator_stop(const char *interface_name)
{
+ int wifi_state = 0;
+ guint64 tx, rx;
+
INFO("Stop Wi-Fi indicator");
- vconf_set_int(VCONFKEY_WIFI_STRENGTH, VCONFKEY_WIFI_STRENGTH_MAX);
+ netconfig_vconf_get_int(VCONFKEY_WIFI_STATE, &wifi_state);
+
+ if (wifi_state != VCONFKEY_WIFI_CONNECTED) {
+ if (netconfig_wifi_get_bytes_statistics(&tx, &rx, TRUE))
+ netconfig_wifi_set_bytes_pkt_vconf(tx, rx, FALSE);
+
+ netconfig_stop_timer(&netconfig_wifi_statistics_timer);
+ }
- netconfig_stop_timer(&netconfig_wifi_indicator_timer);
+ __destroy_rssi_data(interface_name);
}