aml-commonlib: add wpa_wifi_util [2/2]
PD#SWPL-151513
Problem:
Currently, connecting to wifi mainly uses script commands, which
are not convenient for programs to call.
Solution:
Use wpa_client.so to communicate with the wpa_supplicant backend program
via socket to avoid calling wpa_cli directly.
Verify:
a5
Change-Id: I1d12b08569f9044bbb58d48c68a93d7615efea92
Signed-off-by: yifan.li <yifan.li@amlogic.com>
diff --git a/aml_wpa_wifi_util/Makefile b/aml_wpa_wifi_util/Makefile
new file mode 100644
index 0000000..f9606bc
--- /dev/null
+++ b/aml_wpa_wifi_util/Makefile
@@ -0,0 +1,37 @@
+CFLAGS += -Wall -g -I../aml_log
+LDFLAGS += -L../aml_log
+LDLIBS += -laml_log -lwpa_client -lpthread
+
+SRC = aml_wpa_wifi_util.c
+TARGET = libaml_wpa_wifi_util.so
+BIN_TARGET = aml_wpa_wifi_test_demo
+
+# determine if you need to build the demo as needed, set 1 to build, set 0 not to build
+BUILD_BIN_TARGET := 0
+
+ifeq ($(BUILD_BIN_TARGET),1)
+TARGET += $(BIN_TARGET)
+endif
+
+all: $(TARGET)
+
+$(TARGET): $(SRC)
+ $(CC) $(CFLAGS) $(LDFLAGS) -shared -fPIC \
+ -o $@ $^ $(LDLIBS)
+
+ifeq ($(BUILD_BIN_TARGET),1)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $(BIN_TARGET) aml_wpa_wifi_test_demo.c -L. -laml_wpa_wifi_util $(LDLIBS) -w
+endif
+
+clean:
+ rm $(TARGET)
+
+install:
+ install -m 0644 libaml_wpa_wifi_util.so $(TARGET_DIR)/usr/lib/
+ if [ -f "$(BIN_TARGET)" ]; then install -m 0755 $(BIN_TARGET) $(TARGET_DIR)/usr/bin/; fi
+ install -m 0644 aml_wpa_wifi_util.h $(STAGING_DIR)/usr/include/
+ install -m 0644 libaml_wpa_wifi_util.so $(STAGING_DIR)/usr/lib/
+
+uninstall:
+ rm -f $(TARGET_DIR)/usr/lib/libaml_wpa_wifi_util.so
+ if [ -f "$(TARGET_DIR)/usr/bin/$(BIN_TARGET)" ]; then rm -f $(TARGET_DIR)/usr/bin/$(BIN_TARGET); fi
\ No newline at end of file
diff --git a/aml_wpa_wifi_util/aml_wpa_wifi_test_demo.c b/aml_wpa_wifi_util/aml_wpa_wifi_test_demo.c
new file mode 100644
index 0000000..dbde73f
--- /dev/null
+++ b/aml_wpa_wifi_util/aml_wpa_wifi_test_demo.c
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2023 Amlogic, Inc. All rights reserved.
+ *
+ * All information contained herein is Amlogic confidential.
+ *
+ * This software is provided to you pursuant to Software License Agreement
+ * (SLA) with Amlogic Inc ("Amlogic"). This software may be used
+ * only in accordance with the terms of this agreement.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification is strictly prohibited without prior written permission from
+ * Amlogic.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <pthread.h>
+#include <signal.h>
+
+#include "aml_wpa_wifi_util.h"
+
+#define INVALID_INPUT -99
+#define MAX_TEST_CASE 7
+#define INPUT_NUMBER(var, ...) get_input_string(type_int, var, __VA_ARGS__)
+#define INPUT_STRING(var, ...) get_input_string(type_string, var, __VA_ARGS__)
+#define INPUT_CHAR(var, ...) get_input_string(type_char, var, __VA_ARGS__)
+
+static const char *wpa_wifi_connection_status_strings[] = {
+ "WPA_WIFI_INVALID",
+ "WPA_WIFI_SUCCESS",
+ "WPA_WIFI_CONNECTING",
+ "WPA_WIFI_DISCONNECTED",
+ "WPA_WIFI_ERROR_NOT_FOUND",
+ "WPA_WIFI_ERROR_INVALID_CREDENTIALS",
+ "WPA_WIFI_ERROR_TIMEOUT_EXPIRED",
+ "WPA_WIFI_ERROR_DEV_DISCONNECT",
+ "WPA_WIFI_ERROR_UNKNOWN"
+};
+
+static const char *wpa_wifi_scan_status_strings[] = {
+ "WPA_WIFI_SCAN_STATE_IDLE",
+ "WPA_WIFI_SCAN_STATE_CMD_SENT",
+ "WPA_WIFI_SCAN_STATE_STARTED",
+ "WPA_WIFI_SCAN_STATE_RESULTS_RECEIVED",
+};
+
+static const char *wpa_wifi_signal_level[] = {
+ "Level 0, Range rssi <= -88",
+ "Level 1, Range (-88, -77]",
+ "Level 2, Range (-77, -66]",
+ "Level 3, Range (-66, -55]",
+ "Level 4, Range rssi > -55"
+};
+
+typedef enum _input_types {
+ type_int = 0,
+ type_string = 1,
+ type_char = 2
+}INPUT_TYPES_E;
+
+void get_input_string(INPUT_TYPES_E var_type, void *input, const char *prompt, ...)
+{
+ #define MAX_INPUT 100
+ va_list argp;
+ char buf[MAX_INPUT];
+ va_start(argp, prompt);
+ vprintf(prompt, argp);
+ va_end(argp);
+
+ fgets(buf, MAX_INPUT, stdin);
+ if (var_type == type_int) {
+ if (isdigit(buf[0]))
+ sscanf(buf,"%d",(int*)input);
+ else
+ *(int*)input = -1;
+ }
+ else if (var_type == type_string) {
+ sscanf(buf,"%[^\n]",(char*)input);
+ }
+ else if (var_type == type_char) {
+ sscanf(buf,"%c",(char*)input);
+ }
+ /*add more cases if required...*/
+ return;
+}
+
+void exit_handler(int sig)
+{
+ wpa_wifi_uninit();
+ printf("signal is %d, exit! \n", sig);
+ exit(0);
+}
+
+/*
+ custom wifi connection status callback function
+*/
+void demo_wifi_connect_callback(char *ssid, const WPA_WIFI_STATUS_TYPE *cur_status) {
+ if (WPA_WIFI_SUCCESS == *cur_status) {
+ printf("ssid [%s] connect successfully\n", ssid);
+ } else {
+ printf("ssid [%s] is connecting or fail, status is %s\n", ssid, wpa_wifi_connection_status_strings[*cur_status]);
+ }
+}
+
+void help()
+{
+ printf("\n****************** AMLOGIC WPA WiFi Basic API Test Options ******************\n");
+ printf(" [ 1 ] Connect to ssid \n");
+ printf(" [ 2 ] Disconnect current connection \n");
+ printf(" [ 3 ] Scan and get ssids \n");
+ printf(" [ 4 ] Reconnect the last ssid \n");
+ printf(" [ 5 ] Get current wifi connection status\n");
+ printf(" [ 6 ] Get current wifi scan status \n");
+ printf(" [ 7 ] Get current wifi connection info \n");
+ printf(" [ h ] Show this list \n");
+ printf(" [ q ] Quit \n");
+ printf("***********************************************************************\n");
+}
+
+int main() {
+ wpa_wifi_init(DEFAULT_WPA_SUPL_CTRL, demo_wifi_connect_callback, 0, 1);
+
+ char input[16];
+ char ssid[WPA_SSID_SIZE_MAX];
+ char password[WPA_PSK_SIZE_MAX];
+ WPA_WIFI_AP_INFO wifi_ap_array[WPA_AP_NUM_MAX];
+ WPA_WIFI_STATUS_TYPE cur_status;
+ int ap_num;
+ int select;
+ int ret;
+ int is_ap_sort_by_signal_strength;
+
+ signal(SIGTERM, exit_handler);
+ signal(SIGINT, exit_handler);
+ signal(SIGPIPE, exit_handler);
+
+ help();
+ while (1) {
+ input[0]='\0';
+ INPUT_STRING(&input,"\n[ Enter your choice ]: ");
+ if (input[0] == 'h') {
+ help();
+ continue;
+ }
+ else if (input[0] == 'q') {
+ exit_handler(0);
+ }
+ else {
+ if (!isdigit(input[0]))
+ select = INVALID_INPUT;
+ else
+ select = atoi(input);
+
+ if (select == INVALID_INPUT || select < 0 || select > MAX_TEST_CASE) {
+ printf("Entered option [%s] is not a valid one, supported are [h, q, 1-%d]\n",input,MAX_TEST_CASE);
+ continue;
+ }
+ }
+ switch (select) {
+ case 1:
+ INPUT_STRING(ssid, "[[ Please enter the SSID ]] \n");
+ INPUT_STRING(password, "[[ Please enter PSK for SSID %s ]] \n",ssid);
+ wpa_wifi_send_connect_cmd(ssid, password);
+ break;
+ case 2:
+ wpa_wifi_send_disconnect_cmd();
+ break;
+ case 3:
+ INPUT_NUMBER(&is_ap_sort_by_signal_strength, "[[ Please enter whether you want to sort by intensity, 1 means yes, 0 means no ]] \n");
+ wpa_wifi_send_scan_cmd();
+ ret = wpa_wifi_get_scan_results(wifi_ap_array, WPA_AP_NUM_MAX, &ap_num, is_ap_sort_by_signal_strength);
+ if (RETURN_OK == ret) {
+ printf("get scan results successfully, ssid number is %d \n", ap_num);
+ for (int i = 0; i < ap_num; ++i) {
+ printf("ap %d: ssid is [%s], strength is [%d], level info is: [%s]\n", i, \
+ wifi_ap_array[i].ssid, wifi_ap_array[i].signal_strength, wpa_wifi_signal_level[wifi_ap_array[i].signal_level]);
+ }
+ } else {
+ printf("get scan results fail\n");
+ }
+ break;
+ case 4:
+ wpa_wifi_send_reconnect_cmd();
+ break;
+ case 5:
+ wpa_wifi_get_current_wifi_status(&cur_status);
+ printf("current wifi connection status is %s\n", wpa_wifi_connection_status_strings[cur_status]);
+ break;
+ case 6:
+ wpa_wifi_get_current_scan_status(&cur_status);
+ printf("current wifi scan status is %s\n", wpa_wifi_scan_status_strings[cur_status]);
+ break;
+ case 7:
+ wpa_wifi_send_status_cmd();
+ break;
+ default:
+ printf("Option [%d] not supported \n",select);
+ continue;
+ }
+ }
+}
\ No newline at end of file
diff --git a/aml_wpa_wifi_util/aml_wpa_wifi_util.c b/aml_wpa_wifi_util/aml_wpa_wifi_util.c
new file mode 100644
index 0000000..30580c1
--- /dev/null
+++ b/aml_wpa_wifi_util/aml_wpa_wifi_util.c
@@ -0,0 +1,634 @@
+/*
+ * Copyright (C) 2023 Amlogic, Inc. All rights reserved.
+ *
+ * All information contained herein is Amlogic confidential.
+ *
+ * This software is provided to you pursuant to Software License Agreement
+ * (SLA) with Amlogic Inc ("Amlogic"). This software may be used
+ * only in accordance with the terms of this agreement.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification is strictly prohibited without prior written permission from
+ * Amlogic.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <pthread.h>
+#include <signal.h>
+
+#include "aml_wpa_wifi_util.h"
+#include "aml_log.h"
+
+#define MAX_LINE_LENGTH 256
+static WPA_WIFI_AP_INFO wpa_wifi_array[WPA_AP_NUM_MAX];
+static WPA_WIFI_MANAGER g_wpa_manager;
+
+static int sorted_by_ssid_dictionary(const void *a, const void *b) {
+ const WPA_WIFI_AP_INFO *ap_info_a = (const WPA_WIFI_AP_INFO *)a;
+ const WPA_WIFI_AP_INFO *ap_info_b = (const WPA_WIFI_AP_INFO *)b;
+
+ return strcasecmp(ap_info_a->ssid, ap_info_b->ssid);
+}
+
+static int sorted_by_signal_strength(const void *a, const void *b) {
+ const WPA_WIFI_AP_INFO *ap_info_a = (const WPA_WIFI_AP_INFO *)a;
+ const WPA_WIFI_AP_INFO *ap_info_b = (const WPA_WIFI_AP_INFO *)b;
+
+ return ap_info_b->signal_strength - ap_info_a->signal_strength ;
+}
+
+static int parse_scan_results(char *res_buf, int is_sort_by_strength) {
+ int count = 0, token;
+ char signal_str[64];
+ char *start_ptr, *end_ptr;
+
+ if (!res_buf)
+ return RETURN_ERR;
+
+#define SCAN_HEADER "bssid / frequency / signal level / flags / ssid"
+ if (strncmp(res_buf, SCAN_HEADER, sizeof(SCAN_HEADER) - 1) != 0) {
+ AML_LOGE("Scan result header mismatch, result format might have changed, [%s]\n", res_buf);
+ return RETURN_ERR;
+ }
+ // Skip first line (Header)
+ if ((start_ptr = strchr(res_buf, '\n')) == NULL)
+ return RETURN_ERR;
+ start_ptr++;
+// get next token separated by delimeter, copy a string from current position upto position of 'end'
+#define COPY_NEXT_TOKEN(output, start, end, delim) \
+ { \
+ if (token > 0) { \
+ end = strchr(start, delim); \
+ if (!end) { \
+ break; \
+ } \
+ } \
+ size_t length = end - start; \
+ if (length >= sizeof(output)) { \
+ break; \
+ } \
+ memcpy(output, start, length); \
+ output[length] = '\0'; \
+ start = end + 1; \
+ token++; \
+ }
+
+ // Parse scan results
+ while ((end_ptr = strchr(start_ptr, '\t')) != NULL) {
+ token = 0;
+
+ /* BSSID */
+ COPY_NEXT_TOKEN(wpa_wifi_array[count].bssid, start_ptr, end_ptr, '\t');
+
+ /* Frequency */
+ COPY_NEXT_TOKEN(signal_str, start_ptr, end_ptr, '\t');
+ wpa_wifi_array[count].frequency = atoi(signal_str);
+
+ /* Signal Strength */
+ COPY_NEXT_TOKEN(signal_str, start_ptr, end_ptr, '\t');
+
+ /* Signal Level */
+ wpa_wifi_array[count].signal_strength = atoi(signal_str);
+ if (wpa_wifi_array[count].signal_strength <= -88) {
+ wpa_wifi_array[count].signal_level = WPA_WIFI_LEVEL_0;
+ } else if (wpa_wifi_array[count].signal_strength <= -77) {
+ wpa_wifi_array[count].signal_level = WPA_WIFI_LEVEL_1;
+ } else if (wpa_wifi_array[count].signal_strength <= -66) {
+ wpa_wifi_array[count].signal_level = WPA_WIFI_LEVEL_2;
+ } else if (wpa_wifi_array[count].signal_strength <= -55) {
+ wpa_wifi_array[count].signal_level = WPA_WIFI_LEVEL_3;
+ } else {
+ wpa_wifi_array[count].signal_level = WPA_WIFI_LEVEL_4;
+ }
+
+ /* Flags (Encryption Mode) */
+ COPY_NEXT_TOKEN(wpa_wifi_array[count].flags, start_ptr, end_ptr, '\t');
+
+ /* SSID */
+ COPY_NEXT_TOKEN(wpa_wifi_array[count].ssid, start_ptr, end_ptr, '\n');
+
+ if (count >= WPA_AP_NUM_MAX - 1) {
+ AML_LOGW("WARNING - Scan reached Maximum supported AP (%d), stopping...\n", WPA_AP_NUM_MAX);
+ break;
+ }
+ count++;
+ }
+
+ // Sort by strength or by ssid
+ if (is_sort_by_strength) {
+ qsort(wpa_wifi_array, count, sizeof(WPA_WIFI_AP_INFO), sorted_by_signal_strength);
+ } else {
+ qsort(wpa_wifi_array, count, sizeof(WPA_WIFI_AP_INFO), sorted_by_ssid_dictionary);
+ }
+
+ AML_LOGI("Total scan AP count=%d\n", count);
+ return count;
+}
+
+static int extract_psk_from_wpa_conf(const char *filename, const char *target_ssid, char *output_psk) {
+ FILE *file = fopen(filename, "r");
+ if (file == NULL) {
+ AML_LOGE("Error opening %s file\n", filename);
+ return RETURN_ERR;
+ }
+
+ char line[MAX_LINE_LENGTH];
+ char current_ssid[WPA_SSID_SIZE_MAX];
+ char current_psk[WPA_PSK_SIZE_MAX];
+
+ output_psk[0] = '\0';
+
+ while (fgets(line, MAX_LINE_LENGTH, file) != NULL) {
+ if (strstr(line, "network={") != NULL) {
+ current_ssid[0] = '\0';
+ current_psk[0] = '\0';
+
+ while (fgets(line, MAX_LINE_LENGTH, file) != NULL) {
+ if (strstr(line, "ssid=") != NULL) {
+ sscanf(line, " ssid=\"%[^\"]\"", current_ssid);
+ }
+ else if (strstr(line, "psk=") != NULL) {
+ sscanf(line, " psk=\"%[^\"]\"", current_psk);
+ }
+ else if (strstr(line, "}") != NULL) {
+ break;
+ }
+ }
+ if (strcmp(current_ssid, target_ssid) == 0) {
+ strcpy(output_psk, current_psk);
+ return RETURN_OK;
+ }
+ }
+ }
+ fclose(file);
+ return RETURN_ERR;
+}
+
+static int send_wpa_cli_command(char *reply, size_t reply_len, const char *cmd, ...) {
+ char cmd_buf[WPA_SUP_CMD_MAX];
+ int ret;
+
+ va_list argp;
+ va_start(argp, cmd);
+ vsnprintf(cmd_buf, sizeof(cmd_buf), cmd, argp);
+ va_end(argp);
+
+ /* clear previous result string. */
+ memset(reply, 0, reply_len);
+
+ if (!g_wpa_manager.ctrl_handle) {
+ AML_LOGE("%s: cmd=%s, error=init_err\n",__func__,cmd_buf);
+ return WPA_SUP_CMD_INIT_ERR;
+ }
+
+ ret = wpa_ctrl_request(g_wpa_manager.ctrl_handle, cmd_buf, strlen(cmd_buf), reply, &reply_len, NULL);
+
+ if (ret == WPA_SUP_CMD_TIMEOUT) {
+ AML_LOGE("%s : cmd=%s, error=timeout \n", __func__, cmd_buf);
+ return WPA_SUP_CMD_TIMEOUT;
+ } else if (ret < 0) {
+ AML_LOGE("%s : cmd=%s, error=failed \n", __func__, cmd_buf);
+ return WPA_SUP_CMD_FAILED;
+ }
+ AML_LOGD("send wpa cmd is %s \n", cmd_buf);
+ return WPA_SUP_CMD_SUCCESSFUL;
+}
+
+int wpa_wifi_send_scan_cmd() {
+ char result[128];
+ int ret;
+ int result_len = sizeof(result)-1;
+ pthread_mutex_lock(&g_wpa_manager.sup_lock);
+ if (g_wpa_manager.cur_scan_status == WPA_WIFI_SCAN_STATE_RESULTS_RECEIVED) {
+ AML_LOGD("Scan is finish, please firstly get the last scan results \n");
+ pthread_mutex_unlock(&g_wpa_manager.sup_lock);
+ return RETURN_OK;
+ }
+ ret = send_wpa_cli_command(result, result_len, "SCAN");
+ pthread_mutex_unlock(&g_wpa_manager.sup_lock);
+ if (ret) {
+ AML_LOGE("send wpa cmd SCAN fail\n");
+ return ret;
+ }
+ while (strstr(result, "FAIL-BUSY") != NULL) {
+ result_len = sizeof(result)-1;
+ AML_LOGD("scan command returned %s .. waiting \n", result);
+ pthread_mutex_lock(&g_wpa_manager.sup_lock);
+ sleep(1);
+ send_wpa_cli_command(result, result_len, "SCAN");
+ pthread_mutex_unlock(&g_wpa_manager.sup_lock);
+ }
+
+ AML_LOGI("send wpa cmd SCAN successfully, return msg is %s\n", result);
+ pthread_mutex_lock(&g_wpa_manager.sup_lock);
+ g_wpa_manager.cur_scan_status = WPA_WIFI_SCAN_STATE_CMD_SENT;
+ pthread_mutex_unlock(&g_wpa_manager.sup_lock);
+ return ret;
+}
+
+int wpa_wifi_send_status_cmd() {
+ char result[512];
+ int ret;
+ pthread_mutex_lock(&g_wpa_manager.sup_lock);
+ ret = send_wpa_cli_command(result, sizeof(result)-1, "STATUS");
+ pthread_mutex_unlock(&g_wpa_manager.sup_lock);
+ if (!ret) {
+ AML_LOGI("send wpa cmd STATUS successfully, scurrent status is :\n %s\n", result);
+ } else {
+ AML_LOGE("send wpa cmd STATUS fail\n");
+ }
+ return ret;
+}
+
+int wpa_wifi_send_save_config_cmd() {
+ char result[64];
+ int ret;
+ pthread_mutex_lock(&g_wpa_manager.sup_lock);
+ ret = send_wpa_cli_command(result, sizeof(result)-1, "SAVE_CONFIG");
+ pthread_mutex_unlock(&g_wpa_manager.sup_lock);
+ if (!ret) {
+ AML_LOGI("send wpa cmd SAVE_CONFIG successfully\n");
+ } else {
+ AML_LOGE("send wpa cmd SAVE_CONFIG fail\n");
+ }
+ return ret;
+}
+
+int wpa_wifi_send_enable_cmd(int network_id) {
+ char result[64];
+ int ret;
+ char cmd[256];
+ memset(cmd, 0, sizeof(cmd));
+ snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %d", network_id);
+ pthread_mutex_lock(&g_wpa_manager.sup_lock);
+ ret = send_wpa_cli_command(result, sizeof(result)-1, cmd);
+ pthread_mutex_unlock(&g_wpa_manager.sup_lock);
+ if (!ret) {
+ AML_LOGI("send wpa cmd ENABLE_NETWORK successfully\n");
+ } else {
+ AML_LOGE("send wpa cmd ENABLE_NETWORK fail\n");
+ }
+ return ret;
+}
+
+int wpa_wifi_send_disable_cmd(int network_id) {
+ char result[64];
+ int ret;
+ char cmd[256];
+ memset(cmd, 0, sizeof(cmd));
+ snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %d", network_id);
+ pthread_mutex_lock(&g_wpa_manager.sup_lock);
+ ret = send_wpa_cli_command(result, sizeof(result)-1, cmd);
+ pthread_mutex_unlock(&g_wpa_manager.sup_lock);
+ if (!ret) {
+ AML_LOGI("send wpa cmd DISABLE_NETWORK successfully\n");
+ } else {
+ AML_LOGE("send wpa cmd DISABLE_NETWORK fail\n");
+ }
+ return ret;
+}
+
+int wpa_wifi_send_disconnect_cmd() {
+ char result[64];
+ int ret;
+ pthread_mutex_lock(&g_wpa_manager.sup_lock);
+ ret = send_wpa_cli_command(result, sizeof(result)-1, "DISCONNECT");
+ pthread_mutex_unlock(&g_wpa_manager.sup_lock);
+ if (!ret) {
+ AML_LOGI("send wpa cmd DISCONNECT successfully\n");
+ pthread_mutex_lock(&g_wpa_manager.sup_lock);
+ g_wpa_manager.cur_wifi_status = WPA_WIFI_DISCONNECTED;
+ pthread_mutex_unlock(&g_wpa_manager.sup_lock);
+ } else {
+ AML_LOGE("send wpa cmd DISCONNECT fail\n");
+ }
+ return ret;
+}
+
+int wpa_wifi_send_reconnect_cmd() {
+ char result[64];
+ int ret;
+ pthread_mutex_lock(&g_wpa_manager.sup_lock);
+ ret = send_wpa_cli_command(result, sizeof(result)-1, "RECONNECT");
+ pthread_mutex_unlock(&g_wpa_manager.sup_lock);
+ if (!ret) {
+ AML_LOGI("send wpa cmd RECONNECT successfully\n");
+ } else {
+ AML_LOGE("send wpa cmd RECONNECT fail\n");
+ }
+ return ret;
+}
+
+int wpa_wifi_send_connect_cmd(const char* ssid, const char* passward) {
+ char result[64];
+ pthread_mutex_lock(&g_wpa_manager.sup_lock);
+ g_wpa_manager.cur_wifi_status = WPA_WIFI_INVALID;
+ send_wpa_cli_command(result, sizeof(result)-1, "REMOVE_NETWORK %d", g_wpa_manager.cur_enable_network_id);
+ send_wpa_cli_command(result, sizeof(result)-1, "ADD_NETWORK");
+
+ // set ssid
+ send_wpa_cli_command(result, sizeof(result)-1, "SET_NETWORK %d ssid \"%s\"", g_wpa_manager.cur_enable_network_id, ssid);
+ send_wpa_cli_command(result, sizeof(result)-1, "SET_NETWORK %d key_mgmt WPA-PSK", g_wpa_manager.cur_enable_network_id);
+ // set psk
+ send_wpa_cli_command(result, sizeof(result)-1, "SET_NETWORK %d psk \"%s\"", g_wpa_manager.cur_enable_network_id, passward);
+
+ send_wpa_cli_command(result, sizeof(result)-1, "SET_NETWORK %d pairwise CCMP TKIP", g_wpa_manager.cur_enable_network_id);
+ send_wpa_cli_command(result, sizeof(result)-1, "SET_NETWORK %d group CCMP TKIP", g_wpa_manager.cur_enable_network_id);
+ send_wpa_cli_command(result, sizeof(result)-1, "SET_NETWORK %d proto RSN", g_wpa_manager.cur_enable_network_id);
+
+ send_wpa_cli_command(result, sizeof(result)-1, "ENABLE_NETWORK %d", g_wpa_manager.cur_enable_network_id);
+ send_wpa_cli_command(result, sizeof(result)-1, "REASSOCIATE");
+ pthread_mutex_unlock(&g_wpa_manager.sup_lock);
+
+ return RETURN_OK;
+}
+
+/*
+ Monitoring thread, sends state messages to wifi service manager
+*/
+static void* wpa_wifi_event_monitor_thread() {
+ char *start;
+ char event_buf[512];
+ size_t event_buf_len;
+ char result_buf[4096];
+ while (!g_wpa_manager.monitor_is_stop && g_wpa_manager.ctrl_handle) {
+ if (wpa_ctrl_pending(g_wpa_manager.ctrl_handle) > 0) {
+ memset(event_buf, 0, sizeof(event_buf));
+ memset(result_buf, 0, sizeof(result_buf));
+
+ event_buf_len = sizeof(event_buf) - 1;
+ if (0 == wpa_ctrl_recv(g_wpa_manager.ctrl_handle, event_buf, &event_buf_len)) {
+ start = strchr(event_buf, '>') + 1;
+ if (start == NULL) continue;
+ AML_LOGI("Received event (length = %d) message: %s\n", (int)event_buf_len, start);
+
+ if (strstr(start, WPA_EVENT_SCAN_STARTED) != NULL) {
+ AML_LOGI("Scanning started \n");
+
+ pthread_mutex_lock(&g_wpa_manager.sup_lock);
+ // Only actively triggered scans will Flush the BSS
+ if (g_wpa_manager.cur_scan_status == WPA_WIFI_SCAN_STATE_CMD_SENT) {
+ /* Flush the BSS everytime so that there is no stale information */
+ AML_LOGI("Flushing the BSS now\n");
+ send_wpa_cli_command(result_buf, sizeof(result_buf)-1, "BSS_FLUSH %d", g_wpa_manager.cur_enable_network_id);
+ g_wpa_manager.cur_scan_status = WPA_WIFI_SCAN_STATE_STARTED;
+ }
+ pthread_mutex_unlock(&g_wpa_manager.sup_lock);
+ }
+ else if (strstr(start, WPA_EVENT_SCAN_RESULTS) != NULL) {
+ AML_LOGI("Scanning results received \n");
+ if (g_wpa_manager.cur_scan_status == WPA_WIFI_SCAN_STATE_STARTED) {
+ pthread_mutex_lock(&g_wpa_manager.sup_lock);
+ g_wpa_manager.cur_scan_status = WPA_WIFI_SCAN_STATE_RESULTS_RECEIVED;
+ pthread_mutex_unlock(&g_wpa_manager.sup_lock);
+ }
+ }
+ else if ((strstr(start, WPS_EVENT_AP_AVAILABLE_PBC) != NULL)){
+ AML_LOGI("WPS Connection in progress\n");
+ pthread_mutex_lock(&g_wpa_manager.sup_lock);
+ g_wpa_manager.cur_wifi_status = WPA_WIFI_CONNECTING;
+ pthread_mutex_unlock(&g_wpa_manager.sup_lock);
+ }
+ else if (strstr(start, WPS_EVENT_TIMEOUT) != NULL) {
+ AML_LOGI("WPS Connection is timeout\n");
+ char cur_ssid[WPA_SSID_SIZE_MAX];
+ pthread_mutex_lock(&g_wpa_manager.sup_lock);
+ // get ssid
+ send_wpa_cli_command(cur_ssid, sizeof(cur_ssid)-1,"GET_NETWORK %d ssid", g_wpa_manager.cur_enable_network_id);
+ g_wpa_manager.cur_wifi_status = WPA_WIFI_ERROR_NOT_FOUND;
+ pthread_mutex_unlock(&g_wpa_manager.sup_lock);
+ if (g_wpa_manager.connect_callback) {
+ g_wpa_manager.connect_callback(cur_ssid, &g_wpa_manager.cur_wifi_status);
+ }
+ }
+ else if (strstr(start, WPS_EVENT_SUCCESS) != NULL) {
+ AML_LOGI("WPS is successful...Associating now\n");
+ }
+ else if (strstr(start, WPA_EVENT_CONNECTED) != NULL) {
+ AML_LOGI("Authentication completed successfully and data connection enabled\n");
+ char cur_ssid[WPA_SSID_SIZE_MAX];
+ pthread_mutex_lock(&g_wpa_manager.sup_lock);
+ // get ssid
+ send_wpa_cli_command(cur_ssid, sizeof(cur_ssid)-1,"GET_NETWORK %d ssid", g_wpa_manager.cur_enable_network_id);
+ if (strcmp(g_wpa_manager.cur_connected_ssid, cur_ssid) != 0) {
+ // mean new ssid connection
+ strcpy(g_wpa_manager.cur_connected_ssid, cur_ssid);
+ AML_LOGD("Update the current connected ssid to %s\n", cur_ssid);
+ }
+ g_wpa_manager.cur_wifi_status = WPA_WIFI_SUCCESS;
+
+ if (g_wpa_manager.save_when_connected) {
+ send_wpa_cli_command(result_buf, sizeof(result_buf)-1,"SAVE_CONFIG");
+ }
+ pthread_mutex_unlock(&g_wpa_manager.sup_lock);
+ if (g_wpa_manager.connect_callback) {
+ g_wpa_manager.connect_callback(cur_ssid, &g_wpa_manager.cur_wifi_status);
+ }
+ }
+ else if (strstr(start, WPA_EVENT_DISCONNECTED) != NULL) {
+ char cur_ssid[WPA_SSID_SIZE_MAX];
+ pthread_mutex_lock(&g_wpa_manager.sup_lock);
+ // get ssid
+ send_wpa_cli_command(cur_ssid, sizeof(cur_ssid)-1,"GET_NETWORK %d ssid", g_wpa_manager.cur_enable_network_id);
+ g_wpa_manager.cur_wifi_status = WPA_WIFI_DISCONNECTED;
+ pthread_mutex_unlock(&g_wpa_manager.sup_lock);
+ AML_LOGI("Disconnected from the network:%s\n", cur_ssid);
+ if (g_wpa_manager.connect_callback) {
+ g_wpa_manager.connect_callback(cur_ssid, &g_wpa_manager.cur_wifi_status);
+ }
+ }
+ else if (strstr(start, WPA_EVENT_TEMP_DISABLED) != NULL){
+ char cur_ssid[WPA_SSID_SIZE_MAX];
+ pthread_mutex_lock(&g_wpa_manager.sup_lock);
+ // get ssid
+ send_wpa_cli_command(cur_ssid, sizeof(cur_ssid)-1,"GET_NETWORK %d ssid", g_wpa_manager.cur_enable_network_id);
+
+ AML_LOGI("Network authentication failure (Incorrect password), ssid is %s\n", cur_ssid);
+
+ g_wpa_manager.cur_wifi_status = WPA_WIFI_ERROR_INVALID_CREDENTIALS;
+ pthread_mutex_unlock(&g_wpa_manager.sup_lock);
+ if (g_wpa_manager.connect_callback) {
+ g_wpa_manager.connect_callback(cur_ssid, &g_wpa_manager.cur_wifi_status);
+ }
+ }
+ else if (strstr(start, WPA_EVENT_NETWORK_NOT_FOUND) != NULL) {
+ char cur_ssid[WPA_SSID_SIZE_MAX];
+ pthread_mutex_lock(&g_wpa_manager.sup_lock);
+ // get ssid
+ send_wpa_cli_command(cur_ssid, sizeof(cur_ssid)-1,"GET_NETWORK %d ssid", g_wpa_manager.cur_enable_network_id);
+
+ AML_LOGI("Received a network not found event, ssid is %s\n", cur_ssid);
+
+ g_wpa_manager.cur_wifi_status = WPA_WIFI_ERROR_NOT_FOUND;
+ pthread_mutex_unlock(&g_wpa_manager.sup_lock);
+ if (g_wpa_manager.connect_callback) {
+ g_wpa_manager.connect_callback(cur_ssid, &g_wpa_manager.cur_wifi_status);
+ }
+ }
+ else {
+ continue;
+ }
+ }
+ }
+ else {
+ usleep(WPA_SUP_TIMEOUT);
+ }
+ }
+ return NULL;
+}
+
+int wpa_wifi_get_current_wifi_status(WPA_WIFI_STATUS_TYPE* status) {
+ pthread_mutex_lock(&g_wpa_manager.sup_lock);
+ *status = g_wpa_manager.cur_wifi_status;
+ pthread_mutex_unlock(&g_wpa_manager.sup_lock);
+ AML_LOGI("get wpa current wifi connection status is %d\n", g_wpa_manager.cur_wifi_status);
+ return RETURN_OK;
+}
+
+int wpa_wifi_get_current_scan_status(WPA_WIFI_SCAN_STATE* status) {
+ pthread_mutex_lock(&g_wpa_manager.sup_lock);
+ *status = g_wpa_manager.cur_scan_status;
+ pthread_mutex_unlock(&g_wpa_manager.sup_lock);
+ AML_LOGI("get wpa current wifi scan status is %d\n", g_wpa_manager.cur_scan_status);
+ return RETURN_OK;
+}
+
+static int is_ssid_duplicate(WPA_WIFI_AP_INFO wifi_array[], int count, char *ssid) {
+ for (int i = 0; i < count; i++) {
+ if (strcmp(wifi_array[i].ssid, ssid) == 0) {
+ // SSID found in the array, it's a duplicate
+ AML_LOGD("ssid [%s] found in the array is a duplicate, the bssid is [%s]\n", ssid, wifi_array[i].bssid);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int wpa_wifi_get_scan_results(WPA_WIFI_AP_INFO wifi_array_to_fill[], const int array_size, int* ap_count, int is_sort_by_strength) {
+ if (NULL == wifi_array_to_fill) {
+ AML_LOGE("Invalid wpa_ctrl connection or wifi_array_to_fill array\n");
+ return RETURN_ERR;
+ }
+ int retry = 0;
+ int found_ap_count = 0;
+ char long_result_str[4096];
+ int result_len=sizeof(long_result_str)-1;
+ while ((g_wpa_manager.cur_scan_status != WPA_WIFI_SCAN_STATE_RESULTS_RECEIVED) && (retry++ < 40)) {
+ AML_LOGD("Scanning !!!\n");
+ usleep(WPA_SUP_TIMEOUT);
+ }
+ if (g_wpa_manager.cur_scan_status != WPA_WIFI_SCAN_STATE_RESULTS_RECEIVED) {
+ AML_LOGE("Getting scan results is out-of-time\n");
+ return RETURN_ERR;
+ }
+ pthread_mutex_lock(&g_wpa_manager.sup_lock);
+ send_wpa_cli_command(long_result_str, result_len, "SCAN_RESULTS");
+ pthread_mutex_unlock(&g_wpa_manager.sup_lock);
+
+ // parsing the scan results
+ found_ap_count = parse_scan_results(long_result_str, is_sort_by_strength);
+ if (RETURN_ERR == found_ap_count) {
+ AML_LOGE("Parse scan results fail\n");
+ return RETURN_ERR;
+ }
+ pthread_mutex_lock(&g_wpa_manager.sup_lock);
+ g_wpa_manager.cur_scan_status = WPA_WIFI_SCAN_STATE_IDLE;
+ pthread_mutex_unlock(&g_wpa_manager.sup_lock);
+
+ // extract ssid, which may have duplicates or nulls
+ int real_count = 0;
+ for (int index = 0; index < found_ap_count && found_ap_count < array_size; ++index) {
+ if (strlen(wpa_wifi_array[index].ssid) > 0 && !is_ssid_duplicate(wifi_array_to_fill, real_count, wpa_wifi_array[index].ssid)) {
+ strncpy(wifi_array_to_fill[real_count].ssid, wpa_wifi_array[index].ssid, WPA_SSID_SIZE_MAX - 1);
+ strncpy(wifi_array_to_fill[real_count].bssid, wpa_wifi_array[index].bssid, WPA_BSSID_SIZE_MAX - 1);
+ wifi_array_to_fill[real_count].signal_strength = wpa_wifi_array[index].signal_strength;
+ wifi_array_to_fill[real_count].signal_level = wpa_wifi_array[index].signal_level;
+ wifi_array_to_fill[real_count].frequency = wpa_wifi_array[index].frequency;
+ ++real_count;
+ }
+ }
+
+ *ap_count = real_count;
+
+ AML_LOGI("The actual ssid scanned was %d, and %d were obtained after de-weighting and de-nulling\n", found_ap_count, real_count);
+ return RETURN_OK;
+}
+
+/*
+ Mainly to make sure to get the status of connected, when the wifi is already connected;
+ the other statuses don't matter
+*/
+static int init_cur_wifi_status() {
+ char result[512];
+ int ret;
+ pthread_mutex_lock(&g_wpa_manager.sup_lock);
+ ret = send_wpa_cli_command(result, sizeof(result)-1, "STATUS");
+ pthread_mutex_unlock(&g_wpa_manager.sup_lock);
+ if (!ret) {
+ AML_LOGI("get wpa wifi STATUS successfully, scurrent status is :\n %s\n", result);
+ if (strstr(result, "wpa_state=COMPLETED") != NULL) {
+ g_wpa_manager.cur_wifi_status = WPA_WIFI_SUCCESS;
+ }
+ } else {
+ AML_LOGE("get wpa wifi STATUS fail\n");
+ }
+ return ret;
+}
+
+int wpa_wifi_init (const char* wpa_supl_ctrl, wpa_wifi_connect_callback connect_callback, int enable_network_id, int save_when_connected) {
+ int retry = 0;
+ g_wpa_manager.connect_callback = connect_callback;
+ g_wpa_manager.cur_enable_network_id = enable_network_id;
+ g_wpa_manager.save_when_connected = save_when_connected;
+ g_wpa_manager.monitor_is_stop = 0;
+ g_wpa_manager.cur_connected_ssid[0] = '\0';
+ g_wpa_manager.ctrl_handle = wpa_ctrl_open(wpa_supl_ctrl);
+
+ while (g_wpa_manager.ctrl_handle == NULL) {
+ g_wpa_manager.ctrl_handle = wpa_ctrl_open(wpa_supl_ctrl);
+ if (retry++ > MAX_RETRY) break;
+ sleep(1);
+ }
+
+ init_cur_wifi_status();
+ // get current ssid
+ pthread_mutex_lock(&g_wpa_manager.sup_lock);
+ send_wpa_cli_command(g_wpa_manager.cur_connected_ssid, sizeof(g_wpa_manager.cur_connected_ssid)-1,"GET_NETWORK %d ssid", g_wpa_manager.cur_enable_network_id);
+ pthread_mutex_unlock(&g_wpa_manager.sup_lock);
+
+ if (wpa_ctrl_attach(g_wpa_manager.ctrl_handle) != 0) {
+ AML_LOGE("wpa_ctrl_attach failed \n");
+ return RETURN_ERR;
+ }
+ if (pthread_create(&g_wpa_manager.monitor_thread_id, NULL, wpa_wifi_event_monitor_thread, NULL) != 0) {
+ AML_LOGE("thread creation failed for wpa_wifi_event_monitor_thread() \n");
+ return RETURN_ERR;
+ }
+ return RETURN_OK;
+}
+
+int wpa_wifi_uninit(){
+ wpa_ctrl_detach(g_wpa_manager.ctrl_handle);
+ g_wpa_manager.monitor_is_stop = 1;
+ wpa_ctrl_close(g_wpa_manager.ctrl_handle);
+ pthread_join(g_wpa_manager.monitor_thread_id, NULL);
+ return RETURN_OK;
+}
\ No newline at end of file
diff --git a/aml_wpa_wifi_util/aml_wpa_wifi_util.h b/aml_wpa_wifi_util/aml_wpa_wifi_util.h
new file mode 100644
index 0000000..86a01f6
--- /dev/null
+++ b/aml_wpa_wifi_util/aml_wpa_wifi_util.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2023 Amlogic, Inc. All rights reserved.
+ *
+ * All information contained herein is Amlogic confidential.
+ *
+ * This software is provided to you pursuant to Software License Agreement
+ * (SLA) with Amlogic Inc ("Amlogic"). This software may be used
+ * only in accordance with the terms of this agreement.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification is strictly prohibited without prior written permission from
+ * Amlogic.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef AML_WPA_WIFI_UTIL_H
+#define AML_WPA_WIFI_UTIL_H
+#include "wpa_ctrl.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Default network
+#define DEFAULT_WPA_SUPL_CTRL "/var/run/wpa_supplicant/wlan0"
+#define DEFAULT_NETWORK_ID 0
+#define WPA_SUPPLICANT_CONF_PATH "/etc/wpa_supplicant.conf"
+
+// Return codes
+#define RETURN_OK 0
+#define RETURN_ERR -1
+
+/*
+ Return values for WPA Supplicant command execution
+*/
+#define WPA_SUP_CMD_SUCCESSFUL 0
+#define WPA_SUP_CMD_FAILED -1 // Return value in case WPA command failed
+#define WPA_SUP_CMD_TIMEOUT -2 // Return value in case WPA command timed out
+#define WPA_SUP_CMD_INIT_ERR -3 // Return value in case wifi_init is not done
+
+#define WPA_SUP_TIMEOUT 500000 // 500 msec
+#define WPA_SUP_CMD_MAX 256 // Maximum command size that can be sent to WPA Supplicant
+#define WPA_SSID_SIZE_MAX 64 // Maximum SSID length
+#define WPA_BSSID_SIZE_MAX 64 // Maximum BSSID length
+#define WPA_PSK_SIZE_MAX 64 // Maximum PSK length
+#define WPA_AP_NUM_MAX 64 // Maximum number of scanned APs to store
+
+#define MAX_RETRY 10
+
+/*
+ Wi-Fi status types
+*/
+typedef enum {
+ WPA_WIFI_INVALID = 0,
+ WPA_WIFI_SUCCESS,
+ WPA_WIFI_CONNECTING,
+ WPA_WIFI_DISCONNECTED,
+ WPA_WIFI_ERROR_NOT_FOUND,
+ WPA_WIFI_ERROR_INVALID_CREDENTIALS,
+ WPA_WIFI_ERROR_TIMEOUT_EXPIRED,
+ WPA_WIFI_ERROR_DEV_DISCONNECT,
+ WPA_WIFI_ERROR_UNKNOWN
+} WPA_WIFI_STATUS_TYPE;
+
+/*
+ Wi-Fi scan state types
+*/
+typedef enum {
+ WPA_WIFI_SCAN_STATE_IDLE,
+ WPA_WIFI_SCAN_STATE_CMD_SENT,
+ WPA_WIFI_SCAN_STATE_STARTED,
+ WPA_WIFI_SCAN_STATE_RESULTS_RECEIVED,
+} WPA_WIFI_SCAN_STATE;
+
+typedef void(* wpa_wifi_connect_callback) (char *ssid, const WPA_WIFI_STATUS_TYPE *cur_status);
+
+typedef struct {
+ struct wpa_ctrl *ctrl_handle;
+
+ // Callback function for Wi-Fi connection events
+ wpa_wifi_connect_callback connect_callback;
+
+ int monitor_is_stop;
+ pthread_t monitor_thread_id;
+
+ // scan state and wifi connect status
+ WPA_WIFI_SCAN_STATE cur_scan_status;
+ WPA_WIFI_STATUS_TYPE cur_wifi_status;
+
+ pthread_mutex_t sup_lock;
+
+ // Whether we want to save SSID information to configuration file: 1=save, 0=don't save
+ int cur_enable_network_id;
+ int save_when_connected;
+
+ char cur_connected_ssid[WPA_SSID_SIZE_MAX];
+}WPA_WIFI_MANAGER;
+
+typedef enum {
+ WPA_WIFI_LEVEL_0, // rssi <= -100
+ WPA_WIFI_LEVEL_1, // (-100, -88]
+ WPA_WIFI_LEVEL_2, // (-88, -77]
+ WPA_WIFI_LEVEL_3, // (-66, -55]
+ WPA_WIFI_LEVEL_4 // rssi >= -55
+} WPA_WIFI_SIGNAL_LEVEL;
+
+typedef struct {
+ char bssid[WPA_BSSID_SIZE_MAX]; // BSSID
+ int frequency; // Frequency
+ int signal_strength; // Signal Strength
+ WPA_WIFI_SIGNAL_LEVEL signal_level; // Signal Level
+ char flags[256]; // Flags
+ char ssid[WPA_SSID_SIZE_MAX]; // SSID
+} WPA_WIFI_AP_INFO;
+
+int wpa_wifi_send_scan_cmd();
+int wpa_wifi_send_status_cmd();
+int wpa_wifi_send_save_config_cmd();
+int wpa_wifi_send_disable_cmd(int network_id);
+int wpa_wifi_send_enable_cmd(int network_id);
+
+/*
+ Only wpa-psk is supported for now, any legal encryption is supported
+*/
+int wpa_wifi_send_connect_cmd(const char* ssid, const char* passward);
+int wpa_wifi_send_disconnect_cmd();
+int wpa_wifi_send_reconnect_cmd();
+
+int wpa_wifi_get_current_wifi_status(WPA_WIFI_STATUS_TYPE* status);
+int wpa_wifi_get_current_scan_status(WPA_WIFI_SCAN_STATE* status);
+int wpa_wifi_get_scan_results(WPA_WIFI_AP_INFO wifi_array_to_fill[], const int array_size, int* ap_count, int is_sort_by_strength);
+
+int wpa_wifi_init(const char* wpa_supl_ctrl, wpa_wifi_connect_callback connect_callback, int enable_network_id, int save_when_connected);
+int wpa_wifi_uninit();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //AML_WPA_WIFI_UTIL_H
\ No newline at end of file