Skip to content

Commit

Permalink
Added wifi.suspend() function to wifi module
Browse files Browse the repository at this point in the history
Exposed Wifi Forced sleep API

`wifi.suspend()` and `wifi.resume()`
  • Loading branch information
dnc40085 committed Apr 10, 2016
1 parent 7d576ef commit 295f905
Show file tree
Hide file tree
Showing 4 changed files with 319 additions and 52 deletions.
255 changes: 204 additions & 51 deletions app/modules/wifi.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,6 @@ static uint8 getap_output_format=0;

#define INVALID_MAC_STR "MAC:FF:FF:FF:FF:FF:FF"

//wifi.sleep variables
#define FPM_SLEEP_MAX_TIME 0xFFFFFFF
static bool FLAG_wifi_force_sleep_enabled=0;

#ifdef WIFI_SMART_ENABLE
static void wifi_smart_succeed_cb(sc_status status, void *pdata){
NODE_DBG("wifi_smart_succeed_cb is called.\n");
Expand Down Expand Up @@ -311,67 +307,222 @@ static int wifi_getphymode( lua_State* L )
return 1;
}

//wifi.sleep()
static int wifi_sleep(lua_State* L)
/* Begin WiFi suspend functions*/

static int wifi_resume_cb_ref = LUA_NOREF; // Holds resume callback reference
static int wifi_suspend_cb_ref = LUA_NOREF; // Holds suspend callback reference
static uint8 wifi_resume_mode = 0;
static os_timer_t wifi_is_suspended_timer; // Timer structure for wifi_rf_closed_timer

// C callback for bringing WiFi back from forced sleep
static void wifi_resume_cb(void)
{
uint8 desired_sleep_state = 2;
sint8 wifi_fpm_do_sleep_return_value = 1;
if(lua_isnumber(L, 1))
wifi_fpm_close(); // Disable force sleep API
SLEEP_DBG("\n\tWiFi resume\n");

// If resume_opmode is STATION_MODE, SOFTAP_MODE or STATIONAP_MODE
if (wifi_resume_mode > 0 && wifi_resume_mode < 4)
{
if(luaL_checknumber(L, 1) == 0)
{
desired_sleep_state = 0;
}
else if(luaL_checknumber(L, 1) == 1)
{
desired_sleep_state = 1;
}
// If wifi_set_opmode_current is successful
if (wifi_set_opmode_current(wifi_resume_mode))
{
// If opmode is STATION_MODE or STATIONAP_MODE
if (wifi_resume_mode == STATION_MODE || wifi_resume_mode == STATIONAP_MODE)
{
wifi_station_connect(); // Connect to currently configured Access Point
}
SLEEP_DBG("\n\tWiFi mode restored\n");
wifi_resume_mode = 0; // reset variable to default value
}
}
if (!FLAG_wifi_force_sleep_enabled && desired_sleep_state == 1 )

// If resume callback was defined
if (wifi_resume_cb_ref != LUA_NOREF)
{
uint8 wifi_current_opmode = wifi_get_opmode();
if (wifi_current_opmode == 1 || wifi_current_opmode == 3 )
{
wifi_station_disconnect();
}
// set WiFi mode to null mode
wifi_set_opmode(NULL_MODE);
// set force sleep type
wifi_fpm_set_sleep_type(MODEM_SLEEP_T);
wifi_fpm_open();
wifi_fpm_do_sleep_return_value = wifi_fpm_do_sleep(FPM_SLEEP_MAX_TIME);
if (wifi_fpm_do_sleep_return_value == 0)
{
FLAG_wifi_force_sleep_enabled = TRUE;
}
else
{
wifi_fpm_close();
FLAG_wifi_force_sleep_enabled = FALSE;
}
lua_State* L = lua_getstate(); // Get Lua main thread pointer
lua_rawgeti(L, LUA_REGISTRYINDEX, wifi_resume_cb_ref); // Push resume callback onto the stack
lua_unref(L, wifi_resume_cb_ref); // Remove resume callback from registry
wifi_resume_cb_ref = LUA_NOREF; // Update variable since reference is no longer valid
lua_call(L, 0, 0); // Execute resume callback
}
return;
}

// This callback executes the suspend lua callback when Wifi is finally suspended
static void wifi_is_suspended_timer_cb(int arg)
{
// If WiFi is suspended
if (fpm_rf_is_closed())
{
os_timer_disarm(&wifi_is_suspended_timer); // Stop rf_closed_timer
SLEEP_DBG("\n\tWiFi is suspended\n");

// If suspend callback was defined
if (wifi_suspend_cb_ref != LUA_NOREF)
{
lua_State* L = lua_getstate(); // Get main Lua thread pointer
lua_rawgeti(L, LUA_REGISTRYINDEX, wifi_suspend_cb_ref); // Push suspend callback onto stack
lua_unref(L, wifi_suspend_cb_ref); // remove suspend callback from LUA_REGISTRY
wifi_suspend_cb_ref = LUA_NOREF; // Update variable since reference is no longer valid
lua_call(L, 0, 0); // Execute suspend callback
}
}
else if(FLAG_wifi_force_sleep_enabled && desired_sleep_state == 0)
}

// Lua: wifi.suspend([[duration], [Suspend_CB, [Resume_CB]], [Preserve_wifi_mode]])
static int wifi_suspend(lua_State* L)
{
// If no parameters were provided
if (lua_isnone(L, 1))
{
FLAG_wifi_force_sleep_enabled = FALSE;
// wake up to use WiFi again
wifi_fpm_do_wakeup();
wifi_fpm_close();
// If WiFi is suspended
if (fpm_rf_is_closed())
{
lua_pushnumber(L, WIFI_SUSPENDED);
}
// If WiFi suspension is pending
else if (fpm_is_open())
{
lua_pushnumber(L, WIFI_SUSPENSION_PENDING);
}
else
{
lua_pushnumber(L, WIFI_AWAKE);
}
return 1; // Return WiFi suspension state
}

if (desired_sleep_state == 1 && FLAG_wifi_force_sleep_enabled == FALSE)
// If forced sleep api is enabled
if (fpm_is_open())
{
lua_pushnil(L);
lua_pushnumber(L, wifi_fpm_do_sleep_return_value);
// If WiFi is suspended
if (fpm_rf_is_closed())
{
return luaL_error(L, "WiFi already suspended");
}
else
{
return luaL_error(L, "WiFi suspension pending");
}
}
else

uint8 current_wifi_mode = wifi_get_opmode(); // Get Current WiFi mode
uint32 suspend_duration = 0; // variable to hold suspend duration
uint8 stack_ptr = 1; // pointer to iterate through items on stack

// If a suspend duration is provided
if (lua_isnumber(L, stack_ptr))
{
lua_pushnumber(L, FLAG_wifi_force_sleep_enabled);
lua_pushnil(L);
// Verify duration is 0 or 50000 - 268435454, if it isn't return error
luaL_argcheck(L,
(((luaL_checknumber(L, stack_ptr) > 49999) && (luaL_checknumber(L, stack_ptr) < FPM_SLEEP_MAX_TIME)) ||
(luaL_checknumber(L, stack_ptr) == 0)), stack_ptr, "50000-268435454 us");

suspend_duration = luaL_checknumber(L, 1); // Get suspend duration
stack_ptr++; // Increment the stack pointer
}
return 2;

// If suspend duration is 0, then set it to FPM_SLEEP_MAX_TIME
if (suspend_duration == 0)
{
suspend_duration = FPM_SLEEP_MAX_TIME;
}

// If a suspend callback was provided
if (lua_isfunction(L, stack_ptr))
{
// If there is already a suspend callback reference
if (wifi_suspend_cb_ref != LUA_NOREF)
{
luaL_unref(L, LUA_REGISTRYINDEX, wifi_suspend_cb_ref); // Discard old callback
}
lua_pushvalue(L, stack_ptr); // Push suspend callback to the top of the stack
wifi_suspend_cb_ref = luaL_ref(L, LUA_REGISTRYINDEX); // Register suspend callback in LUA_REGISTRY and store it's reference
stack_ptr++; //Increment the stack pointer
}

// If a resume callback was provided
if (lua_isfunction(L, stack_ptr))
{
// If there is already a resume callback reference
if (wifi_resume_cb_ref != LUA_NOREF)
{
luaL_unref(L, LUA_REGISTRYINDEX, wifi_resume_cb_ref); // Discard old callback
}
lua_pushvalue(L, stack_ptr); // Push resume callback to the top of the stack
wifi_resume_cb_ref = luaL_ref(L, LUA_REGISTRYINDEX); // Register resume callback in LUA_REGISTRY and store it's reference
stack_ptr++; // Increment the stack pointer
}

// If Preserve_wifi_mode parameter is TRUE and current WiFi mode is not NULL_MODE
if (lua_toboolean(L, stack_ptr) == 1 && current_wifi_mode != 0)
{
SLEEP_DBG("\n\tWiFi opmode will be preserved\n");
wifi_resume_mode = current_wifi_mode;
}

if (current_wifi_mode == STATION_MODE || current_wifi_mode == STATIONAP_MODE)
{
wifi_station_disconnect(); // Disconnect from Access Point
}

// If wifi_set_opmode_current is successful
if (wifi_set_opmode_current(NULL_MODE))
{
wifi_fpm_open(); // Enable force sleep API

// Verify forced sleep api is enabled
if (fpm_is_open())
{
wifi_fpm_set_wakeup_cb(wifi_resume_cb); // Set resume C callback
sint8 return_value = wifi_fpm_do_sleep(suspend_duration); // Request WiFi suspension and store return value

// If wifi_fpm_do_sleep success
if (return_value == 0)
{
SLEEP_DBG("\n\twifi_fpm_do_sleep success, starting rf_closed_timer\n");
os_timer_disarm(&wifi_is_suspended_timer); // Disable timer if it is already running
os_timer_setfn(&wifi_is_suspended_timer,(os_timer_func_t *) wifi_is_suspended_timer_cb, NULL); //Set timer callback for wifi_rf_closed_timer
os_timer_arm(&wifi_is_suspended_timer, 1, 1); // Start rf_closed_timer
}
else // This should never happen
{
wifi_fpm_close();
return luaL_error(L, "wifi_fpm_do_sleep returned %d", return_value);
}
}
}
return 0;
}

// Lua: wifi.resume([Resume_CB])
static int wifi_resume(lua_State* L)
{
// If forced sleep api is not enabled, return error
if (!fpm_is_open())
{
return luaL_error(L, "WIFi not suspended");
}

// If a resume callback was provided
if (lua_isfunction(L, 1))
{
// If there is already a resume callback reference
if (wifi_resume_cb_ref != LUA_NOREF)
{
luaL_unref(L, LUA_REGISTRYINDEX, wifi_resume_cb_ref); // Discard old callback
}
lua_pushvalue(L, 1); //Push resume callback to the top of the stack
wifi_resume_cb_ref = luaL_ref(L, LUA_REGISTRYINDEX); // Register resume callback in LUA_REGISTRY and store it's reference
SLEEP_DBG("\n\tResume CB registered\n");
}
wifi_fpm_do_wakeup(); // Wake up from sleep
wifi_resume_cb(); // Finish WiFi wakeup
return 0;
}

/* End WiFi suspend functions*/

// Lua: mac = wifi.xx.getmac()
static int wifi_getmac( lua_State* L, uint8_t mode )
{
Expand Down Expand Up @@ -895,6 +1046,7 @@ static int wifi_station_listap( lua_State* L )
{
unregister_lua_cb(L, &wifi_scan_succeed);
}
return 0;
}

// Lua: wifi.sta.gethostname()
Expand Down Expand Up @@ -1267,7 +1419,8 @@ static const LUA_REG_TYPE wifi_map[] = {
{ LSTRKEY( "getchannel" ), LFUNCVAL( wifi_getchannel ) },
{ LSTRKEY( "setphymode" ), LFUNCVAL( wifi_setphymode ) },
{ LSTRKEY( "getphymode" ), LFUNCVAL( wifi_getphymode ) },
{ LSTRKEY( "sleep" ), LFUNCVAL( wifi_sleep ) },
{ LSTRKEY( "suspend" ), LFUNCVAL( wifi_suspend ) },
{ LSTRKEY( "resume" ), LFUNCVAL( wifi_resume ) },
#ifdef WIFI_SMART_ENABLE
{ LSTRKEY( "startsmart" ), LFUNCVAL( wifi_start_smart ) },
{ LSTRKEY( "stopsmart" ), LFUNCVAL( wifi_exit_smart ) },
Expand Down
20 changes: 19 additions & 1 deletion app/modules/wifi_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
#include "c_stdio.h"
#include "task/task.h"

//#define WIFI_SLEEP_DEBUG
//#define WIFI_EVENTMON_DEBUG

void wifi_add_sprintf_field(lua_State* L, char* name, char* string, ...);
void wifi_add_int_field(lua_State* L, char* name, lua_Integer integer);

Expand All @@ -35,12 +38,27 @@ static inline void unregister_lua_cb(lua_State* L, int* cb_ref)
}
}

#ifdef NODE_DEBUG
#if defined(WIFI_EVENTMON_DEBUG) || defined(NODE_DEBUG)
#define EVENT_DBG(...) c_printf(__VA_ARGS__)
#else
#define EVENT_DBG(...) //c_printf(__VA_ARGS__)
#endif

#if defined(WIFI_SLEEP_DEBUG) || defined(NODE_DEBUG)
#define SLEEP_DBG(...) c_printf(__VA_ARGS__)
#else
#define SLEEP_DBG(...) //c_printf(__VA_ARGS__)
#endif

enum wifi_suspension_state
{
WIFI_AWAKE = 0,
WIFI_SUSPENSION_PENDING = 1,
WIFI_SUSPENDED = 2
};



#ifdef WIFI_SDK_EVENT_MONITOR_ENABLE
extern const LUA_REG_TYPE wifi_event_monitor_map[];
void wifi_eventmon_init();
Expand Down
Loading

0 comments on commit 295f905

Please sign in to comment.