wifi_interface.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. /******************************************************************************
  2. * 2016 IdeasX v0.3.1 Module Firmware
  3. *
  4. * File Name: wifi.c
  5. * Author: Tyler Berezowsky
  6. * Description: This file is going to need alot of help by a C wizard, but it currently works...I think.
  7. *
  8. * 2016/8/8, v1.0 created this file
  9. *******************************************************************************/
  10. #include "interface/wifi_interface.h"
  11. #include "log/esp_log.h"
  12. #include "esp_common.h"
  13. static const char* TAG = "WiFi Interface";
  14. static wifi_config_t wifi_config;
  15. static struct bss_info *bss_link, *head_bss_link;
  16. /******************************************************************************
  17. * FunctionName : destory_linked_list
  18. * Description :
  19. * Parameters :
  20. * Returns :
  21. *******************************************************************************/
  22. static bool ICACHE_FLASH_ATTR destory_linked_list(void)
  23. {
  24. if(head_bss_link != NULL)
  25. {
  26. while(head_bss_link != NULL)
  27. {
  28. bss_link = head_bss_link;
  29. head_bss_link = head_bss_link->next.stqe_next;
  30. os_free(bss_link);
  31. }
  32. return TRUE;
  33. }
  34. else
  35. {
  36. return FALSE;
  37. }
  38. }
  39. /******************************************************************************
  40. * FunctionName : copy_linked_list
  41. * Description :
  42. * Parameters :
  43. * Returns :
  44. *******************************************************************************/
  45. static struct bss_info* ICACHE_FLASH_ATTR copy_linked_list(struct bss_info *ptr_original_node)
  46. {
  47. struct bss_info *ptr_new_head, *ptr_new_node;
  48. if(ptr_original_node != NULL)
  49. {
  50. ptr_new_head = (struct bss_info *)os_malloc(sizeof(struct bss_info));
  51. if (ptr_new_head == NULL)
  52. {
  53. ESP_LOGE(TAG, "no RAM!");
  54. return NULL;
  55. }
  56. }
  57. else
  58. return NULL;
  59. os_memcpy(ptr_new_head, ptr_original_node, sizeof(struct bss_info));
  60. ptr_original_node = ptr_original_node->next.stqe_next;
  61. ptr_new_node = ptr_new_head;
  62. while(ptr_original_node != NULL)
  63. {
  64. ptr_new_node->next.stqe_next = (struct bss_info *)os_malloc(sizeof(struct bss_info));
  65. ptr_new_node = ptr_new_node->next.stqe_next;
  66. os_memcpy(ptr_new_node, ptr_original_node, sizeof(struct bss_info));
  67. if (ptr_new_node == NULL)
  68. {
  69. ESP_LOGE(TAG, "No RAM!");
  70. while(ptr_new_head != NULL)
  71. {
  72. ptr_new_node = ptr_new_head;
  73. ptr_new_head = ptr_new_head->next.stqe_next;
  74. os_free(ptr_new_node);
  75. }
  76. ESP_LOGE(TAG, "deleted linked list");
  77. return NULL;
  78. }
  79. ptr_original_node = ptr_original_node->next.stqe_next;
  80. }
  81. return ptr_new_head;
  82. }
  83. /******************************************************************************
  84. * FunctionName : wifi_timeout_cb
  85. * Description :
  86. * Parameters :
  87. * Returns :
  88. *******************************************************************************/
  89. static void ICACHE_FLASH_ATTR wifi_timeout_cb(void)
  90. {
  91. ESP_LOGI(TAG, "wifi connection timed out");
  92. wifi_config.wifi_process = false;
  93. if (wifi_config.fail_cb != NULL)
  94. wifi_config.fail_cb(WIFI_TIMEOUT_FAILURE);
  95. }
  96. /******************************************************************************
  97. * FunctionName : wifi_event_handler_cb
  98. * Description :
  99. * Parameters :
  100. * Returns :
  101. *******************************************************************************/
  102. static void ICACHE_FLASH_ATTR wifi_event_handler_cb(System_Event_t *evt)
  103. {
  104. switch (evt->event)
  105. {
  106. case EVENT_STAMODE_CONNECTED:
  107. {
  108. wifi_config.ap_flag = true;
  109. ESP_LOGD(TAG, "connected to ssid %s, channel %d",
  110. evt->event_info.connected.ssid,
  111. evt->event_info.connected.channel);
  112. break;
  113. }
  114. case EVENT_STAMODE_DISCONNECTED:
  115. {
  116. wifi_config.ap_flag = false;
  117. wifi_config.ip_flag = false;
  118. ESP_LOGD(TAG, "disconnected from ssid %s, reason %d",
  119. evt->event_info.disconnected.ssid,
  120. evt->event_info.disconnected.reason);
  121. if (wifi_config.wifi_process == false)
  122. {
  123. wifi_station_disconnect();
  124. if (wifi_config.fail_cb != NULL)
  125. wifi_config.fail_cb(WIFI_AP_DISCONNECTED);
  126. }
  127. break;
  128. }
  129. case EVENT_STAMODE_AUTHMODE_CHANGE:
  130. {
  131. wifi_config.ap_flag = false;
  132. wifi_config.ip_flag = false;
  133. ESP_LOGD(TAG, "mode: %d -> %d",
  134. evt->event_info.auth_change.old_mode,
  135. evt->event_info.auth_change.new_mode);
  136. if (wifi_config.wifi_process == false)
  137. {
  138. if (wifi_config.fail_cb != NULL)
  139. wifi_config.fail_cb(WIFI_AP_AUTHMODE_CHANGE);
  140. }
  141. break;
  142. }
  143. case EVENT_STAMODE_GOT_IP:
  144. {
  145. wifi_config.ip_flag = true;
  146. os_timer_disarm(&wifi_config.timeout_timer);
  147. ESP_LOGD(TAG, "ip:" IPSTR ",mask:" IPSTR ",gw:" IPSTR,
  148. IP2STR(&evt->event_info.got_ip.ip),
  149. IP2STR(&evt->event_info.got_ip.mask),
  150. IP2STR(&evt->event_info.got_ip.gw));
  151. wifi_config.wifi_process = false;
  152. if (wifi_config.success_cb != NULL)
  153. wifi_config.success_cb();
  154. break;
  155. }
  156. default:
  157. {
  158. ESP_LOGD(TAG, "unknown Wi-Fi failure code");
  159. break;
  160. }
  161. }
  162. }
  163. /******************************************************************************
  164. * FunctionName : wifi_process
  165. * Description :
  166. * Parameters :
  167. * Returns :
  168. *******************************************************************************/
  169. static ICACHE_FLASH_ATTR wifi_process(void)
  170. {
  171. uint8_t ssid[33];
  172. uint8_t ap_index;
  173. struct station_config stationConfig[5];
  174. // retrive stations stored in flash
  175. uint8_t num = wifi_station_get_ap_info(stationConfig);
  176. if (num == 0)
  177. {
  178. if (wifi_config.fail_cb != NULL)
  179. wifi_config.fail_cb(WIFI_NO_STORED_APS_FAILURE);
  180. return;
  181. }
  182. // loop through every value in the RSSI sorted linked list
  183. ESP_LOGD(TAG, "searching stored access points")
  184. while(bss_link != NULL)
  185. {
  186. // feed SW watch dog timer to prevent rest
  187. system_soft_wdt_feed();
  188. // retrive SSID from RSSI sorted linked list
  189. os_memset(ssid, 0, 33);
  190. if (os_strlen(bss_link->ssid) <= 32)
  191. {
  192. os_memcpy(ssid, bss_link->ssid, os_strlen(bss_link->ssid));
  193. }
  194. else
  195. {
  196. os_memcpy(ssid, bss_link->ssid, 32);
  197. }
  198. // search the linked list for an AP stored in the cache which was also
  199. // found in the access point scan
  200. for (ap_index=0;ap_index<num;ap_index++)
  201. {
  202. ESP_LOGV(TAG, "comparing aps \"%s\" and \"%s\"", ssid, stationConfig[ap_index].ssid);
  203. if (!strcmp(ssid, stationConfig[ap_index].ssid))
  204. {
  205. ESP_LOGD(TAG, "access point located: %s", ssid);
  206. wifi_config.ap_found = true;
  207. os_timer_arm(&wifi_config.timeout_timer, wifi_config.timeout_delay, false);
  208. wifi_station_ap_change(ap_index);
  209. wifi_station_connect();
  210. break;
  211. }
  212. }
  213. bss_link = bss_link->next.stqe_next;
  214. // stop looping through RSSI sorted scan results and start connection
  215. // timeout timer
  216. if (wifi_config.ap_found)
  217. {
  218. break;
  219. }
  220. }
  221. if (!wifi_config.ap_found)
  222. {
  223. if (wifi_config.fail_cb != NULL)
  224. wifi_config.fail_cb(WIFI_NO_AVAILABLE_APS_FAILURE);
  225. ESP_LOGD(TAG, "access point not found")
  226. }
  227. destory_linked_list();
  228. }
  229. /******************************************************************************
  230. * FunctionName : wifi_scan_done
  231. * Description :
  232. * Parameters :
  233. * Returns :
  234. *******************************************************************************/
  235. static void ICACHE_FLASH_ATTR wifi_scan_done(void *arg, STATUS status)
  236. {
  237. uint8_t ssid[33];
  238. uint8_t bssid[6];
  239. if (status == OK) // if the scan was sucessful
  240. {
  241. bss_link = (struct bss_info *)arg;
  242. struct bss_info *bss_link_next, *bss_link_curr, *bss_link_prev, *bss_link_head;
  243. uint32_t i,numAP,j;
  244. if (bss_link == NULL)
  245. {
  246. if (wifi_config.fail_cb != NULL)
  247. wifi_config.fail_cb(WIFI_NO_AVAILABLE_APS_FAILURE);
  248. return;
  249. }
  250. // copy linked list because SDK will end up destorying it
  251. bss_link = copy_linked_list(bss_link);
  252. bss_link_head = bss_link;
  253. // get len of linked list
  254. numAP=0;
  255. while(bss_link != NULL)
  256. {
  257. numAP++;
  258. bss_link = bss_link->next.stqe_next;
  259. }
  260. ESP_LOGD(TAG, "number of APs found: %d", numAP);
  261. bss_link = bss_link_head; // reset to head
  262. // sort linked list by rssi
  263. for(i=0;i<numAP-1;i++)
  264. {
  265. bss_link_prev = NULL;
  266. bss_link_curr = bss_link;
  267. bss_link_next = bss_link->next.stqe_next;
  268. for(j=0; j<numAP-1-i; j++)
  269. {
  270. system_soft_wdt_feed();
  271. if (bss_link_next->rssi > bss_link_curr->rssi) {
  272. if (bss_link_prev == NULL) {
  273. // swap node position and head position
  274. bss_link_curr->next.stqe_next = bss_link_next->next.stqe_next;
  275. bss_link_next->next.stqe_next = bss_link_curr;
  276. bss_link = bss_link_next; // store new head
  277. bss_link_prev = bss_link_next;
  278. bss_link_next = bss_link_curr->next.stqe_next;
  279. } else {
  280. // swap node positions
  281. bss_link_prev->next.stqe_next = bss_link_next;
  282. bss_link_curr->next.stqe_next = bss_link_next->next.stqe_next; // could be null
  283. bss_link_next->next.stqe_next = bss_link_curr;
  284. bss_link_prev = bss_link_next;
  285. bss_link_next = bss_link_curr->next.stqe_next;
  286. }
  287. } else {
  288. // move along like nothing happened
  289. bss_link_prev = bss_link_curr;
  290. bss_link_curr = bss_link_next;
  291. bss_link_next = bss_link_next->next.stqe_next;
  292. }
  293. }
  294. }
  295. bss_link_head = bss_link; // store head
  296. // print sorted list of stations
  297. while (bss_link != NULL) {
  298. os_memset(ssid, 0, 33);
  299. os_memset(bssid, 0, 6);
  300. if (os_strlen(bss_link->ssid) <= 32) {
  301. os_memcpy(ssid, bss_link->ssid, os_strlen(bss_link->ssid));
  302. } else {
  303. os_memcpy(ssid, bss_link->ssid, 32);
  304. }
  305. ESP_LOGD(TAG, "(%d,\"%s\",%x, %d)", bss_link->authmode, ssid, bssid, bss_link->rssi);
  306. bss_link = bss_link->next.stqe_next;
  307. }
  308. bss_link = bss_link_head; // reset to head
  309. head_bss_link = bss_link_head; // ahhh, this is lazy.
  310. wifi_set_event_handler_cb(wifi_event_handler_cb);
  311. wifi_process();
  312. }
  313. else // if scan was unsuccessful
  314. {
  315. ESP_LOGD(TAG, "scan failed");
  316. if (wifi_config.fail_cb != NULL)
  317. wifi_config.fail_cb(WIFI_SCAN_FAILURE);
  318. wifi_config.wifi_process = false;
  319. }
  320. }
  321. /******************************************************************************
  322. * FunctionName : WiFi_Initialize
  323. * Description :
  324. * Parameters :
  325. * Returns :
  326. *******************************************************************************/
  327. void ICACHE_FLASH_ATTR WiFi_Initialize(void)
  328. {
  329. wifi_set_opmode(STATION_MODE);
  330. wifi_station_ap_number_set(5);
  331. wifi_station_disconnect();
  332. wifi_station_set_auto_connect(false);
  333. wifi_config.fail_cb = NULL;
  334. wifi_config.success_cb = NULL;
  335. }
  336. /******************************************************************************
  337. * FunctionName : WiFi_Disconnect
  338. * Description :
  339. * Parameters :
  340. * Returns :
  341. *******************************************************************************/
  342. void ICACHE_FLASH_ATTR WiFi_Disconnect(void)
  343. {
  344. wifi_config.ip_flag = false;
  345. wifi_config.ap_flag = false;
  346. wifi_station_disconnect();
  347. }
  348. /******************************************************************************
  349. * FunctionName : WiFi_SetCallbacks
  350. * Description :
  351. * Parameters :
  352. * Returns :
  353. *******************************************************************************/
  354. void ICACHE_FLASH_ATTR WiFi_SetCallbacks(wifi_success_function_t success_cb, wifi_fail_function_t fail_cb)
  355. {
  356. wifi_config.success_cb = success_cb;
  357. wifi_config.fail_cb = fail_cb;
  358. }
  359. /******************************************************************************
  360. * FunctionName : WiFi_Connect
  361. * Description :
  362. * Parameters :
  363. * Returns :
  364. *******************************************************************************/
  365. void ICACHE_FLASH_ATTR WiFi_Connect(uint32_t timeout_delay)
  366. {
  367. wifi_config.timeout_delay = timeout_delay;
  368. wifi_config.ip_flag = false;
  369. wifi_config.ap_flag = false;
  370. wifi_config.ap_found = false;
  371. wifi_config.wifi_process = true;
  372. wifi_set_event_handler_cb(NULL);
  373. os_timer_disarm(&wifi_config.timeout_timer);
  374. os_timer_setfn(&wifi_config.timeout_timer, (os_timer_func_t *)wifi_timeout_cb, NULL);
  375. // check for stored APs
  376. // if none call no_credentials_cb(), shutdown WIFI, return
  377. ESP_LOGI(TAG, "starting Wi-Fi scan");
  378. wifi_station_scan(NULL, wifi_scan_done); // start Wi-Fi scan.
  379. }