amebaz_wlan.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642
  1. /*
  2. * File : amebaz_wlan.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2017, RT-Thread Development Team
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. *
  20. * Change Logs:
  21. * Date Author Notes
  22. * 2017-5-30 Bernard the first version
  23. * 2018-6-12 flyingcys add amebaz wlan interface
  24. */
  25. #include <rtthread.h>
  26. #include <netif/ethernetif.h>
  27. #include "wifi_structures.h"
  28. #include "wifi_constants.h"
  29. #include <wifi/wifi_util.h>
  30. #include <wifi/wifi_conf.h>
  31. #define PASSWD_LEN 65
  32. #define SCAN_WAIT_TIME 10000
  33. typedef enum
  34. {
  35. WIFI_NONE,
  36. WIFI_STATION,
  37. WIFI_AP,
  38. } rt_wlan_mode_t;
  39. struct rt_wlan_info
  40. {
  41. rt_wlan_mode_t mode; /* wifi mode */
  42. rtw_security_t security;
  43. char *ssid;
  44. uint8_t bssid[6];
  45. /* maximal data rate */
  46. uint32_t datarate;
  47. /* radio channel */
  48. uint16_t channel;
  49. /* signal strength */
  50. int16_t rssi;
  51. };
  52. typedef struct rt_wlan_scan_result
  53. {
  54. char ap_num;
  55. struct rt_wlan_info *ap_table;
  56. } rt_wlan_scan_result_t;
  57. static rtw_network_info_t wifi_info = {0};
  58. static rtw_ap_info_t ap_info = {0};
  59. static unsigned char wifi_password[65] = {0};
  60. static unsigned char ap_password[PASSWD_LEN] = {0};
  61. static rt_sem_t scan_done_sem = RT_NULL;
  62. static char *scan_buf = RT_NULL;
  63. static int ApNum = 0;
  64. extern struct netif *rltk_wlan_get_netif(int idx);
  65. static void LwIP_ReleaseIP(uint8_t idx)
  66. {
  67. struct ip_addr ipaddr;
  68. struct ip_addr netmask;
  69. struct ip_addr gw;
  70. struct netif *pnetif = rltk_wlan_get_netif(idx);
  71. IP4_ADDR(&ipaddr, 0, 0, 0, 0);
  72. IP4_ADDR(&netmask, 255, 255, 255, 0);
  73. IP4_ADDR(&gw, 0, 0, 0, 0);
  74. netif_set_addr(pnetif, &ipaddr , &netmask, &gw);
  75. }
  76. static rtw_result_t amebaz_scan_result_handler( rtw_scan_handler_result_t* malloced_scan_result )
  77. {
  78. if (malloced_scan_result->scan_complete != RTW_TRUE) {
  79. rtw_scan_result_t* record = &malloced_scan_result->ap_details;
  80. record->SSID.val[record->SSID.len] = 0; /* Ensure the SSID is null terminated */
  81. ++ ApNum;
  82. if(malloced_scan_result->user_data)
  83. memcpy((void *)((char *)malloced_scan_result->user_data+(ApNum-1)*sizeof(rtw_scan_result_t)), (char *)record, sizeof(rtw_scan_result_t));
  84. }
  85. else
  86. {
  87. rt_kprintf("ap num:%d\n", ApNum);
  88. if(scan_done_sem)
  89. {
  90. rt_sem_release(scan_done_sem);
  91. }
  92. }
  93. return RTW_SUCCESS;
  94. }
  95. static int amebaz_wifi_do_scan(void)
  96. {
  97. int ret = RTW_SUCCESS;
  98. rt_kprintf("wifi scan start...\n");
  99. scan_buf = malloc(65*sizeof(rtw_scan_result_t));
  100. if(scan_buf == NULL){
  101. ret = RTW_BUFFER_UNAVAILABLE_TEMPORARY;
  102. return -RT_ENOMEM;
  103. }
  104. memset(scan_buf, 0, 65 * sizeof(rtw_scan_result_t));
  105. if((ret = wifi_scan_networks(amebaz_scan_result_handler, scan_buf)) != RTW_SUCCESS){
  106. rt_kprintf("ERROR: wifi scan failed\n\r");
  107. return -RT_ERROR;
  108. }
  109. return RT_EOK;
  110. }
  111. int amebaz_wifi_scan(struct rt_wlan_scan_result *dst)
  112. {
  113. rt_uint32_t i;
  114. rt_uint32_t j = 0;
  115. scan_done_sem = rt_sem_create("scandone", 0, RT_IPC_FLAG_FIFO);
  116. if(scan_done_sem == RT_NULL)
  117. return -RT_ENOMEM;
  118. if(amebaz_wifi_do_scan() != RT_EOK)
  119. {
  120. rt_kprintf("amebaz_wifi_do_scan failed...\n");
  121. return -RT_ERROR;
  122. }
  123. if(rt_sem_take(scan_done_sem, rt_tick_from_millisecond(SCAN_WAIT_TIME)) != RT_EOK)
  124. {
  125. rt_kprintf("scan wait timeout...\n");
  126. return -RT_ETIMEOUT;
  127. }
  128. if(scan_done_sem)
  129. {
  130. rt_sem_delete(scan_done_sem);
  131. scan_done_sem = RT_NULL;
  132. }
  133. rtw_scan_result_t *ptr = (rtw_scan_result_t *)scan_buf;
  134. dst->ap_num = ApNum;
  135. ApNum = 0;
  136. dst->ap_table = (struct rt_wlan_info *)rt_malloc(sizeof(struct rt_wlan_info) * dst->ap_num);
  137. if(dst->ap_table == RT_NULL)
  138. {
  139. rt_kprintf("rt_malloc for ap table failed...\n");
  140. goto __exit;
  141. }
  142. for(i = 0; i < dst->ap_num; i ++)
  143. {
  144. dst->ap_table[i].mode = 1;
  145. dst->ap_table[i].security = ptr->security;
  146. dst->ap_table[i].ssid = (char *)rt_malloc(33);
  147. if(dst->ap_table[i].ssid == RT_NULL)
  148. {
  149. rt_kprintf("rt_malloc for ssid Failed! times:%d,total:%d\n",i,ApNum);
  150. j = i;
  151. goto __exit;
  152. }
  153. memset(dst->ap_table[i].ssid, 0, 33);
  154. memcpy(dst->ap_table[i].ssid, ptr->SSID.val, ptr->SSID.len);
  155. memcpy(dst->ap_table[i].bssid, ptr->BSSID.octet, 6);
  156. dst->ap_table[i].datarate = 0;
  157. dst->ap_table[i].channel = ptr->channel;
  158. dst->ap_table[i].rssi = ptr->signal_strength;
  159. ptr ++;
  160. }
  161. if(scan_buf != RT_NULL)
  162. {
  163. rt_free(scan_buf);
  164. scan_buf = RT_NULL;
  165. }
  166. return RT_EOK;
  167. __exit:
  168. if(scan_buf != RT_NULL)
  169. {
  170. rt_free(scan_buf);
  171. scan_buf = RT_NULL;
  172. }
  173. if(dst->ap_table)
  174. {
  175. for(i = 0; i < j; i ++)
  176. rt_free(dst->ap_table[i].ssid);
  177. rt_free(dst->ap_table);
  178. dst->ap_table = RT_NULL;
  179. dst->ap_num = 0;
  180. }
  181. return -RT_ERROR;
  182. }
  183. void amebaz_wifi_info_init(void)
  184. {
  185. memset(wifi_info.ssid.val, 0, sizeof(wifi_info.ssid.val));
  186. memset(wifi_info.bssid.octet, 0, 6);
  187. memset(wifi_password, 0, sizeof(wifi_password));
  188. wifi_info.ssid.len = 0;
  189. wifi_info.password = NULL;
  190. wifi_info.password_len = 0;
  191. wifi_info.key_id = -1;
  192. memset(ap_info.ssid.val, 0, sizeof(ap_info.ssid.val));
  193. ap_info.ssid.len = 0;
  194. ap_info.security_type = RTW_SECURITY_UNKNOWN;
  195. ap_info.password = NULL;
  196. ap_info.password_len = 0;
  197. ap_info.channel = 1;
  198. }
  199. static int amebaz_wifi_set_sta_info(char *ssid, char *passwd)
  200. {
  201. if(ssid == RT_NULL || strlen(ssid) > 32)
  202. {
  203. rt_kprintf("Invalid argument...\n");
  204. return -RT_EINVAL;
  205. }
  206. strcpy(wifi_info.ssid.val, ssid);
  207. wifi_info.ssid.len = strlen(ssid);
  208. if(passwd != NULL)
  209. {
  210. if(strlen(passwd) > 64)
  211. {
  212. rt_kprintf("Invalid argument...\n");
  213. return -RT_EINVAL;
  214. }
  215. strcpy(wifi_password, passwd);
  216. wifi_info.password = wifi_password;
  217. wifi_info.password_len = strlen(passwd);
  218. }
  219. else
  220. wifi_info.password = RT_NULL;
  221. return RT_EOK;
  222. }
  223. static int amebaz_wifi_set_ap_info(char *ssid, char *passwd, int channel)
  224. {
  225. if(ssid == RT_NULL || strlen(ssid) > 32)
  226. {
  227. rt_kprintf("Invalid argument...\n");
  228. return -RT_EINVAL;
  229. }
  230. strcpy(ap_info.ssid.val, ssid);
  231. ap_info.ssid.len = strlen(ssid);
  232. if(passwd != NULL)
  233. {
  234. if(strlen(passwd) > 64)
  235. {
  236. rt_kprintf("Invalid argument...\n");
  237. return -RT_EINVAL;
  238. }
  239. strcpy(ap_password, passwd);
  240. ap_info.password = ap_password;
  241. ap_info.password_len = strlen(passwd);
  242. }
  243. else
  244. ap_info.password = RT_NULL;
  245. ap_info.channel = channel;
  246. return RT_EOK;
  247. }
  248. static int amebaz_wifi_do_connect(void)
  249. {
  250. int mode, ret;
  251. char empty_bssid[6] = {0};
  252. char assoc_by_bssid = 0;
  253. rt_kprintf("amebaz wifi do connect start...\n");
  254. if(memcmp (wifi_info.bssid.octet, empty_bssid, 6))
  255. {
  256. assoc_by_bssid = 1;
  257. }
  258. else if(wifi_info.ssid.val[0] == 0)
  259. {
  260. ret = RTW_BADARG;
  261. return -RT_ERROR;
  262. }
  263. if(wifi_info.password != RT_NULL)
  264. {
  265. if((wifi_info.key_id >= 0) && (wifi_info.key_id <= 3))
  266. {
  267. wifi_info.security_type = RTW_SECURITY_WEP_PSK;
  268. }
  269. else
  270. {
  271. wifi_info.security_type = RTW_SECURITY_WPA2_AES_PSK;
  272. }
  273. }
  274. else
  275. {
  276. wifi_info.security_type = RTW_SECURITY_OPEN;
  277. }
  278. //Check if in AP mode
  279. wext_get_mode(WLAN0_NAME, &mode);
  280. if(mode == IW_MODE_MASTER)
  281. {
  282. #if 0
  283. #if CONFIG_LWIP_LAYER
  284. dhcps_deinit();
  285. #endif
  286. wifi_off();
  287. vTaskDelay(20);
  288. if (wifi_on(RTW_MODE_STA) < 0){
  289. printf("\n\rERROR: Wifi on failed!");
  290. ret = RTW_ERROR;
  291. goto EXIT;
  292. }
  293. #endif
  294. }
  295. if(assoc_by_bssid)
  296. {
  297. rt_kprintf("Joining BSS by BSSID \"MAC_FMT\" ...\n", MAC_ARG(wifi_info.bssid.octet));
  298. ret = wifi_connect_bssid(wifi_info.bssid.octet, (char*)wifi_info.ssid.val, wifi_info.security_type, (char*)wifi_info.password,
  299. ETH_ALEN, wifi_info.ssid.len, wifi_info.password_len, wifi_info.key_id, NULL);
  300. }
  301. else
  302. {
  303. rt_kprintf("\n\rJoining BSS by SSID %s...\n\r", (char*)wifi_info.ssid.val);
  304. ret = wifi_connect((char*)wifi_info.ssid.val, wifi_info.security_type,
  305. (char*)wifi_info.password, wifi_info.ssid.len,
  306. wifi_info.password_len, wifi_info.key_id, NULL);
  307. }
  308. if(ret!= RTW_SUCCESS)
  309. {
  310. if(ret == RTW_INVALID_KEY)
  311. rt_kprintf("ERROR:Invalid Key\n");
  312. rt_kprintf("ERROR: Can't connect to AP\n");
  313. return -RT_ERROR;
  314. }
  315. rt_kprintf("now start dhcp...\n");
  316. netif_set_connected(1);
  317. dhcp_start(netif_default);
  318. rt_kprintf("dhcp success...\n");
  319. return RT_EOK;
  320. }
  321. int amebaz_wifi_connect(char *ssid, char *passwd)
  322. {
  323. int ret;
  324. ret = amebaz_wifi_set_sta_info(ssid, passwd);
  325. if(ret != RT_EOK)
  326. {
  327. amebaz_wifi_info_init();
  328. return ret;
  329. }
  330. if(amebaz_wifi_do_connect() != RT_EOK)
  331. {
  332. amebaz_wifi_info_init();
  333. rt_kprintf("amebaz_wifi_do_connect failed...\n");
  334. return -RT_ERROR;
  335. }
  336. amebaz_wifi_info_init();
  337. return RT_EOK;
  338. }
  339. static int amebaz_wifi_do_disconnect(void)
  340. {
  341. int timeout = 20;
  342. char essid[33];
  343. int ret = RTW_SUCCESS;
  344. if(wext_get_ssid(WLAN0_NAME, (unsigned char *) essid) < 0)
  345. {
  346. rt_kprintf("\nWIFI disconnected!\n");
  347. return -RT_ERROR;
  348. }
  349. if((ret = wifi_disconnect()) < 0)
  350. {
  351. return -RT_ERROR;
  352. }
  353. while(1)
  354. {
  355. if(wext_get_ssid(WLAN0_NAME, (unsigned char *) essid) < 0)
  356. {
  357. rt_kprintf("\nWIFI disconnected!\n");
  358. break;
  359. }
  360. if(timeout == 0)
  361. {
  362. rt_kprintf("ERROR: Deassoc timeout!\n\r");
  363. ret = RTW_TIMEOUT;
  364. break;
  365. }
  366. vTaskDelay(10);
  367. timeout --;
  368. }
  369. LwIP_ReleaseIP(WLAN0_IDX);
  370. if(ret != RTW_SUCCESS)
  371. return -RT_ERROR;
  372. rt_kprintf("amebaz wifi do disconnect success...\n");
  373. return RT_EOK;
  374. }
  375. int amebaz_wifi_disconnect(void)
  376. {
  377. int ret = RT_EOK;
  378. ret = amebaz_wifi_do_disconnect();
  379. if(ret != RT_EOK)
  380. rt_kprintf("amebaz_wifi_do_disconnect failed...\n");
  381. amebaz_wifi_info_init();
  382. return ret;
  383. }
  384. static int amebaz_wifi_do_ap_start(void)
  385. {
  386. struct ip_addr ipaddr;
  387. struct ip_addr netmask;
  388. struct ip_addr gw;
  389. struct netif *pnetif = rltk_wlan_get_netif(1);
  390. int timeout = 20;
  391. int ret = RTW_SUCCESS;
  392. if(ap_info.ssid.val[0] == 0){
  393. rt_kprintf("ERROR: SSID can't be empty\n\r");
  394. return -RT_ERROR;
  395. }
  396. if(ap_info.password == NULL)
  397. {
  398. ap_info.security_type = RTW_SECURITY_OPEN;
  399. }
  400. else
  401. {
  402. if(ap_info.password_len <= RTW_MAX_PSK_LEN && ap_info.password_len >= RTW_MIN_PSK_LEN)
  403. {
  404. ap_info.security_type = RTW_SECURITY_WPA2_AES_PSK;
  405. }
  406. else
  407. {
  408. rt_kprintf("ERROR: password length is between 8 to 64 \n");
  409. return -RT_ERROR;
  410. }
  411. }
  412. //#if CONFIG_LWIP_LAYER
  413. // dhcps_deinit();
  414. // IP4_ADDR(&ipaddr, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
  415. // IP4_ADDR(&netmask, NETMASK_ADDR0, NETMASK_ADDR1 , NETMASK_ADDR2, NETMASK_ADDR3);
  416. // IP4_ADDR(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
  417. // netif_set_addr(pnetif, &ipaddr, &netmask,&gw);
  418. //#ifdef CONFIG_DONT_CARE_TP
  419. // pnetif->flags |= NETIF_FLAG_IPSWITCH;
  420. //#endif
  421. //#endif
  422. wifi_off();
  423. vTaskDelay(20);
  424. if (wifi_on(RTW_MODE_AP) < 0)
  425. {
  426. rt_kprintf("ERROR: Wifi on failed!\n");
  427. return -RT_ERROR;
  428. }
  429. rt_kprintf("Now start AP mode...\n");
  430. if((ret = wifi_start_ap((char*)ap_info.ssid.val, ap_info.security_type, (char*)ap_info.password, ap_info.ssid.len, ap_info.password_len, ap_info.channel) ) < 0)
  431. {
  432. rt_kprintf("ERROR: Operation failed!");
  433. return -RT_ERROR;
  434. }
  435. while(1)
  436. {
  437. char essid[33];
  438. if(wext_get_ssid(WLAN0_NAME, (unsigned char *) essid) > 0)
  439. {
  440. if(strcmp((const char *) essid, (const char *)ap_info.ssid.val) == 0)
  441. {
  442. rt_kprintf("AP %s started...\n", ap_info.ssid.val);
  443. ret = RTW_SUCCESS;
  444. break;
  445. }
  446. }
  447. if(timeout == 0)
  448. {
  449. rt_kprintf("ERROR: Start AP timeout!");
  450. ret = RTW_TIMEOUT;
  451. break;
  452. }
  453. vTaskDelay(10);
  454. timeout --;
  455. }
  456. if(ret != RTW_SUCCESS)
  457. return -RT_ERROR;
  458. //#if CONFIG_LWIP_LAYER
  459. //LwIP_UseStaticIP(pnetif);
  460. // dhcps_init(pnetif);
  461. //#endif
  462. return RT_EOK;
  463. }
  464. static int amebaz_wifi_do_ap_stop(void)
  465. {
  466. return RT_EOK;
  467. }
  468. int amebaz_wifi_ap_start(char *ssid, char *passwd, int channel)
  469. {
  470. int ret;
  471. ret = amebaz_wifi_set_ap_info(ssid, passwd, channel);
  472. if(ret != RT_EOK)
  473. {
  474. amebaz_wifi_info_init();
  475. return ret;
  476. }
  477. if(amebaz_wifi_do_ap_start() != RT_EOK)
  478. {
  479. amebaz_wifi_info_init();
  480. rt_kprintf("amebaz_wifi_ap_start failed...\n");
  481. return -RT_ERROR;
  482. }
  483. amebaz_wifi_info_init();
  484. return RT_EOK;
  485. }
  486. int amebaz_wifi_ap_stop(void)
  487. {
  488. int ret;
  489. if(amebaz_wifi_do_ap_stop() != RT_EOK)
  490. {
  491. amebaz_wifi_info_init();
  492. rt_kprintf("amebaz_wifi_ap_stop failed...\n");
  493. return -RT_ERROR;
  494. }
  495. amebaz_wifi_info_init();
  496. return RT_EOK;
  497. }
  498. int amebaz_wifi_get_rssi(void)
  499. {
  500. int rssi = 0;
  501. wifi_get_rssi(&rssi);
  502. return rssi;
  503. }
  504. void amebaz_wifi_set_channel(int channel)
  505. {
  506. wifi_set_channel(channel);
  507. }
  508. int amebaz_wifi_get_channel(void)
  509. {
  510. int channel;
  511. wifi_get_channel(&channel);
  512. return channel;
  513. }
  514. int amebaz_wifi_init(rt_wlan_mode_t mode)
  515. {
  516. int ret;
  517. rtw_mode_t rtw_mode;
  518. if(mode == WIFI_STATION)
  519. rtw_mode = RTW_MODE_STA;
  520. else if(mode == WIFI_AP)
  521. rtw_mode = RTW_MODE_AP;
  522. if(wifi_on(mode) < 0)
  523. return -RT_ERROR;
  524. if(wifi_set_autoreconnect(1) < 0)
  525. return -RT_ERROR;
  526. return RT_EOK;
  527. }