wifi_eventmon.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. // WiFi Event Monitor
  2. #include "module.h"
  3. #include "lauxlib.h"
  4. #include "platform.h"
  5. #include "c_string.h"
  6. #include "c_stdlib.h"
  7. #include "c_types.h"
  8. #include "user_interface.h"
  9. #include "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_STATION_STATUS_MONITOR_ENABLE
  15. //variables for wifi event monitor
  16. static int wifi_station_status_cb_ref[6] = {[0 ... 6-1] = LUA_NOREF};
  17. static os_timer_t wifi_sta_status_timer;
  18. static uint8 prev_wifi_status=0;
  19. // wifi.sta.eventMonStop()
  20. void wifi_station_event_mon_stop(lua_State* L)
  21. {
  22. os_timer_disarm(&wifi_sta_status_timer);
  23. if(lua_isstring(L,1))
  24. {
  25. int i;
  26. for (i=0; i<6; i++)
  27. {
  28. unregister_lua_cb(L, &wifi_station_status_cb_ref[i]);
  29. }
  30. }
  31. return;
  32. }
  33. static void wifi_status_cb(int arg)
  34. {
  35. lua_State* L = lua_getstate();
  36. if (wifi_get_opmode() == SOFTAP_MODE)
  37. {
  38. os_timer_disarm(&wifi_sta_status_timer);
  39. return;
  40. }
  41. int wifi_status = wifi_station_get_connect_status();
  42. if (wifi_status != prev_wifi_status)
  43. {
  44. if(wifi_station_status_cb_ref[wifi_status] != LUA_NOREF)
  45. {
  46. lua_rawgeti(L, LUA_REGISTRYINDEX, wifi_station_status_cb_ref[wifi_status]);
  47. lua_pushnumber(L, prev_wifi_status);
  48. lua_call(L, 1, 0);
  49. }
  50. }
  51. prev_wifi_status = wifi_status;
  52. }
  53. // wifi.sta.eventMonReg()
  54. int wifi_station_event_mon_reg(lua_State* L)
  55. {
  56. platform_print_deprecation_note("wifi.sta.eventmonreg() is replaced by wifi.eventmon.register()", "in the next version");
  57. uint8 id=(uint8)luaL_checknumber(L, 1);
  58. if ((id > 5)) // verify user specified a valid wifi status
  59. {
  60. return luaL_error( L, "valid wifi status:0-5" );
  61. }
  62. if (lua_type(L, 2) == LUA_TFUNCTION || lua_type(L, 2) == LUA_TLIGHTFUNCTION) //check if 2nd item on stack is a function
  63. {
  64. lua_pushvalue(L, 2); //push function to top of stack
  65. 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]
  66. }
  67. else
  68. {
  69. unregister_lua_cb(L, &wifi_station_status_cb_ref[id]); // unregister user's callback
  70. }
  71. return 0;
  72. }
  73. // wifi.sta.eventMonStart()
  74. int wifi_station_event_mon_start(lua_State* L)
  75. {
  76. if(wifi_get_opmode() == SOFTAP_MODE) //Verify ESP is in either Station mode or StationAP mode
  77. {
  78. return luaL_error( L, "Can't monitor in SOFTAP mode" );
  79. }
  80. if (wifi_station_status_cb_ref[0] == LUA_NOREF && wifi_station_status_cb_ref[1] == LUA_NOREF &&
  81. wifi_station_status_cb_ref[2] == LUA_NOREF && wifi_station_status_cb_ref[3] == LUA_NOREF &&
  82. wifi_station_status_cb_ref[4] == LUA_NOREF && wifi_station_status_cb_ref[5] == LUA_NOREF )
  83. { //verify user has registered callbacks
  84. return luaL_error( L, "No callbacks defined" );
  85. }
  86. uint32 ms = 150; //set default timer interval
  87. if(lua_isnumber(L, 1)) // check if user has specified a different timer interval
  88. {
  89. ms=luaL_checknumber(L, 1); // retrieve user-defined interval
  90. }
  91. os_timer_disarm(&wifi_sta_status_timer);
  92. os_timer_setfn(&wifi_sta_status_timer, (os_timer_func_t *)wifi_status_cb, NULL);
  93. os_timer_arm(&wifi_sta_status_timer, ms, 1);
  94. return 0;
  95. }
  96. #endif
  97. #ifdef WIFI_SDK_EVENT_MONITOR_ENABLE
  98. //variables for wifi event monitor
  99. static task_handle_t wifi_event_monitor_task_id; //variable to hold task id for task handler(process_event_queue)
  100. typedef struct evt_queue{
  101. System_Event_t *evt;
  102. struct evt_queue * next;
  103. }evt_queue_t; //structure to hold pointers to event info and next item in queue
  104. static evt_queue_t *wifi_event_queue_head; //pointer to beginning of queue
  105. static evt_queue_t *wifi_event_queue_tail; //pointer to end of queue
  106. static int wifi_event_cb_ref[EVENT_MAX+1] = { [0 ... EVENT_MAX] = LUA_NOREF}; //holds references to registered Lua callbacks
  107. // wifi.eventmon.register()
  108. static int wifi_event_monitor_register(lua_State* L)
  109. {
  110. uint8 id = (uint8)luaL_checknumber(L, 1);
  111. if ( id > EVENT_MAX ) //Check if user is trying to register a callback for a valid event.
  112. {
  113. return luaL_error( L, "valid wifi events:0-%d", EVENT_MAX );
  114. }
  115. else
  116. {
  117. if (lua_type(L, 2) == LUA_TFUNCTION || lua_type(L, 2) == LUA_TLIGHTFUNCTION) //check if 2nd item on stack is a function
  118. {
  119. lua_pushvalue(L, 2); // copy argument (func) to the top of stack
  120. 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]
  121. }
  122. else // unregister user's callback
  123. {
  124. unregister_lua_cb(L, &wifi_event_cb_ref[id]);
  125. }
  126. return 0;
  127. }
  128. }
  129. static void wifi_event_monitor_handle_event_cb(System_Event_t *evt)
  130. {
  131. EVENT_DBG("\n\twifi_event_monitor_handle_event_cb is called\n");
  132. if((wifi_event_cb_ref[evt->event] != LUA_NOREF) || ((wifi_event_cb_ref[EVENT_MAX] != LUA_NOREF) &&
  133. !(evt->event == EVENT_STAMODE_CONNECTED || evt->event == EVENT_STAMODE_DISCONNECTED ||
  134. evt->event == EVENT_STAMODE_AUTHMODE_CHANGE || evt->event == EVENT_STAMODE_GOT_IP ||
  135. evt->event == EVENT_STAMODE_DHCP_TIMEOUT || evt->event == EVENT_SOFTAPMODE_STACONNECTED ||
  136. evt->event == EVENT_SOFTAPMODE_STADISCONNECTED || evt->event == EVENT_SOFTAPMODE_PROBEREQRECVED ||
  137. evt->event == EVENT_OPMODE_CHANGED)))
  138. {
  139. evt_queue_t *temp = (evt_queue_t*)c_malloc(sizeof(evt_queue_t)); //allocate memory for new queue item
  140. temp->evt = (System_Event_t*)c_malloc(sizeof(System_Event_t)); //allocate memory to hold event structure
  141. if(!temp || !temp->evt)
  142. {
  143. luaL_error(lua_getstate(), "wifi.eventmon malloc: out of memory");
  144. return;
  145. }
  146. c_memcpy(temp->evt, evt, sizeof(System_Event_t)); //copy event data to new struct
  147. if(wifi_event_queue_head == NULL && wifi_event_queue_tail == NULL)// if queue is empty add item to queue
  148. {
  149. wifi_event_queue_head = wifi_event_queue_tail = temp;
  150. EVENT_DBG("\n\tqueue empty, adding event and posting task\n");
  151. task_post_low(wifi_event_monitor_task_id, false);
  152. }
  153. else //if queue is not empty append item to end of queue
  154. {
  155. wifi_event_queue_tail->next=temp;
  156. wifi_event_queue_tail=temp;
  157. EVENT_DBG("\n\tqueue not empty, appending queue\n");
  158. }
  159. }
  160. }
  161. static void wifi_event_monitor_process_event_queue(task_param_t param, uint8 priority)
  162. {
  163. lua_State* L = lua_getstate();
  164. evt_queue_t *temp = wifi_event_queue_head; //copy event_queue_head pointer to temporary pointer
  165. System_Event_t *evt = temp->evt; //copy event data pointer to temporary pointer
  166. EVENT_DBG("\t\tevent %u\n", evt->event);
  167. if(wifi_event_cb_ref[evt->event] != LUA_NOREF) // check if user has registered a callback
  168. {
  169. lua_rawgeti(L, LUA_REGISTRYINDEX, wifi_event_cb_ref[evt->event]); //get user's callback
  170. }
  171. else if((wifi_event_cb_ref[EVENT_MAX]!=LUA_NOREF) &&
  172. !(evt->event==EVENT_STAMODE_CONNECTED||evt->event==EVENT_STAMODE_DISCONNECTED||
  173. evt->event==EVENT_STAMODE_AUTHMODE_CHANGE||evt->event==EVENT_STAMODE_GOT_IP||
  174. evt->event==EVENT_STAMODE_DHCP_TIMEOUT||evt->event==EVENT_SOFTAPMODE_STACONNECTED||
  175. evt->event==EVENT_SOFTAPMODE_STADISCONNECTED||evt->event==EVENT_SOFTAPMODE_PROBEREQRECVED))
  176. { //if user has registered an EVENT_MAX(default) callback and event is not implemented...
  177. lua_rawgeti(L, LUA_REGISTRYINDEX, wifi_event_cb_ref[EVENT_MAX]); //get user's callback
  178. }
  179. lua_newtable( L );
  180. switch (evt->event)
  181. {
  182. case EVENT_STAMODE_CONNECTED:
  183. EVENT_DBG("\n\tSTAMODE_CONNECTED\n");
  184. wifi_add_sprintf_field(L, "SSID", (char*)evt->event_info.connected.ssid);
  185. wifi_add_sprintf_field(L, "BSSID", MACSTR, MAC2STR(evt->event_info.connected.bssid));
  186. wifi_add_int_field(L, "channel", evt->event_info.connected.channel);
  187. EVENT_DBG("\tConnected to SSID %s, Channel %d\n",
  188. evt->event_info.connected.ssid,
  189. evt->event_info.connected.channel);
  190. break;
  191. case EVENT_STAMODE_DISCONNECTED:
  192. EVENT_DBG("\n\tSTAMODE_DISCONNECTED\n");
  193. wifi_add_sprintf_field(L, "SSID", (char*)evt->event_info.disconnected.ssid);
  194. wifi_add_int_field(L, "reason", evt->event_info.disconnected.reason);
  195. wifi_add_sprintf_field(L, "BSSID", MACSTR, MAC2STR(evt->event_info.disconnected.bssid));
  196. EVENT_DBG("\tDisconnect from SSID %s, reason %d\n",
  197. evt->event_info.disconnected.ssid,
  198. evt->event_info.disconnected.reason);
  199. break;
  200. case EVENT_STAMODE_AUTHMODE_CHANGE:
  201. EVENT_DBG("\n\tSTAMODE_AUTHMODE_CHANGE\n");
  202. wifi_add_int_field(L, "old_auth_mode", evt->event_info.auth_change.old_mode);
  203. wifi_add_int_field(L, "new_auth_mode", evt->event_info.auth_change.new_mode);
  204. EVENT_DBG("\tAuthmode: %u -> %u\n",
  205. evt->event_info.auth_change.old_mode,
  206. evt->event_info.auth_change.new_mode);
  207. break;
  208. case EVENT_STAMODE_GOT_IP:
  209. EVENT_DBG("\n\tGOT_IP\n");
  210. wifi_add_sprintf_field(L, "IP", IPSTR, IP2STR(&evt->event_info.got_ip.ip));
  211. wifi_add_sprintf_field(L, "netmask", IPSTR, IP2STR(&evt->event_info.got_ip.mask));
  212. wifi_add_sprintf_field(L, "gateway", IPSTR, IP2STR(&evt->event_info.got_ip.gw));
  213. EVENT_DBG("\tIP:" IPSTR ",Mask:" IPSTR ",GW:" IPSTR "\n",
  214. IP2STR(&evt->event_info.got_ip.ip),
  215. IP2STR(&evt->event_info.got_ip.mask),
  216. IP2STR(&evt->event_info.got_ip.gw));
  217. break;
  218. case EVENT_STAMODE_DHCP_TIMEOUT:
  219. EVENT_DBG("\n\tSTAMODE_DHCP_TIMEOUT\n");
  220. break;
  221. case EVENT_SOFTAPMODE_STACONNECTED:
  222. EVENT_DBG("\n\tSOFTAPMODE_STACONNECTED\n");
  223. wifi_add_sprintf_field(L, "MAC", MACSTR, MAC2STR(evt->event_info.sta_connected.mac));
  224. wifi_add_int_field(L, "AID", evt->event_info.sta_connected.aid);
  225. EVENT_DBG("\tStation: " MACSTR "join, AID = %d\n",
  226. MAC2STR(evt->event_info.sta_connected.mac),
  227. evt->event_info.sta_connected.aid);
  228. break;
  229. case EVENT_SOFTAPMODE_STADISCONNECTED:
  230. EVENT_DBG("\n\tSOFTAPMODE_STADISCONNECTED\n");
  231. wifi_add_sprintf_field(L, "MAC", MACSTR, MAC2STR(evt->event_info.sta_disconnected.mac));
  232. wifi_add_int_field(L, "AID", evt->event_info.sta_disconnected.aid);
  233. EVENT_DBG("\tstation: " MACSTR "leave, AID = %d\n",
  234. MAC2STR(evt->event_info.sta_disconnected.mac),
  235. evt->event_info.sta_disconnected.aid);
  236. break;
  237. case EVENT_SOFTAPMODE_PROBEREQRECVED:
  238. EVENT_DBG("\n\tSOFTAPMODE_PROBEREQRECVED\n");
  239. wifi_add_sprintf_field(L, "MAC", MACSTR, MAC2STR(evt->event_info.ap_probereqrecved.mac));
  240. wifi_add_int_field(L, "RSSI", evt->event_info.ap_probereqrecved.rssi);
  241. EVENT_DBG("Station PROBEREQ: " MACSTR " RSSI = %d\n",
  242. MAC2STR(evt->event_info.ap_probereqrecved.mac),
  243. evt->event_info.ap_probereqrecved.rssi);
  244. break;
  245. case EVENT_OPMODE_CHANGED:
  246. EVENT_DBG("\n\tOPMODE_CHANGED\n");
  247. wifi_add_int_field(L, "old_mode", evt->event_info.opmode_changed.old_opmode);
  248. wifi_add_int_field(L, "new_mode", evt->event_info.opmode_changed.new_opmode);
  249. EVENT_DBG("\topmode: %u -> %u\n",
  250. evt->event_info.opmode_changed.old_opmode,
  251. evt->event_info.opmode_changed.new_opmode);
  252. break;
  253. default://if event is not implemented, return event id
  254. EVENT_DBG("\n\tswitch/case default\n");
  255. wifi_add_sprintf_field(L, "info", "event %u not implemented", evt->event);
  256. break;
  257. }
  258. lua_call(L, 1, 0); //execute user's callback and pass Lua table
  259. if (wifi_event_queue_head == wifi_event_queue_tail) //if queue is empty..
  260. {
  261. wifi_event_queue_head = wifi_event_queue_tail = NULL; //set queue pointers to NULL
  262. EVENT_DBG("\n\tQueue empty\n");
  263. }
  264. else //if queue is not empty...
  265. {
  266. wifi_event_queue_head = wifi_event_queue_head->next; //append item to end of queue
  267. EVENT_DBG("\n\tmore in queue, posting task...\n");
  268. task_post_low(wifi_event_monitor_task_id, false); //post task to process next item in queue
  269. }
  270. c_free(evt); //free memory used by event structure
  271. c_free(temp); //free memory used by queue structure
  272. }
  273. #ifdef WIFI_EVENT_MONITOR_DISCONNECT_REASON_LIST_ENABLE
  274. static const LUA_REG_TYPE wifi_event_monitor_reason_map[] =
  275. {
  276. { LSTRKEY( "UNSPECIFIED" ), LNUMVAL( REASON_UNSPECIFIED ) },
  277. { LSTRKEY( "AUTH_EXPIRE" ), LNUMVAL( REASON_AUTH_EXPIRE ) },
  278. { LSTRKEY( "AUTH_LEAVE" ), LNUMVAL( REASON_AUTH_LEAVE ) },
  279. { LSTRKEY( "ASSOC_EXPIRE" ), LNUMVAL( REASON_ASSOC_EXPIRE ) },
  280. { LSTRKEY( "ASSOC_TOOMANY" ), LNUMVAL( REASON_ASSOC_TOOMANY ) },
  281. { LSTRKEY( "NOT_AUTHED" ), LNUMVAL( REASON_NOT_AUTHED ) },
  282. { LSTRKEY( "NOT_ASSOCED" ), LNUMVAL( REASON_NOT_ASSOCED ) },
  283. { LSTRKEY( "ASSOC_LEAVE" ), LNUMVAL( REASON_ASSOC_LEAVE ) },
  284. { LSTRKEY( "ASSOC_NOT_AUTHED" ), LNUMVAL( REASON_ASSOC_NOT_AUTHED ) },
  285. { LSTRKEY( "DISASSOC_PWRCAP_BAD" ), LNUMVAL( REASON_DISASSOC_PWRCAP_BAD ) },
  286. { LSTRKEY( "DISASSOC_SUPCHAN_BAD" ), LNUMVAL( REASON_DISASSOC_SUPCHAN_BAD ) },
  287. { LSTRKEY( "IE_INVALID" ), LNUMVAL( REASON_IE_INVALID ) },
  288. { LSTRKEY( "MIC_FAILURE" ), LNUMVAL( REASON_MIC_FAILURE ) },
  289. { LSTRKEY( "4WAY_HANDSHAKE_TIMEOUT" ), LNUMVAL( REASON_4WAY_HANDSHAKE_TIMEOUT ) },
  290. { LSTRKEY( "GROUP_KEY_UPDATE_TIMEOUT" ), LNUMVAL( REASON_GROUP_KEY_UPDATE_TIMEOUT ) },
  291. { LSTRKEY( "IE_IN_4WAY_DIFFERS" ), LNUMVAL( REASON_IE_IN_4WAY_DIFFERS ) },
  292. { LSTRKEY( "GROUP_CIPHER_INVALID" ), LNUMVAL( REASON_GROUP_CIPHER_INVALID ) },
  293. { LSTRKEY( "PAIRWISE_CIPHER_INVALID" ), LNUMVAL( REASON_PAIRWISE_CIPHER_INVALID ) },
  294. { LSTRKEY( "AKMP_INVALID" ), LNUMVAL( REASON_AKMP_INVALID ) },
  295. { LSTRKEY( "UNSUPP_RSN_IE_VERSION" ), LNUMVAL( REASON_UNSUPP_RSN_IE_VERSION ) },
  296. { LSTRKEY( "INVALID_RSN_IE_CAP" ), LNUMVAL( REASON_INVALID_RSN_IE_CAP ) },
  297. { LSTRKEY( "802_1X_AUTH_FAILED" ), LNUMVAL( REASON_802_1X_AUTH_FAILED ) },
  298. { LSTRKEY( "CIPHER_SUITE_REJECTED" ), LNUMVAL( REASON_CIPHER_SUITE_REJECTED ) },
  299. { LSTRKEY( "BEACON_TIMEOUT" ), LNUMVAL( REASON_BEACON_TIMEOUT ) },
  300. { LSTRKEY( "NO_AP_FOUND" ), LNUMVAL( REASON_NO_AP_FOUND ) },
  301. { LSTRKEY( "AUTH_FAIL" ), LNUMVAL( REASON_AUTH_FAIL ) },
  302. { LSTRKEY( "ASSOC_FAIL" ), LNUMVAL( REASON_ASSOC_FAIL ) },
  303. { LSTRKEY( "HANDSHAKE_TIMEOUT" ), LNUMVAL( REASON_HANDSHAKE_TIMEOUT ) },
  304. { LNILKEY, LNILVAL }
  305. };
  306. #endif
  307. const LUA_REG_TYPE wifi_event_monitor_map[] =
  308. {
  309. { LSTRKEY( "register" ), LFUNCVAL( wifi_event_monitor_register ) },
  310. { LSTRKEY( "unregister" ), LFUNCVAL( wifi_event_monitor_register ) },
  311. { LSTRKEY( "STA_CONNECTED" ), LNUMVAL( EVENT_STAMODE_CONNECTED ) },
  312. { LSTRKEY( "STA_DISCONNECTED" ), LNUMVAL( EVENT_STAMODE_DISCONNECTED ) },
  313. { LSTRKEY( "STA_AUTHMODE_CHANGE" ), LNUMVAL( EVENT_STAMODE_AUTHMODE_CHANGE ) },
  314. { LSTRKEY( "STA_GOT_IP" ), LNUMVAL( EVENT_STAMODE_GOT_IP ) },
  315. { LSTRKEY( "STA_DHCP_TIMEOUT" ), LNUMVAL( EVENT_STAMODE_DHCP_TIMEOUT ) },
  316. { LSTRKEY( "AP_STACONNECTED" ), LNUMVAL( EVENT_SOFTAPMODE_STACONNECTED ) },
  317. { LSTRKEY( "AP_STADISCONNECTED" ), LNUMVAL( EVENT_SOFTAPMODE_STADISCONNECTED ) },
  318. { LSTRKEY( "AP_PROBEREQRECVED" ), LNUMVAL( EVENT_SOFTAPMODE_PROBEREQRECVED ) },
  319. { LSTRKEY( "WIFI_MODE_CHANGED" ), LNUMVAL( EVENT_OPMODE_CHANGED ) },
  320. { LSTRKEY( "EVENT_MAX" ), LNUMVAL( EVENT_MAX ) },
  321. #ifdef WIFI_EVENT_MONITOR_DISCONNECT_REASON_LIST_ENABLE
  322. { LSTRKEY( "reason" ), LROVAL( wifi_event_monitor_reason_map ) },
  323. #endif
  324. { LNILKEY, LNILVAL }
  325. };
  326. void wifi_eventmon_init()
  327. {
  328. wifi_event_monitor_task_id = task_get_id(wifi_event_monitor_process_event_queue);//get task id from task interface
  329. wifi_set_event_handler_cb(wifi_event_monitor_handle_event_cb);
  330. return;
  331. }
  332. #endif
  333. #endif