1 /*
2  * Copyright 2020-2024 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "wpl.h"
9 #ifndef WPL_NO_WLAN_INIT
10 #include "wlan_bt_fw.h"
11 #endif
12 #include "wlan.h"
13 #include "wifi.h"
14 #include "wm_net.h"
15 #include "dhcp-server.h"
16 #include <stdio.h>
17 #include "event_groups.h"
18 
19 /*******************************************************************************
20  * Definitions
21  ******************************************************************************/
22 
23 #define MAX_JSON_NETWORK_RECORD_LENGTH 185U
24 
25 #define WPL_SYNC_TIMEOUT_MS portMAX_DELAY
26 
27 #define UAP_NETWORK_NAME "uap-network"
28 
29 #define EVENT_BIT(event) ((uint32_t)1U << (event))
30 
31 #define WPL_SYNC_INIT_GROUP (EVENT_BIT(WLAN_REASON_INITIALIZED) | EVENT_BIT(WLAN_REASON_INITIALIZATION_FAILED))
32 
33 #define WPL_SYNC_CONNECT_GROUP                                                                  \
34     (EVENT_BIT(WLAN_REASON_SUCCESS) | EVENT_BIT(WLAN_REASON_CONNECT_FAILED) |                    \
35         EVENT_BIT(WLAN_REASON_NETWORK_NOT_FOUND) | EVENT_BIT(WLAN_REASON_NETWORK_AUTH_FAILED) | \
36         EVENT_BIT(WLAN_REASON_ADDRESS_FAILED))
37 
38 #define WPL_SYNC_DISCONNECT_GROUP EVENT_BIT(WLAN_REASON_USER_DISCONNECT)
39 
40 #define WPL_SYNC_UAP_START_GROUP (EVENT_BIT(WLAN_REASON_UAP_SUCCESS) | EVENT_BIT(WLAN_REASON_UAP_START_FAILED))
41 
42 #define WPL_SYNC_UAP_STOP_GROUP (EVENT_BIT(WLAN_REASON_UAP_STOPPED) | EVENT_BIT(WLAN_REASON_UAP_STOP_FAILED))
43 
44 #define EVENT_SCAN_DONE     23
45 #define WPL_SYNC_SCAN_GROUP EVENT_BIT(EVENT_SCAN_DONE)
46 
47 typedef enum _wpl_state
48 {
49     WPL_NOT_INITIALIZED,
50     WPL_INITIALIZED,
51     WPL_STARTED,
52 } wpl_state_t;
53 
54 /*******************************************************************************
55  * Variables
56  ******************************************************************************/
57 static wpl_state_t s_wplState            = WPL_NOT_INITIALIZED;
58 static bool s_wplStaConnected            = false;
59 static bool s_wplUapActivated            = false;
60 static EventGroupHandle_t s_wplSyncEvent = NULL;
61 static linkLostCb_t s_linkLostCb         = NULL;
62 static char *ssids_json                  = NULL;
63 
64 /*******************************************************************************
65  * Prototypes
66  ******************************************************************************/
67 int wlan_event_callback(enum wlan_event_reason reason, void *data);
68 static int WLP_process_results(unsigned int count);
69 
70 /*******************************************************************************
71  * Code
72  ******************************************************************************/
73 /* Callback Function passed to WLAN Connection Manager. The callback function
74  * gets called when there are WLAN Events that need to be handled by the
75  * application.
76  */
wlan_event_callback(enum wlan_event_reason reason,void * data)77 int wlan_event_callback(enum wlan_event_reason reason, void *data)
78 {
79 #ifdef WPL_DEBUG
80     PRINTF("-------- wlan_event_callback %d --------\r\n", reason);
81 #endif
82     if (s_wplState >= WPL_INITIALIZED)
83     {
84         (void)xEventGroupSetBits(s_wplSyncEvent, EVENT_BIT((uint32_t)reason));
85     }
86 
87     switch (reason)
88     {
89         case WLAN_REASON_SUCCESS:
90             if (s_wplStaConnected)
91             {
92                 s_linkLostCb(true);
93             }
94             break;
95 
96         case WLAN_REASON_AUTH_SUCCESS:
97             break;
98 
99         case WLAN_REASON_CONNECT_FAILED:
100         case WLAN_REASON_NETWORK_NOT_FOUND:
101         case WLAN_REASON_NETWORK_AUTH_FAILED:
102             if (s_wplStaConnected)
103             {
104                 s_linkLostCb(false);
105             }
106             break;
107 
108         case WLAN_REASON_ADDRESS_SUCCESS:
109             break;
110         case WLAN_REASON_ADDRESS_FAILED:
111             break;
112         case WLAN_REASON_LINK_LOST:
113             if (s_wplStaConnected)
114             {
115                 s_linkLostCb(false);
116             }
117             break;
118 
119         case WLAN_REASON_CHAN_SWITCH:
120             break;
121         case WLAN_REASON_WPS_DISCONNECT:
122             break;
123         case WLAN_REASON_USER_DISCONNECT:
124             break;
125         case WLAN_REASON_INITIALIZED:
126             break;
127         case WLAN_REASON_INITIALIZATION_FAILED:
128             break;
129         case WLAN_REASON_PS_ENTER:
130             break;
131         case WLAN_REASON_PS_EXIT:
132             break;
133         case WLAN_REASON_UAP_SUCCESS:
134             break;
135 
136         case WLAN_REASON_UAP_CLIENT_ASSOC:
137 #ifdef WPL_DEBUG
138             PRINTF("Client => ");
139             print_mac((const char *)data);
140             PRINTF("Associated with Soft AP\r\n");
141 #endif
142             break;
143         case WLAN_REASON_UAP_CLIENT_DISSOC:
144 #ifdef WPL_DEBUG
145             PRINTF("Client => ");
146             print_mac((const char *)data);
147             PRINTF("Dis-Associated from Soft AP\r\n");
148 #endif
149             break;
150 
151         case WLAN_REASON_UAP_START_FAILED:
152             break;
153         case WLAN_REASON_UAP_STOP_FAILED:
154             break;
155         case WLAN_REASON_UAP_STOPPED:
156             break;
157         default:
158 #ifdef WPL_DEBUG
159             PRINTF("Unknown Wifi CB Reason %d\r\n", reason);
160 #endif
161             break;
162     }
163 
164     return WM_SUCCESS;
165 }
166 
WPL_Init(void)167 wpl_ret_t WPL_Init(void)
168 {
169     wpl_ret_t status = WPLRET_SUCCESS;
170 
171     if (s_wplState != WPL_NOT_INITIALIZED)
172     {
173         status = WPLRET_FAIL;
174     }
175 
176     if (status == WPLRET_SUCCESS)
177     {
178         if (s_wplSyncEvent == NULL)
179         {
180             s_wplSyncEvent = xEventGroupCreate();
181         }
182 
183         if (s_wplSyncEvent == NULL)
184         {
185             status = WPLRET_FAIL;
186         }
187     }
188 
189 #ifndef WPL_NO_WLAN_INIT
190     if (status == WPLRET_SUCCESS)
191     {
192         const int ret = wlan_init(wlan_fw_bin, wlan_fw_bin_len);
193         if (ret != WM_SUCCESS)
194         {
195             status = WPLRET_FAIL;
196         }
197     }
198 #endif
199 
200     if (status == WPLRET_SUCCESS)
201     {
202         s_wplState = WPL_INITIALIZED;
203     }
204 
205     return status;
206 }
207 
WPL_Start(linkLostCb_t callbackFunction)208 wpl_ret_t WPL_Start(linkLostCb_t callbackFunction)
209 {
210     wpl_ret_t status = WPLRET_SUCCESS;
211     int ret;
212     EventBits_t syncBit;
213 
214     if (s_wplState != WPL_INITIALIZED)
215     {
216         status = WPLRET_NOT_READY;
217     }
218 
219     if (status == WPLRET_SUCCESS)
220     {
221         (void)xEventGroupClearBits(s_wplSyncEvent, WPL_SYNC_INIT_GROUP);
222 
223         ret = wlan_start(&wlan_event_callback);
224         if (ret != WM_SUCCESS)
225         {
226             status = WPLRET_FAIL;
227         }
228     }
229 
230     if (status == WPLRET_SUCCESS)
231     {
232         syncBit = xEventGroupWaitBits(s_wplSyncEvent, WPL_SYNC_INIT_GROUP, pdTRUE, pdFALSE, WPL_SYNC_TIMEOUT_MS);
233         if ((syncBit & EVENT_BIT(WLAN_REASON_INITIALIZED)) != 0U)
234         {
235             s_linkLostCb = callbackFunction;
236             status       = WPLRET_SUCCESS;
237         }
238         else if ((syncBit & EVENT_BIT(WLAN_REASON_INITIALIZATION_FAILED)) != 0U)
239         {
240             status = WPLRET_FAIL;
241         }
242         else
243         {
244             status = WPLRET_TIMEOUT;
245         }
246     }
247 
248     if (status == WPLRET_SUCCESS)
249     {
250         s_wplState = WPL_STARTED;
251     }
252 
253     return status;
254 }
255 
WPL_Stop(void)256 wpl_ret_t WPL_Stop(void)
257 {
258     wpl_ret_t status = WPLRET_SUCCESS;
259     int ret;
260 
261     if (s_wplState != WPL_STARTED)
262     {
263         status = WPLRET_NOT_READY;
264     }
265 
266     if (status == WPLRET_SUCCESS)
267     {
268         ret = wlan_stop();
269         if (ret != WM_SUCCESS)
270         {
271             status = WPLRET_FAIL;
272         }
273     }
274 
275     if (status == WPLRET_SUCCESS)
276     {
277         s_wplState = WPL_INITIALIZED;
278     }
279 
280     return status;
281 }
282 
WPL_Start_AP(const char * ssid,const char * password,int chan)283 wpl_ret_t WPL_Start_AP(const char *ssid, const char *password, int chan)
284 {
285     wpl_ret_t status = WPLRET_SUCCESS;
286     int ret;
287     enum wlan_security_type security = WLAN_SECURITY_NONE;
288     EventBits_t syncBit;
289     struct wlan_network uap_network;
290     size_t ssid_len = strlen(ssid);
291     size_t password_len = strlen(password);
292 
293     if ((s_wplState != WPL_STARTED) || (s_wplUapActivated != false))
294     {
295         status = WPLRET_NOT_READY;
296     }
297 
298     if ((ssid_len == 0U) || (ssid_len > IEEEtypes_SSID_SIZE))
299     {
300         status = WPLRET_BAD_PARAM;
301     }
302 
303     if (((0U < password_len) && (password_len < WPL_WIFI_PASSWORD_MIN_LEN)) ||
304         (password_len > WPL_WIFI_PASSWORD_LENGTH))
305     {
306         status = WPLRET_BAD_PARAM;
307     }
308 
309     if (status == WPLRET_SUCCESS)
310     {
311         if (password_len == 0U)
312         {
313             security = WLAN_SECURITY_NONE;
314         }
315         else
316         {
317             security = WLAN_SECURITY_WPA2;
318         }
319     }
320 
321     if (status == WPLRET_SUCCESS)
322     {
323         wlan_initialize_uap_network(&uap_network);
324 
325         (void)memcpy(uap_network.ssid, ssid, ssid_len);
326         uap_network.ip.ipv4.address  = ipaddr_addr(WPL_WIFI_AP_IP_ADDR);
327         uap_network.ip.ipv4.gw       = ipaddr_addr(WPL_WIFI_AP_IP_ADDR);
328         uap_network.channel          = (unsigned int)chan;
329         uap_network.security.type    = security;
330         uap_network.security.psk_len = (uint8_t)password_len;
331         (void)strncpy(uap_network.security.psk, password, password_len);
332     }
333 
334     if (status == WPLRET_SUCCESS)
335     {
336         ret = wlan_add_network(&uap_network);
337         if (ret != WM_SUCCESS)
338         {
339             status = WPLRET_FAIL;
340         }
341     }
342 
343     if (status == WPLRET_SUCCESS)
344     {
345         (void)xEventGroupClearBits(s_wplSyncEvent, WPL_SYNC_UAP_START_GROUP);
346 
347         ret = wlan_start_network(uap_network.name);
348         if (ret != WM_SUCCESS)
349         {
350             status = WPLRET_FAIL;
351         }
352         else
353         {
354             syncBit =
355                 xEventGroupWaitBits(s_wplSyncEvent, WPL_SYNC_UAP_START_GROUP, pdTRUE, pdFALSE, WPL_SYNC_TIMEOUT_MS);
356             if ((syncBit & EVENT_BIT(WLAN_REASON_UAP_SUCCESS)) != 0U)
357             {
358                 status = WPLRET_SUCCESS;
359             }
360             else if ((syncBit & EVENT_BIT(WLAN_REASON_UAP_START_FAILED)) != 0U)
361             {
362                 status = WPLRET_FAIL;
363             }
364             else
365             {
366                 status = WPLRET_TIMEOUT;
367             }
368         }
369 
370         if (status != WPLRET_SUCCESS)
371         {
372             wlan_remove_network(uap_network.name);
373         }
374     }
375 
376     if (status == WPLRET_SUCCESS)
377     {
378         ret = dhcp_server_start(net_get_uap_handle());
379         if (ret != WM_SUCCESS)
380         {
381             wlan_stop_network(uap_network.name);
382             wlan_remove_network(uap_network.name);
383             status = WPLRET_FAIL;
384         }
385     }
386 
387     if (status == WPLRET_SUCCESS)
388     {
389         s_wplUapActivated = true;
390     }
391 
392     return status;
393 }
394 
WPL_Stop_AP(void)395 wpl_ret_t WPL_Stop_AP(void)
396 {
397     wpl_ret_t status = WPLRET_SUCCESS;
398     int ret;
399     EventBits_t syncBit;
400 
401     if ((s_wplState != WPL_STARTED) || (s_wplUapActivated != true))
402     {
403         status = WPLRET_NOT_READY;
404     }
405 
406     if (status == WPLRET_SUCCESS)
407     {
408         dhcp_server_stop();
409 
410         (void)xEventGroupClearBits(s_wplSyncEvent, WPL_SYNC_UAP_START_GROUP);
411 
412         ret = wlan_stop_network(UAP_NETWORK_NAME);
413         if (ret != WM_SUCCESS)
414         {
415             status = WPLRET_FAIL;
416         }
417         else
418         {
419             syncBit =
420                 xEventGroupWaitBits(s_wplSyncEvent, WPL_SYNC_UAP_STOP_GROUP, pdTRUE, pdFALSE, WPL_SYNC_TIMEOUT_MS);
421             if ((syncBit & EVENT_BIT(WLAN_REASON_UAP_STOPPED)) != 0U)
422             {
423                 status = WPLRET_SUCCESS;
424             }
425             else if ((syncBit & EVENT_BIT(WLAN_REASON_UAP_STOP_FAILED)) != 0U)
426             {
427                 status = WPLRET_FAIL;
428             }
429             else
430             {
431                 status = WPLRET_TIMEOUT;
432             }
433         }
434     }
435 
436     if (status == WPLRET_SUCCESS)
437     {
438         ret = wlan_remove_network(UAP_NETWORK_NAME);
439         if (ret != WM_SUCCESS)
440         {
441             status = WPLRET_FAIL;
442         }
443     }
444 
445     if (status == WPLRET_SUCCESS)
446     {
447         s_wplUapActivated = false;
448     }
449 
450     return status;
451 }
452 
WLP_process_results(unsigned int count)453 static int WLP_process_results(unsigned int count)
454 {
455     int ret                             = 0;
456     struct wlan_scan_result scan_result = {0};
457     uint32_t ssids_json_len             = count * MAX_JSON_NETWORK_RECORD_LENGTH;
458 
459     /* Add length of "{"networks":[]}" */
460     ssids_json_len += 15U;
461 
462     ssids_json = pvPortMalloc(ssids_json_len);
463     if (ssids_json == NULL)
464     {
465         PRINTF("[!] Memory allocation failed\r\n");
466         (void)xEventGroupSetBits(s_wplSyncEvent, EVENT_BIT(EVENT_SCAN_DONE));
467         return WM_FAIL;
468     }
469 
470     /* Start building JSON */
471     (void)strcpy(ssids_json, "{\"networks\":[");
472     uint32_t ssids_json_idx = strlen(ssids_json);
473 
474     for (uint32_t i = 0; i < count; i++)
475     {
476         ret = wlan_get_scan_result(i, &scan_result);
477         if (ret == WM_SUCCESS)
478         {
479             PRINTF("%s\r\n", scan_result.ssid);
480             PRINTF("     BSSID         : %02X:%02X:%02X:%02X:%02X:%02X\r\n", (unsigned int)scan_result.bssid[0],
481                    (unsigned int)scan_result.bssid[1], (unsigned int)scan_result.bssid[2],
482                    (unsigned int)scan_result.bssid[3], (unsigned int)scan_result.bssid[4],
483                    (unsigned int)scan_result.bssid[5]);
484             PRINTF("     RSSI          : %ddBm\r\n", -(int)scan_result.rssi);
485             PRINTF("     Channel       : %d\r\n", (int)scan_result.channel);
486 
487             char security[40];
488             security[0] = '\0';
489 
490             if (scan_result.wpa2_entp == 1U)
491             {
492                 (void)strcat(security, "WPA2_ENTP ");
493             }
494             if (scan_result.wep == 1U)
495             {
496                 (void)strcat(security, "WEP ");
497             }
498             if (scan_result.wpa == 1U)
499             {
500                 (void)strcat(security, "WPA ");
501             }
502             if (scan_result.wpa2 == 1U)
503             {
504                 (void)strcat(security, "WPA2 ");
505             }
506             if (scan_result.wpa3_sae == 1U)
507             {
508                 (void)strcat(security, "WPA3_SAE ");
509             }
510 
511             if (i != 0U)
512             {
513                 /* Add ',' separator before next entry */
514                 ssids_json[ssids_json_idx++] = ',';
515             }
516 
517             ret = snprintf(
518                 ssids_json + ssids_json_idx, ssids_json_len - ssids_json_idx - 1U,
519                 "{\"ssid\":\"%s\",\"bssid\":\"%02X:%02X:%02X:%02X:%02X:%02X\",\"signal\":\"%ddBm\",\"channel\":%d,"
520                 "\"security\":\"%s\"}",
521                 scan_result.ssid, (unsigned int)scan_result.bssid[0], (unsigned int)scan_result.bssid[1],
522                 (unsigned int)scan_result.bssid[2], (unsigned int)scan_result.bssid[3], (unsigned int)scan_result.bssid[4],
523                 (unsigned int)scan_result.bssid[5], -(int)scan_result.rssi, (int)scan_result.channel, security);
524             if (ret > 0)
525             {
526                 ssids_json_idx += (uint32_t)ret;
527             }
528             else
529             {
530                 PRINTF("[!] JSON creation failed\r\n");
531                 vPortFree(ssids_json);
532                 ssids_json = NULL;
533                 (void)xEventGroupSetBits(s_wplSyncEvent, EVENT_BIT(EVENT_SCAN_DONE));
534                 return WM_FAIL;
535             }
536         }
537     }
538 
539     /* End of JSON "]}" */
540     (void)strcpy(ssids_json + ssids_json_idx, "]}");
541 
542     (void)xEventGroupSetBits(s_wplSyncEvent, EVENT_BIT(EVENT_SCAN_DONE));
543     return WM_SUCCESS;
544 }
545 
WPL_Scan(void)546 char *WPL_Scan(void)
547 {
548     wpl_ret_t status = WPLRET_SUCCESS;
549     int ret;
550     EventBits_t syncBit;
551 
552     if (s_wplState != WPL_STARTED)
553     {
554         status = WPLRET_NOT_READY;
555     }
556 
557     if (status == WPLRET_SUCCESS)
558     {
559         ret = wlan_scan(&WLP_process_results);
560         if (ret != WM_SUCCESS)
561         {
562             status = WPLRET_FAIL;
563         }
564     }
565 
566     if (status == WPLRET_SUCCESS)
567     {
568         syncBit = xEventGroupWaitBits(s_wplSyncEvent, WPL_SYNC_SCAN_GROUP, pdTRUE, pdFALSE, WPL_SYNC_TIMEOUT_MS);
569         if ((syncBit & EVENT_BIT(EVENT_SCAN_DONE)) != 0U)
570         {
571             status = WPLRET_SUCCESS;
572         }
573         else
574         {
575             status = WPLRET_TIMEOUT;
576         }
577     }
578 
579     if (status == WPLRET_SUCCESS)
580     {
581         return ssids_json;
582     }
583 
584     return NULL;
585 }
586 
WPL_AddNetworkWithSecurity(const char * ssid,const char * password,const char * label,wpl_security_t security)587 wpl_ret_t WPL_AddNetworkWithSecurity(const char *ssid, const char *password, const char *label, wpl_security_t security)
588 {
589     wpl_ret_t status = WPLRET_SUCCESS;
590     int ret;
591     struct wlan_network sta_network;
592     memset(&sta_network, 0, sizeof(struct wlan_network));
593 
594     size_t ssid_len = strlen(ssid);
595     size_t password_len = strlen(password);
596     size_t label_len = strlen(label);
597 
598     if (s_wplState != WPL_STARTED)
599     {
600         status = WPLRET_NOT_READY;
601     }
602 
603     if ((label_len == 0U) || (label_len > WLAN_NETWORK_NAME_MAX_LENGTH))
604     {
605         status = WPLRET_BAD_PARAM;
606     }
607 
608     if ((ssid_len == 0U) || (ssid_len > IEEEtypes_SSID_SIZE))
609     {
610         status = WPLRET_BAD_PARAM;
611     }
612 
613     if (((0U < password_len) && (password_len < WPL_WIFI_PASSWORD_MIN_LEN)) ||
614         (password_len > WPL_WIFI_PASSWORD_LENGTH))
615     {
616         status = WPLRET_BAD_PARAM;
617     }
618 
619     if (status == WPLRET_SUCCESS)
620     {
621         if (password_len == 0U)
622         {
623             sta_network.security.type = WLAN_SECURITY_NONE;
624         }
625         else
626         {
627             switch (security)
628             {
629                 case WPL_SECURITY_WILDCARD:
630                     sta_network.security.type = WLAN_SECURITY_WILDCARD;
631                     sta_network.security.mfpc = true;
632                     sta_network.security.mfpr = true;
633                     sta_network.security.password_len = password_len;
634                     strncpy(sta_network.security.password, password, password_len);
635                     sta_network.security.psk_len = (uint8_t)password_len;
636                     strncpy(sta_network.security.psk, password, password_len);
637                     break;
638                 case WPL_SECURITY_WPA3_SAE:
639                     sta_network.security.type = WLAN_SECURITY_WPA3_SAE;
640                     sta_network.security.mfpc = true;
641                     sta_network.security.mfpr = true;
642                     sta_network.security.password_len = password_len;
643                     strncpy(sta_network.security.password, password, password_len);
644                     break;
645                 default:
646                     PRINTF("[!] Unimplemented security type (%d)\r\n", security);
647                     status = WPLRET_BAD_PARAM;
648                     break;
649             }
650         }
651     }
652 
653     if (status == WPLRET_SUCCESS)
654     {
655         strncpy(sta_network.name, label, label_len);
656         strncpy(sta_network.ssid, ssid, ssid_len);
657         sta_network.ip.ipv4.addr_type = ADDR_TYPE_DHCP;
658         sta_network.ssid_specific     = 1;
659 
660         ret = wlan_add_network(&sta_network);
661         if (ret != WM_SUCCESS)
662         {
663             status = WPLRET_FAIL;
664         }
665     }
666 
667     return status;
668 }
669 
WPL_AddNetwork(const char * ssid,const char * password,const char * label)670 wpl_ret_t WPL_AddNetwork(const char *ssid, const char *password, const char *label)
671 {
672     return WPL_AddNetworkWithSecurity(ssid, password, label, WPL_SECURITY_WILDCARD);
673 }
674 
WPL_RemoveNetwork(const char * label)675 wpl_ret_t WPL_RemoveNetwork(const char *label)
676 {
677     wpl_ret_t status = WPLRET_SUCCESS;
678     int ret;
679     size_t label_len = strlen(label);
680 
681     if (s_wplState != WPL_STARTED)
682     {
683         status = WPLRET_NOT_READY;
684     }
685 
686     if ((label_len == 0U) || (label_len > WLAN_NETWORK_NAME_MAX_LENGTH))
687     {
688         status = WPLRET_BAD_PARAM;
689     }
690 
691     if (status == WPLRET_SUCCESS)
692     {
693         ret = wlan_remove_network(label);
694         if (ret != WM_SUCCESS)
695         {
696             status = WPLRET_FAIL;
697         }
698     }
699 
700     return status;
701 }
702 
WPL_Join(char * label)703 wpl_ret_t WPL_Join(char *label)
704 {
705     wpl_ret_t status = WPLRET_SUCCESS;
706     int ret;
707     EventBits_t syncBit;
708     size_t label_len = strlen(label);
709 
710     if ((s_wplState != WPL_STARTED) || (s_wplStaConnected != false))
711     {
712         status = WPLRET_NOT_READY;
713     }
714 
715     if ((label_len == 0U) || (label_len > WLAN_NETWORK_NAME_MAX_LENGTH))
716     {
717         status = WPLRET_BAD_PARAM;
718     }
719 
720     if (status == WPLRET_SUCCESS)
721     {
722         (void)xEventGroupClearBits(s_wplSyncEvent, WPL_SYNC_CONNECT_GROUP);
723 
724         ret = wlan_connect(label);
725         if (ret != WM_SUCCESS)
726         {
727             status = WPLRET_FAIL;
728         }
729     }
730 
731     if (status == WPLRET_SUCCESS)
732     {
733         syncBit = xEventGroupWaitBits(s_wplSyncEvent, WPL_SYNC_CONNECT_GROUP, pdTRUE, pdFALSE, WPL_SYNC_TIMEOUT_MS);
734         if ((syncBit & EVENT_BIT(WLAN_REASON_SUCCESS)) != 0U)
735         {
736             status = WPLRET_SUCCESS;
737         }
738         else if ((syncBit & EVENT_BIT(WLAN_REASON_CONNECT_FAILED)) != 0U)
739         {
740             status = WPLRET_FAIL;
741         }
742         else if ((syncBit & EVENT_BIT(WLAN_REASON_NETWORK_NOT_FOUND)) != 0U)
743         {
744             status = WPLRET_NOT_FOUND;
745         }
746         else if ((syncBit & EVENT_BIT(WLAN_REASON_NETWORK_AUTH_FAILED)) != 0U)
747         {
748             status = WPLRET_AUTH_FAILED;
749         }
750         else if ((syncBit & EVENT_BIT(WLAN_REASON_ADDRESS_FAILED)) != 0U)
751         {
752             status = WPLRET_ADDR_FAILED;
753         }
754         else
755         {
756             status = WPLRET_TIMEOUT;
757         }
758 
759         if (status != WPLRET_SUCCESS)
760         {
761             /* Abort the next connection attempt */
762             (void)WPL_Leave();
763         }
764     }
765 
766     if (status == WPLRET_SUCCESS)
767     {
768         s_wplStaConnected = true;
769     }
770 
771     return status;
772 }
773 
WPL_Leave(void)774 wpl_ret_t WPL_Leave(void)
775 {
776     wpl_ret_t status = WPLRET_SUCCESS;
777     int ret;
778     EventBits_t syncBit;
779 
780     if (s_wplState != WPL_STARTED)
781     {
782         status = WPLRET_NOT_READY;
783     }
784 
785     enum wlan_connection_state connection_state = WLAN_DISCONNECTED;
786     ret = wlan_get_connection_state(&connection_state);
787     if (ret != WM_SUCCESS)
788     {
789         status = WPLRET_FAIL;
790     }
791     else
792     {
793         if (connection_state == WLAN_DISCONNECTED)
794         {
795             s_wplStaConnected = false;
796             return WPLRET_SUCCESS;
797         }
798     }
799 
800     if (status == WPLRET_SUCCESS)
801     {
802         (void)xEventGroupClearBits(s_wplSyncEvent, WPL_SYNC_DISCONNECT_GROUP);
803 
804         ret = wlan_disconnect();
805         if (ret != WM_SUCCESS)
806         {
807             status = WPLRET_FAIL;
808         }
809     }
810 
811     if (status == WPLRET_SUCCESS)
812     {
813         syncBit = xEventGroupWaitBits(s_wplSyncEvent, WPL_SYNC_DISCONNECT_GROUP, pdTRUE, pdFALSE, WPL_SYNC_TIMEOUT_MS);
814         if ((syncBit & EVENT_BIT(WLAN_REASON_USER_DISCONNECT)) != 0U)
815         {
816             status = WPLRET_SUCCESS;
817         }
818         else
819         {
820             status = WPLRET_TIMEOUT;
821         }
822     }
823 
824     s_wplStaConnected = false;
825 
826     return status;
827 }
828 
WPL_GetIP(char * ip,int client)829 wpl_ret_t WPL_GetIP(char *ip, int client)
830 {
831     wpl_ret_t status = WPLRET_SUCCESS;
832     int ret;
833     struct wlan_ip_config addr;
834 
835     if (ip == NULL)
836     {
837         status = WPLRET_FAIL;
838     }
839 
840     if (status == WPLRET_SUCCESS)
841     {
842         if (client == 1)
843         {
844             ret = wlan_get_address(&addr);
845         }
846         else
847         {
848             ret = wlan_get_uap_address(&addr);
849         }
850 
851         if (ret == WM_SUCCESS)
852         {
853             net_inet_ntoa(addr.ipv4.address, ip);
854         }
855         else
856         {
857             status = WPLRET_FAIL;
858         }
859     }
860 
861     return status;
862 }
863