2015-12-28 08:13:02 +01:00
// WiFi Event Monitor
# include "module.h"
# include "lauxlib.h"
# include "platform.h"
2019-07-21 23:58:21 +02:00
# include <string.h>
2019-07-23 06:22:38 +02:00
# include <stddef.h>
2015-12-28 08:13:02 +01:00
2019-07-23 06:22:38 +02:00
# include <stdint.h>
2015-12-28 08:13:02 +01:00
# include "user_interface.h"
2019-07-23 17:47:18 +02:00
# include "smart/smart.h"
2015-12-28 08:13:02 +01:00
# include "smartconfig.h"
# include "user_config.h"
# include "wifi_common.h"
# if defined(LUA_USE_MODULES_WIFI)
# 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)
static int wifi_event_cb_ref [ EVENT_MAX + 1 ] = { [ 0 . . . EVENT_MAX ] = LUA_NOREF } ; //holds references to registered Lua callbacks
2018-01-10 21:24:41 +01:00
# ifdef LUA_USE_MODULES_WIFI_MONITOR
static int ( * hook_fn ) ( System_Event_t * ) ;
void wifi_event_monitor_register_hook ( int ( * fn ) ( System_Event_t * ) ) {
hook_fn = fn ;
}
# endif
2015-12-28 08:13:02 +01:00
// wifi.eventmon.register()
2017-05-21 16:18:56 +02:00
int wifi_event_monitor_register ( lua_State * L )
2015-12-28 08:13:02 +01:00
{
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
{
2020-04-27 02:13:38 +02:00
if ( lua_isfunction ( L , 2 ) ) //check if 2nd item on stack is a function
2015-12-28 08:13:02 +01:00
{
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 ;
}
}
2018-05-20 09:46:04 +02:00
static sint32_t event_queue_ref = LUA_NOREF ;
2015-12-28 08:13:02 +01:00
static void wifi_event_monitor_handle_event_cb ( System_Event_t * evt )
{
2018-05-20 09:46:04 +02:00
EVENT_DBG ( " was called (Event:%d) " , evt - > event ) ;
2015-12-28 08:13:02 +01:00
2018-01-10 21:24:41 +01:00
# ifdef LUA_USE_MODULES_WIFI_MONITOR
if ( hook_fn & & hook_fn ( evt ) ) {
return ;
}
# endif
2015-12-28 08:13:02 +01:00
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 | |
2017-05-15 09:05:22 +02:00
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 - > event = = EVENT_OPMODE_CHANGED ) ) )
2015-12-28 08:13:02 +01:00
{
2018-05-20 09:46:04 +02:00
lua_State * L = lua_getstate ( ) ;
if ( event_queue_ref = = LUA_NOREF ) { //if event queue has not been created, create it now
lua_newtable ( L ) ;
event_queue_ref = luaL_ref ( L , LUA_REGISTRYINDEX ) ;
2015-12-28 08:13:02 +01:00
}
2018-05-20 09:46:04 +02:00
lua_rawgeti ( L , LUA_REGISTRYINDEX , event_queue_ref ) ;
2015-12-28 08:13:02 +01:00
2018-05-20 09:46:04 +02:00
System_Event_t * evt_tmp = lua_newuserdata ( L , sizeof ( System_Event_t ) ) ;
2019-07-21 23:58:21 +02:00
memcpy ( evt_tmp , evt , sizeof ( System_Event_t ) ) ; //copy event data to new struct
2018-05-20 09:46:04 +02:00
sint32_t evt_ud_ref = luaL_ref ( L , LUA_REGISTRYINDEX ) ;
size_t queue_len = lua_objlen ( L , - 1 ) ;
//add event to queue
lua_pushnumber ( L , queue_len + 1 ) ;
lua_pushnumber ( L , evt_ud_ref ) ;
lua_rawset ( L , - 3 ) ;
if ( queue_len = = 0 ) { //if queue was empty, post task
EVENT_DBG ( " Posting task " ) ;
2015-12-28 08:13:02 +01:00
task_post_low ( wifi_event_monitor_task_id , false ) ;
}
2018-05-20 09:46:04 +02:00
else {
EVENT_DBG ( " Appending queue, items in queue: %d " , lua_objlen ( L , - 1 ) ) ;
2015-12-28 08:13:02 +01:00
}
2018-05-20 09:46:04 +02:00
lua_pop ( L , 1 ) ;
} //else{} //there are no callbacks registered, so the event can't be processed
2015-12-28 08:13:02 +01:00
}
static void wifi_event_monitor_process_event_queue ( task_param_t param , uint8 priority )
{
lua_State * L = lua_getstate ( ) ;
2018-05-20 09:46:04 +02:00
lua_rawgeti ( L , LUA_REGISTRYINDEX , event_queue_ref ) ;
int index = 1 ;
lua_rawgeti ( L , 1 , index ) ;
sint32 event_ref = lua_tonumber ( L , - 1 ) ;
lua_pop ( L , 1 ) ;
//remove event reference from queue
int queue_length = lua_objlen ( L , 1 ) ;
lua_rawgeti ( L , 1 , index ) ;
for ( ; index < queue_length ; index + + ) {
lua_rawgeti ( L , 1 , index + 1 ) ;
lua_rawseti ( L , 1 , index ) ;
}
lua_pushnil ( L ) ;
lua_rawseti ( L , 1 , queue_length ) ;
lua_pop ( L , 1 ) ;
2015-12-28 08:13:02 +01:00
2018-05-20 09:46:04 +02:00
lua_rawgeti ( L , LUA_REGISTRYINDEX , event_ref ) ; //get event userdata from registry
System_Event_t * evt = lua_touserdata ( L , - 1 ) ;
lua_pop ( L , 1 ) ; //pop userdata from stack
queue_length = lua_objlen ( L , 1 ) ;
if ( queue_length > 0 ) {
task_post_low ( wifi_event_monitor_task_id , false ) ; //post task to process next item in queue
EVENT_DBG ( " %d events left in queue, posting task " , queue_length ) ;
}
lua_pop ( L , 1 ) ; //pop event queue from stack
2015-12-28 08:13:02 +01:00
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 :
2018-05-20 09:46:04 +02:00
EVENT_DBG ( " Event: %d (STAMODE_CONNECTED) " , EVENT_STAMODE_CONNECTED ) ;
2015-12-28 08:13:02 +01:00
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 ) ;
2018-05-20 09:46:04 +02:00
EVENT_DBG ( " Connected to SSID %s, Channel %d " ,
2015-12-28 08:13:02 +01:00
evt - > event_info . connected . ssid ,
evt - > event_info . connected . channel ) ;
break ;
case EVENT_STAMODE_DISCONNECTED :
2018-05-20 09:46:04 +02:00
EVENT_DBG ( " Event: %d (STAMODE_DISCONNECTED) " , EVENT_STAMODE_DISCONNECTED ) ;
2015-12-28 08:13:02 +01:00
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 ) ) ;
2018-05-20 09:46:04 +02:00
EVENT_DBG ( " Disconnect from SSID %s, reason %d " ,
2015-12-28 08:13:02 +01:00
evt - > event_info . disconnected . ssid ,
evt - > event_info . disconnected . reason ) ;
break ;
case EVENT_STAMODE_AUTHMODE_CHANGE :
2018-05-20 09:46:04 +02:00
EVENT_DBG ( " Event: %d (STAMODE_AUTHMODE_CHANGE) " , EVENT_STAMODE_AUTHMODE_CHANGE ) ;
2015-12-28 08:13:02 +01:00
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 ) ;
2018-05-20 09:46:04 +02:00
EVENT_DBG ( " Authmode: %u -> %u " ,
2015-12-28 08:13:02 +01:00
evt - > event_info . auth_change . old_mode ,
evt - > event_info . auth_change . new_mode ) ;
break ;
case EVENT_STAMODE_GOT_IP :
2018-05-20 09:46:04 +02:00
EVENT_DBG ( " Event: %d (STAMODE_GOT_IP) " , EVENT_STAMODE_GOT_IP ) ;
2015-12-28 08:13:02 +01:00
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 ) ) ;
2018-05-20 09:46:04 +02:00
EVENT_DBG ( " IP: " IPSTR " ,Mask: " IPSTR " ,GW: " IPSTR " " ,
2015-12-28 08:13:02 +01:00
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 :
2018-05-20 09:46:04 +02:00
EVENT_DBG ( " Event: %d (STAMODE_DHCP_TIMEOUT) " , EVENT_STAMODE_DHCP_TIMEOUT ) ;
2015-12-28 08:13:02 +01:00
break ;
case EVENT_SOFTAPMODE_STACONNECTED :
2018-05-20 09:46:04 +02:00
EVENT_DBG ( " Event: %d (SOFTAPMODE_STACONNECTED) " , EVENT_SOFTAPMODE_STACONNECTED ) ;
2015-12-28 08:13:02 +01:00
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 ) ;
2018-05-20 09:46:04 +02:00
EVENT_DBG ( " Station: " MACSTR " join, AID = %d " ,
2015-12-28 08:13:02 +01:00
MAC2STR ( evt - > event_info . sta_connected . mac ) ,
evt - > event_info . sta_connected . aid ) ;
break ;
case EVENT_SOFTAPMODE_STADISCONNECTED :
2018-05-20 09:46:04 +02:00
EVENT_DBG ( " Event: %d (SOFTAPMODE_STADISCONNECTED) " , EVENT_SOFTAPMODE_STADISCONNECTED ) ;
2015-12-28 08:13:02 +01:00
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 ) ;
2018-05-20 09:46:04 +02:00
EVENT_DBG ( " station: " MACSTR " leave, AID = %d " ,
2015-12-28 08:13:02 +01:00
MAC2STR ( evt - > event_info . sta_disconnected . mac ) ,
evt - > event_info . sta_disconnected . aid ) ;
break ;
case EVENT_SOFTAPMODE_PROBEREQRECVED :
2018-05-20 09:46:04 +02:00
EVENT_DBG ( " Event: %d (SOFTAPMODE_PROBEREQRECVED) " , EVENT_SOFTAPMODE_PROBEREQRECVED ) ;
2015-12-28 08:13:02 +01:00
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 ) ;
2018-05-20 09:46:04 +02:00
EVENT_DBG ( " Station PROBEREQ: " MACSTR " RSSI = %d " ,
2015-12-28 08:13:02 +01:00
MAC2STR ( evt - > event_info . ap_probereqrecved . mac ) ,
evt - > event_info . ap_probereqrecved . rssi ) ;
break ;
2017-05-15 09:05:22 +02:00
case EVENT_OPMODE_CHANGED :
2018-05-20 09:46:04 +02:00
EVENT_DBG ( " Event: %d (OPMODE_CHANGED) " , EVENT_OPMODE_CHANGED ) ;
2017-05-15 09:05:22 +02:00
wifi_add_int_field ( L , " old_mode " , evt - > event_info . opmode_changed . old_opmode ) ;
wifi_add_int_field ( L , " new_mode " , evt - > event_info . opmode_changed . new_opmode ) ;
2018-05-20 09:46:04 +02:00
EVENT_DBG ( " opmode: %u -> %u " ,
2017-05-15 09:05:22 +02:00
evt - > event_info . opmode_changed . old_opmode ,
evt - > event_info . opmode_changed . new_opmode ) ;
break ;
default : //if event is not implemented, return event id
2018-05-20 09:46:04 +02:00
EVENT_DBG ( " Event: %d (switch/case default) " , evt - > event ) ;
2015-12-28 08:13:02 +01:00
wifi_add_sprintf_field ( L , " info " , " event %u not implemented " , evt - > event ) ;
break ;
}
2018-05-20 09:46:04 +02:00
luaL_unref ( L , LUA_REGISTRYINDEX , event_ref ) ; //the userdata containing event info is no longer needed
event_ref = LUA_NOREF ;
2015-12-28 08:13:02 +01:00
2018-05-20 09:46:04 +02:00
lua_call ( L , 1 , 0 ) ; //execute user's callback and pass Lua table
return ;
2015-12-28 08:13:02 +01:00
}
# ifdef WIFI_EVENT_MONITOR_DISCONNECT_REASON_LIST_ENABLE
2020-04-27 02:13:38 +02:00
LROT_BEGIN ( wifi_event_monitor_reason , NULL , 0 )
2019-05-08 13:08:20 +02:00
LROT_NUMENTRY ( UNSPECIFIED , REASON_UNSPECIFIED )
LROT_NUMENTRY ( AUTH_EXPIRE , REASON_AUTH_EXPIRE )
LROT_NUMENTRY ( AUTH_LEAVE , REASON_AUTH_LEAVE )
LROT_NUMENTRY ( ASSOC_EXPIRE , REASON_ASSOC_EXPIRE )
LROT_NUMENTRY ( ASSOC_TOOMANY , REASON_ASSOC_TOOMANY )
LROT_NUMENTRY ( NOT_AUTHED , REASON_NOT_AUTHED )
LROT_NUMENTRY ( NOT_ASSOCED , REASON_NOT_ASSOCED )
LROT_NUMENTRY ( ASSOC_LEAVE , REASON_ASSOC_LEAVE )
LROT_NUMENTRY ( ASSOC_NOT_AUTHED , REASON_ASSOC_NOT_AUTHED )
LROT_NUMENTRY ( DISASSOC_PWRCAP_BAD , REASON_DISASSOC_PWRCAP_BAD )
LROT_NUMENTRY ( DISASSOC_SUPCHAN_BAD , REASON_DISASSOC_SUPCHAN_BAD )
LROT_NUMENTRY ( IE_INVALID , REASON_IE_INVALID )
LROT_NUMENTRY ( MIC_FAILURE , REASON_MIC_FAILURE )
LROT_NUMENTRY ( 4 WAY_HANDSHAKE_TIMEOUT , REASON_4WAY_HANDSHAKE_TIMEOUT )
LROT_NUMENTRY ( GROUP_KEY_UPDATE_TIMEOUT , REASON_GROUP_KEY_UPDATE_TIMEOUT )
LROT_NUMENTRY ( IE_IN_4WAY_DIFFERS , REASON_IE_IN_4WAY_DIFFERS )
LROT_NUMENTRY ( GROUP_CIPHER_INVALID , REASON_GROUP_CIPHER_INVALID )
LROT_NUMENTRY ( PAIRWISE_CIPHER_INVALID , REASON_PAIRWISE_CIPHER_INVALID )
LROT_NUMENTRY ( AKMP_INVALID , REASON_AKMP_INVALID )
LROT_NUMENTRY ( UNSUPP_RSN_IE_VERSION , REASON_UNSUPP_RSN_IE_VERSION )
LROT_NUMENTRY ( INVALID_RSN_IE_CAP , REASON_INVALID_RSN_IE_CAP )
LROT_NUMENTRY ( 802 _1X_AUTH_FAILED , REASON_802_1X_AUTH_FAILED )
LROT_NUMENTRY ( CIPHER_SUITE_REJECTED , REASON_CIPHER_SUITE_REJECTED )
LROT_NUMENTRY ( BEACON_TIMEOUT , REASON_BEACON_TIMEOUT )
LROT_NUMENTRY ( NO_AP_FOUND , REASON_NO_AP_FOUND )
LROT_NUMENTRY ( AUTH_FAIL , REASON_AUTH_FAIL )
LROT_NUMENTRY ( ASSOC_FAIL , REASON_ASSOC_FAIL )
LROT_NUMENTRY ( HANDSHAKE_TIMEOUT , REASON_HANDSHAKE_TIMEOUT )
2020-04-27 02:13:38 +02:00
LROT_END ( wifi_event_monitor_reason , NULL , 0 )
2019-05-08 13:08:20 +02:00
2015-12-28 08:13:02 +01:00
# endif
2020-04-27 02:13:38 +02:00
LROT_BEGIN ( wifi_event_monitor , NULL , 0 )
2019-05-08 13:08:20 +02:00
LROT_FUNCENTRY ( register , wifi_event_monitor_register )
LROT_FUNCENTRY ( unregister , wifi_event_monitor_register )
LROT_NUMENTRY ( STA_CONNECTED , EVENT_STAMODE_CONNECTED )
LROT_NUMENTRY ( STA_DISCONNECTED , EVENT_STAMODE_DISCONNECTED )
LROT_NUMENTRY ( STA_AUTHMODE_CHANGE , EVENT_STAMODE_AUTHMODE_CHANGE )
LROT_NUMENTRY ( STA_GOT_IP , EVENT_STAMODE_GOT_IP )
LROT_NUMENTRY ( STA_DHCP_TIMEOUT , EVENT_STAMODE_DHCP_TIMEOUT )
LROT_NUMENTRY ( AP_STACONNECTED , EVENT_SOFTAPMODE_STACONNECTED )
LROT_NUMENTRY ( AP_STADISCONNECTED , EVENT_SOFTAPMODE_STADISCONNECTED )
LROT_NUMENTRY ( AP_PROBEREQRECVED , EVENT_SOFTAPMODE_PROBEREQRECVED )
LROT_NUMENTRY ( WIFI_MODE_CHANGED , EVENT_OPMODE_CHANGED )
LROT_NUMENTRY ( EVENT_MAX , EVENT_MAX )
2015-12-28 08:13:02 +01:00
# ifdef WIFI_EVENT_MONITOR_DISCONNECT_REASON_LIST_ENABLE
2019-05-08 13:08:20 +02:00
LROT_TABENTRY ( reason , wifi_event_monitor_reason )
2015-12-28 08:13:02 +01:00
# endif
2020-04-27 02:13:38 +02:00
LROT_END ( wifi_event_monitor , NULL , 0 )
2019-05-08 13:08:20 +02:00
2015-12-28 08:13:02 +01:00
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