From 1060aa851220abe81f961305fe9d5f897a11d962 Mon Sep 17 00:00:00 2001 From: Mayank Haarit Date: Thu, 6 Sep 2018 17:19:53 +0530 Subject: [PATCH] [net-config] Suspend/Resume WLAN driver This patch suspend and resume wlan driver as per below action : 1) On LCD ON/OFF state change callback 2) On the basis of current service state Change-Id: I90d2b67c5d6fa6be80421c5bf817aefccdc3fe88 Signed-off-by: Mayank Haarit --- include/wifi-power.h | 1 + src/wifi-power.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/wifi-state.c | 8 ++++-- 3 files changed, 85 insertions(+), 3 deletions(-) diff --git a/include/wifi-power.h b/include/wifi-power.h index 598d290..49f25aa 100755 --- a/include/wifi-power.h +++ b/include/wifi-power.h @@ -31,6 +31,7 @@ void wifi_power_deinitialize(void); int wifi_power_on(void); int wifi_power_off(void); +void wifi_set_early_suspend(gboolean); #if defined TIZEN_WEARABLE int wifi_power_on_wearable(gboolean device_picker_test); #endif diff --git a/src/wifi-power.c b/src/wifi-power.c index e052147..c900012 100755 --- a/src/wifi-power.c +++ b/src/wifi-power.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include "log.h" #include "util.h" @@ -61,11 +63,19 @@ #define NETCONFIG_TECH_WAITING_INTERVAL 500 #define NETCONFIG_TECH_WAITING_COUNT 6 +#define MAX_DRV_CMD_SIZE 248 +#define WLAN_IOCTL_SUSPEND (SIOCDEVPRIVATE + 1) static gboolean connman_wifi_technology_state = FALSE; static gboolean wifi_firmware_recovery_mode = FALSE; static int airplane_mode = 0; +typedef struct { + char *buf; + int used_len; + int total_len; +} netconfig_wifi_priv_cmd; + static gboolean __is_wifi_restricted(void) { #if defined TIZEN_WEARABLE @@ -497,6 +507,66 @@ static void __emergency_mode_changed_cb(keynode_t *node, void *user_data) } +void wifi_set_early_suspend(gboolean value) +{ + static gboolean old_state = FALSE; + struct ifreq ifr; + char buf[MAX_DRV_CMD_SIZE]; + netconfig_wifi_priv_cmd priv_cmd; + int ret = 0; + int ioctl_sock = 0; + int pm_state = 0; + wifi_service_state_e wifi_state; + + if (old_state == value) { + DBG("Old and new states are same"); + return; + } + + if (netconfig_vconf_get_int(VCONFKEY_PM_STATE, &pm_state) < 0) + ERR("Fail to get VCONFKEY_PM_STATE"); + + wifi_state = wifi_state_get_service_state(); + + if (value == TRUE && + (pm_state < VCONFKEY_PM_STATE_LCDOFF || + wifi_state == NETCONFIG_WIFI_ASSOCIATION || + wifi_state == NETCONFIG_WIFI_CONFIGURATION)){ + DBG(""); + return; + } + + memset(buf, 0, sizeof(buf)); + snprintf(buf, sizeof(buf), "SETSUSPENDMODE %d", value); + + memset(&ifr, 0, sizeof(struct ifreq)); + g_strlcpy((char *)ifr.ifr_name, WIFI_IFNAME, IFNAMSIZ); + + DBG("Early suspend command: [%s]", buf); + + memset(&priv_cmd, 0, sizeof(priv_cmd)); + priv_cmd.buf = buf; + priv_cmd.used_len = sizeof(buf); + priv_cmd.total_len = sizeof(buf); + ifr.ifr_data = (char *)&priv_cmd; + + ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0); + if (ioctl_sock < 0) { + DBG("socket(PF_INET,SOCK_DGRAM) failed"); + return; + } + + ret = ioctl(ioctl_sock, WLAN_IOCTL_SUSPEND, &ifr); + + if (ret < 0) + ERR("Fail to issue private commands: %d. %s", ret, strerror(errno)); + else { + old_state = value; + } + + close(ioctl_sock); +} + static void __pm_state_changed_cb(keynode_t* node, void* user_data) { int new_state = -1; @@ -523,9 +593,18 @@ static void __pm_state_changed_cb(keynode_t* node, void* user_data) DBG("Old PM state: %d, current: %d (1 normal / 2 lcddim / 3 lcdoff / 4 sleep)", prev_state, new_state); if ((new_state == VCONFKEY_PM_STATE_NORMAL) && (prev_state >= VCONFKEY_PM_STATE_LCDOFF)) { + /* Send early suspend mode based on LCD state and disallow early suspend count */ + if (wifi_state != VCONFKEY_WIFI_OFF) { + wifi_set_early_suspend(FALSE); + DBG("Unset early suspend"); + } + netconfig_wifi_bgscan_stop(); netconfig_wifi_bgscan_set_interval(SCAN_EXPONENTIAL_MIN); netconfig_wifi_bgscan_start(TRUE); + } else if ((new_state == VCONFKEY_PM_STATE_LCDOFF) && (prev_state < VCONFKEY_PM_STATE_LCDOFF) && (wifi_state != VCONFKEY_WIFI_OFF)) { + wifi_set_early_suspend(TRUE); + DBG("Set early suspend"); } prev_state = new_state; diff --git a/src/wifi-state.c b/src/wifi-state.c index 27c64f1..237e2e0 100755 --- a/src/wifi-state.c +++ b/src/wifi-state.c @@ -541,12 +541,14 @@ void wifi_state_set_service_state(wifi_service_state_e new_state) DBG("Wi-Fi service state, old state[%s] ==> new state[%s]", _convert_wifi_service_state_to_string(old_state), _convert_wifi_service_state_to_string(new_state)); - /* During DHCP, temporarily disable Wi-Fi power saving */ - if ((old_state < NETCONFIG_WIFI_ASSOCIATION || old_state == NETCONFIG_WIFI_FAILURE) && new_state == NETCONFIG_WIFI_CONFIGURATION) { + /* From association, temporarily disable Wi-Fi power saving */ + if ((old_state < NETCONFIG_WIFI_ASSOCIATION || old_state == NETCONFIG_WIFI_FAILURE) && new_state == NETCONFIG_WIFI_ASSOCIATION) { _set_power_lock(TRUE); + wifi_set_early_suspend(FALSE); dhcp_stage = TRUE; - } else if (dhcp_stage == TRUE) { + } else if (dhcp_stage == TRUE && new_state != NETCONFIG_WIFI_CONFIGURATION) { _set_power_lock(FALSE); + wifi_set_early_suspend(TRUE); dhcp_stage = FALSE; } -- 2.7.4