wifi_eventmon.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. // WiFi Event Monitor
  2. #include "module.h"
  3. #include "lauxlib.h"
  4. #include "platform.h"
  5. #include <string.h>
  6. #include <stddef.h>
  7. #include <stdint.h>
  8. #include "user_interface.h"
  9. #include "smart/smart.h"
  10. #include "smartconfig.h"
  11. #include "user_config.h"
  12. #include "wifi_common.h"
  13. #if defined(LUA_USE_MODULES_WIFI)
  14. #ifdef WIFI_SDK_EVENT_MONITOR_ENABLE
  15. //variables for wifi event monitor
  16. static task_handle_t wifi_event_monitor_task_id; //variable to hold task id for task handler(process_event_queue)
  17. static int wifi_event_cb_ref[EVENT_MAX+1] = { [0 ... EVENT_MAX] = LUA_NOREF}; //holds references to registered Lua callbacks
  18. #ifdef LUA_USE_MODULES_WIFI_MONITOR
  19. static int (*hook_fn)(System_Event_t *);
  20. void wifi_event_monitor_register_hook(int (*fn)(System_Event_t*)) {
  21. hook_fn = fn;
  22. }
  23. #endif
  24. // wifi.eventmon.register()
  25. int wifi_event_monitor_register(lua_State* L)
  26. {
  27. uint8 id = (uint8)luaL_checknumber(L, 1);
  28. if ( id > EVENT_MAX ) //Check if user is trying to register a callback for a valid event.
  29. {
  30. return luaL_error( L, "valid wifi events:0-%d", EVENT_MAX );
  31. }
  32. else
  33. {
  34. if (lua_isfunction(L, 2)) //check if 2nd item on stack is a function
  35. {
  36. lua_pushvalue(L, 2); // copy argument (func) to the top of stack
  37. 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]
  38. }
  39. else // unregister user's callback
  40. {
  41. unregister_lua_cb(L, &wifi_event_cb_ref[id]);
  42. }
  43. return 0;
  44. }
  45. }
  46. static sint32_t event_queue_ref = LUA_NOREF;
  47. static void wifi_event_monitor_handle_event_cb(System_Event_t *evt)
  48. {
  49. EVENT_DBG("was called (Event:%d)", evt->event);
  50. #ifdef LUA_USE_MODULES_WIFI_MONITOR
  51. if (hook_fn && hook_fn(evt)) {
  52. return;
  53. }
  54. #endif
  55. if((wifi_event_cb_ref[evt->event] != LUA_NOREF) || ((wifi_event_cb_ref[EVENT_MAX] != LUA_NOREF) &&
  56. !(evt->event == EVENT_STAMODE_CONNECTED || evt->event == EVENT_STAMODE_DISCONNECTED ||
  57. evt->event == EVENT_STAMODE_AUTHMODE_CHANGE || evt->event == EVENT_STAMODE_GOT_IP ||
  58. evt->event == EVENT_STAMODE_DHCP_TIMEOUT || evt->event == EVENT_SOFTAPMODE_STACONNECTED ||
  59. evt->event == EVENT_SOFTAPMODE_STADISCONNECTED || evt->event == EVENT_SOFTAPMODE_PROBEREQRECVED ||
  60. evt->event == EVENT_OPMODE_CHANGED)))
  61. {
  62. lua_State* L = lua_getstate();
  63. if(event_queue_ref == LUA_NOREF){ //if event queue has not been created, create it now
  64. lua_newtable(L);
  65. event_queue_ref = luaL_ref(L, LUA_REGISTRYINDEX);
  66. }
  67. lua_rawgeti(L, LUA_REGISTRYINDEX, event_queue_ref);
  68. System_Event_t* evt_tmp = lua_newuserdata(L, sizeof(System_Event_t));
  69. memcpy(evt_tmp, evt, sizeof(System_Event_t)); //copy event data to new struct
  70. sint32_t evt_ud_ref = luaL_ref(L, LUA_REGISTRYINDEX);
  71. size_t queue_len = lua_objlen(L, -1);
  72. //add event to queue
  73. lua_pushnumber(L, queue_len+1);
  74. lua_pushnumber(L, evt_ud_ref);
  75. lua_rawset(L, -3);
  76. if(queue_len == 0){ //if queue was empty, post task
  77. EVENT_DBG("Posting task");
  78. task_post_low(wifi_event_monitor_task_id, false);
  79. }
  80. else{
  81. EVENT_DBG("Appending queue, items in queue: %d", lua_objlen(L, -1));
  82. }
  83. lua_pop(L, 1);
  84. } //else{} //there are no callbacks registered, so the event can't be processed
  85. }
  86. static void wifi_event_monitor_process_event_queue(task_param_t param, uint8 priority)
  87. {
  88. lua_State* L = lua_getstate();
  89. lua_rawgeti(L, LUA_REGISTRYINDEX, event_queue_ref);
  90. int index = 1;
  91. lua_rawgeti(L, 1, index);
  92. sint32 event_ref = lua_tonumber(L, -1);
  93. lua_pop(L, 1);
  94. //remove event reference from queue
  95. int queue_length = lua_objlen(L, 1);
  96. lua_rawgeti(L, 1, index);
  97. for(; index<queue_length;index++){
  98. lua_rawgeti(L, 1, index+1);
  99. lua_rawseti(L, 1, index);
  100. }
  101. lua_pushnil(L);
  102. lua_rawseti(L, 1, queue_length);
  103. lua_pop(L, 1);
  104. lua_rawgeti(L, LUA_REGISTRYINDEX, event_ref); //get event userdata from registry
  105. System_Event_t *evt = lua_touserdata(L, -1);
  106. lua_pop(L, 1); //pop userdata from stack
  107. queue_length = lua_objlen(L, 1);
  108. if (queue_length>0){
  109. task_post_low(wifi_event_monitor_task_id, false); //post task to process next item in queue
  110. EVENT_DBG("%d events left in queue, posting task", queue_length);
  111. }
  112. lua_pop(L, 1); //pop event queue from stack
  113. if(wifi_event_cb_ref[evt->event] != LUA_NOREF) // check if user has registered a callback
  114. {
  115. lua_rawgeti(L, LUA_REGISTRYINDEX, wifi_event_cb_ref[evt->event]); //get user's callback
  116. }
  117. else if((wifi_event_cb_ref[EVENT_MAX]!=LUA_NOREF) &&
  118. !(evt->event==EVENT_STAMODE_CONNECTED||evt->event==EVENT_STAMODE_DISCONNECTED||
  119. evt->event==EVENT_STAMODE_AUTHMODE_CHANGE||evt->event==EVENT_STAMODE_GOT_IP||
  120. evt->event==EVENT_STAMODE_DHCP_TIMEOUT||evt->event==EVENT_SOFTAPMODE_STACONNECTED||
  121. evt->event==EVENT_SOFTAPMODE_STADISCONNECTED||evt->event==EVENT_SOFTAPMODE_PROBEREQRECVED))
  122. { //if user has registered an EVENT_MAX(default) callback and event is not implemented...
  123. lua_rawgeti(L, LUA_REGISTRYINDEX, wifi_event_cb_ref[EVENT_MAX]); //get user's callback
  124. }
  125. lua_newtable( L );
  126. switch (evt->event)
  127. {
  128. case EVENT_STAMODE_CONNECTED:
  129. EVENT_DBG("Event: %d (STAMODE_CONNECTED)", EVENT_STAMODE_CONNECTED);
  130. wifi_add_sprintf_field(L, "SSID", (char*)evt->event_info.connected.ssid);
  131. wifi_add_sprintf_field(L, "BSSID", MACSTR, MAC2STR(evt->event_info.connected.bssid));
  132. wifi_add_int_field(L, "channel", evt->event_info.connected.channel);
  133. EVENT_DBG("Connected to SSID %s, Channel %d",
  134. evt->event_info.connected.ssid,
  135. evt->event_info.connected.channel);
  136. break;
  137. case EVENT_STAMODE_DISCONNECTED:
  138. EVENT_DBG("Event: %d (STAMODE_DISCONNECTED)", EVENT_STAMODE_DISCONNECTED);
  139. wifi_add_sprintf_field(L, "SSID", (char*)evt->event_info.disconnected.ssid);
  140. wifi_add_int_field(L, "reason", evt->event_info.disconnected.reason);
  141. wifi_add_sprintf_field(L, "BSSID", MACSTR, MAC2STR(evt->event_info.disconnected.bssid));
  142. EVENT_DBG("Disconnect from SSID %s, reason %d",
  143. evt->event_info.disconnected.ssid,
  144. evt->event_info.disconnected.reason);
  145. break;
  146. case EVENT_STAMODE_AUTHMODE_CHANGE:
  147. EVENT_DBG("Event: %d (STAMODE_AUTHMODE_CHANGE)", EVENT_STAMODE_AUTHMODE_CHANGE);
  148. wifi_add_int_field(L, "old_auth_mode", evt->event_info.auth_change.old_mode);
  149. wifi_add_int_field(L, "new_auth_mode", evt->event_info.auth_change.new_mode);
  150. EVENT_DBG("Authmode: %u -> %u",
  151. evt->event_info.auth_change.old_mode,
  152. evt->event_info.auth_change.new_mode);
  153. break;
  154. case EVENT_STAMODE_GOT_IP:
  155. EVENT_DBG("Event: %d (STAMODE_GOT_IP)", EVENT_STAMODE_GOT_IP);
  156. wifi_add_sprintf_field(L, "IP", IPSTR, IP2STR(&evt->event_info.got_ip.ip));
  157. wifi_add_sprintf_field(L, "netmask", IPSTR, IP2STR(&evt->event_info.got_ip.mask));
  158. wifi_add_sprintf_field(L, "gateway", IPSTR, IP2STR(&evt->event_info.got_ip.gw));
  159. EVENT_DBG("IP:" IPSTR ",Mask:" IPSTR ",GW:" IPSTR "",
  160. IP2STR(&evt->event_info.got_ip.ip),
  161. IP2STR(&evt->event_info.got_ip.mask),
  162. IP2STR(&evt->event_info.got_ip.gw));
  163. break;
  164. case EVENT_STAMODE_DHCP_TIMEOUT:
  165. EVENT_DBG("Event: %d (STAMODE_DHCP_TIMEOUT)", EVENT_STAMODE_DHCP_TIMEOUT);
  166. break;
  167. case EVENT_SOFTAPMODE_STACONNECTED:
  168. EVENT_DBG("Event: %d (SOFTAPMODE_STACONNECTED)", EVENT_SOFTAPMODE_STACONNECTED);
  169. wifi_add_sprintf_field(L, "MAC", MACSTR, MAC2STR(evt->event_info.sta_connected.mac));
  170. wifi_add_int_field(L, "AID", evt->event_info.sta_connected.aid);
  171. EVENT_DBG("Station: " MACSTR "join, AID = %d",
  172. MAC2STR(evt->event_info.sta_connected.mac),
  173. evt->event_info.sta_connected.aid);
  174. break;
  175. case EVENT_SOFTAPMODE_STADISCONNECTED:
  176. EVENT_DBG("Event: %d (SOFTAPMODE_STADISCONNECTED)", EVENT_SOFTAPMODE_STADISCONNECTED);
  177. wifi_add_sprintf_field(L, "MAC", MACSTR, MAC2STR(evt->event_info.sta_disconnected.mac));
  178. wifi_add_int_field(L, "AID", evt->event_info.sta_disconnected.aid);
  179. EVENT_DBG("station: " MACSTR "leave, AID = %d",
  180. MAC2STR(evt->event_info.sta_disconnected.mac),
  181. evt->event_info.sta_disconnected.aid);
  182. break;
  183. case EVENT_SOFTAPMODE_PROBEREQRECVED:
  184. EVENT_DBG("Event: %d (SOFTAPMODE_PROBEREQRECVED)", EVENT_SOFTAPMODE_PROBEREQRECVED);
  185. wifi_add_sprintf_field(L, "MAC", MACSTR, MAC2STR(evt->event_info.ap_probereqrecved.mac));
  186. wifi_add_int_field(L, "RSSI", evt->event_info.ap_probereqrecved.rssi);
  187. EVENT_DBG("Station PROBEREQ: " MACSTR " RSSI = %d",
  188. MAC2STR(evt->event_info.ap_probereqrecved.mac),
  189. evt->event_info.ap_probereqrecved.rssi);
  190. break;
  191. case EVENT_OPMODE_CHANGED:
  192. EVENT_DBG("Event: %d (OPMODE_CHANGED)", EVENT_OPMODE_CHANGED);
  193. wifi_add_int_field(L, "old_mode", evt->event_info.opmode_changed.old_opmode);
  194. wifi_add_int_field(L, "new_mode", evt->event_info.opmode_changed.new_opmode);
  195. EVENT_DBG("opmode: %u -> %u",
  196. evt->event_info.opmode_changed.old_opmode,
  197. evt->event_info.opmode_changed.new_opmode);
  198. break;
  199. default://if event is not implemented, return event id
  200. EVENT_DBG("Event: %d (switch/case default)", evt->event);
  201. wifi_add_sprintf_field(L, "info", "event %u not implemented", evt->event);
  202. break;
  203. }
  204. luaL_unref(L, LUA_REGISTRYINDEX, event_ref); //the userdata containing event info is no longer needed
  205. event_ref = LUA_NOREF;
  206. luaL_pcallx(L, 1, 0); //execute user's callback and pass Lua table
  207. return;
  208. }
  209. #ifdef WIFI_EVENT_MONITOR_DISCONNECT_REASON_LIST_ENABLE
  210. LROT_BEGIN(wifi_event_monitor_reason, NULL, 0)
  211. LROT_NUMENTRY( UNSPECIFIED, REASON_UNSPECIFIED )
  212. LROT_NUMENTRY( AUTH_EXPIRE, REASON_AUTH_EXPIRE )
  213. LROT_NUMENTRY( AUTH_LEAVE, REASON_AUTH_LEAVE )
  214. LROT_NUMENTRY( ASSOC_EXPIRE, REASON_ASSOC_EXPIRE )
  215. LROT_NUMENTRY( ASSOC_TOOMANY, REASON_ASSOC_TOOMANY )
  216. LROT_NUMENTRY( NOT_AUTHED, REASON_NOT_AUTHED )
  217. LROT_NUMENTRY( NOT_ASSOCED, REASON_NOT_ASSOCED )
  218. LROT_NUMENTRY( ASSOC_LEAVE, REASON_ASSOC_LEAVE )
  219. LROT_NUMENTRY( ASSOC_NOT_AUTHED, REASON_ASSOC_NOT_AUTHED )
  220. LROT_NUMENTRY( DISASSOC_PWRCAP_BAD, REASON_DISASSOC_PWRCAP_BAD )
  221. LROT_NUMENTRY( DISASSOC_SUPCHAN_BAD, REASON_DISASSOC_SUPCHAN_BAD )
  222. LROT_NUMENTRY( IE_INVALID, REASON_IE_INVALID )
  223. LROT_NUMENTRY( MIC_FAILURE, REASON_MIC_FAILURE )
  224. LROT_NUMENTRY( 4WAY_HANDSHAKE_TIMEOUT, REASON_4WAY_HANDSHAKE_TIMEOUT )
  225. LROT_NUMENTRY( GROUP_KEY_UPDATE_TIMEOUT, REASON_GROUP_KEY_UPDATE_TIMEOUT )
  226. LROT_NUMENTRY( IE_IN_4WAY_DIFFERS, REASON_IE_IN_4WAY_DIFFERS )
  227. LROT_NUMENTRY( GROUP_CIPHER_INVALID, REASON_GROUP_CIPHER_INVALID )
  228. LROT_NUMENTRY( PAIRWISE_CIPHER_INVALID, REASON_PAIRWISE_CIPHER_INVALID )
  229. LROT_NUMENTRY( AKMP_INVALID, REASON_AKMP_INVALID )
  230. LROT_NUMENTRY( UNSUPP_RSN_IE_VERSION, REASON_UNSUPP_RSN_IE_VERSION )
  231. LROT_NUMENTRY( INVALID_RSN_IE_CAP, REASON_INVALID_RSN_IE_CAP )
  232. LROT_NUMENTRY( 802_1X_AUTH_FAILED, REASON_802_1X_AUTH_FAILED )
  233. LROT_NUMENTRY( CIPHER_SUITE_REJECTED, REASON_CIPHER_SUITE_REJECTED )
  234. LROT_NUMENTRY( BEACON_TIMEOUT, REASON_BEACON_TIMEOUT )
  235. LROT_NUMENTRY( NO_AP_FOUND, REASON_NO_AP_FOUND )
  236. LROT_NUMENTRY( AUTH_FAIL, REASON_AUTH_FAIL )
  237. LROT_NUMENTRY( ASSOC_FAIL, REASON_ASSOC_FAIL )
  238. LROT_NUMENTRY( HANDSHAKE_TIMEOUT, REASON_HANDSHAKE_TIMEOUT )
  239. LROT_END(wifi_event_monitor_reason, NULL, 0)
  240. #endif
  241. LROT_BEGIN(wifi_event_monitor, NULL, 0)
  242. LROT_FUNCENTRY( register, wifi_event_monitor_register )
  243. LROT_FUNCENTRY( unregister, wifi_event_monitor_register )
  244. LROT_NUMENTRY( STA_CONNECTED, EVENT_STAMODE_CONNECTED )
  245. LROT_NUMENTRY( STA_DISCONNECTED, EVENT_STAMODE_DISCONNECTED )
  246. LROT_NUMENTRY( STA_AUTHMODE_CHANGE, EVENT_STAMODE_AUTHMODE_CHANGE )
  247. LROT_NUMENTRY( STA_GOT_IP, EVENT_STAMODE_GOT_IP )
  248. LROT_NUMENTRY( STA_DHCP_TIMEOUT, EVENT_STAMODE_DHCP_TIMEOUT )
  249. LROT_NUMENTRY( AP_STACONNECTED, EVENT_SOFTAPMODE_STACONNECTED )
  250. LROT_NUMENTRY( AP_STADISCONNECTED, EVENT_SOFTAPMODE_STADISCONNECTED )
  251. LROT_NUMENTRY( AP_PROBEREQRECVED, EVENT_SOFTAPMODE_PROBEREQRECVED )
  252. LROT_NUMENTRY( WIFI_MODE_CHANGED, EVENT_OPMODE_CHANGED )
  253. LROT_NUMENTRY( EVENT_MAX, EVENT_MAX )
  254. #ifdef WIFI_EVENT_MONITOR_DISCONNECT_REASON_LIST_ENABLE
  255. LROT_TABENTRY( reason, wifi_event_monitor_reason )
  256. #endif
  257. LROT_END(wifi_event_monitor, NULL, 0)
  258. void wifi_eventmon_init()
  259. {
  260. wifi_event_monitor_task_id = task_get_id(wifi_event_monitor_process_event_queue);//get task id from task interface
  261. wifi_set_event_handler_cb(wifi_event_monitor_handle_event_cb);
  262. return;
  263. }
  264. #endif
  265. #endif