#include <stdlib.h>
#include <glib.h>
#include <tzplatform_config.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
#include "log.h"
#include "util.h"
#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
}
+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;
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;
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;
}