Merge "[rdk-b][mt7986][wifi-hal][Refactor setRadioExtChannel]"
diff --git a/src/wifi/wifi_hal.c b/src/wifi/wifi_hal.c
index 5e8dd2f..dfa962b 100644
--- a/src/wifi/wifi_hal.c
+++ b/src/wifi/wifi_hal.c
@@ -34,7 +34,7 @@
Copyright (c) 2008-2009 Luis R. Rodriguez
Licensed under the ISC license
*/
-
+#define MTK_IMPL
#define HAL_NETLINK_IMPL
#define _GNU_SOURCE /* needed for strcasestr */
@@ -69,11 +69,22 @@
#define IF_NAME_SIZE 50
#define CONFIG_PREFIX "/nvram/hostapd"
#define ACL_PREFIX "/tmp/hostapd-acl"
+#define DENY_PREFIX "/tmp/hostapd-deny"
//#define ACL_PREFIX "/tmp/wifi_acl_list" //RDKB convention
#define SOCK_PREFIX "/var/run/hostapd/wifi"
#define VAP_STATUS_FILE "/tmp/vap-status"
+#define ESSID_FILE "/tmp/essid"
+#define GUARD_INTERVAL_FILE "/tmp/guard-interval"
+#define CHANNEL_STATS_FILE "/tmp/channel_stats"
+#define DFS_ENABLE_FILE "/nvram/dfs_enable.txt"
+#define VLAN_FILE "/nvram/hostapd.vlan"
+#define PSK_FILE "/tmp/hostapd"
+#define CHAIN_MASK_FILE "/tmp/chain_mask"
+#define AMSDU_FILE "/tmp/AMSDU"
+
#define DRIVER_2GHZ "ath9k"
#define DRIVER_5GHZ "ath10k_pci"
+#define BRIDGE_NAME "brlan0"
/*
MAX_APS - Number of all AP available in system
@@ -97,6 +108,7 @@
#define MAX_BUF_SIZE 128
#define MAX_CMD_SIZE 1024
+#define MAX_ASSOCIATED_STA_NUM 2007
//Uncomment to enable debug logs
//#define WIFI_DEBUG
@@ -155,8 +167,18 @@
band_invalid = -1,
band_2_4 = 0,
band_5 = 1,
+ band_6 = 2,
} wifi_band;
+typedef enum {
+ WIFI_MODE_A = 0x01,
+ WIFI_MODE_B = 0x02,
+ WIFI_MODE_G = 0x04,
+ WIFI_MODE_N = 0x08,
+ WIFI_MODE_AC = 0x10,
+ WIFI_MODE_AX = 0x20,
+} wifi_ieee80211_Mode;
+
#ifdef WIFI_HAL_VERSION_3
// Return number of elements in array
@@ -180,6 +202,7 @@
wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key);
wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str);
char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key);
+static int ieee80211_channel_to_frequency(int channel, int *freqMHz);
static wifi_secur_list map_security[] =
{
@@ -373,6 +396,8 @@
static BOOL Radio_flag = TRUE;
//wifi_setApBeaconRate(1, beaconRate);
+BOOL multiple_set = FALSE;
+
struct params
{
char * name;
@@ -416,6 +441,28 @@
return cmd_ret >> 8;
}
+wifi_band wifi_index_to_band(int apIndex)
+{
+ char cmd[128] = {0};
+ char buf[64] = {0};
+ int freq = 0;
+ wifi_band band = band_invalid;
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+ snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep 'freq=' | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
+ _syscmd(cmd, buf, sizeof(buf));
+ freq = strtol(buf, NULL, 10);
+ if (freq > 2401 && freq < 2495)
+ band = band_2_4;
+ else if (freq > 5160 && freq < 5915)
+ band = band_5;
+ else if (freq > 5955 && freq < 7125)
+ band = band_6;
+
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+ return band;
+}
+
static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
{
char cmd[MAX_CMD_SIZE]={'\0'};
@@ -452,6 +499,8 @@
static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
{
+ if (multiple_set == TRUE)
+ return RETURN_OK;
char cmd[MAX_CMD_SIZE]="", output[32]="";
FILE *fp;
int i;
@@ -478,6 +527,8 @@
static int wifi_reloadAp(int apIndex)
{
+ if (multiple_set == TRUE)
+ return RETURN_OK;
char cmd[MAX_CMD_SIZE]="";
char buf[MAX_BUF_SIZE]="";
@@ -612,14 +663,78 @@
return RETURN_OK;
}
+INT wifi_getMaxRadioNumber(INT *max_radio_num)
+{
+ char cmd[64] = {0};
+ char buf[4] = {0};
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+
+ snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
+ _syscmd(cmd, buf, sizeof(buf));
+ *max_radio_num = strtoul(buf, NULL, 10);
+
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+
+ return RETURN_OK;
+}
+
+// Input must be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
{
- return 0;
+ struct params params={'\0'};
+ char config_file[MAX_BUF_SIZE] = {0};
+ char buf[MAX_BUF_SIZE] = {'\0'};
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+ if (strlen (beaconRate) < 5)
+ return RETURN_ERR;
+ // Copy the numeric value
+ strncpy(buf, beaconRate, strlen(beaconRate) - 4);
+ buf[strlen(beaconRate) - 4] = '\0';
+
+ params.name = "beacon_rate";
+ // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
+ if (strncmp(buf, "5.5", 3) == 0) {
+ snprintf(buf, sizeof(buf), "55");
+ params.value = buf;
+ } else {
+ strcat(buf, "0");
+ params.value = buf;
+ }
+
+ sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
+ wifi_hostapdWrite(config_file, ¶ms, 1);
+ wifi_hostapdProcessUpdate(radioIndex, ¶ms, 1);
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+
+ return RETURN_OK;
}
INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
{
- return 0;
+ char config_file[MAX_BUF_SIZE] = {'\0'};
+ char temp_output[MAX_BUF_SIZE] = {'\0'};
+ char buf[MAX_BUF_SIZE] = {'\0'};
+ float rate = 0;
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+ if (NULL == beaconRate)
+ return RETURN_ERR;
+
+ sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
+ wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
+ // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
+ if(strlen(buf) > 0) {
+ rate = atof(buf)/10;
+ snprintf(temp_output, sizeof(temp_output), "%.1fMbps", rate);
+ } else {
+ snprintf(temp_output, sizeof(temp_output), "1Mbps"); // default value
+ }
+ strncpy(beaconRate, temp_output, sizeof(temp_output));
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+
+ return RETURN_OK;
}
INT wifi_setLED(INT radioIndex, BOOL enable)
@@ -724,15 +839,17 @@
*/
INT wifi_factoryResetRadio(int radioIndex) //RDKB
{
+ system("systemctl stop hostapd.service");
+
WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
if(radioIndex == 0)
- system("cp /etc/hostapd-2G.conf /nvram/hostapd0.conf");
+ system("rm /nvram/hostapd0.conf");
else if(radioIndex == 1)
- system("cp /etc/hostapd-5G.conf /nvram/hostapd1.conf");
+ system("rm /nvram/hostapd1.conf");
else
return RETURN_ERR;
- system("systemctl restart hostapd.service");
+ system("systemctl start hostapd.service");
WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
return RETURN_OK;
}
@@ -871,6 +988,10 @@
INT wifi_reset()
{
//TODO: resets the wifi subsystem, deletes all APs
+ system("systemctl stop hostapd.service");
+ sleep(2);
+ system("systemctl start hostapd.service");
+ sleep(5);
return RETURN_OK;
}
@@ -896,6 +1017,8 @@
INT wifi_down()
{
//TODO: turns off transmit power for the entire Wifi subsystem, for all radios
+ system("systemctl stop hostapd.service");
+ sleep(2);
return RETURN_OK;
}
@@ -930,9 +1053,16 @@
// outputs the country code to a max 64 character string
INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
{
- if (NULL == output_string)
+ char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
+ if(!output_string || !(radioIndex==0 || radioIndex==1))
+ return RETURN_ERR;
+
+ sprintf(cmd,"hostapd_cli -i %s%d status driver | grep country | cut -d '=' -f2", AP_PREFIX, radioIndex);
+ _syscmd(cmd, buf, sizeof(buf));
+ if(strlen(buf) > 0)
+ snprintf(output_string, 64, "%s", buf);
+ else
return RETURN_ERR;
- snprintf(output_string, 64, "US");
return RETURN_OK;
}
@@ -940,6 +1070,108 @@
INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
{
//Set wifi config. Wait for wifi reset to apply
+ char str[MAX_BUF_SIZE]={'\0'};
+ char cmd[MAX_CMD_SIZE]={'\0'};
+ struct params params;
+ char config_file[MAX_BUF_SIZE] = {0};
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+ if(NULL == CountryCode || strlen(CountryCode) >= 32 )
+ return RETURN_ERR;
+
+ params.name = "country_code";
+ params.value = CountryCode;
+ sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, radioIndex);
+ int ret = wifi_hostapdWrite(config_file, ¶ms, 1);
+ if (ret) {
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
+ ,__func__, ret);
+ }
+
+ ret = wifi_hostapdProcessUpdate(radioIndex, ¶ms, 1);
+ if (ret) {
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
+ ,__func__, ret);
+ }
+ wifi_reloadAp(radioIndex);
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+
+ return RETURN_OK;
+}
+
+INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
+{
+ char channel_util_file[64] = {0};
+ char cmd[128] = {0};
+ char buf[128] = {0};
+ char line[128] = {0};
+ char *param = NULL, *value = NULL;
+ int read = 0;
+ unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
+ unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
+ size_t len = 0;
+ FILE *f = NULL;
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+
+ snprintf(cmd, sizeof(cmd), "iw %s%d scan | grep signal | awk '{print $2}' | sort -n | tail -n1", AP_PREFIX, radioIndex);
+ _syscmd(cmd, buf, sizeof(buf));
+ outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
+
+ memset(cmd, 0, sizeof(cmd));
+ memset(buf, 0, sizeof(buf));
+ snprintf(cmd, sizeof(cmd), "iw %s%d survey dump | grep 'in use' -A6", AP_PREFIX, radioIndex);
+ if ((f = popen(cmd, "r")) == NULL) {
+ wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
+ return RETURN_ERR;
+ }
+
+ read = getline(&line, &len, f);
+ while (read != -1) {
+ param = strtok(line, ":\t");
+ value = strtok(NULL, " ");
+ if(strstr(param, "frequency") != NULL) {
+ outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
+ }
+ if(strstr(param, "noise") != NULL) {
+ outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
+ outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
+ }
+ if(strstr(param, "channel active time") != NULL) {
+ ActiveTime = strtol(value, NULL, 10);
+ }
+ if(strstr(param, "channel busy time") != NULL) {
+ BusyTime = strtol(value, NULL, 10);
+ }
+ if(strstr(param, "channel transmit time") != NULL) {
+ TransmitTime = strtol(value, NULL, 10);
+ }
+ read = getline(&line, &len, f);
+ }
+ pclose(f);
+
+ // The file should store the last active, busy and transmit time
+ snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
+ f = fopen(channel_util_file, "r");
+ if (f != NULL) {
+ read = getline(&line, &len, f);
+ preActiveTime = strtol(line, NULL, 10);
+ read = getline(&line, &len, f);
+ preBusyTime = strtol(line, NULL, 10);
+ read = getline(&line, &len, f);
+ preTransmitTime = strtol(line, NULL, 10);
+ fclose(f);
+ }
+
+ outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
+ outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
+
+ f = fopen(channel_util_file, "w");
+ if (f != NULL) {
+ fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
+ fclose(f);
+ }
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
return RETURN_OK;
}
@@ -984,13 +1216,18 @@
snprintf(interface_path, sizeof(interface_path), "/sys/class/net/%s%d/address", RADIO_PREFIX, radioIndex);
fp = fopen(interface_path, "r");
- if(fp)
+ if(!fp)
{
- *output_bool = TRUE;
- fclose(fp);
+ return RETURN_ERR;
}
//TODO: check if hostapd with config is running
+ char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0};
+ sprintf(cmd, "hostapd_cli -i %s%d status | grep state | cut -d '=' -f2", AP_PREFIX, radioIndex);
+ _syscmd(cmd, buf, sizeof(buf));
+ if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 || strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0)
+ *output_bool = TRUE;
+ fclose(fp);
return RETURN_OK;
}
@@ -1014,18 +1251,17 @@
snprintf(cmd, sizeof(cmd), "iw %s%d del", AP_PREFIX, apIndex);
_syscmd(cmd, buf, sizeof(buf));
}
- snprintf(cmd, sizeof(cmd), "rmmod %s", radioIndex? DRIVER_5GHZ :DRIVER_2GHZ);
+ snprintf(cmd, sizeof(cmd), "ifconfig %s%d down 2>&1", RADIO_PREFIX, radioIndex);
_syscmd(cmd, buf, sizeof(buf));
if(strlen(buf))
- fprintf(stderr, "Could not remove driver module");
+ fprintf(stderr, "Could not shut down the radio interface: %s%d", RADIO_PREFIX, radioIndex);
}
else
{
- //Inserting driver for Wifi Radio
- snprintf(cmd, sizeof(cmd), "modprobe %s", radioIndex? DRIVER_5GHZ :DRIVER_2GHZ);
+ snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>&1", RADIO_PREFIX, radioIndex);
_syscmd(cmd, buf, sizeof(buf));
if(strlen(buf))
- fprintf(stderr, "FATAL: Could not insert driver module");
+ fprintf(stderr, "Could not up the radio interface: %s%d", RADIO_PREFIX, radioIndex);
sleep(1);
if(radioIndex == 1)//If "wlan0" interface created for 5GHz radio, then need to rename to wlan1
{
@@ -1090,34 +1326,115 @@
//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
{
- char cmd[1024] = {0};
- char buf[1024] = {0};
- char HConf_file[MAX_BUF_SIZE] = {'\0'};
- char interface_name[50] = {0};
+ // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
+ // For max bit rate, we should always choose the best MCS
+ char mode[64] = {0};
+ char channel_bandwidth_str[16] = {0};
+ char *tmp = NULL;
+ UINT mode_map = 0;
+ UINT num_subcarrier = 0;
+ UINT code_bits = 0;
+ float code_rate = 0; // use max code rate
+ int NSS = 0;
+ UINT Symbol_duration = 0;
+ UINT GI_duration = 0;
+ wifi_band band = band_invalid;
+ wifi_guard_interval_t gi = wifi_guard_interval_auto;
+ BOOL enable = FALSE;
+ float bit_rate = 0;
WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
if (NULL == output_string)
return RETURN_ERR;
- sprintf(HConf_file,"%s%d%s","/nvram/hostapd",radioIndex,".conf");
- GetInterfaceName(interface_name,HConf_file);
+ wifi_getRadioEnable(radioIndex, &enable);
+ if (enable == FALSE) {
+ snprintf(output_string, 64, "0 Mb/s");
+ return RETURN_OK;
+ }
- sprintf(cmd, "iwconfig %s | grep 'Bit Rate' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1,2", interface_name);
- _syscmd(cmd, buf, sizeof(buf));
+ if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
+ fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
+ return RETURN_ERR;
+ }
- if(strlen(buf) > 0)
- snprintf(output_string, 64, "%s", buf);
- else
- {
- wifi_getRadioOperatingChannelBandwidth(radioIndex,buf);
- if((strcmp(buf,"20MHz") == 0) && (radioIndex == 0))
- strcpy(output_string,"144 Mb/s");
- else if((strcmp(buf,"20MHz") == 0) && (radioIndex == 1))
- strcpy(output_string,"54 Mb/s");
- else if((strcmp(buf,"40MHz") == 0) && (radioIndex == 1))
- strcpy(output_string,"300 Mb/s");
- //TODO: CHECK VALID VALUE
+ if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
+ fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
+ return RETURN_ERR;
+ }
+
+ if (gi == wifi_guard_interval_3200)
+ GI_duration = 32;
+ else if (gi == wifi_guard_interval_1600)
+ GI_duration = 16;
+ else if (gi == wifi_guard_interval_800)
+ GI_duration = 8;
+ else // auto, 400
+ GI_duration = 4;
+
+ if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
+ fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
+ return RETURN_ERR;
+ }
+
+ if (strstr(channel_bandwidth_str, "80+80") != NULL)
+ strcpy(channel_bandwidth_str, "160");
+
+ if (mode_map & WIFI_MODE_AX) {
+ if (strstr(channel_bandwidth_str, "160") != NULL)
+ num_subcarrier = 1960;
+ else if (strstr(channel_bandwidth_str, "80") != NULL)
+ num_subcarrier = 980;
+ else if (strstr(channel_bandwidth_str, "40") != NULL)
+ num_subcarrier = 468;
+ else if (strstr(channel_bandwidth_str, "20") != NULL)
+ num_subcarrier = 234;
+ code_bits = 10;
+ code_rate = (float)5/6;
+ Symbol_duration = 128;
+ } else if (mode_map & WIFI_MODE_AC) {
+ if (strstr(channel_bandwidth_str, "160") != NULL)
+ num_subcarrier = 468;
+ else if (strstr(channel_bandwidth_str, "80") != NULL)
+ num_subcarrier = 234;
+ else if (strstr(channel_bandwidth_str, "40") != NULL)
+ num_subcarrier = 108;
+ else if (strstr(channel_bandwidth_str, "20") != NULL)
+ num_subcarrier = 52;
+ code_bits = 8;
+ code_rate = (float)5/6;
+ Symbol_duration = 32;
+ } else if (mode_map & WIFI_MODE_N) {
+ if (strstr(channel_bandwidth_str, "160") != NULL)
+ num_subcarrier = 468;
+ else if (strstr(channel_bandwidth_str, "80") != NULL)
+ num_subcarrier = 234;
+ else if (strstr(channel_bandwidth_str, "40") != NULL)
+ num_subcarrier = 108;
+ else if (strstr(channel_bandwidth_str, "20") != NULL)
+ num_subcarrier = 52;
+ code_bits = 6;
+ code_rate = (float)3/4;
+ Symbol_duration = 32;
+ } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
+ // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
+ snprintf(output_string, 64, "65 Mb/s");
+ return RETURN_OK;
+ } else {
+ snprintf(output_string, 64, "0 Mb/s");
+ return RETURN_OK;
+ }
+
+ // Spatial streams
+ if (wifi_getRadioTxChainMask(radioIndex, &NSS) != RETURN_OK) {
+ fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
+ return RETURN_ERR;
}
+
+ // multiple 10 is to align duration unit (0.1 us)
+ bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
+ snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
+
WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
return RETURN_OK;
@@ -1149,10 +1466,23 @@
//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
{
+ wifi_band band = band_invalid;
+
WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
if (NULL == output_string)
return RETURN_ERR;
- snprintf(output_string, 64, (radioIndex == 0)?"2.4GHz":"5GHz");
+
+ band = wifi_index_to_band(radioIndex);
+
+ memset(output_string, 0, 10);
+ if (band == band_2_4)
+ strcpy(output_string, "2.4GHz");
+ else if (band == band_5)
+ strcpy(output_string, "5GHz");
+ else if (band == band_6)
+ strcpy(output_string, "6GHz");
+ else
+ return RETURN_ERR;
WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
return RETURN_OK;
@@ -1328,10 +1658,50 @@
//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
{
+ char cmd[128]={0};
+ char buf[128]={0};
+ char temp_output[128] = {0};
+ wifi_band band;
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
if (NULL == output_string)
return RETURN_ERR;
- snprintf(output_string, 64, (radioIndex==0)?"b,g,n":"a,n,ac");
+
+ band = wifi_index_to_band(radioIndex);
+ if (band == band_2_4) {
+ strcat(temp_output, "b,g,");
+ } else if (band == band_5) {
+ strcat(temp_output, "a,");
+ }
+
+ // ht capabilities
+ snprintf(cmd, sizeof(cmd), "iw phy%d info | grep '[^PHY|MAC|VHT].Capabilities' | head -n 1 | cut -d ':' -f2 | sed 's/^.//' | tr -d '\\n'", radioIndex);
+ _syscmd(cmd, buf, sizeof(buf));
+ if (strncmp(buf, "0x00", 4) != 0) {
+ strcat(temp_output, "n,");
+ }
+
+ // vht capabilities
+ if (band == band_5) {
+ snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'VHT Capabilities' | cut -d '(' -f2 | cut -c1-10 | tr -d '\\n'", radioIndex);
+ _syscmd(cmd, buf, sizeof(buf));
+ if (strncmp(buf, "0x00000000", 10) != 0) {
+ strcat(temp_output, "ac,");
+ }
+ }
+
+ // he capabilities
+ snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'HE MAC Capabilities' | head -n 2 | tail -n 1 | cut -d '(' -f2 | cut -c1-6 | tr -d '\\n'", radioIndex);
+ _syscmd(cmd, buf, sizeof(buf));
+ if (strncmp (buf, "0x0000", 6) != 0) {
+ strcat(temp_output, "ax,");
+ }
+ // Remove the last comma
+ if (strlen(temp_output) != 0)
+ temp_output[strlen(temp_output)-1] = '\0';
+ strncpy(output_string, temp_output, strlen(temp_output));
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
return RETURN_OK;
}
@@ -1423,7 +1793,63 @@
#endif
}
+INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
+{
+ char cmd[128] = {0};
+ char buf[64] = {0};
+ char config_file[64] = {0};
+ wifi_band band;
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+ if(NULL == output_string || NULL == pureMode)
+ return RETURN_ERR;
+
+ // grep all of the ieee80211 protocol config set to 1
+ snprintf(config_file, sizeof(cmd), "%s%d.conf", CONFIG_PREFIX, radioIndex);
+ snprintf(cmd, sizeof(cmd), "cat %s | grep -E \"ieee.*=1\" | cut -d '=' -f1 | tr -d 'ieee80211'", config_file);
+ _syscmd(cmd, buf, sizeof(buf));
+
+ band = wifi_index_to_band(radioIndex);
+ // puremode is a bit map
+ *pureMode = 0;
+ if (band == band_2_4) {
+ strcat(output_string, "b,g");
+ *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
+ if (strstr(buf, "n") != NULL) {
+ strcat(output_string, ",n");
+ *pureMode |= WIFI_MODE_N;
+ }
+ if (strstr(buf, "ax") != NULL) {
+ strcat(output_string, ",ax");
+ *pureMode |= WIFI_MODE_AX;
+ }
+ } else if (band == band_5) {
+ strcat(output_string, "a");
+ *pureMode |= WIFI_MODE_A;
+ if (strstr(buf, "n") != NULL) {
+ strcat(output_string, ",n");
+ *pureMode |= WIFI_MODE_N;
+ }
+ if (strstr(buf, "ac") != NULL) {
+ strcat(output_string, ",ac");
+ *pureMode |= WIFI_MODE_AC;
+ }
+ if (strstr(buf, "ax") != NULL) {
+ strcat(output_string, ",ax");
+ *pureMode |= WIFI_MODE_AX;
+ }
+ } else if (band == band_6) {
+ if (strstr(buf, "ax") != NULL) {
+ strcat(output_string, "ax");
+ *pureMode |= WIFI_MODE_AX;
+ }
+ }
+
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+ return RETURN_OK;
+}
+
-//Set the radio operating mode, and pure mode flag.
+// Set the radio operating mode, and pure mode flag.
INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
{
WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
@@ -1518,14 +1944,81 @@
return RETURN_OK;
}
+// Set the radio operating mode, and pure mode flag.
+INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
+{
+ int num_hostapd_support_mode = 3; // n, ac, ax
+ struct params list[num_hostapd_support_mode];
+ char config_file[64] = {0};
+ char bandwidth[16] = {0};
+ int mode_check_bit = 1 << 3; // n mode
+ wifi_ieee80211_Mode mode = (wifi_ieee80211_Mode)pureMode;
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
+ // Set radio mode
+ list[0].name = "ieee80211n";
+ list[1].name = "ieee80211ac";
+ list[2].name = "ieee80211ax";
+ snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
+
+ // check the bit map from n to ax, and set hostapd config
+ if (mode & WIFI_MODE_N)
+ list[0].value = "1";
+ else
+ list[0].value = "0";
+ if (mode & WIFI_MODE_AC)
+ list[1].value = "1";
+ else
+ list[1].value = "0";
+ if (mode & WIFI_MODE_AX)
+ list[2].value = "1";
+ else
+ list[2].value = "0";
+ wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
+
+ if (channelMode == NULL || strlen(channelMode) == 0)
+ return RETURN_OK;
+ // Set bandwidth
+ if (strstr(channelMode, "40") != NULL)
+ strcpy(bandwidth, "40MHz");
+ else if (strstr(channelMode, "80") != NULL)
+ strcpy(bandwidth, "80MHz");
+ else if (strstr(channelMode, "160") != NULL)
+ strcpy(bandwidth, "160MHz");
+ else // 11A, 11B, 11G....
+ strcpy(bandwidth, "20MHz");
+
+ writeBandWidth(radioIndex, bandwidth);
+ wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
+
+ wifi_reloadAp(radioIndex);
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+
+ return RETURN_OK;
+}
+
//Get the list of supported channel. eg: "1-11"
//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
{
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
if (NULL == output_string)
return RETURN_ERR;
- //TODO:read this from iw phy phyX info |grep MHz
- snprintf(output_string, 64, (radioIndex == 0)?"1,2,3,4,5,6,7,8,9,10,11":"36,40,44,48,52,56,60,64,100,104,108,112,116,120,124,128,132,136,140");
+ char cmd[256] = {0};
+ char buf[128] = {0};
+ BOOL dfs_enable = false;
+ // Parse possible channel number and separate them with commas.
+ wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
+ if (dfs_enable)
+ snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'", radioIndex);
+ else
+ snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | grep -v 'radar' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'", radioIndex);
+
+ _syscmd(cmd,buf,sizeof(buf));
+ strncpy(output_string, buf, sizeof(buf));
+
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+ return RETURN_OK;
#if 0
char IFName[50] ={0};
char buf[MAX_BUF_SIZE] = {0};
@@ -1591,6 +2084,12 @@
//Get the running channel number
INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
{
+#ifdef MTK_IMPL
+ if(!wifi_getApChannel(radioIndex, output_ulong))
+ return RETURN_OK;
+ else
+ return RETURN_ERR;
+#else
char cmd[1024] = {0}, buf[5] = {0};
WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
@@ -1611,6 +2110,7 @@
WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
return RETURN_OK;
+#endif
}
@@ -1808,12 +2308,53 @@
//To-do
INT wifi_setBandSteeringApGroup(char *ApGroup)
{
+ return RETURN_OK;
+}
+
+INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
+{
+ char config_file[128] = {'\0'};
+ char buf[128] = {'\0'};
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+ if (dtimInterval == NULL)
+ return RETURN_ERR;
+
+ snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
+ wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
+
+ if (strlen(buf) == 0) {
+ *dtimInterval = 2;
+ } else {
+ *dtimInterval = strtoul(buf, NULL, 10);
+ }
+
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
return RETURN_OK;
}
INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
{
- return RETURN_OK;
+ struct params params={0};
+ char config_file[MAX_BUF_SIZE] = {'\0'};
+ char buf[MAX_BUF_SIZE] = {'\0'};
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+ if (dtimInterval < 1 || dtimInterval > 255) {
+ return RETURN_ERR;
+ WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
+ }
+
+ params.name = "dtim_period";
+ snprintf(buf, sizeof(buf), "%d", dtimInterval);
+ params.value = buf;
+
+ sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
+ wifi_hostapdWrite(config_file, ¶ms, 1);
+ wifi_hostapdProcessUpdate(apIndex, ¶ms, 1);
+
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+ return RETURN_OK;
}
//Check if the driver support the Dfs
@@ -1821,7 +2362,7 @@
{
if (NULL == output_bool)
return RETURN_ERR;
- *output_bool=FALSE;
+ *output_bool=TRUE;
return RETURN_OK;
}
@@ -1863,17 +2404,64 @@
//Get the Dfs enable status
INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
{
+ char buf[16] = {0};
+ FILE *f = NULL;
+ wifi_band band;
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+
+ *output_bool = TRUE; // default
if (NULL == output_bool)
return RETURN_ERR;
- *output_bool = FALSE;
+ band = wifi_index_to_band(radioIndex);
+ if (band != band_5)
+ return RETURN_OK;
+
+ f = fopen(DFS_ENABLE_FILE, "r");
+ if (f != NULL) {
+ fgets(buf, 2, f);
+ if (strncmp(buf, "0", 0) == 0)
+ *output_bool = FALSE;
+ fclose(f);
+ }
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
return RETURN_OK;
}
//Set the Dfs enable status
INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
{
- return RETURN_ERR;
+ char buf[128] = {0};
+ char config_file[128] = {0};
+ FILE *f = NULL;
+ struct params params={0};
+ wifi_band band;
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+
+ band = wifi_index_to_band(radioIndex);
+ if (band != band_5)
+ return RETURN_OK;
+
+ f = fopen(DFS_ENABLE_FILE, "w");
+ if (f == NULL)
+ return RETURN_ERR;
+ fprintf(f, "%d", enable);
+ fclose(f);
+
+ params.name = "acs_exclude_dfs";
+ sprintf(buf, "%d", enable?"1":"0");
+ params.value = buf;
+ sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
+ wifi_hostapdWrite(config_file, ¶ms, 1);
+ wifi_hostapdProcessUpdate(radioIndex, ¶ms, 1);
+
+ wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
+
+ wifi_reloadAp(radioIndex);
+
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
}
//Check if the driver support the AutoChannelRefreshPeriod
@@ -1906,18 +2494,23 @@
//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
{
+ char cmd[128] = {0}, buf[64] = {0};
+ char interface_name[64] = {0};
+ int ret = 0, len=0;
+ BOOL radio_enable = FALSE;
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+
if (NULL == output_string)
return RETURN_ERR;
- WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
- char cmd[1024] = {0}, buf[64] = {0};
- int ret = 0, len=0;
+ if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
+ return RETURN_ERR;
- snprintf(cmd, sizeof(cmd),
- "ls -1 /sys/class/net/%s%d/device/ieee80211/phy*/device/net/ | "
- "xargs -I {} iw dev {} info | grep width | head -n1 | "
- "cut -d ' ' -f6", RADIO_PREFIX, radioIndex);
+ if (radio_enable != TRUE)
+ return RETURN_OK;
+ snprintf(cmd, sizeof(cmd),"iw dev %s%d info | grep 'width' | cut -d ' ' -f6", AP_PREFIX, radioIndex);
ret = _syscmd(cmd, buf, sizeof(buf));
len = strlen(buf);
if((ret != 0) || (len == 0))
@@ -2116,19 +2709,54 @@
//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
{
- //save config and apply instantly
- if (NULL == output_string)
+ wifi_guard_interval_t GI;
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+
+ if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
return RETURN_ERR;
- snprintf(output_string, 64, (radioIndex == 0) ? "400nsec" : "400nsec");
+ if (GI == wifi_guard_interval_400)
+ strcpy(output_string, "400nsec");
+ else if (GI == wifi_guard_interval_800)
+ strcpy(output_string, "800nsec");
+ else if (GI == wifi_guard_interval_1600)
+ strcpy(output_string, "1600nsec");
+ else if (GI == wifi_guard_interval_3200)
+ strcpy(output_string, "3200nsec");
+ else
+ strcpy(output_string, "auto");
+
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
return RETURN_OK;
}
//Set the guard interval value.
INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
{
- //Apply setting instantly
- return RETURN_ERR;
+ wifi_guard_interval_t GI;
+ int ret = 0;
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+
+ if (strcmp(string, "400nsec") == 0)
+ GI = wifi_guard_interval_400;
+ else if (strcmp(string , "800nsec") == 0 || strcmp(string, "auto") == 0)
+ GI = wifi_guard_interval_800;
+ else if (strcmp(string , "1600nsec") == 0)
+ GI = wifi_guard_interval_1600;
+ else if (strcmp(string , "3200nsec") == 0)
+ GI = wifi_guard_interval_3200;
+
+ ret = wifi_setGuardInterval(radioIndex, GI);
+
+ if (ret == RETURN_ERR) {
+ wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
+ return RETURN_ERR;
+ }
+
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+ return RETURN_OK;
}
//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
@@ -2157,25 +2785,23 @@
return RETURN_OK;
}
-//Get current Transmit Power, eg "75", "100"
+//Get current Transmit Power in dBm units.
//The transmite power level is in units of full power for this radio.
INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
{
char cmd[128]={0};
- char buf[256]={0};
- INT apIndex;
- //save config and apply instantly
+ char buf[16]={0};
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
- if (NULL == output_ulong)
+ if(output_ulong == NULL)
return RETURN_ERR;
- //zqiu:TODO:save config
- apIndex = (radioIndex==0) ?0 :1;
-
- snprintf(cmd, sizeof(cmd), "iwlist %s%d txpower | grep Tx-Power | cut -d'=' -f2", AP_PREFIX, apIndex);
+ snprintf(cmd, sizeof(cmd), "iw %s%d info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", AP_PREFIX, radioIndex);
_syscmd(cmd, buf, sizeof(buf));
- *output_ulong = atol(buf);
+ *output_ulong = strtol(buf, NULL, 10);
+
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
return RETURN_OK;
}
@@ -2183,12 +2809,38 @@
//The transmite power level is in units of full power for this radio.
INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
{
+ char *support;
char cmd[128]={0};
- char buf[256]={0};
- INT apIndex;
+ char buf[128]={0};
+ char txpower_str[64] = {0};
+ int txpower = 0;
+ int maximum_tx = 0;
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+
+ snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, radioIndex);
+ _syscmd(cmd, buf, sizeof(buf));
+ maximum_tx = strtol(buf, NULL, 10);
- snprintf(cmd, sizeof(cmd), "iwconfig %s%d txpower %lu", AP_PREFIX, radioIndex, TransmitPower);
+ // Get the Tx power supported list and check that is the input in the list
+ snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
+ wifi_getRadioTransmitPowerSupported(radioIndex, buf);
+ support = strtok(buf, ",");
+ while(true)
+ {
+ if(support == NULL) { // input not in the list
+ wifi_dbg_printf("Input value is invalid.\n");
+ return RETURN_ERR;
+ }
+ if (strncmp(txpower_str, support, strlen(support)) == 0) {
+ break;
+ }
+ support = strtok(NULL, ",");
+ }
+ txpower = TransmitPower*maximum_tx/100;
+ snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", radioIndex, txpower);
_syscmd(cmd, buf, sizeof(buf));
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
return RETURN_OK;
}
@@ -2198,7 +2850,7 @@
{
if (NULL == Supported)
return RETURN_ERR;
- *Supported = FALSE;
+ *Supported = TRUE;
return RETURN_OK;
}
@@ -2206,17 +2858,46 @@
//Get 80211h feature enable
INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
{
- if (NULL == enable)
+ char buf[64]={'\0'};
+ char config_file[64] = {'\0'};
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+ if(enable == NULL)
return RETURN_ERR;
- *enable = FALSE;
+
+ sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
+ wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
+
+ if (strncmp(buf, "1", 1) == 0)
+ *enable = TRUE;
+ else
+ *enable = FALSE;
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
return RETURN_OK;
}
//Set 80211h feature enable
INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
{
- return RETURN_ERR;
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+ struct params params={'\0'};
+ char config_file[MAX_BUF_SIZE] = {0};
+
+ params.name = "ieee80211h";
+
+ if (enable) {
+ params.value = "1";
+ } else {
+ params.value = "0";
+ }
+
+ sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
+ wifi_hostapdWrite(config_file, ¶ms, 1);
+
+ wifi_hostapdProcessUpdate(radioIndex, ¶ms, 1);
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+ return RETURN_OK;
}
//Indicates the Carrier Sense ranges supported by the radio. It is measured in dBm. Refer section A.2.3.2 of CableLabs Wi-Fi MGMT Specification.
@@ -2248,57 +2929,77 @@
//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
{
- if (NULL == output)
+ char cmd[MAX_BUF_SIZE]={'\0'};
+ char buf[MAX_CMD_SIZE]={'\0'};
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+ if(output == NULL)
return RETURN_ERR;
- *output = 100;
+
+ snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, radioIndex);
+ _syscmd(cmd, buf, sizeof(buf));
+ *output = atoi(buf);
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
return RETURN_OK;
}
INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
{
- return RETURN_ERR;
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+ struct params params={'\0'};
+ char buf[MAX_BUF_SIZE] = {'\0'};
+ char config_file[MAX_BUF_SIZE] = {'\0'};
+
+ params.name = "beacon_int";
+ snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
+ params.value = buf;
+
+ sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
+ wifi_hostapdWrite(config_file, ¶ms, 1);
+
+ wifi_hostapdProcessUpdate(radioIndex, ¶ms, 1);
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+ return RETURN_OK;
}
//Comma-separated list of strings. The set of data rates, in Mbps, that have to be supported by all stations that desire to join this BSS. The stations have to be able to receive and transmit at each of the data rates listed inBasicDataTransmitRates. For example, a value of "1,2", indicates that stations support 1 Mbps and 2 Mbps. Most control packets use a data rate in BasicDataTransmitRates.
INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
{
- if (NULL == output)
- return RETURN_ERR;
- snprintf(output, 64, (radioIndex == 0) ? "1,2" : "1.5,150");
-#if 0
//TODO: need to revisit below implementation
char *temp;
- char temp_output[128];
- char temp_TransmitRates[512];
- char config_file[MAX_BUF_SIZE] = {0};
+ char temp_output[128] = {0};
+ char temp_TransmitRates[64] = {0};
+ char config_file[64] = {0};
WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
if (NULL == output)
return RETURN_ERR;
sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
- wifi_hostapdRead(config_file,"basic_rates",output,64);
-
- strcpy(temp_TransmitRates,output);
- strcpy(temp_output,"");
- temp = strtok(temp_TransmitRates," ");
- while(temp!=NULL)
- {
- temp[strlen(temp)-1]=0;
- if((temp[0]=='5') && (temp[1]=='\0'))
- {
- temp="5.5";
- }
- strcat(temp_output,temp);
- temp = strtok(NULL," ");
- if(temp!=NULL)
+ wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
+
+ if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
+ wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
+ } else {
+ temp = strtok(temp_TransmitRates," ");
+ while(temp!=NULL)
{
- strcat(temp_output,",");
+ // Convert 100 kbps to Mbps
+ temp[strlen(temp)-1]=0;
+ if((temp[0]=='5') && (temp[1]=='\0'))
+ {
+ temp="5.5";
+ }
+ strcat(temp_output,temp);
+ temp = strtok(NULL," ");
+ if(temp!=NULL)
+ {
+ strcat(temp_output,",");
+ }
}
+ strcpy(output,temp_output);
}
- strcpy(output,temp_output);
WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
-#endif
return RETURN_OK;
}
@@ -2850,47 +3551,243 @@
return ret;
}
+struct channels_noise {
+ int channel;
+ int noise;
+};
+
+// Return noise array for each channel
+int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
+{
+ FILE *f = NULL;
+ char cmd[128] = {0};
+ char *line = NULL;
+ size_t len = 0;
+ ssize_t read = 0;
+ int tmp = 0, arr_index = -1;
+
+ sprintf(cmd, "iw dev %s%d survey dump | grep 'frequency\\|noise' | awk '{print $2}'", AP_PREFIX, radioIndex);
+
+ if ((f = popen(cmd, "r")) == NULL) {
+ wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
+ return RETURN_ERR;
+ }
+ line = malloc(sizeof(char) * 256);
+ while((read = getline(&line, &len, f)) != -1) {
+ sscanf(line, "%d", &tmp);
+ if (tmp > 0) { // channel frequency, the first line must be frequency
+ arr_index++;
+ channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
+ } else { // noise
+ channels_noise_arr[arr_index].noise = tmp;
+ }
+ }
+ free(line);
+ pclose(f);
+ return RETURN_OK;
+}
+
//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
{
- INT status = RETURN_ERR;
- UINT index;
- wifi_neighbor_ap2_t *pt=NULL;
- char cmd[128]={0};
- char buf[8192]={0};
+ int index = -1;
+ wifi_neighbor_ap2_t *scan_array = NULL;
+ char cmd[256]={0};
+ char buf[128]={0};
+ char file_name[32] = {0};
+ char filter_SSID[32] = {0};
+ char line[256] = {0};
+ char *ret = NULL;
+ int freq=0;
+ FILE *f = NULL;
+ size_t len=0;
+ int channels_num = 0;
+ int vht_channel_width = 0;
+ bool get_nosie_ret = false;
+ bool filter_enable = false;
+ bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
- WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
- sprintf(cmd, "iwlist %s%d scan",AP_PREFIX,(radioIndex==0)?0:1); //suppose ap0 mapping to radio0
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
+
+ snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
+ f = fopen(file_name, "r");
+ if (f != NULL) {
+ fgets(filter_SSID, sizeof(file_name), f);
+ if (strlen(filter_SSID) != 0)
+ filter_enable = true;
+ fclose(f);
+ }
+
+ snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", radioIndex);
_syscmd(cmd, buf, sizeof(buf));
+ channels_num = strtol(buf, NULL, 10);
+ struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
+ get_nosie_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
- *output_array_size=2;
- //zqiu: HAL alloc the array and return to caller. Caller response to free it.
- *neighbor_ap_array=(wifi_neighbor_ap2_t *)calloc(sizeof(wifi_neighbor_ap2_t), *output_array_size);
- for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
- strcpy(pt->ap_SSID,"");
- strcpy(pt->ap_BSSID,"");
- strcpy(pt->ap_Mode,"");
- pt->ap_Channel=1;
- pt->ap_SignalStrength=0;
- strcpy(pt->ap_SecurityModeEnabled,"");
- strcpy(pt->ap_EncryptionMode,"");
- strcpy(pt->ap_OperatingFrequencyBand,"");
- strcpy(pt->ap_SupportedStandards,"");
- strcpy(pt->ap_OperatingStandards,"");
- strcpy(pt->ap_OperatingChannelBandwidth,"");
- pt->ap_BeaconPeriod=1;
- pt->ap_Noise=0;
- strcpy(pt->ap_BasicDataTransferRates,"");
- strcpy(pt->ap_SupportedDataTransferRates,"");
- pt->ap_DTIMPeriod=1;
- pt->ap_ChannelUtilization=0;
+ sprintf(cmd, "iw dev %s%d scan | grep '%s%d\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
+ // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", AP_PREFIX, radioIndex, AP_PREFIX, radioIndex);
+ fprintf(stderr, "cmd: %s\n", cmd);
+ if ((f = popen(cmd, "r")) == NULL) {
+ wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
+ return RETURN_ERR;
}
+ ret = fgets(line, sizeof(line), f);
+ while (ret != NULL) {
+ if(strstr(line, "BSS") != NULL) { // new neighbor info
+ // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
+ // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
+ // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
- status = RETURN_OK;
+ if (!filter_BSS) {
+ index++;
+ wifi_neighbor_ap2_t *tmp;
+ tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
+ if (tmp == NULL) { // no more memory to use
+ index--;
+ wifi_dbg_printf("%s: realloc failed\n", __func__);
+ break;
+ }
+ scan_array = tmp;
+ }
+ memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
+
+ filter_BSS = false;
+ sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
+ strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
+ strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
+ strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
+ } else if (strstr(line, "freq") != NULL) {
+ sscanf(line," freq: %d", &freq);
+ scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
+
+ if (freq >= 2412 && freq <= 2484) {
+ strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
+ strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
+ strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
+ }
+ else if (freq >= 5160 && freq <= 5805) {
+ strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
+ strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
+ strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
+ }
+
+ scan_array[index].ap_Noise = 0;
+ if (get_nosie_ret) {
+ for (int i = 0; i < channels_num; i++) {
+ if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
+ scan_array[index].ap_Noise = channels_noise_arr[i].noise;
+ break;
+ }
+ }
+ }
+ } else if (strstr(line, "beacon interval") != NULL) {
+ sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
+ } else if (strstr(line, "signal") != NULL) {
+ sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
+ } else if (strstr(line,"SSID") != NULL) {
+ sscanf(line," SSID: %s", scan_array[index].ap_SSID);
+ if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
+ filter_BSS = true;
+ }
+ } else if (strstr(line, "Supported rates") != NULL) {
+ char SRate[80] = {0}, *tmp = NULL;
+ memset(buf, 0, sizeof(buf));
+ strcpy(SRate, line);
+ tmp = strtok(SRate, ":");
+ tmp = strtok(NULL, ":");
+ strcpy(buf, tmp);
+ memset(SRate, 0, sizeof(SRate));
+
+ tmp = strtok(buf, " \n");
+ while (tmp != NULL) {
+ strcat(SRate, tmp);
+ if (SRate[strlen(SRate) - 1] == '*') {
+ SRate[strlen(SRate) - 1] = '\0';
+ }
+ strcat(SRate, ",");
+
+ tmp = strtok(NULL, " \n");
+ }
+ SRate[strlen(SRate) - 1] = '\0';
+ strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
+ } else if (strstr(line, "DTIM") != NULL) {
+ sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
+ } else if (strstr(line, "VHT capabilities") != NULL) {
+ strcat(scan_array[index].ap_SupportedStandards, ",ac");
+ strcpy(scan_array[index].ap_OperatingStandards, "ac");
+ } else if (strstr(line, "HT capabilities") != NULL) {
+ strcat(scan_array[index].ap_SupportedStandards, ",n");
+ strcpy(scan_array[index].ap_OperatingStandards, "n");
+ } else if (strstr(line, "VHT operation") != NULL) {
+ ret = fgets(line, sizeof(line), f);
+ sscanf(line," * channel width: %d", &vht_channel_width);
+ if(vht_channel_width == 1) {
+ snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
+ } else {
+ snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
+ }
+ if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
+ continue;
+ } else if (strstr(line, "HT operation") != NULL) {
+ ret = fgets(line, sizeof(line), f);
+ sscanf(line," * secondary channel offset: %s", &buf);
+ if (!strcmp(buf, "above")) {
+ //40Mhz +
+ snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
+ }
+ else if (!strcmp(buf, "below")) {
+ //40Mhz -
+ snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
+ } else {
+ //20Mhz
+ snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
+ }
+ if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
+ continue;
+ } else if (strstr(line, "HE capabilities") != NULL) {
+ strcat(scan_array[index].ap_SupportedStandards, ",ax");
+ strcpy(scan_array[index].ap_OperatingStandards, "ax");
+ ret = fgets(line, sizeof(line), f);
+ if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
+ if (strstr(line, "HE40/2.4GHz") != NULL)
+ strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
+ else
+ strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
+ } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
+ if (strstr(line, "HE80/5GHz") != NULL) {
+ strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
+ ret = fgets(line, sizeof(line), f);
+ } else
+ continue;
+ if (strstr(line, "HE160/5GHz") != NULL)
+ strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
+ }
+ continue;
+ } else if (strstr(line, "WPA") != NULL) {
+ strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
+ } else if (strstr(line, "RSN") != NULL) {
+ strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
+ } else if (strstr(line, "Group cipher") != NULL) {
+ sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
+ if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
+ strcpy(scan_array[index].ap_EncryptionMode, "AES");
+ }
+ }
+ ret = fgets(line, sizeof(line), f);
+ }
+
+ if (!filter_BSS) {
+ *output_array_size = index + 1;
+ } else {
+ memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
+ *output_array_size = index;
+ }
+ *neighbor_ap_array = scan_array;
+ pclose(f);
WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
- return status;
+ return RETURN_OK;
}
//>> Deprecated: used for old RDKB code.
@@ -3429,74 +4326,237 @@
// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
{
- //save config and Apply instantly
- return RETURN_ERR;
-}
+ char config_file[64] = {'\0'};
+ char buf[64] = {'\0'};
+ struct params list;
-//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
-INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
-{
- char cmd[64];
- char buf[512];
- //save config and apply instantly
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+ list.name = "ht_coex";
+ snprintf(buf, sizeof(buf), "%d", enable);
+ list.value = buf;
- //zqiu:TODO: save config
- if (threshold > 0) {
- snprintf(cmd, sizeof(cmd), "iwconfig %s%d frag %d", AP_PREFIX, apIndex, threshold);
- } else {
- snprintf(cmd, sizeof(cmd), "iwconfig %s%d frag off", AP_PREFIX, apIndex );
- }
- _syscmd(cmd,buf, sizeof(buf));
+ snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
+ wifi_hostapdWrite(config_file, &list, 1);
+ wifi_hostapdProcessUpdate(apIndex, &list, 1);
+
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
return RETURN_OK;
}
-// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
-INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
+//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
+INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
{
- //Save config and Apply instantly
- return RETURN_ERR;
-}
+ char config_file[MAX_BUF_SIZE] = {'\0'};
+ char buf[MAX_BUF_SIZE] = {'\0'};
+ struct params list;
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+ if (threshold < 256 || threshold > 2346 )
+ return RETURN_ERR;
+ list.name = "fragm_threshold";
+ snprintf(buf, sizeof(buf), "%d", threshold);
+ list.value = buf;
+
+ snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
+ wifi_hostapdWrite(config_file, &list, 1);
+ wifi_hostapdProcessUpdate(apIndex, &list, 1);
+
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+
+ return RETURN_OK;
+}
+
+// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
+INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
+{
+ char config_file[64] = {'\0'};
+ char cmd[128] = {'\0'};
+ char buf[64] = {'\0'};
+ char stbc_config[16] = {'\0'};
+ wifi_band band;
+ int iterator = 0;
+ BOOL current_stbc = FALSE;
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+
+ band = wifi_index_to_band(radioIndex);
+ if (band == band_invalid)
+ return RETURN_ERR;
+
+ if (band == band_2_4)
+ iterator = 1;
+ else if (band == band_5)
+ iterator = 2;
+ else
+ return RETURN_OK;
+
+ snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
+
+ // set ht and vht config
+ for (int i = 0; i < iterator; i++) {
+ memset(stbc_config, 0, sizeof(stbc_config));
+ memset(cmd, 0, sizeof(cmd));
+ memset(buf, 0, sizeof(buf));
+ snprintf(stbc_config, sizeof(stbc_config), "%sht_capab", (i == 0)?"":"v");
+ snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
+ _syscmd(cmd, buf, sizeof(buf));
+ if (strlen(buf) != 0)
+ current_stbc = TRUE;
+ if (current_stbc == STBC_Enable)
+ continue;
+
+ if (STBC_Enable == TRUE) {
+ // Append the STBC flags in capab config
+ memset(cmd, 0, sizeof(cmd));
+ if (i == 0)
+ snprintf(cmd, sizeof(cmd), "sed -E -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
+ else
+ snprintf(cmd, sizeof(cmd), "sed -E -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1][RX-STBC-1]/' %s", config_file);
+ _syscmd(cmd, buf, sizeof(buf));
+ } else if (STBC_Enable == FALSE) {
+ // Remove the STBC flags and remain other flags in capab
+ memset(cmd, 0, sizeof(cmd));
+ snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
+ _syscmd(cmd, buf, sizeof(buf));
+ memset(cmd, 0, sizeof(cmd));
+ snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
+ _syscmd(cmd, buf, sizeof(buf));
+ }
+ }
+
+ wifi_reloadAp(radioIndex);
+
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+ return RETURN_OK;
+}
// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
{
- return RETURN_ERR;
+ char AMSDU_file_path[64] = {0};
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+
+ if(output_bool == NULL)
+ return RETURN_ERR;
+
+ sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
+
+ if (access(AMSDU_file_path, F_OK) == 0)
+ *output_bool = TRUE;
+ else
+ *output_bool = FALSE;
+
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+ return RETURN_OK;
}
// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
{
- //Apply instantly
- return RETURN_ERR;
+ char cmd[64]={0};
+ char buf[64]={0};
+ char AMSDU_file_path[64] = {0};
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+
+ sprintf(cmd, "mt76-vendor %s%d set ap_wireless amsdu=%d", AP_PREFIX, radioIndex, amsduEnable);
+ _syscmd(cmd, buf, sizeof(buf));
+
+ sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
+ memset(cmd, 0, sizeof(cmd));
+ if (amsduEnable == TRUE)
+ sprintf(cmd, "touch %s", AMSDU_file_path);
+ else
+ sprintf(cmd, "rm %s 2> /dev/null", AMSDU_file_path);
+ _syscmd(cmd, buf, sizeof(buf));
+
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+ return RETURN_OK;
}
//P2 // outputs the number of Tx streams
INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
{
- return RETURN_ERR;
+ char buf[8] = {0};
+ char cmd[128] = {0};
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+
+ sprintf(cmd, "cat %s%d.txt 2> /dev/null", CHAIN_MASK_FILE, radioIndex);
+ _syscmd(cmd, buf, sizeof(buf));
+
+ // if there is no record, output the max number of spatial streams
+ if (strlen(buf) == 0) {
+ sprintf(cmd, "iw phy%d info | grep 'TX MCS and NSS set' -A8 | head -n8 | grep 'streams: MCS' | wc -l", radioIndex);
+ _syscmd(cmd, buf, sizeof(buf));
+ }
+
+ *output_int = (INT)strtol(buf, NULL, 10);
+
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+
+ return RETURN_OK;
}
//P2 // sets the number of Tx streams to an enviornment variable
INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
{
- //save to wifi config, wait for wifi reset or wifi_pushTxChainMask to apply
- return RETURN_ERR;
+ char cmd[128] = {0};
+ char buf[128] = {0};
+ char chain_mask_file[128] = {0};
+ FILE *f = NULL;
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+
+ if (numStreams == 0) {
+ fprintf(stderr, "The mask did not support 0 (auto).\n", numStreams);
+ return RETURN_ERR;
+ }
+ wifi_setRadioEnable(radioIndex, FALSE);
+ sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", radioIndex, numStreams);
+ _syscmd(cmd, buf, sizeof(buf));
+
+ if (strlen(buf) > 0) {
+ fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
+ return RETURN_ERR;
+ }
+ wifi_setRadioEnable(radioIndex, TRUE);
+
+ sprintf(chain_mask_file, "%s%d.txt", CHAIN_MASK_FILE, radioIndex);
+ f = fopen(chain_mask_file, "w");
+ if (f == NULL) {
+ fprintf(stderr, "%s: fopen failed.\n", __func__);
+ return RETURN_ERR;
+ }
+ fprintf(f, "%d", numStreams);
+ fclose(f);
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+ return RETURN_OK;
}
//P2 // outputs the number of Rx streams
INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
{
- if (NULL == output_int)
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+ if (wifi_getRadioTxChainMask(radioIndex, output_int) == RETURN_ERR) {
+ fprintf(stderr, "%s: wifi_getRadioTxChainMask return error.\n", __func__);
return RETURN_ERR;
- *output_int = 1;
+ }
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
return RETURN_OK;
}
//P2 // sets the number of Rx streams to an enviornment variable
INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
{
- //save to wifi config, wait for wifi reset or wifi_pushRxChainMask to apply
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+ if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
+ fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
+ return RETURN_ERR;
+ }
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
return RETURN_ERR;
}
@@ -3581,16 +4641,52 @@
//Get radio IGMP snooping enable setting
INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
{
- if (NULL == output_bool)
+ char cmd[128]={0};
+ char buf[4]={0};
+ bool bridge = FALSE, mac80211 = FALSE;
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+
+ if(output_bool == NULL)
return RETURN_ERR;
- *output_bool = TRUE;
+
+ *output_bool = FALSE;
+
+ snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
+ _syscmd(cmd, buf, sizeof(buf));
+ if (strncmp(buf, "1", 1) == 0)
+ bridge = TRUE;
+
+ snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", BRIDGE_NAME, AP_PREFIX, radioIndex);
+ _syscmd(cmd, buf, sizeof(buf));
+ if (strncmp(buf, "1", 1) == 0)
+ mac80211 = TRUE;
+
+ if (bridge && mac80211)
+ *output_bool = TRUE;
+
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
return RETURN_OK;
}
//Set radio IGMP snooping enable setting
INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
{
- return RETURN_ERR;
+ char cmd[128]={0};
+ char buf[4]={0};
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+
+ // bridge
+ snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
+ _syscmd(cmd, buf, sizeof(buf));
+
+ // mac80211
+ for (int i = 0; i < NUMBER_OF_RADIOS; i++) {
+ snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", enable, BRIDGE_NAME, AP_PREFIX, i);
+ _syscmd(cmd, buf, sizeof(buf));
+ }
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+ return RETURN_OK;
}
//Get the Reset count of radio
@@ -3729,8 +4825,21 @@
// sets the beacon interval on the hardware for this AP
INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
{
- //save config and apply instantly
- return RETURN_ERR;
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+ struct params params={'\0'};
+ char buf[MAX_BUF_SIZE] = {'\0'};
+ char config_file[MAX_BUF_SIZE] = {'\0'};
+
+ params.name = "beacon_int";
+ snprintf(buf, sizeof(buf), "%u", beaconInterval);
+ params.value = buf;
+
+ sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
+ wifi_hostapdWrite(config_file, ¶ms, 1);
+
+ wifi_hostapdProcessUpdate(apIndex, ¶ms, 1);
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+ return RETURN_OK;
}
INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
@@ -3890,8 +4999,30 @@
// mode mapping as: 1: open, 2: shared, 4:auto
INT wifi_setApAuthMode(INT apIndex, INT mode)
{
- //Apply instantly
- return RETURN_ERR;
+ struct params params={0};
+ char config_file[64] = {0};
+ int ret;
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
+
+ wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
+ params.name = "auth_algs";
+
+ if (mode & 1 && mode & 2)
+ params.value = "3";
+ else if (mode & 2)
+ params.value = "2";
+ else if (mode & 1)
+ params.value = "1";
+ else
+ params.value = "0";
+
+ sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
+ wifi_hostapdWrite(config_file, ¶ms, 1);
+ wifi_hostapdProcessUpdate(apIndex, ¶ms, 1);
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
+
+ return RETURN_OK;
}
// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
@@ -3913,6 +5044,10 @@
params.value = "WPA-PSK";
else if(strcmp(authMode,"EAPAuthentication") == 0)
params.value = "WPA-EAP";
+ else if (strcmp(authMode, "SAEAuthentication") == 0)
+ params.value = "SAE";
+ else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
+ params.value = "WPA-EAP-SUITE-B-192";
else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
return RETURN_OK; //This is taken careof in beaconType
@@ -4015,6 +5150,20 @@
return RETURN_OK;
}
+INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
+{
+ char cmd[MAX_CMD_SIZE]={'\0'};
+ int ret = 0;
+
+ sprintf(cmd, "hostapd_cli -i %s%d deny_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
+ ret = _syscmd(cmd,macArray,buf_size);
+ if (ret != 0)
+ return RETURN_ERR;
+
+ return RETURN_OK;
+}
+
+
// Get the list of stations associated per AP
INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
{
@@ -4071,10 +5220,20 @@
// outputs the number of devices in the filter list
INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
{
- if (NULL == output_uint)
+ char cmd[MAX_BUF_SIZE]={0};
+ char buf[MAX_CMD_SIZE]={0};
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+ if(output_uint == NULL)
return RETURN_ERR;
- *output_uint = 0;
- return RETURN_ERR;
+
+ snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
+ _syscmd(cmd, buf, sizeof(buf));
+
+ *output_uint = atoi(buf);
+
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+ return RETURN_OK;
}
INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
@@ -4106,7 +5265,7 @@
char aclArray[512] = {0}, *acl = NULL;
char assocArray[512] = {0}, *asso = NULL;
- wifi_getApAclDevices(apIndex, aclArray, sizeof(aclArray));
+ wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
// if there are no devices connected there is nothing to do
@@ -4123,17 +5282,11 @@
acl = strtok(NULL, "\r\n");
}
+ wifi_setApMacAddressControlMode(apIndex, 2);
}
else
{
- //kick off the MAC which is not in ACL array (allow list)
- asso = strtok(assocArray, "\r\n");
- while (asso != NULL) {
- if (strlen(asso) >= 17 && !strcasestr(aclArray, asso))
- wifi_kickApAssociatedDevice(apIndex, asso);
-
- asso = strtok(NULL, "\r\n");
- }
+ wifi_setApMacAddressControlMode(apIndex, 0);
}
#if 0
@@ -4261,17 +5414,41 @@
struct params list[2];
char buf[MAX_BUF_SIZE] = {0};
char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
+ char deny_file[MAX_BUF_SIZE] = {0};
list[0].name = "macaddr_acl";
- sprintf(buf, "%d", filterMode);
- list[0].value = buf ;
- if (filterMode == 1 || filterMode == 2) {//TODO: check for filterMode(2)
+ if (filterMode == 0) {
+ sprintf(buf, "%d", 0);
+ list[0].value = buf;
+
+ char cmd[128], rtn[128];
+ snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d deny_acl CLEAR", AP_PREFIX, apIndex);
+ _syscmd(cmd, rtn, sizeof(rtn));
+ memset(cmd,0,sizeof(cmd));
+ // Delete deny_mac_file in hostapd configuration
+ snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
+ _syscmd(cmd, rtn, sizeof(rtn));
+ }
+ else if (filterMode == 1) {
+ sprintf(buf, "%d", filterMode);
+ list[0].value = buf;
sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
list[1].name = "accept_mac_file";
list[1].value = acl_file;
items = 2;
+ } else if (filterMode == 2) {
+ //TODO: deny_mac_file
+ sprintf(buf, "%d", 0);
+ list[0].value = buf;
+ list[1].name = "deny_mac_file";
+ sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
+ list[1].value = deny_file;
+ items = 2;
+ } else {
+ return RETURN_ERR;
}
+
sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
wifi_hostapdWrite(config_file, list, items);
@@ -4341,12 +5518,64 @@
// reset the vlan configuration for this ap
INT wifi_resetApVlanCfg(INT apIndex)
{
- //TODO: remove existing vlan for this ap
+ char original_config_file[64] = {0};
+ char current_config_file[64] = {0};
+ char buf[64] = {0};
+ char cmd[64] = {0};
+ char vlan_file[64] = {0};
+ char vlan_tagged_interface[16] = {0};
+ char vlan_bridge[16] = {0};
+ char vlan_naming[16] = {0};
+ struct params list[4] = {0};
+ wifi_band band;
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+
+ band = wifi_index_to_band(apIndex);
+ if (band == band_2_4)
+ sprintf(original_config_file, "/etc/hostapd-2G.conf");
+ else if (band = band_5)
+ sprintf(original_config_file, "/etc/hostapd-5G.conf");
+ else if (band = band_6)
+ sprintf(original_config_file, "/etc/hostapd-6G.conf");
+
+ wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
+
+ if (strlen(vlan_file) == 0)
+ strcpy(vlan_file, VLAN_FILE);
+ // The file should exist or this vap would not work.
+ if (access(vlan_file, F_OK) != 0) {
+ sprintf(cmd, "touch %s", vlan_file);
+ _syscmd(cmd, buf, sizeof(buf));
+ }
+ list[0].name = "vlan_file";
+ list[0].value = vlan_file;
+
+ wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
+ list[1].name = "vlan_tagged_interface";
+ list[1].value = vlan_tagged_interface;
+
+ wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
+ list[2].name = "vlan_bridge";
+ list[2].value = vlan_bridge;
+
+ wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
+ list[3].name = "vlan_naming";
+ list[3].value = vlan_naming;
+
+ sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
+ wifi_hostapdWrite(current_config_file, list, 4);
//Reapply vlan settings
- wifi_pushBridgeInfo(apIndex);
+ // wifi_pushBridgeInfo(apIndex);
- return RETURN_ERR;
+ // restart this ap
+ wifi_setApEnable(apIndex, FALSE);
+ wifi_setApEnable(apIndex, TRUE);
+
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+
+ return RETURN_OK;
}
// creates configuration variables needed for WPA/WPS. These variables are implementation dependent and in some implementations these variables are used by hostapd when it is started. Specific variables that are needed are dependent on the hostapd implementation. These variables are set by WPA/WPS security functions in this wifi HAL. If not needed for a particular implementation this function may simply return no error.
@@ -4442,7 +5671,7 @@
if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
{
- sprintf(cmd, "%s%s%d%s", "ifconfig ", AP_PREFIX, apIndex, " | grep UP");
+ sprintf(cmd, "ifconfig %s%d 2> /dev/null | grep UP", AP_PREFIX, apIndex);
*output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
}
@@ -4501,6 +5730,7 @@
wifi_hostapdWrite(config_file, &list, 1);
wifi_hostapdProcessUpdate(apIndex, &list, 1);
//TODO: call hostapd_cli for dynamic_config_control
+ wifi_reloadAp(apIndex);
WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
return RETURN_OK;
@@ -4537,7 +5767,17 @@
//get the running status from driver
if(!output)
return RETURN_ERR;
- *output=TRUE;
+
+ char config_file[MAX_BUF_SIZE] = {0};
+ char buf[16] = {0};
+
+ sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
+ wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
+ if (strncmp("1",buf,1) == 0)
+ *output = TRUE;
+ else
+ *output = FALSE;
+
return RETURN_OK;
}
@@ -4547,7 +5787,17 @@
//get the running status from driver
if(!output)
return RETURN_ERR;
- *output=TRUE;
+
+ char config_file[MAX_BUF_SIZE] = {0};
+ char buf[16] = {0};
+
+ sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
+ wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
+ if (strncmp("1",buf,1) == 0)
+ *output = TRUE;
+ else
+ *output = FALSE;
+
return RETURN_OK;
}
@@ -4555,7 +5805,20 @@
INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
{
//Save config and apply instantly.
- return RETURN_ERR;
+ char config_file[MAX_BUF_SIZE] = {0};
+ struct params list;
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+ list.name = "wmm_enabled";
+ list.value = enable?"1":"0";
+
+ sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
+ wifi_hostapdWrite(config_file, &list, 1);
+ wifi_hostapdProcessUpdate(apIndex, &list, 1);
+ wifi_reloadAp(apIndex);
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+
+ return RETURN_OK;
}
//Whether U-APSD support is currently enabled. When enabled, this is indicated in beacon frames. Note: U-APSD can only be enabled if WMM is also enabled.
@@ -4572,15 +5835,28 @@
INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
{
//save config and apply instantly.
- return RETURN_ERR;
-}
+ char config_file[MAX_BUF_SIZE] = {0};
+ struct params list;
-// Sets the WMM ACK polity on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
-INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
-{
- //save config and apply instantly.
- return RETURN_ERR;
-}
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+ list.name = "uapsd_advertisement_enabled";
+ list.value = enable?"1":"0";
+
+ sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
+ wifi_hostapdWrite(config_file, &list, 1);
+ wifi_hostapdProcessUpdate(apIndex, &list, 1);
+ wifi_reloadAp(apIndex);
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+
+ return RETURN_OK;
+}
+
+// Sets the WMM ACK polity on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
+INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
+{
+ //save config and apply instantly.
+ return RETURN_ERR;
+}
//The maximum number of devices that can simultaneously be connected to the access point. A value of 0 means that there is no specific limit.
INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
@@ -4588,14 +5864,60 @@
//get the running status from driver
if(!output_uint)
return RETURN_ERR;
- *output_uint = 5;
+
+ char output[16]={'\0'};
+ char config_file[MAX_BUF_SIZE] = {0};
+
+ sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
+ wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
+ if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
+ else {
+ int device_num = atoi(output);
+ if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
+ wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
+ return RETURN_ERR;
+ }
+ else {
+ *output_uint = device_num;
+ }
+ }
+
return RETURN_OK;
}
INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
{
//store to wifi config, apply instantly
- return RETURN_ERR;
+ char str[MAX_BUF_SIZE]={'\0'};
+ char cmd[MAX_CMD_SIZE]={'\0'};
+ struct params params;
+ char config_file[MAX_BUF_SIZE] = {0};
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+ if (number > MAX_ASSOCIATED_STA_NUM || number < 0) {
+ WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
+ return RETURN_ERR;
+ }
+ sprintf(str, "%d", number);
+ params.name = "max_num_sta";
+ params.value = str;
+
+ sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
+ int ret = wifi_hostapdWrite(config_file, ¶ms, 1);
+ if (ret) {
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
+ ,__func__, ret);
+ }
+
+ ret = wifi_hostapdProcessUpdate(apIndex, ¶ms, 1);
+ if (ret) {
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
+ ,__func__, ret);
+ }
+ wifi_reloadAp(apIndex);
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+
+ return RETURN_OK;
}
//The HighWatermarkThreshold value that is lesser than or equal to MaxAssociatedDevices. Setting this parameter does not actually limit the number of clients that can associate with this access point as that is controlled by MaxAssociatedDevices. MaxAssociatedDevices or 50. The default value of this parameter should be equal to MaxAssociatedDevices. In case MaxAssociatedDevices is 0 (zero), the default value of this parameter should be 50. A value of 0 means that there is no specific limit and Watermark calculation algorithm should be turned off.
@@ -4604,13 +5926,17 @@
//get the current threshold
if(!output_uint)
return RETURN_ERR;
- *output_uint = 50;
+ wifi_getApMaxAssociatedDevices(apIndex, output_uint);
+ if (*output_uint == 0)
+ *output_uint = 50;
return RETURN_OK;
}
INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
{
//store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
+ if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
+ return RETURN_OK;
return RETURN_ERR;
}
@@ -4647,29 +5973,50 @@
if(!output || apIndex>=MAX_APS)
return RETURN_ERR;
//snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
- snprintf(output, 128, "None,WPA2-Personal");
+ snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
return RETURN_OK;
}
//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
{
- char config_file[MAX_BUF_SIZE] = {0};
- char buf[32] = {0};
+ char config_file[128] = {0};
+ char wpa[16] = {0};
+ char key_mgmt[64] = {0};
+ char buf[16] = {0};
if (!output)
return RETURN_ERR;
sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
- wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
+ wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
+
+ strcpy(output, "None");//Copying "None" to output string for default case
+ wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
+ if (strstr(key_mgmt, "WPA-PSK")) {
+ if (strcmp(wpa, "1"))
+ snprintf(output, 32, "WPA-Personal");
+ else if (strcmp(wpa, "2"))
+ snprintf(output, 32, "WPA2-Personal");
+ else if (strcmp(wpa, "3"))
+ snprintf(output, 32, "WPA-WPA2-Personal");
- strcpy(output,"None");//Copying "None" to output string for default case
- if((strcmp(buf, "3")==0))
- snprintf(output, 32, "WPA-WPA2-Personal");
- else if((strcmp(buf, "2")==0))
- snprintf(output, 32, "WPA2-Personal");
- else if((strcmp(buf, "1")==0))
- snprintf(output, 32, "WPA-Personal");
- //TODO: need to handle enterprise authmode
+ } else if (strstr(key_mgmt, "WPA-EAP")) {
+ if (strcmp(wpa, "1"))
+ snprintf(output, 32, "WPA-Enterprise");
+ else if (strcmp(wpa, "2"))
+ snprintf(output, 32, "WPA2-Enterprise");
+ else if (strcmp(wpa, "3"))
+ snprintf(output, 32, "WPA-WPA2-Enterprise");
+ } else if (strstr(key_mgmt, "SAE")) {
+ wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
+ int disable = strtol(buf, NULL, 16);
+ if (disable & 0x1)
+ snprintf(output, 32, "WPA3-Personal");
+ else
+ snprintf(output, 32, "WPA3-Transition");
+ } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
+ snprintf(output, 32, "WPA3-Enterprise");
+ }
//save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
return RETURN_OK;
@@ -4712,7 +6059,6 @@
if(!encMode)
return RETURN_ERR;
- printf("%s: apIndex %d, encMode %s\n",__func__, apIndex, encMode);
if (strcmp(encMode, "None")==0)
{
strcpy(securityType,"None");
@@ -4748,6 +6094,16 @@
strcpy(securityType,"11i");
strcpy(authMode,"EAPAuthentication");
}
+ else if (strcmp(encMode, "WPA3-Personal") == 0)
+ {
+ strcpy(securityType,"11i");
+ strcpy(authMode,"SAEAuthentication");
+ }
+ else if (strcmp(encMode, "WPA3-Enterprise") == 0)
+ {
+ strcpy(securityType,"11i");
+ strcpy(authMode,"EAP_192-bit_Authentication");
+ }
else
{
strcpy(securityType,"None");
@@ -4870,42 +6226,222 @@
//When set to true, this AccessPoint instance's WiFi security settings are reset to their factory default values. The affected settings include ModeEnabled, WEPKey, PreSharedKey and KeyPassphrase.
INT wifi_setApSecurityReset(INT apIndex)
{
- //apply instantly
- return RETURN_ERR;
+ char original_config_file[64] = {0};
+ char current_config_file[64] = {0};
+ char buf[64] = {0};
+ char cmd[64] = {0};
+ char wpa[4] = {0};
+ char wpa_psk[64] = {0};
+ char wpa_passphrase[64] = {0};
+ char wpa_psk_file[128] = {0};
+ char wpa_key_mgmt[64] = {0};
+ char wpa_pairwise[32] = {0};
+ wifi_band band;
+ struct params list[6];
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+
+ band = wifi_index_to_band(apIndex);
+ if (band == band_2_4)
+ sprintf(original_config_file, "/etc/hostapd-2G.conf");
+ else if (band = band_5)
+ sprintf(original_config_file, "/etc/hostapd-5G.conf");
+ else if (band = band_6)
+ sprintf(original_config_file, "/etc/hostapd-6G.conf");
+ else
+ return RETURN_ERR;
+
+ wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
+ list[0].name = "wpa";
+ list[0].value = wpa;
+
+ wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
+ list[1].name = "wpa_psk";
+ list[1].value = wpa_psk;
+
+ wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
+ list[2].name = "wpa_passphrase";
+ list[2].value = wpa_passphrase;
+
+ wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
+
+ if (strlen(wpa_psk_file) == 0)
+ strcpy(wpa_psk_file, PSK_FILE);
+
+ if (access(wpa_psk_file, F_OK) != 0) {
+ sprintf(cmd, "touch %s", wpa_psk_file);
+ _syscmd(cmd, buf, sizeof(buf));
+ }
+ list[3].name = "wpa_psk_file";
+ list[3].value = wpa_psk_file;
+
+ wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
+ list[4].name = "wpa_key_mgmt";
+ list[4].value = wpa_key_mgmt;
+
+ wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
+ list[5].name = "wpa_pairwise";
+ list[5].value = wpa_pairwise;
+
+ sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
+ wifi_hostapdWrite(current_config_file, list, 6);
+
+ wifi_setApEnable(apIndex, FALSE);
+ wifi_setApEnable(apIndex, TRUE);
+
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+ return RETURN_OK;
}
//The IP Address and port number of the RADIUS server used for WLAN security. RadiusServerIPAddr is only applicable when ModeEnabled is an Enterprise type (i.e. WPA-Enterprise, WPA2-Enterprise or WPA-WPA2-Enterprise).
INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
{
+ char config_file[64] = {0};
+ char buf[64] = {0};
+ char cmd[256] = {0};
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+
if(!IP_output || !Port_output || !RadiusSecret_output)
return RETURN_ERR;
- snprintf(IP_output, 64, "75.56.77.78");
- *Port_output = 123;
- snprintf(RadiusSecret_output, 64, "12345678");
+
+ // Read the first matched config
+ snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
+ sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
+ _syscmd(cmd, buf, sizeof(buf));
+ strncpy(IP_output, buf, 64);
+ memset(buf, 0, sizeof(buf));
+ sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
+ _syscmd(cmd, buf, sizeof(buf));
+ *Port_output = atoi(buf);
+
+ memset(buf, 0, sizeof(buf));
+ sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
+ _syscmd(cmd, buf, sizeof(buf));
+ strncpy(RadiusSecret_output, buf, 64);
+
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
return RETURN_OK;
}
INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
{
- //store the paramters, and apply instantly
- return RETURN_ERR;
+ char config_file[64] = {0};
+ char port_str[8] = {0};
+ char cmd[256] = {0};
+ char buf[128] = {0};
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+
+ snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
+
+ snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
+ _syscmd(cmd, buf, sizeof(buf));
+ memset(cmd, 0, sizeof(cmd));
+
+ snprintf(port_str, sizeof(port_str), "%d", port);
+ if (strlen(buf) == 0)
+ // Append
+ snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
+ "auth_server_addr=%s\\n"
+ "auth_server_port=%s\\n"
+ "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
+ else {
+ // Delete the three lines setting after the "# radius 1" comment
+ snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
+ _syscmd(cmd, buf, sizeof(buf));
+ memset(cmd, 0, sizeof(cmd));
+ // Use "# radius 1" comment to find the location to insert the radius setting
+ snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
+ "# radius 1\\n"
+ "auth_server_addr=%s\\n"
+ "auth_server_port=%s\\n"
+ "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
+ }
+ if(_syscmd(cmd, buf, sizeof(buf))) {
+ wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
+ return RETURN_ERR;
+ }
+
+ wifi_reloadAp(apIndex);
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+ return RETURN_OK;
}
INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
{
+ char config_file[64] = {0};
+ char buf[64] = {0};
+ char cmd[256] = {0};
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+
if(!IP_output || !Port_output || !RadiusSecret_output)
return RETURN_ERR;
- snprintf(IP_output, 64, "75.56.77.78");
- *Port_output = 123;
- snprintf(RadiusSecret_output, 64, "12345678");
+
+ // Read the second matched config
+ snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
+ sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
+ _syscmd(cmd, buf, sizeof(buf));
+ strncpy(IP_output, buf, 64);
+
+ memset(buf, 0, sizeof(buf));
+ sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
+ _syscmd(cmd, buf, sizeof(buf));
+ *Port_output = atoi(buf);
+
+ memset(buf, 0, sizeof(buf));
+ sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
+ _syscmd(cmd, buf, sizeof(buf));
+ strncpy(RadiusSecret_output, buf, 64);
+
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
return RETURN_OK;
}
INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
{
- //store the paramters, and apply instantly
- return RETURN_ERR;
+ char config_file[64] = {0};
+ char port_str[8] = {0};
+ char cmd[256] = {0};
+ char buf[128] = {0};
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+
+ snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
+
+ snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
+ _syscmd(cmd, buf, sizeof(buf));
+ memset(cmd, 0, sizeof(cmd));
+
+ snprintf(port_str, sizeof(port_str), "%d", port);
+ if (strlen(buf) == 0)
+ // Append
+ snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
+ "auth_server_addr=%s\\n"
+ "auth_server_port=%s\\n"
+ "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
+ else {
+ // Delete the three lines setting after the "# radius 2" comment
+ snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
+ _syscmd(cmd, buf, sizeof(buf));
+ memset(cmd, 0, sizeof(cmd));
+ // Use "# radius 2" comment to find the location to insert the radius setting
+ snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
+ "# radius 2\\n"
+ "auth_server_addr=%s\\n"
+ "auth_server_port=%s\\n"
+ "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
+ }
+ if(_syscmd(cmd, buf, sizeof(buf))) {
+ wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
+ return RETURN_ERR;
+ }
+
+ wifi_reloadAp(apIndex);
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+ return RETURN_OK;
}
//RadiusSettings
@@ -5104,7 +6640,7 @@
snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep wps_state | cut -d'=' -f2", AP_PREFIX, apIndex);
_syscmd(cmd, buf, sizeof(buf));
- if(!strcmp(buf, "configured"))
+ if(!strncmp(buf, "configured", 10))
snprintf(output_string, 32, "Configured");
WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
@@ -6218,10 +7754,56 @@
//To-do
INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
{
+ char output[16]={'\0'};
+ char config_file[MAX_BUF_SIZE] = {0};
+
+ if (!output_string)
+ return RETURN_ERR;
+
+ sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
+ wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
+
+ if (strlen(output) == 0)
+ snprintf(output_string, 64, "Disabled");
+ else if (strncmp(output, "0", 1) == 0)
+ snprintf(output_string, 64, "Disabled");
+ else if (strncmp(output, "1", 1) == 0)
+ snprintf(output_string, 64, "Optional");
+ else if (strncmp(output, "2", 1) == 0)
+ snprintf(output_string, 64, "Required");
+ else {
+ wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
+ return RETURN_ERR;
+ }
+
+ wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
return RETURN_OK;
}
INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
{
+ char str[MAX_BUF_SIZE]={'\0'};
+ char cmd[MAX_CMD_SIZE]={'\0'};
+ struct params params;
+ char config_file[MAX_BUF_SIZE] = {0};
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+ if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
+ return RETURN_ERR;
+
+ params.name = "ieee80211w";
+ if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
+ params.value = "0";
+ else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
+ params.value = "1";
+ else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
+ params.value = "2";
+ else{
+ wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
+ return RETURN_ERR;
+ }
+ sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
+ wifi_hostapdWrite(config_file, ¶ms, 1);
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
return RETURN_OK;
}
INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
@@ -6647,112 +8229,205 @@
INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
{
- char cmd[1024] = {0};
- char buf[1024] = {0};
- WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+ int index = -1;
wifi_neighbor_ap2_t *scan_array = NULL;
- int scan_count=0;
- int i =0;
+ char cmd[256]={0};
+ char buf[128]={0};
+ char file_name[32] = {0};
+ char filter_SSID[32] = {0};
+ char line[256] = {0};
+ char *ret = NULL;
int freq=0;
- size_t len=0;
FILE *f = NULL;
- ssize_t read = 0;
- char *line =NULL;
- char radio_ifname[64];
- char secondary_chan[64];
+ size_t len=0;
+ int channels_num = 0;
int vht_channel_width = 0;
+ bool get_nosie_ret = false;
+ bool filter_enable = false;
+ bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
- if(wifi_getRadioIfName(radio_index,radio_ifname)!=RETURN_OK)
- return RETURN_ERR;
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
- /* sched_start is not supported on open source ath9k ath10k firmware
- * Using active scan as a workaround */
- sprintf(cmd,"iw dev %s scan |grep '^BSS\\|SSID:\\|freq:\\|signal:\\|HT operation:\\|secondary channel offset:\\|* channel width:'", radio_ifname);
- if((f = popen(cmd, "r")) == NULL) {
+ snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
+ f = fopen(file_name, "r");
+ if (f != NULL) {
+ fgets(filter_SSID, sizeof(file_name), f);
+ if (strlen(filter_SSID) != 0)
+ filter_enable = true;
+ fclose(f);
+ }
+
+ snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", radio_index);
+ _syscmd(cmd, buf, sizeof(buf));
+ channels_num = strtol(buf, NULL, 10);
+
+ struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
+ get_nosie_ret = get_noise(radio_index, channels_noise_arr, channels_num);
+
+ sprintf(cmd, "iw dev %s%d scan dump | grep '%s%d\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
+ // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", AP_PREFIX, radio_index, AP_PREFIX, radio_index);
+ fprintf(stderr, "cmd: %s\n", cmd);
+ if ((f = popen(cmd, "r")) == NULL) {
wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
return RETURN_ERR;
}
- read = getline(&line, &len, f);
- while (read != -1) {
- if(strncmp(line,"BSS",3) == 0) {
- i = scan_count;
- scan_count++;
- scan_array = realloc(scan_array,sizeof(wifi_neighbor_ap2_t)*scan_count);
- memset(&(scan_array[i]),0, sizeof(wifi_neighbor_ap2_t));
- sscanf(line,"BSS %17s", scan_array[i].ap_BSSID);
+ ret = fgets(line, sizeof(line), f);
+ while (ret != NULL) {
+ if(strstr(line, "BSS") != NULL) { // new neighbor info
+ // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
+ // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
+ // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
+
+ if (!filter_BSS) {
+ index++;
+ wifi_neighbor_ap2_t *tmp;
+ tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
+ if (tmp == NULL) { // no more memory to use
+ index--;
+ wifi_dbg_printf("%s: realloc failed\n", __func__);
+ break;
+ }
+ scan_array = tmp;
+ }
+ memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
- read = getline(&line, &len, f);
+ filter_BSS = false;
+ sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
+ strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
+ strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
+ strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
+ } else if (strstr(line, "freq") != NULL) {
sscanf(line," freq: %d", &freq);
- scan_array[i].ap_Channel = ieee80211_frequency_to_channel(freq);
+ scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
- read = getline(&line, &len, f);
- sscanf(line," signal: %d", &(scan_array[i].ap_SignalStrength));
+ if (freq >= 2412 && freq <= 2484) {
+ strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
+ strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
+ strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
+ }
+ else if (freq >= 5160 && freq <= 5805) {
+ strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
+ strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
+ strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
+ }
- read = getline(&line, &len, f);
- sscanf(line," SSID: %s", scan_array[i].ap_SSID);
- wifi_dbg_printf("%s:Discovered BSS %s, %d, %d , %s\n", __func__, scan_array[i].ap_BSSID, scan_array[i].ap_Channel,scan_array[i].ap_SignalStrength, scan_array[i].ap_SSID);
- read = getline(&line, &len, f);
- if(strncmp(line,"BSS",3)==0) {
- // No HT and no VHT => 20Mhz
- snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11%s", radio_index%1 ? "A": "G");
- wifi_dbg_printf("%s: ap_OperatingChannelBandwidth = '%s'\n", __func__, scan_array[i].ap_OperatingChannelBandwidth);
- continue;
+ scan_array[index].ap_Noise = 0;
+ if (get_nosie_ret) {
+ for (int i = 0; i < channels_num; i++) {
+ if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
+ scan_array[index].ap_Noise = channels_noise_arr[i].noise;
+ break;
+ }
+ }
}
- if(strncmp(line," HT operation:",14)!= 0) {
- wifi_dbg_printf("HT output parsing error (%s)\n", line);
- goto output_error;
+ } else if (strstr(line, "beacon interval") != NULL) {
+ sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
+ } else if (strstr(line, "signal") != NULL) {
+ sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
+ } else if (strstr(line,"SSID") != NULL) {
+ sscanf(line," SSID: %s", scan_array[index].ap_SSID);
+ if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
+ filter_BSS = true;
}
+ } else if (strstr(line, "Supported rates") != NULL) {
+ char SRate[80] = {0}, *tmp = NULL;
+ memset(buf, 0, sizeof(buf));
+ strcpy(SRate, line);
+ tmp = strtok(SRate, ":");
+ tmp = strtok(NULL, ":");
+ strcpy(buf, tmp);
+ memset(SRate, 0, sizeof(SRate));
- read = getline(&line, &len, f);
- sscanf(line," * secondary channel offset: %s", &secondary_chan);
+ tmp = strtok(buf, " \n");
+ while (tmp != NULL) {
+ strcat(SRate, tmp);
+ if (SRate[strlen(SRate) - 1] == '*') {
+ SRate[strlen(SRate) - 1] = '\0';
+ }
+ strcat(SRate, ",");
- if(!strcmp(secondary_chan, "no")) {
- //20Mhz
- snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11N%s_HT20", radio_index%1 ? "A": "G");
+ tmp = strtok(NULL, " \n");
}
-
- if(!strcmp(secondary_chan, "above")) {
+ SRate[strlen(SRate) - 1] = '\0';
+ strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
+ } else if (strstr(line, "DTIM") != NULL) {
+ sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
+ } else if (strstr(line, "VHT capabilities") != NULL) {
+ strcat(scan_array[index].ap_SupportedStandards, ",ac");
+ strcpy(scan_array[index].ap_OperatingStandards, "ac");
+ } else if (strstr(line, "HT capabilities") != NULL) {
+ strcat(scan_array[index].ap_SupportedStandards, ",n");
+ strcpy(scan_array[index].ap_OperatingStandards, "n");
+ } else if (strstr(line, "VHT operation") != NULL) {
+ ret = fgets(line, sizeof(line), f);
+ sscanf(line," * channel width: %d", &vht_channel_width);
+ if(vht_channel_width == 1) {
+ snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
+ } else {
+ snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
+ }
+ if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
+ continue;
+ } else if (strstr(line, "HT operation") != NULL) {
+ ret = fgets(line, sizeof(line), f);
+ sscanf(line," * secondary channel offset: %s", &buf);
+ if (!strcmp(buf, "above")) {
//40Mhz +
- snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radio_index%1 ? "A": "G");
+ snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radio_index%1 ? "A": "G");
}
-
- if(!strcmp(secondary_chan, "below")) {
+ else if (!strcmp(buf, "below")) {
//40Mhz -
- snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
+ snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
+ } else {
+ //20Mhz
+ snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radio_index%1 ? "A": "G");
}
-
-
- read = getline(&line, &len, f);
- if(strncmp(line," VHT operation:",15) !=0) {
- wifi_dbg_printf("%s: ap_OperatingChannelBandwidth = '%s'\n", __func__, scan_array[i].ap_OperatingChannelBandwidth);
- // No VHT
+ if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
continue;
+ } else if (strstr(line, "HE capabilities") != NULL) {
+ strcat(scan_array[index].ap_SupportedStandards, ",ax");
+ strcpy(scan_array[index].ap_OperatingStandards, "ax");
+ ret = fgets(line, sizeof(line), f);
+ if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
+ if (strstr(line, "HE40/2.4GHz") != NULL)
+ strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
+ else
+ strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
+ } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
+ if (strstr(line, "HE80/5GHz") != NULL) {
+ strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
+ ret = fgets(line, sizeof(line), f);
+ } else
+ continue;
+ if (strstr(line, "HE160/5GHz") != NULL)
+ strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
}
- read = getline(&line, &len, f);
- sscanf(line," * channel width: %d", &vht_channel_width);
- if(vht_channel_width == 1) {
- snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11AC_VHT80");
- } else {
- snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11AC_VHT40");
+ continue;
+ } else if (strstr(line, "WPA") != NULL) {
+ strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
+ } else if (strstr(line, "RSN") != NULL) {
+ strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
+ } else if (strstr(line, "Group cipher") != NULL) {
+ sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
+ if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
+ strcpy(scan_array[index].ap_EncryptionMode, "AES");
}
-
}
- wifi_dbg_printf("%s: ap_OperatingChannelBandwidth = '%s'\n", __func__, scan_array[i].ap_OperatingChannelBandwidth);
- read = getline(&line, &len, f);
+ ret = fgets(line, sizeof(line), f);
+ }
+
+ if (!filter_BSS) {
+ *output_array_size = index + 1;
+ } else {
+ memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
+ *output_array_size = index;
}
- wifi_dbg_printf("%s:Counted BSS: %d\n",__func__, scan_count);
- *output_array_size = scan_count;
*neighbor_ap_array = scan_array;
- free(line);
pclose(f);
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
return RETURN_OK;
-
-output_error:
- pclose(f);
- free(line);
- free(scan_array);
- return RETURN_ERR;
}
+
INT wifi_getApAssociatedDeviceStats(
INT apIndex,
mac_address_t *clientMacAddress,
@@ -6845,7 +8520,24 @@
//_syscmd(cmd, buf, sizeof(buf));
sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
- *output_filterMode = atoi(buf);
+ if(strlen(buf) == 0) {
+ *output_filterMode = 0;
+ }
+ else {
+ int macaddr_acl_mode = strtol(buf, NULL, 10);
+ if (macaddr_acl_mode == 1) {
+ *output_filterMode = 1;
+ } else if (macaddr_acl_mode == 0) {
+ wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
+ if (strlen(buf) == 0) {
+ *output_filterMode = 0;
+ } else {
+ *output_filterMode = 2;
+ }
+ } else {
+ return RETURN_ERR;
+ }
+ }
return RETURN_OK;
}
@@ -7033,53 +8725,59 @@
#endif
FILE *fp = NULL;
- char HConf_file[MAX_BUF_SIZE] = {'\0'};
+ char HConf_file[128] = {'\0'};
char interface_name[50] = {0};
- char pipeCmd[MAX_CMD_SIZE] = {0};
- char str[MAX_BUF_SIZE] = {0};
+ char pipeCmd[128] = {0};
+ char str[256] = {0};
wifi_ssidTrafficStats2_t *out = output_struct;
- WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
if (!output_struct)
return RETURN_ERR;
- if (ssidIndex >= 4)
- return RETURN_ERR;
+ memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
+ sprintf(HConf_file, "%s%d.conf", CONFIG_PREFIX, ssidIndex);
+ GetInterfaceName(interface_name, HConf_file);
+ sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
- sprintf(HConf_file,"%s%d%s","/nvram/hostapd",ssidIndex,".conf");
- GetInterfaceName(interface_name,HConf_file);
- sprintf(pipeCmd,"%s%s%s","cat /proc/net/dev | grep ",interface_name," | tr -s ' ' | cut -d ' ' -f11 | tr -d '\n'");
fp = popen(pipeCmd, "r");
- fgets(str, MAX_BUF_SIZE,fp);
- out->ssid_BytesSent = atol(str);
- pclose(fp);
+ if (fp == NULL) {
+ fprintf(stderr, "%s: popen failed\n", __func__);
+ return RETURN_ERR;
+ }
+ fgets(str, sizeof(str), fp);
- sprintf(pipeCmd,"%s%s%s","cat /proc/net/dev | grep ",interface_name," | tr -s ' ' | cut -d ' ' -f3 | tr -d '\n'");
- fp = popen(pipeCmd, "r");
- fgets(str, MAX_BUF_SIZE,fp);
- out->ssid_BytesReceived = atol(str);
- pclose(fp);
+ if (strlen(str) == 0) // interface not exist
+ return RETURN_OK;
- sprintf(pipeCmd,"%s%s%s","cat /proc/net/dev | grep ",interface_name," | tr -s ' ' | cut -d ' ' -f12 | tr -d '\n'");
- fp = popen(pipeCmd, "r");
- fgets(str, MAX_BUF_SIZE,fp);
- out->ssid_PacketsSent = atol(str);
+ sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
+ &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
pclose(fp);
- sprintf(pipeCmd,"%s%s%s","cat /proc/net/dev | grep ",interface_name," | tr -s ' ' | cut -d ' ' -f4 | tr -d '\n'");
+ memset(str, 0, sizeof(str));
+ sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
fp = popen(pipeCmd, "r");
- fgets(str, MAX_BUF_SIZE,fp);
- out->ssid_PacketsReceived = atol(str);
+ if (fp == NULL) {
+ fprintf(stderr, "%s: popen failed\n", __func__);
+ return RETURN_ERR;
+ }
+ fgets(str, sizeof(str), fp);
+
+ sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
+ &out->ssid_BroadcastPacketsSent);
pclose(fp);
- /*
- //TODO:
- out->ssid_UnicastPacketsSent = uni->ims_tx_data_packets;
- out->ssid_UnicastPacketsReceived = uni->ims_rx_data_packets;
- out->ssid_MulticastPacketsSent = multi->ims_tx_data_packets - multi->ims_tx_bcast_data_packets;
- out->ssid_MulticastPacketsReceived = multi->ims_rx_data_packets - multi->ims_rx_bcast_data_packets;
- out->ssid_BroadcastPacketsSent = multi->ims_tx_bcast_data_packets;
- out->ssid_BroadcastPacketsRecevied = multi->ims_rx_bcast_data_packets;
- */
+
+ out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
+ out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
+
+ // Not supported
+ output_struct->ssid_RetransCount = 0;
+ output_struct->ssid_FailedRetransCount = 0;
+ output_struct->ssid_RetryCount = 0;
+ output_struct->ssid_MultipleRetryCount = 0;
+ output_struct->ssid_ACKFailureCount = 0;
+ output_struct->ssid_AggregatedPacketCount = 0;
+
return RETURN_OK;
}
@@ -7185,8 +8883,39 @@
INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
{
- // TODO Implement me!
- return RETURN_OK;
+ char file_name[128] = {0};
+ char buf[128] = {0};
+ FILE *f = NULL;
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+
+ if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
+ for (int index = 0; index < NUMBER_OF_RADIOS; index++) {
+ snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
+ f = fopen(file_name, "w");
+ if (f == NULL)
+ return RETURN_ERR;
+ // For mode == 0 is to disable filter, just don't write to the file.
+ if (mode)
+ fprintf(f, "%s", essid);
+
+ fclose(f);
+ }
+ } else { // special case, need to set AP's SSID as filter for each radio.
+ snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
+ f = fopen(file_name, "w");
+ if (f == NULL)
+ return RETURN_ERR;
+
+ // For mode == 0 is to disable filter, just don't write to the file.
+ if (mode)
+ fprintf(f, "%s", essid);
+
+ fclose(f);
+ }
+
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+ return RETURN_OK;
}
INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
@@ -7376,7 +9105,25 @@
INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
{
- // TODO Implement me!
+ char cmd[128]={0};
+ char buf[128]={0};
+ int freq = 0;
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+
+ // full mode is used to scan all channels.
+ // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
+ if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
+ ieee80211_channel_to_frequency(chan_list[0], &freq);
+
+ if (freq)
+ snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d freq %d", AP_PREFIX, apIndex, dwell_time, freq);
+ else
+ snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d", AP_PREFIX, apIndex, dwell_time);
+
+ _syscmd(cmd, buf, sizeof(buf));
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+
return RETURN_OK;
}
@@ -7434,15 +9181,14 @@
if(_syscmd(cmd,buf,sizeof(buf)))
return RETURN_ERR;
#endif
- char fname[100];
- FILE *fp;
+ char cmd[MAX_CMD_SIZE]={0};
+ char buf[MAX_BUF_SIZE]={0};
- snprintf(fname, sizeof(fname), "%s%d", ACL_PREFIX, apIndex);
- fp = fopen(fname, "w");
- if (!fp) {
- return RETURN_ERR;
- }
- fclose(fp);
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+ sprintf(cmd, "rm %s%d 2>&1 && touch %s%d", ACL_PREFIX, apIndex, ACL_PREFIX, apIndex);
+ if(_syscmd(cmd, buf, sizeof(buf)))
+ return RETURN_ERR;
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
return RETURN_OK;
}
@@ -8551,29 +10297,228 @@
INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
{
- //TO-Do Implement this
- txpwr_pcntg = 0;
+ char cmd[128]={'\0'};
+ char buf[128]={'\0'};
+ char *support;
+ int maximum_tx = 0, current_tx = 0;
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+ if(txpwr_pcntg == NULL)
+ return RETURN_ERR;
+
+ // Get the maximum tx power of the device
+ snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
+ _syscmd(cmd, buf, sizeof(buf));
+ maximum_tx = strtol(buf, NULL, 10);
+
+ // Get the current tx power
+ memset(cmd, 0, sizeof(cmd));
+ memset(buf, 0, sizeof(buf));
+ snprintf(cmd, sizeof(cmd), "iw %s%d info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", AP_PREFIX, apIndex);
+ _syscmd(cmd, buf, sizeof(buf));
+ current_tx = strtol(buf, NULL, 10);
+
+ // Get the power supported list and find the current power percentage in supported list
+ memset(buf, 0, sizeof(buf));
+ wifi_getRadioTransmitPowerSupported(apIndex, buf);
+ support = strtok(buf, ",");
+ while(true)
+ {
+ if(support == NULL) { // current power is not in supported list, this should not happen if the power is set by hal.
+ *txpwr_pcntg = 0;
+ wifi_dbg_printf("current power is not in supported list\n");
+ return RETURN_ERR;
+ }
+ int tmp = maximum_tx*strtol(support, NULL, 10)/100;
+ if (tmp == current_tx) {
+ *txpwr_pcntg = strtol(support, NULL, 10);
+ break;
+ }
+ support = strtok(NULL, ",");
+ }
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
return RETURN_OK;
}
INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
{
- //Zero-wait DFS not supported
- return RETURN_ERR;
+ // TODO precac feature.
+ struct params params = {0};
+ char config_file[128] = {0};
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+
+ params.name = "enable_background_radar";
+ params.value = enable?"1":"0";
+ sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
+ wifi_hostapdWrite(config_file, ¶ms, 1);
+ wifi_hostapdProcessUpdate(radioIndex, ¶ms, 1);
+
+ /* TODO precac feature */
+
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+ return RETURN_OK;
}
INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
{
- //Zero-wait DFS not supported
- return RETURN_ERR;
+ char config_file[128] = {0};
+ char buf[64] = {0};
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+ if (NULL == enable || NULL == precac)
+ return RETURN_ERR;
+
+ sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
+ wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
+ if (strncmp(enable, "1", 1) == 0)
+ *enable = true;
+ else
+ *enable = false;
+
+ /* TODO precac feature */
+
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+ return RETURN_OK;
}
INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
{
+ *supported = TRUE;
+ return RETURN_OK;
+}
+
+INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
+{
+ char cmd[128] = {0};
+ char buf[64] = {0};
+ char band_str[8] = {0};
+ char GI[8] = {0};
+ int tmp = 0;
+ BOOL ax_mode = FALSE;
+ BOOL short_GI = FALSE;
+ FILE *f = NULL;
+ wifi_band band;
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+
+ if (wifi_getRadioMode(radio_index, buf, &tmp) == RETURN_ERR) {
+ wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
+ return RETURN_ERR;
+ }
+ if (strstr(buf, "ax") != NULL)
+ ax_mode = TRUE;
+
+ if (guard_interval == wifi_guard_interval_400 && ax_mode != TRUE) {
+ short_GI = TRUE;
+ strcpy(GI, "0.4");
+ } else if (guard_interval == wifi_guard_interval_1600 && ax_mode == TRUE)
+ strcpy(GI, "1.6");
+ else if (guard_interval == wifi_guard_interval_3200 && ax_mode == TRUE)
+ strcpy(GI, "3.2");
+ else // default
+ strcpy(GI, "0.8");
+
+ band = wifi_index_to_band(radio_index);
+ if (band == band_2_4)
+ strcpy(band_str, "2.4");
+ else if (band == band_5)
+ strcpy(band_str, "5");
+ else if (band == band_6)
+ strcpy(band_str, "6");
+ else {
+ wifi_dbg_printf("%s: invalid band\n");
+ return RETURN_ERR;
+ }
+
+ if (ax_mode == TRUE)
+ snprintf(cmd, sizeof(cmd), "iw dev %s%d set bitrates he-gi-%s %s", AP_PREFIX, radio_index, band_str, GI);
+ else
+ snprintf(cmd, sizeof(cmd), "iw dev %s%d set bitrates %sgi-%s", AP_PREFIX, radio_index, (short_GI)?"s":"l", band_str);
+ _syscmd(cmd, buf, sizeof(buf));
+
+ // Record GI for get GI function
+ snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
+ f = fopen(buf, "w");
+ if (f != NULL) {
+ fprintf(f, "%s", GI);
+ }
+ fclose(f);
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+ return RETURN_OK;
+}
+
+INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
+{
- *supported = false;
- return RETURN_OK;
+ char buf[32] = {0};
+ char cmd[64] = {0};
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+
+ if (guard_interval == NULL)
+ return RETURN_ERR;
+
+ snprintf(cmd, sizeof(cmd), "cat %s%d.txt", GUARD_INTERVAL_FILE, radio_index);
+ _syscmd(cmd, buf, sizeof(buf));
+
+ if (strncmp(buf, "0.4", 3) == 0)
+ *guard_interval = wifi_guard_interval_400;
+ else if (strncmp(buf, "0.8", 3) == 0)
+ *guard_interval = wifi_guard_interval_800;
+ else if (strncmp(buf, "1.6", 3) == 0)
+ *guard_interval = wifi_guard_interval_1600;
+ else if (strncmp(buf, "3.2", 3) == 0)
+ *guard_interval = wifi_guard_interval_3200;
+ else
+ *guard_interval = wifi_guard_interval_auto;
+
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+ return RETURN_OK;
}
+INT wifi_setBSSColor(INT radio_index, UCHAR color)
+{
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+ struct params params = {0};
+ char config_file[128] = {0};
+ char bss_color[4] ={0};
+
+ params.name = "he_bss_color";
+ snprintf(bss_color, sizeof(bss_color), "%hhu", color);
+ params.value = bss_color;
+ sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
+ wifi_hostapdWrite(config_file, ¶ms, 1);
+ wifi_hostapdProcessUpdate(radio_index, ¶ms, 1);
+
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+ return RETURN_OK;
+}
+
+INT wifi_getBSSColor(INT radio_index, UCHAR *color)
+{
+ char config_file[128] = {0};
+ char buf[64] = {0};
+ char temp_output[128] = {'\0'};
+
+ wifi_dbg_printf("\nFunc=%s\n", __func__);
+ if (NULL == color)
+ return RETURN_ERR;
+
+ sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
+ wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
+
+ if(strlen(buf) > 0) {
+ snprintf(temp_output, sizeof(temp_output), "%s", buf);
+ } else {
+ snprintf(temp_output, sizeof(temp_output), "1"); // default value
+ }
+
+ *color = (UCHAR)strtoul(temp_output, NULL, 10);
+ wifi_dbg_printf("\noutput_string=%s\n", color);
+
+ return RETURN_OK;
+}
+
/* multi-psk support */
INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
{
@@ -9096,79 +11041,369 @@
#ifdef WIFI_HAL_VERSION_3
+INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
+{
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+ if (bitMap & WIFI_BITRATE_1MBPS)
+ strcat(BasicRate, "1,");
+ if (bitMap & WIFI_BITRATE_2MBPS)
+ strcat(BasicRate, "2,");
+ if (bitMap & WIFI_BITRATE_5_5MBPS)
+ strcat(BasicRate, "5.5,");
+ if (bitMap & WIFI_BITRATE_6MBPS)
+ strcat(BasicRate, "6,");
+ if (bitMap & WIFI_BITRATE_9MBPS)
+ strcat(BasicRate, "9,");
+ if (bitMap & WIFI_BITRATE_11MBPS)
+ strcat(BasicRate, "11,");
+ if (bitMap & WIFI_BITRATE_12MBPS)
+ strcat(BasicRate, "12,");
+ if (bitMap & WIFI_BITRATE_18MBPS)
+ strcat(BasicRate, "18,");
+ if (bitMap & WIFI_BITRATE_24MBPS)
+ strcat(BasicRate, "24,");
+ if (bitMap & WIFI_BITRATE_36MBPS)
+ strcat(BasicRate, "36,");
+ if (bitMap & WIFI_BITRATE_48MBPS)
+ strcat(BasicRate, "48,");
+ if (bitMap & WIFI_BITRATE_54MBPS)
+ strcat(BasicRate, "54,");
+ if (strlen(BasicRate) != 0) // remove last comma
+ BasicRate[strlen(BasicRate) - 1] = '\0';
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+ return RETURN_OK;
+}
+
+INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
+{
+ UINT BitMap = 0;
+ char *rate;
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+ rate = strtok(BasicRatesList, ",");
+ while(rate != NULL)
+ {
+ if (strcmp(rate, "1") == 0)
+ BitMap |= WIFI_BITRATE_1MBPS;
+ else if (strcmp(rate, "2") == 0)
+ BitMap |= WIFI_BITRATE_2MBPS;
+ else if (strcmp(rate, "5.5") == 0)
+ BitMap |= WIFI_BITRATE_5_5MBPS;
+ else if (strcmp(rate, "6") == 0)
+ BitMap |= WIFI_BITRATE_6MBPS;
+ else if (strcmp(rate, "9") == 0)
+ BitMap |= WIFI_BITRATE_9MBPS;
+ else if (strcmp(rate, "11") == 0)
+ BitMap |= WIFI_BITRATE_11MBPS;
+ else if (strcmp(rate, "12") == 0)
+ BitMap |= WIFI_BITRATE_12MBPS;
+ else if (strcmp(rate, "18") == 0)
+ BitMap |= WIFI_BITRATE_18MBPS;
+ else if (strcmp(rate, "24") == 0)
+ BitMap |= WIFI_BITRATE_24MBPS;
+ else if (strcmp(rate, "36") == 0)
+ BitMap |= WIFI_BITRATE_36MBPS;
+ else if (strcmp(rate, "48") == 0)
+ BitMap |= WIFI_BITRATE_48MBPS;
+ else if (strcmp(rate, "54") == 0)
+ BitMap |= WIFI_BITRATE_54MBPS;
+ rate = strtok(NULL, ",");
+ }
+ *basicRateBitMap = BitMap;
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+ return RETURN_OK;
+}
+
+// This API is used to configured all radio operation parameter in a single set. it includes channel number, channelWidth, mode and auto chammel configuration.
INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
{
- // The only par-radio parameter is a channel number, however there's a 'dynamic' API
- // to change it ("wifi_pushRadioChannel2()") that is used instead.
+ char buf[128] = {0};
+ char cmd[128] = {0};
+ char config_file[64] = {0};
+ int bandwidth;
+ int set_mode;
+ wifi_radio_operationParam_t current_param;
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+
+ multiple_set = TRUE;
+ if (wifi_getRadioOperatingParameters(index, ¤t_param) != RETURN_OK) {
+ fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
+ return RETURN_ERR;
+ }
+ if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
+ if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
+ fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
+ return RETURN_ERR;
+ }
+ }
+ if (current_param.channelWidth != operationParam->channelWidth || (current_param.channel != operationParam->channel && !operationParam->autoChannelEnabled)) {
+ if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
+ bandwidth = 20;
+ else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
+ bandwidth = 40;
+ else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
+ bandwidth = 80;
+ else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
+ bandwidth = 160;
+ if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
+ fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
+ return RETURN_ERR;
+ }
+ }
+ if (current_param.variant != operationParam->variant) {
+ // Two different definition bit map, so need to check every bit.
+ if (operationParam->variant & WIFI_80211_VARIANT_A)
+ set_mode |= WIFI_MODE_A;
+ if (operationParam->variant & WIFI_80211_VARIANT_B)
+ set_mode |= WIFI_MODE_B;
+ if (operationParam->variant & WIFI_80211_VARIANT_G)
+ set_mode |= WIFI_MODE_G;
+ if (operationParam->variant & WIFI_80211_VARIANT_N)
+ set_mode |= WIFI_MODE_N;
+ if (operationParam->variant & WIFI_80211_VARIANT_AC)
+ set_mode |= WIFI_MODE_AC;
+ if (operationParam->variant & WIFI_80211_VARIANT_AX)
+ set_mode |= WIFI_MODE_AX;
+ // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
+ memset(buf, 0, sizeof(buf));
+ if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
+ fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
+ return RETURN_ERR;
+ }
+ }
+ if (current_param.dtimPeriod != operationParam->dtimPeriod) {
+ if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
+ fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
+ return RETURN_ERR;
+ }
+ }
+ if (current_param.beaconInterval != operationParam->beaconInterval) {
+ if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
+ fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
+ return RETURN_ERR;
+ }
+ }
+ if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
+ BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
+ if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
+ fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
+ return RETURN_ERR;
+ }
+ }
+ if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
+ if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
+ fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
+ return RETURN_ERR;
+ }
+ }
+ if (current_param.guardInterval != operationParam->guardInterval) {
+ if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
+ fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
+ return RETURN_ERR;
+ }
+ }
+ if (current_param.transmitPower != operationParam->transmitPower) {
+ if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
+ fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
+ return RETURN_ERR;
+ }
+ }
+ if (current_param.rtsThreshold != operationParam->rtsThreshold) {
+ if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
+ fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
+ return RETURN_ERR;
+ }
+ }
+ if (current_param.obssCoex != operationParam->obssCoex) {
+ if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
+ fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
+ return RETURN_ERR;
+ }
+ }
+ if (current_param.stbcEnable != operationParam->stbcEnable) {
+ if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
+ fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
+ return RETURN_ERR;
+ }
+ }
+ if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
+ if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
+ fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
+ return RETURN_ERR;
+ }
+ }
+
+ // if enable is true, then restart the radio
+ wifi_setRadioEnable(index, FALSE);
+ if (operationParam->enable == TRUE)
+ wifi_setRadioEnable(index, TRUE);
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+
return RETURN_OK;
}
INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
{
- INT ret;
- char band[128];
- ULONG channel;
- BOOL enabled;
- char buf[256];
+ char band[64] = {0};
+ char buf[256] = {0};
+ char config_file[64] = {0};
+ char cmd[128] = {0};
+ int ret = RETURN_ERR;
+ int mode = 0;
+ ULONG channel = 0;
+ BOOL enabled = FALSE;
WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
printf("Entering %s index = %d\n", __func__, (int)index);
- ret = wifi_getRadioEnable(index, &enabled);
- if (ret != RETURN_OK)
+ memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
+ snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
+ if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
{
- printf("%s: cannot get enabled state for radio index %d\n", __func__,
- index);
+ fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
return RETURN_ERR;
}
operationParam->enable = enabled;
memset(band, 0, sizeof(band));
- ret = wifi_getRadioOperatingFrequencyBand(index, band);
- if (ret != RETURN_OK)
+ if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
{
- printf("%s: cannot get radio band for radio index %d\n", __func__, index);
+ fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
return RETURN_ERR;
}
if (!strcmp(band, "2.4GHz"))
- {
operationParam->band = WIFI_FREQUENCY_2_4_BAND;
- operationParam->variant = WIFI_80211_VARIANT_N;
- }
else if (!strcmp(band, "5GHz"))
- {
operationParam->band = WIFI_FREQUENCY_5_BAND;
- operationParam->variant = WIFI_80211_VARIANT_AC;
- }
+ else if (!strcmp(band, "6GHz"))
+ operationParam->band = WIFI_FREQUENCY_6_BAND;
else
{
- printf("%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
+ fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
band);
}
+ wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
+ if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
+ operationParam->channel = 0;
+ operationParam->autoChannelEnabled = TRUE;
+ } else {
+ operationParam->channel = strtol(buf, NULL, 10);
+ operationParam->autoChannelEnabled = FALSE;
+ }
+
memset(buf, 0, sizeof(buf));
- ret = wifi_getRadioOperatingChannelBandwidth(index, buf); // XXX: handle errors
- // XXX: only handle 20/40/80 modes for now
+ if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
+ fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
+ return RETURN_ERR;
+ }
if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
+ else if (!strcmp(buf, "160")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
+ else if (!strcmp(buf, "80+80")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80_80MHZ;
else
{
- printf("%s: Unknown HT mode: '%s'\n", __func__, buf);
- operationParam->channelWidth = 0;
+ fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
+ return false;
}
- ret = wifi_getRadioChannel(index, &channel);
- if (ret != RETURN_OK)
- {
- printf("%s: Failed to get channel number for radio index %d\n", __func__, index);
- channel = 0;
+ if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
+ fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
+ return RETURN_ERR;
}
- operationParam->channel = channel;
- operationParam->csa_beacon_count = 15; // XXX: hardcoded for now
+ // Two different definition bit map, so need to check every bit.
+ if (mode & WIFI_MODE_A)
+ operationParam->variant |= WIFI_80211_VARIANT_A;
+ if (mode & WIFI_MODE_B)
+ operationParam->variant |= WIFI_80211_VARIANT_B;
+ if (mode & WIFI_MODE_G)
+ operationParam->variant |= WIFI_80211_VARIANT_G;
+ if (mode & WIFI_MODE_N)
+ operationParam->variant |= WIFI_80211_VARIANT_N;
+ if (mode & WIFI_MODE_AC)
+ operationParam->variant |= WIFI_80211_VARIANT_AC;
+ if (mode & WIFI_MODE_AX)
+ operationParam->variant |= WIFI_80211_VARIANT_AX;
+ if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
+ fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
+ return RETURN_ERR;
+ }
+ if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
+ fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
+ return RETURN_ERR;
+ }
+ if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
+ fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
+ return RETURN_ERR;
+ }
- operationParam->countryCode = wifi_countrycode_US; // XXX: hardcoded for now
+ memset(buf, 0, sizeof(buf));
+ if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
+ fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
+ return RETURN_ERR;
+ }
+ TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
+
+ memset(buf, 0, sizeof(buf));
+ if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
+ fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
+ return RETURN_ERR;
+ }
+ TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
+
+ memset(buf, 0, sizeof(buf));
+ wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
+ operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
+
+ if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
+ fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
+ return RETURN_ERR;
+ }
+ if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
+ fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
+ return RETURN_ERR;
+ }
+
+ memset(buf, 0, sizeof(buf));
+ wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
+ if (strcmp(buf, "-1") == 0) {
+ operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
+ operationParam->ctsProtection = FALSE;
+ } else {
+ operationParam->rtsThreshold = strtoul(buf, NULL, 10);
+ operationParam->ctsProtection = TRUE;
+ }
+
+ memset(buf, 0, sizeof(buf));
+ wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
+ if (strcmp(buf, "0") == 0)
+ operationParam->obssCoex = FALSE;
+ else
+ operationParam->obssCoex = TRUE;
+
+ snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
+ _syscmd(cmd, buf, sizeof(buf));
+ if (strlen(buf) != 0)
+ operationParam->stbcEnable = TRUE;
+ else
+ operationParam->stbcEnable = FALSE;
+
+ if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
+ fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
+ return RETURN_ERR;
+ }
+
+ // Below value is hardcoded
+
+ operationParam->numSecondaryChannels = 0;
+ for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
+ operationParam->channelSecondary[i] = 0;
+ }
+ operationParam->csa_beacon_count = 15;
+ operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
return RETURN_OK;
@@ -9350,6 +11585,7 @@
wifi_channels_list_t *chlistp;
CHAR output_string[64];
CHAR pchannels[128];
+ wifi_band band;
if(rcap == NULL)
{
@@ -9357,11 +11593,14 @@
}
rcap->numSupportedFreqBand = 1;
- if (1 == radioIndex)
- rcap->band[0] = WIFI_FREQUENCY_5_BAND;
- else
- rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
+ band = wifi_index_to_band(radioIndex);
+ if (band == band_2_4)
+ rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
+ else if (band == band_5)
+ rcap->band[0] = WIFI_FREQUENCY_5_BAND;
+ else if (band == band_6)
+ rcap->band[0] = WIFI_FREQUENCY_6_BAND;
chlistp = &(rcap->channel_list[0]);
memset(pchannels, 0, sizeof(pchannels));
@@ -9420,7 +11659,7 @@
WIFI_CHANNELBANDWIDTH_40MHZ);
}
- else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND )) {
+ else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
WIFI_CHANNELBANDWIDTH_40MHZ |
WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
@@ -9430,10 +11669,13 @@
/* mode - all supported variants */
// rcap->mode[i] = WIFI_80211_VARIANT_H;
if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
- rcap->mode[i] = (WIFI_80211_VARIANT_N);
+ rcap->mode[i] = ( WIFI_80211_VARIANT_B | WIFI_80211_VARIANT_G | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AX );
}
else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
- rcap->mode[i] = ( WIFI_80211_VARIANT_AC );
+ rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
+ }
+ else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
+ rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
}
rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
@@ -9444,7 +11686,7 @@
rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
}
- else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND )) {
+ else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
@@ -9528,13 +11770,197 @@
INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
{
- //TODO
+ char buf[128] = {0};
+ char config_file[128] = {0};
+ char password[64] = {0};
+ char mfp[32] = {0};
+ char wpa_mode[32] = {0};
+ struct params params = {0};
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+
+ multiple_set = TRUE;
+ sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
+ if (security->mode == wifi_security_mode_none) {
+ strcpy(wpa_mode, "None");
+ } else if (security->mode == wifi_security_mode_wpa_personal)
+ strcpy(wpa_mode, "WPA-Personal");
+ else if (security->mode == wifi_security_mode_wpa2_personal)
+ strcpy(wpa_mode, "WPA2-Personal");
+ else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
+ strcpy(wpa_mode, "WPA-WPA2-Personal");
+ else if (security->mode == wifi_security_mode_wpa_enterprise)
+ strcpy(wpa_mode, "WPA-Enterprise");
+ else if (security->mode == wifi_security_mode_wpa2_enterprise)
+ strcpy(wpa_mode, "WPA2-Enterprise");
+ else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
+ strcpy(wpa_mode, "WPA-WPA2-Enterprise");
+ else if (security->mode == wifi_security_mode_wpa3_personal || security->mode == wifi_security_mode_wpa3_transition)
+ strcpy(wpa_mode, "WPA3-Personal");
+ else if (security->mode == wifi_security_mode_wpa3_enterprise)
+ strcpy(wpa_mode, "WPA3-Enterprise");
+
+ wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
+
+ strncpy(password, security->u.key.key, 63);
+ password[63] = '\0';
+ wifi_setApSecurityKeyPassphrase(ap_index, password);
+
+ if (security->mode != wifi_security_mode_none) {
+ memset(¶ms, 0, sizeof(params));
+ params.name = "wpa_pairwise";
+ if (security->encr == wifi_encryption_tkip)
+ params.value = "TKIP";
+ else if (security->encr == wifi_encryption_aes)
+ params.value = "CCMP";
+ else if (security->encr == wifi_encryption_aes_tkip)
+ params.value = "TKIP CCMP";
+ wifi_hostapdWrite(config_file, ¶ms, 1);
+ }
+
+ if (security->mfp == wifi_mfp_cfg_disabled)
+ strcpy(mfp, "Disable");
+ else if (security->mfp == wifi_mfp_cfg_optional)
+ strcpy(mfp, "Optional");
+ else if (security->mfp == wifi_mfp_cfg_required)
+ strcpy(mfp, "Required");
+ wifi_setApSecurityMFPConfig(ap_index, mfp);
+
+ memset(¶ms, 0, sizeof(params));
+ params.name = "transition_disable";
+ if (security->wpa3_transition_disable == TRUE)
+ params.value = "0x01";
+ else
+ params.value = "0x00";
+ wifi_hostapdWrite(config_file, ¶ms, 1);
+
+ memset(¶ms, 0, sizeof(params));
+ params.name = "wpa_group_rekey";
+ snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
+ params.value = buf;
+ wifi_hostapdWrite(config_file, ¶ms, 1);
+
+ memset(¶ms, 0, sizeof(params));
+ params.name = "wpa_strict_rekey";
+ params.value = security->strict_rekey?"1":"0";
+ wifi_hostapdWrite(config_file, ¶ms, 1);
+
+ memset(¶ms, 0, sizeof(params));
+ params.name = "wpa_pairwise_update_count";
+ snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
+ params.value = buf;
+ wifi_hostapdWrite(config_file, ¶ms, 1);
+
+ memset(¶ms, 0, sizeof(params));
+ params.name = "disable_pmksa_caching";
+ params.value = security->disable_pmksa_caching?"1":"0";
+ wifi_hostapdWrite(config_file, ¶ms, 1);
+
+ wifi_setApEnable(ap_index, FALSE);
+ wifi_setApEnable(ap_index, TRUE);
+
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+
return RETURN_OK;
}
INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
{
- //TODO
+ char buf[128] = {0};
+ char config_file[128] = {0};
+ int disable = 0;
+ // struct params params = {0};
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+ sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
+ wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
+ security->mode = wifi_security_mode_none;
+ if (strlen(buf) != 0) {
+ if (strcmp(buf, "WPA-Personal"))
+ security->mode = wifi_security_mode_wpa_personal;
+ else if (strcmp(buf, "WPA2-Personal"))
+ security->mode = wifi_security_mode_wpa2_personal;
+ else if (strcmp(buf, "WPA-WPA2-Personal"))
+ security->mode = wifi_security_mode_wpa_wpa2_personal;
+ else if (strcmp(buf, "WPA-Enterprise"))
+ security->mode = wifi_security_mode_wpa_enterprise;
+ else if (strcmp(buf, "WPA2-Enterprise"))
+ security->mode = wifi_security_mode_wpa2_enterprise;
+ else if (strcmp(buf, "WPA-WPA2-Enterprise"))
+ security->mode = wifi_security_mode_wpa_wpa2_enterprise;
+ else if (strcmp(buf, "WPA3-Personal"))
+ security->mode = wifi_security_mode_wpa3_personal;
+ else if (strcmp(buf, "WPA3-Transition"))
+ security->mode = wifi_security_mode_wpa3_transition;
+ else if (strcmp(buf, "WPA3-Enterprise"))
+ security->mode = wifi_security_mode_wpa3_enterprise;
+ }
+
+ wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
+ if (security->mode == wifi_security_mode_none)
+ security->encr = wifi_encryption_none;
+ else {
+ if (strcmp(buf, "TKIP") == 0)
+ security->encr = wifi_encryption_tkip;
+ else if (strcmp(buf, "CCMP") == 0)
+ security->encr = wifi_encryption_aes;
+ else
+ security->encr = wifi_encryption_aes_tkip;
+ }
+
+ memset(buf, 0, sizeof(buf));
+ wifi_getApSecurityMFPConfig(ap_index, buf);
+ if (strcmp(buf, "Disabled") == 0)
+ security->mfp = wifi_mfp_cfg_disabled;
+ else if (strcmp(buf, "Optional") == 0)
+ security->mfp = wifi_mfp_cfg_optional;
+ else if (strcmp(buf, "Required") == 0)
+ security->mfp = wifi_mfp_cfg_required;
+
+ memset(buf, 0, sizeof(buf));
+ security->wpa3_transition_disable = FALSE;
+ wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
+ disable = strtol(buf, NULL, 16);
+ if (disable != 0)
+ security->wpa3_transition_disable = TRUE;
+
+ memset(buf, 0, sizeof(buf));
+ wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
+ if (strlen(buf) == 0)
+ security->rekey_interval = 86400;
+ else
+ security->rekey_interval = strtol(buf, NULL, 10);
+
+ memset(buf, 0, sizeof(buf));
+ wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
+ if (strlen(buf) == 0)
+ security->strict_rekey = 1;
+ else
+ security->strict_rekey = strtol(buf, NULL, 10);
+
+ memset(buf, 0, sizeof(buf));
+ wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
+ if (strlen(buf) == 0)
+ security->eapol_key_retries = 4;
+ else
+ security->eapol_key_retries = strtol(buf, NULL, 10);
+
+ memset(buf, 0, sizeof(buf));
+ wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
+ if (strlen(buf) == 0)
+ security->disable_pmksa_caching = FALSE;
+ else
+ security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
+
+ /* TODO
+ eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
+ */
+ security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
+ security->eap_identity_req_timeout = 0;
+ security->eap_identity_req_retries = 0;
+ security->eap_req_timeout = 0;
+ security->eap_req_retries = 0;
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
return RETURN_OK;
}
@@ -9543,7 +11969,33 @@
#ifdef WIFI_HAL_VERSION_3_PHASE2
INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
{
- return RETURN_OK;
+ char cmd[128] = {0};
+ char buf[128] = {0};
+ char *mac_addr = NULL;
+ BOOL status = FALSE;
+ size_t len = 0;
+
+ if(ap_index > MAX_APS)
+ return RETURN_ERR;
+
+ *output_numDevices = 0;
+ wifi_getApEnable(ap_index, &status);
+ if (status == FALSE)
+ return RETURN_OK;
+
+ sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, ap_index);
+ _syscmd(cmd, buf, sizeof(buf));
+
+ mac_addr = strtok(buf, "\n");
+ for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
+ *output_numDevices = i + 1;
+ fprintf(stderr, "mac_addr: %s\n", mac_addr);
+ addr_ptr = output_deviceMacAddressArray[i];
+ mac_addr_aton(addr_ptr, mac_addr);
+ mac_addr = strtok(NULL, "\n");
+ }
+
+ return RETURN_OK;
}
#else
INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
@@ -9566,3 +12018,113 @@
return RETURN_OK;
}
#endif
+
+INT wifi_getProxyArp(INT apIndex, BOOL *enable)
+{
+ char output[16]={'\0'};
+ char config_file[MAX_BUF_SIZE] = {0};
+
+ if (!enable)
+ return RETURN_ERR;
+
+ sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
+ wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
+
+ if (strlen(output) == 0)
+ *enable = FALSE;
+ else if (strncmp(output, "1", 1) == 0)
+ *enable = TRUE;
+ else
+ *enable = FALSE;
+
+ wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
+ return RETURN_OK;
+}
+
+INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
+{
+ if (NULL == output_enable || !(radioIndex==0 || radioIndex==1))
+ return RETURN_ERR;
+ *output_enable=TRUE;
+ return RETURN_OK;
+}
+
+INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
+{
+ char cmd[128] = {0};
+ char buf[128] = {0};
+ char line[128] = {0};
+ size_t len = 0;
+ ssize_t read = 0;
+ FILE *f = NULL;
+ int index = 0;
+ int exp = 0;
+ int mantissa = 0;
+ int duration = 0;
+ int radio_index = 0;
+ int max_radio_num = 0;
+ uint twt_wake_interval = 0;
+
+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
+
+ wifi_getMaxRadioNumber(&max_radio_num);
+ radio_index = ap_index % max_radio_num;
+ sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", radio_index);
+ _syscmd(cmd, buf, sizeof(buf));
+ *numSessionReturned = strtol(buf, NULL, 10) - 1;
+ if (*numSessionReturned > maxNumberSessions)
+ *numSessionReturned = maxNumberSessions;
+ else if (*numSessionReturned < 1) {
+ *numSessionReturned = 0;
+ return RETURN_OK;
+ }
+
+ sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | tail -n %d | tr '|' ' ' | tr -s ' '", radio_index, *numSessionReturned);
+ if ((f = popen(cmd, "r")) == NULL) {
+ wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
+ return RETURN_ERR;
+ }
+
+ // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
+ while((read = fgets(line, sizeof(line), f)) != NULL) {
+ char *tmp = NULL;
+ strcpy(buf, line);
+ tmp = strtok(buf, " ");
+ twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
+ tmp = strtok(NULL, " ");
+ twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
+ tmp = strtok(NULL, " ");
+ if (strstr(tmp, "t")) {
+ twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
+ }
+ if (strstr(tmp, "a")) {
+ twtSessions[index].twtParameters.operation.announced = TRUE;
+ }
+ tmp = strtok(NULL, " ");
+ exp = strtol(tmp, NULL, 10);
+ tmp = strtok(NULL, " ");
+ mantissa = strtol(tmp, NULL, 10);
+ tmp = strtok(NULL, " ");
+ duration = strtol(tmp, NULL, 10);
+
+ // only implicit supported
+ twtSessions[index].twtParameters.operation.implicit = TRUE;
+ // only individual agreement supported
+ twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
+
+ // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
+ twt_wake_interval = mantissa * (1 << exp);
+ if (twt_wake_interval/mantissa != (1 << exp)) {
+ // Overflow handling
+ twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
+ } else {
+ twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
+ }
+ twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
+ index++;
+ }
+
+ pclose(f);
+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
+ return RETURN_OK;
+}