2015-12-28 08:13:02 +01:00
// WiFi Event Monitor
# include "module.h"
# include "lauxlib.h"
# include "platform.h"
# include "c_string.h"
# include "c_stdlib.h"
# include "c_types.h"
# include "user_interface.h"
# include "smart.h"
# include "smartconfig.h"
# include "user_config.h"
# include "wifi_common.h"
# if defined(LUA_USE_MODULES_WIFI)
# ifdef WIFI_STATION_STATUS_MONITOR_ENABLE
//variables for wifi event monitor
static int wifi_station_status_cb_ref [ 6 ] = { [ 0 . . . 6 - 1 ] = LUA_NOREF } ;
static os_timer_t wifi_sta_status_timer ;
static uint8 prev_wifi_status = 0 ;
// wifi.sta.eventMonStop()
void wifi_station_event_mon_stop ( lua_State * L )
{
os_timer_disarm ( & wifi_sta_status_timer ) ;
if ( lua_isstring ( L , 1 ) )
{
int i ;
for ( i = 0 ; i < 6 ; i + + )
{
unregister_lua_cb ( L , & wifi_station_status_cb_ref [ i ] ) ;
}
}
return ;
}
static void wifi_status_cb ( int arg )
{
lua_State * L = lua_getstate ( ) ;
if ( wifi_get_opmode ( ) = = SOFTAP_MODE )
{
os_timer_disarm ( & wifi_sta_status_timer ) ;
return ;
}
int wifi_status = wifi_station_get_connect_status ( ) ;
if ( wifi_status ! = prev_wifi_status )
{
if ( wifi_station_status_cb_ref [ wifi_status ] ! = LUA_NOREF )
{
lua_rawgeti ( L , LUA_REGISTRYINDEX , wifi_station_status_cb_ref [ wifi_status ] ) ;
lua_pushnumber ( L , prev_wifi_status ) ;
lua_call ( L , 1 , 0 ) ;
}
}
prev_wifi_status = wifi_status ;
}
// wifi.sta.eventMonReg()
int wifi_station_event_mon_reg ( lua_State * L )
{
2017-03-31 09:48:04 +02:00
platform_print_deprecation_note ( " wifi.sta.eventmonreg() is replaced by wifi.eventmon.register() " , " in the next version " ) ;
2015-12-28 08:13:02 +01:00
uint8 id = ( uint8 ) luaL_checknumber ( L , 1 ) ;
if ( ( id > 5 ) ) // verify user specified a valid wifi status
{
return luaL_error ( L , " valid wifi status:0-5 " ) ;
}
if ( lua_type ( L , 2 ) = = LUA_TFUNCTION | | lua_type ( L , 2 ) = = LUA_TLIGHTFUNCTION ) //check if 2nd item on stack is a function
{
lua_pushvalue ( L , 2 ) ; //push function to top of stack
register_lua_cb ( L , & wifi_station_status_cb_ref [ id ] ) ; //pop function from top of the stack, register it in the LUA_REGISTRY, then assign returned lua_ref to wifi_station_status_cb_ref[id]
}
else
{
unregister_lua_cb ( L , & wifi_station_status_cb_ref [ id ] ) ; // unregister user's callback
}
return 0 ;
}
// wifi.sta.eventMonStart()
int wifi_station_event_mon_start ( lua_State * L )
{
if ( wifi_get_opmode ( ) = = SOFTAP_MODE ) //Verify ESP is in either Station mode or StationAP mode
{
return luaL_error ( L , " Can't monitor in SOFTAP mode " ) ;
}
if ( wifi_station_status_cb_ref [ 0 ] = = LUA_NOREF & & wifi_station_status_cb_ref [ 1 ] = = LUA_NOREF & &
wifi_station_status_cb_ref [ 2 ] = = LUA_NOREF & & wifi_station_status_cb_ref [ 3 ] = = LUA_NOREF & &
wifi_station_status_cb_ref [ 4 ] = = LUA_NOREF & & wifi_station_status_cb_ref [ 5 ] = = LUA_NOREF )
{ //verify user has registered callbacks
return luaL_error ( L , " No callbacks defined " ) ;
}
uint32 ms = 150 ; //set default timer interval
if ( lua_isnumber ( L , 1 ) ) // check if user has specified a different timer interval
{
ms = luaL_checknumber ( L , 1 ) ; // retrieve user-defined interval
}
os_timer_disarm ( & wifi_sta_status_timer ) ;
os_timer_setfn ( & wifi_sta_status_timer , ( os_timer_func_t * ) wifi_status_cb , NULL ) ;
os_timer_arm ( & wifi_sta_status_timer , ms , 1 ) ;
return 0 ;
}
# endif
# ifdef WIFI_SDK_EVENT_MONITOR_ENABLE
//variables for wifi event monitor
static task_handle_t wifi_event_monitor_task_id ; //variable to hold task id for task handler(process_event_queue)
typedef struct evt_queue {
System_Event_t * evt ;
struct evt_queue * next ;
} evt_queue_t ; //structure to hold pointers to event info and next item in queue
static evt_queue_t * wifi_event_queue_head ; //pointer to beginning of queue
static evt_queue_t * wifi_event_queue_tail ; //pointer to end of queue
static int wifi_event_cb_ref [ EVENT_MAX + 1 ] = { [ 0 . . . EVENT_MAX ] = LUA_NOREF } ; //holds references to registered Lua callbacks
// wifi.eventmon.register()
static int wifi_event_monitor_register ( lua_State * L )
{
uint8 id = ( uint8 ) luaL_checknumber ( L , 1 ) ;
if ( id > EVENT_MAX ) //Check if user is trying to register a callback for a valid event.
{
return luaL_error ( L , " valid wifi events:0-%d " , EVENT_MAX ) ;
}
else
{
if ( lua_type ( L , 2 ) = = LUA_TFUNCTION | | lua_type ( L , 2 ) = = LUA_TLIGHTFUNCTION ) //check if 2nd item on stack is a function
{
lua_pushvalue ( L , 2 ) ; // copy argument (func) to the top of stack
register_lua_cb ( L , & wifi_event_cb_ref [ id ] ) ; //pop function from top of the stack, register it in the LUA_REGISTRY, then assign lua_ref to wifi_event_cb_ref[id]
}
else // unregister user's callback
{
unregister_lua_cb ( L , & wifi_event_cb_ref [ id ] ) ;
}
return 0 ;
}
}
static void wifi_event_monitor_handle_event_cb ( System_Event_t * evt )
{
EVENT_DBG ( " \n \t wifi_event_monitor_handle_event_cb is called \n " ) ;
if ( ( wifi_event_cb_ref [ evt - > event ] ! = LUA_NOREF ) | | ( ( wifi_event_cb_ref [ EVENT_MAX ] ! = LUA_NOREF ) & &
! ( evt - > event = = EVENT_STAMODE_CONNECTED | | evt - > event = = EVENT_STAMODE_DISCONNECTED | |
evt - > event = = EVENT_STAMODE_AUTHMODE_CHANGE | | evt - > event = = EVENT_STAMODE_GOT_IP | |
evt - > event = = EVENT_STAMODE_DHCP_TIMEOUT | | evt - > event = = EVENT_SOFTAPMODE_STACONNECTED | |
evt - > event = = EVENT_SOFTAPMODE_STADISCONNECTED | | evt - > event = = EVENT_SOFTAPMODE_PROBEREQRECVED ) ) )
{
evt_queue_t * temp = ( evt_queue_t * ) c_malloc ( sizeof ( evt_queue_t ) ) ; //allocate memory for new queue item
temp - > evt = ( System_Event_t * ) c_malloc ( sizeof ( System_Event_t ) ) ; //allocate memory to hold event structure
if ( ! temp | | ! temp - > evt )
{
luaL_error ( lua_getstate ( ) , " wifi.eventmon malloc: out of memory " ) ;
return ;
}
c_memcpy ( temp - > evt , evt , sizeof ( System_Event_t ) ) ; //copy event data to new struct
if ( wifi_event_queue_head = = NULL & & wifi_event_queue_tail = = NULL ) // if queue is empty add item to queue
{
wifi_event_queue_head = wifi_event_queue_tail = temp ;
EVENT_DBG ( " \n \t queue empty, adding event and posting task \n " ) ;
task_post_low ( wifi_event_monitor_task_id , false ) ;
}
else //if queue is not empty append item to end of queue
{
wifi_event_queue_tail - > next = temp ;
wifi_event_queue_tail = temp ;
EVENT_DBG ( " \n \t queue not empty, appending queue \n " ) ;
}
}
}
static void wifi_event_monitor_process_event_queue ( task_param_t param , uint8 priority )
{
lua_State * L = lua_getstate ( ) ;
evt_queue_t * temp = wifi_event_queue_head ; //copy event_queue_head pointer to temporary pointer
System_Event_t * evt = temp - > evt ; //copy event data pointer to temporary pointer
EVENT_DBG ( " \t \t event %u \n " , evt - > event ) ;
if ( wifi_event_cb_ref [ evt - > event ] ! = LUA_NOREF ) // check if user has registered a callback
{
lua_rawgeti ( L , LUA_REGISTRYINDEX , wifi_event_cb_ref [ evt - > event ] ) ; //get user's callback
}
else if ( ( wifi_event_cb_ref [ EVENT_MAX ] ! = LUA_NOREF ) & &
! ( evt - > event = = EVENT_STAMODE_CONNECTED | | evt - > event = = EVENT_STAMODE_DISCONNECTED | |
evt - > event = = EVENT_STAMODE_AUTHMODE_CHANGE | | evt - > event = = EVENT_STAMODE_GOT_IP | |
evt - > event = = EVENT_STAMODE_DHCP_TIMEOUT | | evt - > event = = EVENT_SOFTAPMODE_STACONNECTED | |
evt - > event = = EVENT_SOFTAPMODE_STADISCONNECTED | | evt - > event = = EVENT_SOFTAPMODE_PROBEREQRECVED ) )
{ //if user has registered an EVENT_MAX(default) callback and event is not implemented...
lua_rawgeti ( L , LUA_REGISTRYINDEX , wifi_event_cb_ref [ EVENT_MAX ] ) ; //get user's callback
}
lua_newtable ( L ) ;
switch ( evt - > event )
{
case EVENT_STAMODE_CONNECTED :
EVENT_DBG ( " \n \t STAMODE_CONNECTED \n " ) ;
wifi_add_sprintf_field ( L , " SSID " , ( char * ) evt - > event_info . connected . ssid ) ;
wifi_add_sprintf_field ( L , " BSSID " , MACSTR , MAC2STR ( evt - > event_info . connected . bssid ) ) ;
wifi_add_int_field ( L , " channel " , evt - > event_info . connected . channel ) ;
EVENT_DBG ( " \t Connected to SSID %s, Channel %d \n " ,
evt - > event_info . connected . ssid ,
evt - > event_info . connected . channel ) ;
break ;
case EVENT_STAMODE_DISCONNECTED :
EVENT_DBG ( " \n \t STAMODE_DISCONNECTED \n " ) ;
wifi_add_sprintf_field ( L , " SSID " , ( char * ) evt - > event_info . disconnected . ssid ) ;
wifi_add_int_field ( L , " reason " , evt - > event_info . disconnected . reason ) ;
wifi_add_sprintf_field ( L , " BSSID " , MACSTR , MAC2STR ( evt - > event_info . disconnected . bssid ) ) ;
EVENT_DBG ( " \t Disconnect from SSID %s, reason %d \n " ,
evt - > event_info . disconnected . ssid ,
evt - > event_info . disconnected . reason ) ;
break ;
case EVENT_STAMODE_AUTHMODE_CHANGE :
EVENT_DBG ( " \n \t STAMODE_AUTHMODE_CHANGE \n " ) ;
wifi_add_int_field ( L , " old_auth_mode " , evt - > event_info . auth_change . old_mode ) ;
wifi_add_int_field ( L , " new_auth_mode " , evt - > event_info . auth_change . new_mode ) ;
EVENT_DBG ( " \t Authmode: %u -> %u \n " ,
evt - > event_info . auth_change . old_mode ,
evt - > event_info . auth_change . new_mode ) ;
break ;
case EVENT_STAMODE_GOT_IP :
EVENT_DBG ( " \n \t GOT_IP \n " ) ;
wifi_add_sprintf_field ( L , " IP " , IPSTR , IP2STR ( & evt - > event_info . got_ip . ip ) ) ;
wifi_add_sprintf_field ( L , " netmask " , IPSTR , IP2STR ( & evt - > event_info . got_ip . mask ) ) ;
wifi_add_sprintf_field ( L , " gateway " , IPSTR , IP2STR ( & evt - > event_info . got_ip . gw ) ) ;
EVENT_DBG ( " \t IP: " IPSTR " ,Mask: " IPSTR " ,GW: " IPSTR " \n " ,
IP2STR ( & evt - > event_info . got_ip . ip ) ,
IP2STR ( & evt - > event_info . got_ip . mask ) ,
IP2STR ( & evt - > event_info . got_ip . gw ) ) ;
break ;
case EVENT_STAMODE_DHCP_TIMEOUT :
EVENT_DBG ( " \n \t STAMODE_DHCP_TIMEOUT \n " ) ;
break ;
case EVENT_SOFTAPMODE_STACONNECTED :
EVENT_DBG ( " \n \t SOFTAPMODE_STACONNECTED \n " ) ;
wifi_add_sprintf_field ( L , " MAC " , MACSTR , MAC2STR ( evt - > event_info . sta_connected . mac ) ) ;
wifi_add_int_field ( L , " AID " , evt - > event_info . sta_connected . aid ) ;
EVENT_DBG ( " \t Station: " MACSTR " join, AID = %d \n " ,
MAC2STR ( evt - > event_info . sta_connected . mac ) ,
evt - > event_info . sta_connected . aid ) ;
break ;
case EVENT_SOFTAPMODE_STADISCONNECTED :
EVENT_DBG ( " \n \t SOFTAPMODE_STADISCONNECTED \n " ) ;
wifi_add_sprintf_field ( L , " MAC " , MACSTR , MAC2STR ( evt - > event_info . sta_disconnected . mac ) ) ;
wifi_add_int_field ( L , " AID " , evt - > event_info . sta_disconnected . aid ) ;
EVENT_DBG ( " \t station: " MACSTR " leave, AID = %d \n " ,
MAC2STR ( evt - > event_info . sta_disconnected . mac ) ,
evt - > event_info . sta_disconnected . aid ) ;
break ;
case EVENT_SOFTAPMODE_PROBEREQRECVED :
EVENT_DBG ( " \n \t SOFTAPMODE_PROBEREQRECVED \n " ) ;
wifi_add_sprintf_field ( L , " MAC " , MACSTR , MAC2STR ( evt - > event_info . ap_probereqrecved . mac ) ) ;
wifi_add_int_field ( L , " RSSI " , evt - > event_info . ap_probereqrecved . rssi ) ;
EVENT_DBG ( " Station PROBEREQ: " MACSTR " RSSI = %d \n " ,
MAC2STR ( evt - > event_info . ap_probereqrecved . mac ) ,
evt - > event_info . ap_probereqrecved . rssi ) ;
break ;
default : //if event is not implemented, push table with userdata containing event data
EVENT_DBG ( " \n \t switch/case default \n " ) ;
wifi_add_sprintf_field ( L , " info " , " event %u not implemented " , evt - > event ) ;
break ;
}
lua_call ( L , 1 , 0 ) ; //execute user's callback and pass Lua table
if ( wifi_event_queue_head = = wifi_event_queue_tail ) //if queue is empty..
{
wifi_event_queue_head = wifi_event_queue_tail = NULL ; //set queue pointers to NULL
EVENT_DBG ( " \n \t Queue empty \n " ) ;
}
else //if queue is not empty...
{
wifi_event_queue_head = wifi_event_queue_head - > next ; //append item to end of queue
EVENT_DBG ( " \n \t more in queue, posting task... \n " ) ;
task_post_low ( wifi_event_monitor_task_id , false ) ; //post task to process next item in queue
}
c_free ( evt ) ; //free memory used by event structure
c_free ( temp ) ; //free memory used by queue structure
}
# ifdef WIFI_EVENT_MONITOR_DISCONNECT_REASON_LIST_ENABLE
static const LUA_REG_TYPE wifi_event_monitor_reason_map [ ] =
{
{ LSTRKEY ( " UNSPECIFIED " ) , LNUMVAL ( REASON_UNSPECIFIED ) } ,
{ LSTRKEY ( " AUTH_EXPIRE " ) , LNUMVAL ( REASON_AUTH_EXPIRE ) } ,
{ LSTRKEY ( " AUTH_LEAVE " ) , LNUMVAL ( REASON_AUTH_LEAVE ) } ,
{ LSTRKEY ( " ASSOC_EXPIRE " ) , LNUMVAL ( REASON_ASSOC_EXPIRE ) } ,
{ LSTRKEY ( " ASSOC_TOOMANY " ) , LNUMVAL ( REASON_ASSOC_TOOMANY ) } ,
{ LSTRKEY ( " NOT_AUTHED " ) , LNUMVAL ( REASON_NOT_AUTHED ) } ,
{ LSTRKEY ( " NOT_ASSOCED " ) , LNUMVAL ( REASON_NOT_ASSOCED ) } ,
{ LSTRKEY ( " ASSOC_LEAVE " ) , LNUMVAL ( REASON_ASSOC_LEAVE ) } ,
{ LSTRKEY ( " ASSOC_NOT_AUTHED " ) , LNUMVAL ( REASON_ASSOC_NOT_AUTHED ) } ,
{ LSTRKEY ( " DISASSOC_PWRCAP_BAD " ) , LNUMVAL ( REASON_DISASSOC_PWRCAP_BAD ) } ,
{ LSTRKEY ( " DISASSOC_SUPCHAN_BAD " ) , LNUMVAL ( REASON_DISASSOC_SUPCHAN_BAD ) } ,
{ LSTRKEY ( " IE_INVALID " ) , LNUMVAL ( REASON_IE_INVALID ) } ,
{ LSTRKEY ( " MIC_FAILURE " ) , LNUMVAL ( REASON_MIC_FAILURE ) } ,
{ LSTRKEY ( " 4WAY_HANDSHAKE_TIMEOUT " ) , LNUMVAL ( REASON_4WAY_HANDSHAKE_TIMEOUT ) } ,
{ LSTRKEY ( " GROUP_KEY_UPDATE_TIMEOUT " ) , LNUMVAL ( REASON_GROUP_KEY_UPDATE_TIMEOUT ) } ,
{ LSTRKEY ( " IE_IN_4WAY_DIFFERS " ) , LNUMVAL ( REASON_IE_IN_4WAY_DIFFERS ) } ,
{ LSTRKEY ( " GROUP_CIPHER_INVALID " ) , LNUMVAL ( REASON_GROUP_CIPHER_INVALID ) } ,
{ LSTRKEY ( " PAIRWISE_CIPHER_INVALID " ) , LNUMVAL ( REASON_PAIRWISE_CIPHER_INVALID ) } ,
{ LSTRKEY ( " AKMP_INVALID " ) , LNUMVAL ( REASON_AKMP_INVALID ) } ,
{ LSTRKEY ( " UNSUPP_RSN_IE_VERSION " ) , LNUMVAL ( REASON_UNSUPP_RSN_IE_VERSION ) } ,
{ LSTRKEY ( " INVALID_RSN_IE_CAP " ) , LNUMVAL ( REASON_INVALID_RSN_IE_CAP ) } ,
{ LSTRKEY ( " 802_1X_AUTH_FAILED " ) , LNUMVAL ( REASON_802_1X_AUTH_FAILED ) } ,
{ LSTRKEY ( " CIPHER_SUITE_REJECTED " ) , LNUMVAL ( REASON_CIPHER_SUITE_REJECTED ) } ,
{ LSTRKEY ( " BEACON_TIMEOUT " ) , LNUMVAL ( REASON_BEACON_TIMEOUT ) } ,
{ LSTRKEY ( " NO_AP_FOUND " ) , LNUMVAL ( REASON_NO_AP_FOUND ) } ,
{ LSTRKEY ( " AUTH_FAIL " ) , LNUMVAL ( REASON_AUTH_FAIL ) } ,
{ LSTRKEY ( " ASSOC_FAIL " ) , LNUMVAL ( REASON_ASSOC_FAIL ) } ,
{ LSTRKEY ( " HANDSHAKE_TIMEOUT " ) , LNUMVAL ( REASON_HANDSHAKE_TIMEOUT ) } ,
{ LNILKEY , LNILVAL }
} ;
# endif
const LUA_REG_TYPE wifi_event_monitor_map [ ] =
{
{ LSTRKEY ( " register " ) , LFUNCVAL ( wifi_event_monitor_register ) } ,
{ LSTRKEY ( " unregister " ) , LFUNCVAL ( wifi_event_monitor_register ) } ,
{ LSTRKEY ( " STA_CONNECTED " ) , LNUMVAL ( EVENT_STAMODE_CONNECTED ) } ,
{ LSTRKEY ( " STA_DISCONNECTED " ) , LNUMVAL ( EVENT_STAMODE_DISCONNECTED ) } ,
{ LSTRKEY ( " STA_AUTHMODE_CHANGE " ) , LNUMVAL ( EVENT_STAMODE_AUTHMODE_CHANGE ) } ,
{ LSTRKEY ( " STA_GOT_IP " ) , LNUMVAL ( EVENT_STAMODE_GOT_IP ) } ,
{ LSTRKEY ( " STA_DHCP_TIMEOUT " ) , LNUMVAL ( EVENT_STAMODE_DHCP_TIMEOUT ) } ,
{ LSTRKEY ( " AP_STACONNECTED " ) , LNUMVAL ( EVENT_SOFTAPMODE_STACONNECTED ) } ,
{ LSTRKEY ( " AP_STADISCONNECTED " ) , LNUMVAL ( EVENT_SOFTAPMODE_STADISCONNECTED ) } ,
{ LSTRKEY ( " AP_PROBEREQRECVED " ) , LNUMVAL ( EVENT_SOFTAPMODE_PROBEREQRECVED ) } ,
{ LSTRKEY ( " EVENT_MAX " ) , LNUMVAL ( EVENT_MAX ) } ,
# ifdef WIFI_EVENT_MONITOR_DISCONNECT_REASON_LIST_ENABLE
{ LSTRKEY ( " reason " ) , LROVAL ( wifi_event_monitor_reason_map ) } ,
# endif
{ LNILKEY , LNILVAL }
} ;
void wifi_eventmon_init ( )
{
wifi_event_monitor_task_id = task_get_id ( wifi_event_monitor_process_event_queue ) ; //get task id from task interface
wifi_set_event_handler_cb ( wifi_event_monitor_handle_event_cb ) ;
return ;
}
# endif
# endif