blob: 05419c934aef6b33e2fc8e76b61a638240a7b462 [file] [log] [blame]
developer72fb0bb2023-01-11 09:46:29 +08001/*
2 * If not stated otherwise in this file or this component's LICENSE file the
3 * following copyright and licenses apply:
4 *
5 * Copyright 2019 RDK Management
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18*/
19
20/*
21* Material from the TR181 data model is Copyright (c) 2010-2017, Broadband Forum
22* Licensed under the BSD-3 license
23*/
24
25/*
26* This file includes material that is Copyright (c) 2020, Plume Design Inc.
27* Licensed under the BSD-3 license
28*/
29
30/* Code in rxStatsInfo_callback and other callbacks is credited as follows:
31Copyright (c) 2007, 2008 Johannes Berg
32Copyright (c) 2007 Andy Lutomirski
33Copyright (c) 2007 Mike Kershaw
34Copyright (c) 2008-2009 Luis R. Rodriguez
35Licensed under the ISC license
36*/
37#define MTK_IMPL
38#define HAL_NETLINK_IMPL
39#define _GNU_SOURCE /* needed for strcasestr */
40
41#include <stdio.h>
42#include <stdlib.h>
43#include <unistd.h>
44#include <string.h>
45#include <fcntl.h>
46#include <stdbool.h>
47#include "wifi_hal.h"
48
49#ifdef HAL_NETLINK_IMPL
50#include <errno.h>
51#include <netlink/attr.h>
52#include <netlink/netlink.h>
53#include <netlink/genl/genl.h>
54#include <netlink/genl/family.h>
55#include <netlink/genl/ctrl.h>
56#include <linux/nl80211.h>
57#include<net/if.h>
58#endif
59
60#include <ev.h>
61#include <wpa_ctrl.h>
62#include <errno.h>
63#include <time.h>
64#define MAC_ALEN 6
65
66#define MAX_BUF_SIZE 256
67#define MAX_CMD_SIZE 256
68#define IF_NAME_SIZE 16
69#define CONFIG_PREFIX "/nvram/hostapd"
70#define ACL_PREFIX "/nvram/hostapd-acl"
71#define DENY_PREFIX "/nvram/hostapd-deny"
72//#define ACL_PREFIX "/tmp/wifi_acl_list" //RDKB convention
73#define SOCK_PREFIX "/var/run/hostapd/wifi"
74#define VAP_STATUS_FILE "/nvram/vap-status"
75#define ESSID_FILE "/tmp/essid"
76#define GUARD_INTERVAL_FILE "/nvram/guard-interval"
77#define CHANNEL_STATS_FILE "/tmp/channel_stats"
78#define DFS_ENABLE_FILE "/nvram/dfs_enable.txt"
79#define VLAN_FILE "/nvram/hostapd.vlan"
80#define PSK_FILE "/nvram/hostapd"
81#define MCS_FILE "/tmp/MCS"
developera1255e42023-05-13 17:45:02 +080082#define POWER_PERCENTAGE "/tmp/POWER"
83#define MGMT_POWER_CTRL "/tmp/mgmt_power_ctrl"
84/*LOGAN_DAT_FILE: may be different on customer's platform.*/
85#define LOGAN_DAT_FILE "/etc/wireless/mediatek/mt7990.b"
86
developer72fb0bb2023-01-11 09:46:29 +080087#define NOACK_MAP_FILE "/tmp/NoAckMap"
developerf6a87542023-05-16 15:47:28 +080088
developer72fb0bb2023-01-11 09:46:29 +080089#define BRIDGE_NAME "brlan0"
90
91/*
92 MAX_APS - Number of all AP available in system
93 2x Home AP
94 2x Backhaul AP
95 2x Guest AP
96 2x Secure Onboard AP
97 2x Service AP
98
99*/
100
101
102#define MAX_APS MAX_NUM_RADIOS*5
developer7e4a2a62023-04-06 19:56:03 +0800103
104#define PREFIX_WIFI2G "ra"
105#define PREFIX_WIFI5G "rai"
106#define PREFIX_WIFI6G "rax"
developer72fb0bb2023-01-11 09:46:29 +0800107
108#ifndef RADIO_PREFIX
109#define RADIO_PREFIX "wlan"
110#endif
111
112#define MAX_ASSOCIATED_STA_NUM 2007
113
114//Uncomment to enable debug logs
115//#define WIFI_DEBUG
116
117#ifdef WIFI_DEBUG
118#define wifi_dbg_printf printf
119#define WIFI_ENTRY_EXIT_DEBUG printf
120#else
121#define wifi_dbg_printf(format, args...) printf("")
122#define WIFI_ENTRY_EXIT_DEBUG(format, args...) printf("")
123#endif
124
125#define HOSTAPD_CONF_0 "/nvram/hostapd0.conf" //private-wifi-2g
126#define HOSTAPD_CONF_1 "/nvram/hostapd1.conf" //private-wifi-5g
127#define HOSTAPD_CONF_4 "/nvram/hostapd4.conf" //public-wifi-2g
128#define HOSTAPD_CONF_5 "/nvram/hostapd5.conf" //public-wifi-5g
129#define DEF_HOSTAPD_CONF_0 "/usr/ccsp/wifi/hostapd0.conf"
130#define DEF_HOSTAPD_CONF_1 "/usr/ccsp/wifi/hostapd1.conf"
131#define DEF_HOSTAPD_CONF_4 "/usr/ccsp/wifi/hostapd4.conf"
132#define DEF_HOSTAPD_CONF_5 "/usr/ccsp/wifi/hostapd5.conf"
133#define DEF_RADIO_PARAM_CONF "/usr/ccsp/wifi/radio_param_def.cfg"
134#define LM_DHCP_CLIENT_FORMAT "%63d %17s %63s %63s"
135
136#define HOSTAPD_HT_CAPAB "[LDPC][SHORT-GI-20][SHORT-GI-40][MAX-AMSDU-7935]"
137
138#define BW_FNAME "/nvram/bw_file.txt"
139
140#define PS_MAX_TID 16
141
developer96b38512023-02-22 11:17:45 +0800142#define MAX_CARD_INDEX 3
143
developer72fb0bb2023-01-11 09:46:29 +0800144static wifi_radioQueueType_t _tid_ac_index_get[PS_MAX_TID] = {
145 WIFI_RADIO_QUEUE_TYPE_BE, /* 0 */
146 WIFI_RADIO_QUEUE_TYPE_BK, /* 1 */
147 WIFI_RADIO_QUEUE_TYPE_BK, /* 2 */
148 WIFI_RADIO_QUEUE_TYPE_BE, /* 3 */
149 WIFI_RADIO_QUEUE_TYPE_VI, /* 4 */
150 WIFI_RADIO_QUEUE_TYPE_VI, /* 5 */
151 WIFI_RADIO_QUEUE_TYPE_VO, /* 6 */
152 WIFI_RADIO_QUEUE_TYPE_VO, /* 7 */
153 WIFI_RADIO_QUEUE_TYPE_BE, /* 8 */
154 WIFI_RADIO_QUEUE_TYPE_BK, /* 9 */
155 WIFI_RADIO_QUEUE_TYPE_BK, /* 10 */
156 WIFI_RADIO_QUEUE_TYPE_BE, /* 11 */
157 WIFI_RADIO_QUEUE_TYPE_VI, /* 12 */
158 WIFI_RADIO_QUEUE_TYPE_VI, /* 13 */
159 WIFI_RADIO_QUEUE_TYPE_VO, /* 14 */
160 WIFI_RADIO_QUEUE_TYPE_VO, /* 15 */
161};
162
163typedef unsigned long long u64;
164
165/* Enum to define WiFi Bands */
166typedef enum
167{
168 band_invalid = -1,
169 band_2_4 = 0,
170 band_5 = 1,
171 band_6 = 2,
172} wifi_band;
173
developer17038e62023-03-02 14:43:43 +0800174char* wifi_band_str[] = {
175 "2G",
176 "5G",
177 "6G",
178};
179
developer72fb0bb2023-01-11 09:46:29 +0800180typedef enum {
181 WIFI_MODE_A = 0x01,
182 WIFI_MODE_B = 0x02,
183 WIFI_MODE_G = 0x04,
184 WIFI_MODE_N = 0x08,
185 WIFI_MODE_AC = 0x10,
186 WIFI_MODE_AX = 0x20,
developera1255e42023-05-13 17:45:02 +0800187 WIFI_MODE_BE = 0x40,
developer72fb0bb2023-01-11 09:46:29 +0800188} wifi_ieee80211_Mode;
189
190#ifdef WIFI_HAL_VERSION_3
191
192// Return number of elements in array
193#ifndef ARRAY_SIZE
194#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
195#endif /* ARRAY_SIZE */
196
197#ifndef ARRAY_AND_SIZE
198#define ARRAY_AND_SIZE(x) (x),ARRAY_SIZE(x)
199#endif /* ARRAY_AND_SIZE */
200
201#define WIFI_ITEM_STR(key, str) {0, sizeof(str)-1, (int)key, (intptr_t)str}
202
203typedef struct {
204 int32_t value;
205 int32_t param;
206 intptr_t key;
207 intptr_t data;
208} wifi_secur_list;
209
210static int util_unii_5g_centerfreq(const char *ht_mode, int channel);
211static int util_unii_6g_centerfreq(const char *ht_mode, int channel);
212wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key);
213wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str);
214char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key);
215static int ieee80211_channel_to_frequency(int channel, int *freqMHz);
216
217static wifi_secur_list map_security[] =
218{
219 WIFI_ITEM_STR(wifi_security_mode_none, "None"),
220 WIFI_ITEM_STR(wifi_security_mode_wep_64, "WEP-64"),
221 WIFI_ITEM_STR(wifi_security_mode_wep_128, "WEP-128"),
222 WIFI_ITEM_STR(wifi_security_mode_wpa_personal, "WPA-Personal"),
223 WIFI_ITEM_STR(wifi_security_mode_wpa_enterprise, "WPA-Enterprise"),
224 WIFI_ITEM_STR(wifi_security_mode_wpa2_personal, "WPA2-Personal"),
225 WIFI_ITEM_STR(wifi_security_mode_wpa2_enterprise, "WPA2-Enterprise"),
226 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_personal, "WPA-WPA2-Personal"),
227 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_enterprise, "WPA-WPA2-Enterprise"),
228 WIFI_ITEM_STR(wifi_security_mode_wpa3_personal, "WPA3-Personal"),
229 WIFI_ITEM_STR(wifi_security_mode_wpa3_transition, "WPA3-Personal-Transition"),
230 WIFI_ITEM_STR(wifi_security_mode_wpa3_enterprise, "WPA3-Enterprise")
231};
232
233wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key)
234{
235 wifi_secur_list *item;
236 int i;
237
238 for (item = list,i = 0;i < list_sz; item++, i++) {
239 if ((int)(item->key) == key) {
240 return item;
241 }
242 }
243
244 return NULL;
245}
246
247char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key)
248{
249 wifi_secur_list *item = wifi_get_item_by_key(list, list_sz, key);
250
251 if (!item) {
252 return "";
253 }
254
255 return (char *)(item->data);
256}
257
258wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str)
259{
260 wifi_secur_list *item;
261 int i;
262
263 for (item = list,i = 0;i < list_sz; item++, i++) {
264 if (strcmp((char *)(item->data), str) == 0) {
265 return item;
266 }
267 }
268
269 return NULL;
270}
271#endif /* WIFI_HAL_VERSION_3 */
272
developer96b38512023-02-22 11:17:45 +0800273
274static char l1profile[32] = "/etc/wireless/l1profile.dat";
developer17038e62023-03-02 14:43:43 +0800275char main_prefix[MAX_NUM_RADIOS][IFNAMSIZ];
276char ext_prefix[MAX_NUM_RADIOS][IFNAMSIZ];
277#define MAX_SSID_LEN 64
278char default_ssid[MAX_NUM_RADIOS][MAX_SSID_LEN];;
developer745f0bd2023-03-06 14:32:53 +0800279int radio_band[MAX_NUM_RADIOS];
developer17038e62023-03-02 14:43:43 +0800280
281static int array_index_to_vap_index(UINT radioIndex, int arrayIndex);
282static int vap_index_to_array_index(int vapIndex, int *radioIndex, int *arrayIndex);
283
developer96b38512023-02-22 11:17:45 +0800284
285static int
286get_value(const char *conf_file, const char *param, char *value, int len)
287{
288 FILE *fp;
289 int ret = -1;
290 int param_len = strlen(param);
291 int buf_len;
292 char buf[256];
293
294 fp = fopen(conf_file, "r");
295 if (!fp) {
296 return -1;
297 }
298
299 while (fgets(buf, sizeof(buf), fp)) {
300 buf_len = strlen(buf);
301 if (buf[buf_len - 1] == '\n') {
302 buf_len--;
303 buf[buf_len] = '\0';
304 }
305 if ((buf_len > param_len) &&
306 (strncmp(buf, param, param_len) == 0) &&
307 (buf[param_len] == '=')) {
308
309 if (buf_len == (param_len + 1)) {
310 value[0] = '\0';
311 ret = 0;
312 } else {
313 ret = snprintf(value, len, "%s", buf + (param_len + 1));
314 }
315 fclose(fp);
316 return ret;
317 }
318 }
319 fclose(fp);
320 return -1;
321}
322
323static int
324get_value_by_idx(const char *conf_file, const char *param, int idx, char *value, int len)
325{
326 char buf[256];
327 int ret;
328 char *save_ptr = NULL;
329 char *tok = NULL;
330
331 ret = get_value(conf_file, param, buf, sizeof(buf));
332 if (ret < 0)
333 return ret;
334
335 tok = strtok_r(buf, ";", &save_ptr);
336 do {
337 if (idx == 0 || tok == NULL)
338 break;
339 else
340 idx--;
341
342 tok = strtok_r(NULL, ";", &save_ptr);
343 } while (tok != NULL);
344
345 if (tok) {
346 ret = snprintf(value, len, "%s", tok);
347 } else {
348 ret = 0;
349 value[0] = '\0';
350 }
351
352 return ret;
353}
354
355
developer72fb0bb2023-01-11 09:46:29 +0800356#ifdef HAL_NETLINK_IMPL
357typedef struct {
358 int id;
359 struct nl_sock* socket;
360 struct nl_cb* cb;
361} Netlink;
362
363static int mac_addr_aton(unsigned char *mac_addr, char *arg)
364{
365 unsigned int mac_addr_int[6]={};
366 sscanf(arg, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", mac_addr_int+0, mac_addr_int+1, mac_addr_int+2, mac_addr_int+3, mac_addr_int+4, mac_addr_int+5);
367 mac_addr[0] = mac_addr_int[0];
368 mac_addr[1] = mac_addr_int[1];
369 mac_addr[2] = mac_addr_int[2];
370 mac_addr[3] = mac_addr_int[3];
371 mac_addr[4] = mac_addr_int[4];
372 mac_addr[5] = mac_addr_int[5];
373 return 0;
374}
375
376static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
377{
378 unsigned int mac_addr_int[6]={};
379 mac_addr_int[0] = arg[0];
380 mac_addr_int[1] = arg[1];
381 mac_addr_int[2] = arg[2];
382 mac_addr_int[3] = arg[3];
383 mac_addr_int[4] = arg[4];
384 mac_addr_int[5] = arg[5];
385 snprintf(mac_addr, 20, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", mac_addr_int[0], mac_addr_int[1],mac_addr_int[2],mac_addr_int[3],mac_addr_int[4],mac_addr_int[5]);
386 return;
387}
388
389static int ieee80211_frequency_to_channel(int freq)
390{
391 /* see 802.11-2007 17.3.8.3.2 and Annex J */
392 if (freq == 2484)
393 return 14;
394 /* see 802.11ax D6.1 27.3.23.2 and Annex E */
395 else if (freq == 5935)
396 return 2;
397 else if (freq < 2484)
398 return (freq - 2407) / 5;
399 else if (freq >= 4910 && freq <= 4980)
400 return (freq - 4000) / 5;
401 else if (freq < 5950)
402 return (freq - 5000) / 5;
403 else if (freq <= 45000) /* DMG band lower limit */
404 /* see 802.11ax D6.1 27.3.23.2 */
405 return (freq - 5950) / 5;
406 else if (freq >= 58320 && freq <= 70200)
407 return (freq - 56160) / 2160;
408 else
409 return 0;
410}
411
412static int initSock80211(Netlink* nl) {
413 nl->socket = nl_socket_alloc();
414 if (!nl->socket) {
415 fprintf(stderr, "Failing to allocate the sock\n");
416 return -ENOMEM;
417 }
418
419 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
420
421 if (genl_connect(nl->socket)) {
422 fprintf(stderr, "Failed to connect\n");
423 nl_close(nl->socket);
424 nl_socket_free(nl->socket);
425 return -ENOLINK;
426 }
427
428 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
429 if (nl->id< 0) {
430 fprintf(stderr, "interface not found.\n");
431 nl_close(nl->socket);
432 nl_socket_free(nl->socket);
433 return -ENOENT;
434 }
435
436 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
437 if ((!nl->cb)) {
438 fprintf(stderr, "Failed to allocate netlink callback.\n");
439 nl_close(nl->socket);
440 nl_socket_free(nl->socket);
441 return ENOMEM;
442 }
443
444 return nl->id;
445}
446
447static int nlfree(Netlink *nl)
448{
449 nl_cb_put(nl->cb);
450 nl_close(nl->socket);
451 nl_socket_free(nl->socket);
452 return 0;
453}
454
455static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
456 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
457 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
458 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
459};
460
461static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
462};
463
464static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
465};
466
467typedef struct _wifi_channelStats_loc {
468 INT array_size;
469 INT ch_number;
470 BOOL ch_in_pool;
471 INT ch_noise;
472 BOOL ch_radar_noise;
473 INT ch_max_80211_rssi;
474 INT ch_non_80211_noise;
475 INT ch_utilization;
476 ULLONG ch_utilization_total;
477 ULLONG ch_utilization_busy;
478 ULLONG ch_utilization_busy_tx;
479 ULLONG ch_utilization_busy_rx;
480 ULLONG ch_utilization_busy_self;
481 ULLONG ch_utilization_busy_ext;
482} wifi_channelStats_t_loc;
483
484typedef struct wifi_device_info {
485 INT wifi_devIndex;
486 UCHAR wifi_devMacAddress[6];
487 CHAR wifi_devIPAddress[64];
488 BOOL wifi_devAssociatedDeviceAuthentiationState;
489 INT wifi_devSignalStrength;
490 INT wifi_devTxRate;
491 INT wifi_devRxRate;
492} wifi_device_info_t;
493
494#endif
495
496//For 5g Alias Interfaces
497static BOOL priv_flag = TRUE;
498static BOOL pub_flag = TRUE;
499static BOOL Radio_flag = TRUE;
500//wifi_setApBeaconRate(1, beaconRate);
501
502BOOL multiple_set = FALSE;
503
504struct params
505{
506 char * name;
507 char * value;
508};
509
510static int _syscmd(char *cmd, char *retBuf, int retBufSize)
511{
512 FILE *f;
513 char *ptr = retBuf;
514 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
515
516 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
517 if((f = popen(cmd, "r")) == NULL) {
518 fprintf(stderr,"\npopen %s error\n", cmd);
519 return RETURN_ERR;
520 }
521
522 while(!feof(f))
523 {
524 *ptr = 0;
525 if(bufSize>=128) {
526 bufbytes=128;
527 } else {
528 bufbytes=bufSize-1;
529 }
530
531 fgets(ptr,bufbytes,f);
532 readbytes=strlen(ptr);
533
534 if(!readbytes)
535 break;
536
537 bufSize-=readbytes;
538 ptr += readbytes;
539 }
540 cmd_ret = pclose(f);
541 retBuf[retBufSize-1]=0;
542 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
543
544 return cmd_ret >> 8;
545}
546
547INT radio_index_to_phy(int radioIndex)
548{
developer17038e62023-03-02 14:43:43 +0800549 /* TODO */
550 return radioIndex;
developer72fb0bb2023-01-11 09:46:29 +0800551}
552
553INT wifi_getMaxRadioNumber(INT *max_radio_num)
554{
555 char cmd[64] = {0};
556 char buf[4] = {0};
557
558 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
559
560 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
561 _syscmd(cmd, buf, sizeof(buf));
562 *max_radio_num = strtoul(buf, NULL, 10) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS:strtoul(buf, NULL, 10);
563
564 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
565
566 return RETURN_OK;
567}
568
developer17038e62023-03-02 14:43:43 +0800569wifi_band radio_index_to_band(int radioIndex)
570{
developer745f0bd2023-03-06 14:32:53 +0800571 return radio_band[radioIndex];
developer17038e62023-03-02 14:43:43 +0800572}
573
developer72fb0bb2023-01-11 09:46:29 +0800574wifi_band wifi_index_to_band(int apIndex)
575{
576 char cmd[128] = {0};
577 char buf[64] = {0};
578 int nl80211_band = 0;
579 int i = 0;
580 int phyIndex = 0;
581 int radioIndex = 0;
582 int max_radio_num = 0;
583 wifi_band band = band_invalid;
584
585 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
586
587 wifi_getMaxRadioNumber(&max_radio_num);
588 radioIndex = apIndex % max_radio_num;
589 phyIndex = radio_index_to_phy(radioIndex);
590 while(i < 10){
591 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Band .:' | tail -n 1 | tr -d ':\\n' | awk '{print $2}'", phyIndex);
592 _syscmd(cmd, buf, sizeof(buf));
593 nl80211_band = strtol(buf, NULL, 10);
594 if (nl80211_band == 1)
595 band = band_2_4;
596 else if (nl80211_band == 2)
597 band = band_5;
598 else if (nl80211_band == 4) // band == 3 is 60GHz
599 band = band_6;
600
601 if(band != band_invalid)
602 break;
developer69b61b02023-03-07 17:17:44 +0800603
developer72fb0bb2023-01-11 09:46:29 +0800604 i++;
605 sleep(1);
606 }
607
608 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
609 return band;
610}
611
612static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
613{
developer7e4a2a62023-04-06 19:56:03 +0800614 char cmd[MAX_CMD_SIZE] = {0};
615 char buf[MAX_BUF_SIZE] = {0};
616 int ret = 0;
developer72fb0bb2023-01-11 09:46:29 +0800617
developer7e4a2a62023-04-06 19:56:03 +0800618 ret = snprintf(cmd, MAX_CMD_SIZE, "cat %s 2> /dev/null | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"",
619 conf_file, param);
developer72fb0bb2023-01-11 09:46:29 +0800620
developer7e4a2a62023-04-06 19:56:03 +0800621 if (ret < 0) {
622 printf("%s: snprintf error!", __func__);
623 return -1;
624 }
625
626 ret = _syscmd(cmd, buf, sizeof(buf));
627 if ((ret != 0) && (strlen(buf) == 0)) {
628 printf("%s: _syscmd error!", __func__);
629 return -1;
630 }
631
632 snprintf(output, output_size, "%s", buf);
633
634 return 0;
developer72fb0bb2023-01-11 09:46:29 +0800635}
636
637static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
638{
developer7e4a2a62023-04-06 19:56:03 +0800639 char cmd[MAX_CMD_SIZE] = {0};
640 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +0800641
developer7e4a2a62023-04-06 19:56:03 +0800642 for (int i = 0; i < item_count; i++) {
developer72fb0bb2023-01-11 09:46:29 +0800643 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
developer7e4a2a62023-04-06 19:56:03 +0800644 if (strlen(buf) == 0) /*no such item, insert it*/
developera1255e42023-05-13 17:45:02 +0800645 snprintf(cmd, sizeof(cmd), "sed -i -e '$a %s=%s' %s", list[i].name, list[i].value, conf_file);
developer7e4a2a62023-04-06 19:56:03 +0800646 else /*find the item, update it*/
developer72fb0bb2023-01-11 09:46:29 +0800647 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=%s/\" %s", list[i].name, list[i].name, list[i].value, conf_file);
developera1255e42023-05-13 17:45:02 +0800648
developer72fb0bb2023-01-11 09:46:29 +0800649 if(_syscmd(cmd, buf, sizeof(buf)))
650 return -1;
651 }
652
developera1255e42023-05-13 17:45:02 +0800653 return 0;
654}
655static int wifi_datfileRead(char *conf_file, char *param, char *output, int output_size)
656{
657 char cmd[MAX_CMD_SIZE] = {0};
658 char buf[MAX_BUF_SIZE] = {0};
659 int ret = 0;
660
661 ret = snprintf(cmd, MAX_CMD_SIZE, "cat %s 2> /dev/null | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"",
662 conf_file, param);
663
664 if (ret < 0) {
665 printf("%s: snprintf error!", __func__);
666 return -1;
667 }
668
669 ret = _syscmd(cmd, buf, sizeof(buf));
670 if ((ret != 0) && (strlen(buf) == 0)) {
671 printf("%s: _syscmd error!", __func__);
672 return -1;
673 }
674
675 snprintf(output, output_size, "%s", buf);
676
developer72fb0bb2023-01-11 09:46:29 +0800677 return 0;
678}
679
developera1255e42023-05-13 17:45:02 +0800680static int wifi_datfileWrite(char *conf_file, struct params *list, int item_count)
681{
682 char cmd[MAX_CMD_SIZE] = {0};
683 char buf[MAX_BUF_SIZE] = {0};
684
685 for (int i = 0; i < item_count; i++) {
686 wifi_datfileRead(conf_file, list[i].name, buf, sizeof(buf));
687 if (strlen(buf) == 0) /*no such item, insert it*/
688 snprintf(cmd, sizeof(cmd), "sed -i -e '$a %s=%s' %s", list[i].name, list[i].value, conf_file);
689 else /*find the item, update it*/
690 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=%s/\" %s", list[i].name, list[i].name, list[i].value, conf_file);
691
692 if(_syscmd(cmd, buf, sizeof(buf)))
693 return -1;
694 }
695
696 return 0;
697}
698
developer72fb0bb2023-01-11 09:46:29 +0800699//For Getting Current Interface Name from corresponding hostapd configuration
700static int wifi_GetInterfaceName(int apIndex, char *interface_name)
701{
702 char config_file[128] = {0};
703
704 if (interface_name == NULL)
705 return RETURN_ERR;
706
707 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
708
709 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
710 wifi_hostapdRead(config_file, "interface", interface_name, 16);
711 if (strlen(interface_name) == 0)
712 return RETURN_ERR;
713
714 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
715 return RETURN_OK;
716}
717
developera1255e42023-05-13 17:45:02 +0800718static UCHAR get_bssnum_byindex(INT radio_index, UCHAR *bss_cnt)
719{
720 char interface_name[IF_NAME_SIZE] = {0};
721 char cmd[MAX_BUF_SIZE]={'\0'};
722 char buf[MAX_CMD_SIZE]={'\0'};
723 UCHAR channel = 0;
724
725 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
726 return RETURN_ERR;
727 /*interface name to channel number*/
728 snprintf(cmd, sizeof(cmd), "iw dev %s info | grep -i 'channel' | cut -d ' ' -f2", interface_name);
729 _syscmd(cmd, buf, sizeof(buf));
730 channel = atoi(buf);
731 WIFI_ENTRY_EXIT_DEBUG("%s:channel=%d\n", __func__, channel);
732 /*count dev number with the same channel*/
733 snprintf(cmd, sizeof(cmd), "iw dev | grep -i 'channel %d' | wc -l", channel);
734 _syscmd(cmd, buf, sizeof(buf));
735 *bss_cnt = atoi(buf) - 1;/*1 for apcli interface*/
736 WIFI_ENTRY_EXIT_DEBUG("%s:bss_cnt=%d\n", __func__, *bss_cnt);
737 return RETURN_OK;
738}
developer72fb0bb2023-01-11 09:46:29 +0800739
740static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
741{
742 char interface_name[16] = {0};
743 if (multiple_set == TRUE)
744 return RETURN_OK;
745 char cmd[MAX_CMD_SIZE]="", output[32]="";
746 FILE *fp;
747 int i;
748 //NOTE RELOAD should be done in ApplySSIDSettings
749 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
750 return RETURN_ERR;
751 for(i=0; i<item_count; i++, list++)
752 {
developerf6a87542023-05-16 15:47:28 +0800753 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s SET %s %s", interface_name, list->name, list->value);
developer72fb0bb2023-01-11 09:46:29 +0800754 if((fp = popen(cmd, "r"))==NULL)
755 {
756 perror("popen failed");
757 return -1;
758 }
759 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
760 {
761 pclose(fp);
762 perror("fgets failed");
763 return -1;
764 }
765 pclose(fp);
766 }
767 return 0;
768}
769
developer7e4a2a62023-04-06 19:56:03 +0800770static int wifi_quick_reload_ap(int apIndex)
771{
772 char interface_name[IF_NAME_SIZE] = {0};
773 char cmd[MAX_CMD_SIZE] = {0};
774 char buf[MAX_BUF_SIZE] = {0};
775
776 if (multiple_set == TRUE)
777 return RETURN_OK;
778
779 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
780 return RETURN_ERR;
781
782 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s reload", interface_name);
783 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
784 return RETURN_ERR;
785
786 return RETURN_OK;
787}
788
developer72fb0bb2023-01-11 09:46:29 +0800789static int wifi_reloadAp(int apIndex)
790{
791 char interface_name[16] = {0};
792 if (multiple_set == TRUE)
793 return RETURN_OK;
794 char cmd[MAX_CMD_SIZE]="";
795 char buf[MAX_BUF_SIZE]="";
796
797 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
798 return RETURN_ERR;
799 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s reload", interface_name);
800 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
801 return RETURN_ERR;
802
803 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s disable", interface_name);
804 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
805 return RETURN_ERR;
806
807 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s enable", interface_name);
808 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
809 return RETURN_ERR;
810
811 return RETURN_OK;
812}
813
814INT File_Reading(CHAR *file, char *Value)
815{
816 FILE *fp = NULL;
817 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
818 int count = 0;
819
820 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
821 fp = popen(file,"r");
822 if(fp == NULL)
823 return RETURN_ERR;
824
825 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
826 {
827 for(count=0;buf[count]!='\n';count++)
828 copy_buf[count]=buf[count];
829 copy_buf[count]='\0';
830 }
831 strcpy(Value,copy_buf);
832 pclose(fp);
833 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
834
835 return RETURN_OK;
836}
837
838void wifi_RestartHostapd_2G()
839{
840 int Public2GApIndex = 4;
841
842 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
843 wifi_setApEnable(Public2GApIndex, FALSE);
844 wifi_setApEnable(Public2GApIndex, TRUE);
845 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
846}
847
848void wifi_RestartHostapd_5G()
849{
850 int Public5GApIndex = 5;
851
852 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
853 wifi_setApEnable(Public5GApIndex, FALSE);
854 wifi_setApEnable(Public5GApIndex, TRUE);
855 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
856}
857
858void wifi_RestartPrivateWifi_2G()
859{
860 int PrivateApIndex = 0;
861
862 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
863 wifi_setApEnable(PrivateApIndex, FALSE);
864 wifi_setApEnable(PrivateApIndex, TRUE);
865 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
866}
867
868void wifi_RestartPrivateWifi_5G()
869{
870 int Private5GApIndex = 1;
871
872 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
873 wifi_setApEnable(Private5GApIndex, FALSE);
874 wifi_setApEnable(Private5GApIndex, TRUE);
875 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
876}
877
878static int writeBandWidth(int radioIndex,char *bw_value)
879{
880 char buf[MAX_BUF_SIZE];
881 char cmd[MAX_CMD_SIZE];
882
883 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
884 if(_syscmd(cmd, buf, sizeof(buf)))
885 {
886 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
887 _syscmd(cmd, buf, sizeof(buf));
888 return RETURN_OK;
889 }
890
891 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
892 _syscmd(cmd,buf,sizeof(buf));
893 return RETURN_OK;
894}
895
896static int readBandWidth(int radioIndex,char *bw_value)
897{
898 char buf[MAX_BUF_SIZE] = {0};
899 char cmd[MAX_CMD_SIZE] = {0};
900 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
901 _syscmd(cmd,buf,sizeof(buf));
902 if(NULL!=strstr(buf,"20MHz"))
903 {
904 strcpy(bw_value,"20MHz");
905 }
906 else if(NULL!=strstr(buf,"40MHz"))
907 {
908 strcpy(bw_value,"40MHz");
909 }
910 else if(NULL!=strstr(buf,"80MHz"))
911 {
912 strcpy(bw_value,"80MHz");
913 }
914 else
915 {
916 return RETURN_ERR;
917 }
918 return RETURN_OK;
919}
920
921// Input could be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
922INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
923{
924 struct params params={'\0'};
925 char config_file[MAX_BUF_SIZE] = {0};
926 char buf[MAX_BUF_SIZE] = {'\0'};
927
928 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
929 // Copy the numeric value
930 if (strlen (beaconRate) >= 5) {
931 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
932 buf[strlen(beaconRate) - 4] = '\0';
933 } else if (strlen(beaconRate) > 0)
934 strcpy(buf, beaconRate);
935 else
936 return RETURN_ERR;
937
938 params.name = "beacon_rate";
939 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
940 if (strncmp(buf, "5.5", 3) == 0) {
941 snprintf(buf, sizeof(buf), "55");
942 params.value = buf;
943 } else {
944 strcat(buf, "0");
945 params.value = buf;
946 }
947
948 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
949 wifi_hostapdWrite(config_file, &params, 1);
950 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
951 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
952
953 return RETURN_OK;
954}
955
956INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
957{
958 char config_file[128] = {'\0'};
959 char temp_output[128] = {'\0'};
960 char buf[128] = {'\0'};
961 char cmd[128] = {'\0'};
962 int rate = 0;
963 int phyId = 0;
964
965 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
966 if (NULL == beaconRate)
967 return RETURN_ERR;
968
969 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
970 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
971 phyId = radio_index_to_phy(radioIndex);
972 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
973 if(strlen(buf) > 0) {
974 if (strncmp(buf, "55", 2) == 0)
975 snprintf(temp_output, sizeof(temp_output), "5.5Mbps");
976 else {
977 rate = strtol(buf, NULL, 10)/10;
978 snprintf(temp_output, sizeof(temp_output), "%dMbps", rate);
979 }
980 } else {
981 // config not set, so we would use lowest rate as default
982 sprintf(cmd, "iw phy%d info | grep Bitrates -A1 | tail -n 1 | awk '{print $2}' | tr -d '.0\\n'", phyId);
983 _syscmd(cmd, buf, sizeof(buf));
984 snprintf(temp_output, sizeof(temp_output), "%sMbps", buf);
985 }
986 strncpy(beaconRate, temp_output, sizeof(temp_output));
987 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
988
989 return RETURN_OK;
990}
991
992INT wifi_setLED(INT radioIndex, BOOL enable)
993{
994 return 0;
995}
996INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
997{
998 return RETURN_OK;
999}
1000/**********************************************************************************
1001 *
developer69b61b02023-03-07 17:17:44 +08001002 * Wifi Subsystem level function prototypes
developer72fb0bb2023-01-11 09:46:29 +08001003 *
1004**********************************************************************************/
1005//---------------------------------------------------------------------------------------------------
1006//Wifi system api
1007//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
developer69b61b02023-03-07 17:17:44 +08001008INT wifi_getHalVersion(CHAR *output_string) //RDKB
developer72fb0bb2023-01-11 09:46:29 +08001009{
1010 if(!output_string)
1011 return RETURN_ERR;
1012 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
1013
1014 return RETURN_OK;
1015}
1016
1017
1018/* wifi_factoryReset() function */
1019/**
developer69b61b02023-03-07 17:17:44 +08001020* @description Clears internal variables to implement a factory reset of the Wi-Fi
developer72fb0bb2023-01-11 09:46:29 +08001021* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
1022*
1023* @param None
1024*
1025* @return The status of the operation.
1026* @retval RETURN_OK if successful.
1027* @retval RETURN_ERR if any error is detected
1028*
1029* @execution Synchronous
1030* @sideeffect None
1031*
1032* @note This function must not suspend and must not invoke any blocking system
1033* calls. It should probably just send a message to a driver event handler task.
1034*
1035*/
1036INT wifi_factoryReset()
1037{
1038 char cmd[128];
1039
1040 /*delete running hostapd conf files*/
1041 wifi_dbg_printf("\n[%s]: deleting hostapd conf file %s and %s",__func__,HOSTAPD_CONF_0,HOSTAPD_CONF_1);
1042 sprintf(cmd, "rm -rf %s %s",HOSTAPD_CONF_0,HOSTAPD_CONF_1);
1043 system(cmd);
1044 system("systemctl restart hostapd.service");
1045
1046 return RETURN_OK;
1047}
1048
1049/* wifi_factoryResetRadios() function */
1050/**
1051* @description Restore all radio parameters without touching access point parameters. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
1052*
1053* @param None
1054* @return The status of the operation
1055* @retval RETURN_OK if successful
1056* @retval RETURN_ERR if any error is detected
1057*
1058* @execution Synchronous
1059*
1060* @sideeffect None
1061*
1062* @note This function must not suspend and must not invoke any blocking system
1063* calls. It should probably just send a message to a driver event handler task.
1064*
1065*/
1066INT wifi_factoryResetRadios()
1067{
1068 if((RETURN_OK == wifi_factoryResetRadio(0)) && (RETURN_OK == wifi_factoryResetRadio(1)))
1069 return RETURN_OK;
1070
1071 return RETURN_ERR;
1072}
1073
1074
1075/* wifi_factoryResetRadio() function */
1076/**
1077* @description Restore selected radio parameters without touching access point parameters
1078*
1079* @param radioIndex - Index of Wi-Fi Radio channel
1080*
1081* @return The status of the operation.
1082* @retval RETURN_OK if successful.
1083* @retval RETURN_ERR if any error is detected
1084*
1085* @execution Synchronous.
1086* @sideeffect None.
1087*
1088* @note This function must not suspend and must not invoke any blocking system
1089* calls. It should probably just send a message to a driver event handler task.
1090*
1091*/
1092INT wifi_factoryResetRadio(int radioIndex) //RDKB
1093{
1094 system("systemctl stop hostapd.service");
1095
1096 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1097 if(radioIndex == 0)
1098 system("rm /nvram/hostapd0.conf");
1099 else if(radioIndex == 1)
1100 system("rm /nvram/hostapd1.conf");
1101 else
1102 return RETURN_ERR;
1103
1104 system("systemctl start hostapd.service");
1105 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1106 return RETURN_OK;
1107}
1108
1109/* wifi_initRadio() function */
1110/**
1111* Description: This function call initializes the specified radio.
developer69b61b02023-03-07 17:17:44 +08001112* Implementation specifics may dictate the functionality since
developer72fb0bb2023-01-11 09:46:29 +08001113* different hardware implementations may have different initilization requirements.
1114* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
1115*
1116* @return The status of the operation.
1117* @retval RETURN_OK if successful.
1118* @retval RETURN_ERR if any error is detected
1119*
1120* @execution Synchronous.
1121* @sideeffect None.
1122*
1123* @note This function must not suspend and must not invoke any blocking system
1124* calls. It should probably just send a message to a driver event handler task.
1125*
1126*/
1127INT wifi_initRadio(INT radioIndex)
1128{
1129 //TODO: Initializes the wifi subsystem (for specified radio)
1130 return RETURN_OK;
1131}
1132void macfilter_init()
1133{
1134 char count[4]={'\0'};
1135 char buf[253]={'\0'};
1136 char tmp[19]={'\0'};
1137 int dev_count,block,mac_entry=0;
1138 char res[4]={'\0'};
1139 char acl_file_path[64] = {'\0'};
1140 FILE *fp = NULL;
1141 int index=0;
1142 char iface[10]={'\0'};
1143 char config_file[MAX_BUF_SIZE] = {0};
1144
1145
1146 sprintf(acl_file_path,"/tmp/mac_filter.sh");
1147
1148 fp=fopen(acl_file_path,"w+");
1149 if (fp == NULL) {
1150 fprintf(stderr, "%s: failed to open file %s.\n", __func__, acl_file_path);
developer17038e62023-03-02 14:43:43 +08001151 return;
developer72fb0bb2023-01-11 09:46:29 +08001152 }
1153 sprintf(buf,"#!/bin/sh \n");
1154 fprintf(fp,"%s\n",buf);
1155
1156 system("chmod 0777 /tmp/mac_filter.sh");
1157
1158 for(index=0;index<=1;index++)
1159 {
1160 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
1161 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
1162 sprintf(buf,"syscfg get %dcountfilter",index);
1163 _syscmd(buf,count,sizeof(count));
1164 mac_entry=atoi(count);
1165
1166 sprintf(buf,"syscfg get %dblockall",index);
1167 _syscmd(buf,res,sizeof(res));
1168 block = atoi(res);
1169
1170 //Allow only those macs mentioned in ACL
1171 if(block==1)
1172 {
1173 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1174 fprintf(fp,"%s\n",buf);
1175 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1176 {
1177 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1178 _syscmd(buf,tmp,sizeof(tmp));
1179 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
1180 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
1181 fprintf(fp,"%s\n",buf);
1182 }
1183 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
1184 fprintf(fp,"%s\n",buf);
1185 }
1186
1187 //Block all the macs mentioned in ACL
1188 else if(block==2)
1189 {
1190 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1191 fprintf(fp,"%s\n",buf);
1192
1193 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1194 {
1195 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1196 _syscmd(buf,tmp,sizeof(tmp));
1197 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
1198 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
1199 fprintf(fp,"%s\n",buf);
1200 }
1201 }
1202 }
1203 fclose(fp);
1204}
1205
developer17038e62023-03-02 14:43:43 +08001206
1207static void
1208wifi_ParseProfile(void)
1209{
1210 int i;
1211 int max_radio_num = 0;
1212 int card_idx;
1213 int band_idx;
1214 int phy_idx = 0;
developer745f0bd2023-03-06 14:32:53 +08001215 int wireless_mode = 0;
developer17038e62023-03-02 14:43:43 +08001216 char buf[MAX_BUF_SIZE] = {0};
1217 char chip_name[12];
1218 char card_profile[MAX_BUF_SIZE] = {0};
1219 char band_profile[MAX_BUF_SIZE] = {0};
1220 FILE* fp;
1221
1222 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1223
1224 memset(main_prefix, 0, sizeof(main_prefix));
1225 memset(ext_prefix, 0, sizeof(ext_prefix));
1226 memset(default_ssid, 0, sizeof(default_ssid));
developer745f0bd2023-03-06 14:32:53 +08001227 for (i = 0; i < MAX_NUM_RADIOS; i++)
1228 radio_band[i] = band_invalid;
developer17038e62023-03-02 14:43:43 +08001229
1230 if (wifi_getMaxRadioNumber(&max_radio_num) != RETURN_OK) {
1231 /* LOG */
1232 return;
1233 }
1234
1235 for (card_idx = 0; card_idx < 3; card_idx++) {
1236 snprintf(buf, sizeof(buf), "INDEX%d", card_idx);
1237 if (get_value(l1profile, buf, chip_name, sizeof(chip_name)) < 0) {
1238 break;
1239 }
1240 snprintf(buf, sizeof(buf), "INDEX%d_profile_path", card_idx);
1241 if (get_value(l1profile, buf, card_profile, sizeof(card_profile)) < 0) {
1242 break;
1243 }
1244 for (band_idx = 0; band_idx < 3; band_idx++) {
1245 snprintf(buf, sizeof(buf), "BN%d_profile_path", band_idx);
1246 if (get_value(card_profile, buf, band_profile, sizeof(band_profile)) < 0) {
1247 /* LOG */
1248 break;
1249 }
1250
1251 snprintf(buf, sizeof(buf), "INDEX%d_main_ifname", card_idx);
1252 if (get_value_by_idx(l1profile, buf, band_idx, main_prefix[phy_idx], IFNAMSIZ) < 0) {
1253 /* LOG */
1254 }
1255
1256 snprintf(buf, sizeof(buf), "INDEX%d_ext_ifname", card_idx);
1257 if (get_value_by_idx(l1profile, buf, band_idx, ext_prefix[phy_idx], IFNAMSIZ) < 0) {
1258 /* LOG */
1259 }
1260
1261 if (get_value(band_profile, "SSID1", default_ssid[phy_idx], sizeof(default_ssid[phy_idx])) < 0) {
1262 /* LOG */
1263 }
developer745f0bd2023-03-06 14:32:53 +08001264 if (get_value(band_profile, "WirelessMode", buf, sizeof(buf)) < 0) {
1265 /* LOG */
1266 }
1267
1268 wireless_mode = atoi(buf);
1269 switch (wireless_mode) {
1270 case 22:
1271 case 16:
1272 case 6:
1273 case 4:
1274 case 1:
1275 radio_band[phy_idx] = band_2_4;
1276 break;
1277 case 23:
1278 case 17:
1279 case 14:
1280 case 11:
1281 case 2:
1282 radio_band[phy_idx] = band_5;
1283 break;
1284 case 24:
1285 case 18:
1286 radio_band[phy_idx] = band_6;
1287 break;
1288 }
developer17038e62023-03-02 14:43:43 +08001289 phy_idx++;
1290 }
1291 }
1292
1293 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1294}
1295
1296static void
1297wifi_PrepareDefaultHostapdConfigs(void)
1298{
developer0132ed92023-03-21 13:48:53 +08001299 int radio_idx;
1300 int bss_idx;
1301 int ap_idx;
1302 int band_idx;
1303 char buf[MAX_BUF_SIZE] = {0};
1304 char config_file[MAX_BUF_SIZE] = {0};
1305 char ssid[MAX_BUF_SIZE] = {0};
1306 char interface[32] = {0};
1307 char ret_buf[MAX_BUF_SIZE] = {0};
1308 char psk_file[64] = {0};
1309 struct params params[3];
developer17038e62023-03-02 14:43:43 +08001310
developer0132ed92023-03-21 13:48:53 +08001311 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1312 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++) {
1313 band_idx = radio_index_to_band(radio_idx);
1314 if (band_idx < 0) {
1315 break;
1316 }
1317 for (bss_idx = 0; bss_idx < 5; bss_idx++) {
1318 ap_idx = array_index_to_vap_index(radio_idx, bss_idx);
1319
1320 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_idx);
1321 snprintf(buf, sizeof(buf), "cp /etc/hostapd-%s.conf %s", wifi_band_str[band_idx], config_file);
1322 _syscmd(buf, ret_buf, sizeof(ret_buf));
developer17038e62023-03-02 14:43:43 +08001323
developer0132ed92023-03-21 13:48:53 +08001324 if (bss_idx == 0) {
1325 snprintf(ssid, sizeof(ssid), "%s", default_ssid[radio_idx]);
1326 snprintf(interface, sizeof(interface), "%s", main_prefix[radio_idx]);
1327 } else {
1328 snprintf(ssid, sizeof(ssid), "%s_%d", default_ssid[radio_idx], bss_idx);
1329 snprintf(interface, sizeof(interface), "%s%d", ext_prefix[radio_idx], bss_idx);
1330 }
developer17038e62023-03-02 14:43:43 +08001331
developer0132ed92023-03-21 13:48:53 +08001332 /* fix wpa_psk_file path */
1333 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", ap_idx);
developer17038e62023-03-02 14:43:43 +08001334
developer0132ed92023-03-21 13:48:53 +08001335 params[0].name = "ssid";
1336 params[0].value = ssid;
1337 params[1].name = "interface";
1338 params[1].value = interface;
1339 params[2].name = "wpa_psk_file";
1340 params[2].value = psk_file;
developer17038e62023-03-02 14:43:43 +08001341
developer0132ed92023-03-21 13:48:53 +08001342 wifi_hostapdWrite(config_file, params, 3);
1343 }
1344 }
1345 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer17038e62023-03-02 14:43:43 +08001346}
1347
1348static void
1349wifiBringUpInterfacesForRadio(int radio_idx)
1350{
developer0132ed92023-03-21 13:48:53 +08001351 int bss_idx;
1352 int ap_idx;
1353 int band_idx;
1354 char cmd[MAX_CMD_SIZE] = {0};
1355 char config_file[MAX_BUF_SIZE] = {0};
1356 char ret_buf[MAX_BUF_SIZE] = {0};
developer8a3bbbf2023-03-15 17:47:23 +08001357 char inf_name[IF_NAME_SIZE] = {0};
developer17038e62023-03-02 14:43:43 +08001358
1359 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer8a3bbbf2023-03-15 17:47:23 +08001360
developered997d32023-04-18 22:45:39 +08001361 bss_idx = 0;
1362 /*TBD: we need refine setup flow and mbss flow*/
1363// for (bss_idx = 0; bss_idx < 5; bss_idx++) {
developer0132ed92023-03-21 13:48:53 +08001364 ap_idx = array_index_to_vap_index(radio_idx, bss_idx);
1365
1366 snprintf(cmd, sizeof(cmd), "touch %s%d.psk", PSK_FILE, ap_idx);
1367 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1368
1369 memset(cmd, 0, MAX_CMD_SIZE);
1370 memset(ret_buf, 0, MAX_BUF_SIZE);
developer17038e62023-03-02 14:43:43 +08001371
developer0132ed92023-03-21 13:48:53 +08001372 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_idx);
1373 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:%s", radio_idx, config_file);
1374 _syscmd(cmd, ret_buf, sizeof(ret_buf));
developer8a3bbbf2023-03-15 17:47:23 +08001375
1376 wifi_GetInterfaceName(ap_idx, inf_name);
1377
1378 memset(cmd, 0, MAX_CMD_SIZE);
1379 memset(ret_buf, 0, MAX_BUF_SIZE);
1380
1381 /* fix vap-status file */
1382 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=1/\" %s", inf_name, inf_name, VAP_STATUS_FILE);
1383 _syscmd(cmd, ret_buf, sizeof(ret_buf));
developered997d32023-04-18 22:45:39 +08001384// }
1385
1386 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer17038e62023-03-02 14:43:43 +08001387}
1388
1389static void
1390wifi_BringUpInterfaces(void)
1391{
1392 int radio_idx;
1393 int bss_idx;
1394 int ap_idx;
1395 int band_idx;
1396 char cmd[MAX_BUF_SIZE] = {0};
1397 char config_file[MAX_BUF_SIZE] = {0};
1398 char ret_buf[MAX_BUF_SIZE]={'\0'};
1399
1400 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1401 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++) {
1402 band_idx = radio_index_to_band(radio_idx);
1403 if (band_idx < 0) {
1404 break;
1405 }
1406 wifiBringUpInterfacesForRadio(radio_idx);
1407 }
1408 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1409}
1410
1411static void
1412wifi_BringDownInterfacesForRadio(int radio_idx)
1413{
1414 int bss_idx;
1415 int ap_idx;
1416 int band_idx;
1417 char cmd[MAX_BUF_SIZE] = {0};
1418 char config_file[MAX_BUF_SIZE] = {0};
1419 char ret_buf[MAX_BUF_SIZE]={'\0'};
1420
1421 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer17038e62023-03-02 14:43:43 +08001422
developer8a3bbbf2023-03-15 17:47:23 +08001423 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s", main_prefix[radio_idx]);
1424 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1425
1426
developer17038e62023-03-02 14:43:43 +08001427 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1428}
1429
1430
1431static void
1432wifi_BringDownInterfaces(void)
1433{
1434 int radio_idx;
1435 int bss_idx;
1436 int ap_idx;
1437 int band_idx;
1438 char cmd[MAX_BUF_SIZE] = {0};
1439 char config_file[MAX_BUF_SIZE] = {0};
1440 char ret_buf[MAX_BUF_SIZE]={'\0'};
1441
1442 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1443 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++) {
1444 band_idx = radio_index_to_band(radio_idx);
1445 if (band_idx < 0) {
1446 break;
1447 }
1448 wifi_BringDownInterfacesForRadio(radio_idx);
1449 }
1450 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1451}
1452
developer8a3bbbf2023-03-15 17:47:23 +08001453static void wifi_vap_status_reset()
1454{
1455 char cmd[MAX_CMD_SIZE] = {0};
1456 char ret_buf[MAX_BUF_SIZE] = {0};
1457 char radio_idx = 0;
1458 char bss_idx = 0;
developer8666b312023-03-24 14:05:31 +08001459
developer8a3bbbf2023-03-15 17:47:23 +08001460 if (access(VAP_STATUS_FILE, F_OK) != 0) {
1461 snprintf(cmd, MAX_CMD_SIZE, "touch %s", VAP_STATUS_FILE);
1462 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1463 } else {
1464 snprintf(cmd, MAX_CMD_SIZE, "echo '' > %s", VAP_STATUS_FILE);
1465 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1466 }
1467
1468 memset(cmd, 0, MAX_CMD_SIZE);
1469 memset(ret_buf, 0, MAX_BUF_SIZE);
1470
1471 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++)
1472 for (bss_idx = 0; bss_idx < 5; bss_idx++) {
1473 snprintf(cmd, MAX_CMD_SIZE, "echo %s%d=0 >> %s", ext_prefix[radio_idx], bss_idx, VAP_STATUS_FILE);
1474 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1475 }
1476
1477}
developer17038e62023-03-02 14:43:43 +08001478
developer72fb0bb2023-01-11 09:46:29 +08001479// Initializes the wifi subsystem (all radios)
1480INT wifi_init() //RDKB
1481{
developer96b38512023-02-22 11:17:45 +08001482 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1483 //Not intitializing macfilter for Turris-Omnia Platform for now
1484 //macfilter_init();
developer17038e62023-03-02 14:43:43 +08001485 wifi_ParseProfile();
1486 wifi_PrepareDefaultHostapdConfigs();
1487 //system("/usr/sbin/iw reg set US");
1488 system("systemctl start hostapd.service");
1489 sleep(2);
developer8a3bbbf2023-03-15 17:47:23 +08001490
1491 wifi_vap_status_reset();
1492
developer17038e62023-03-02 14:43:43 +08001493 wifi_BringUpInterfaces();
developer96b38512023-02-22 11:17:45 +08001494
developer96b38512023-02-22 11:17:45 +08001495
1496 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08001497
1498 return RETURN_OK;
1499}
1500
1501/* wifi_reset() function */
1502/**
1503* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
developer69b61b02023-03-07 17:17:44 +08001504* Implementation specifics may dictate what is actualy reset since
developer72fb0bb2023-01-11 09:46:29 +08001505* different hardware implementations may have different requirements.
1506* Parameters : None
1507*
1508* @return The status of the operation.
1509* @retval RETURN_OK if successful.
1510* @retval RETURN_ERR if any error is detected
1511*
1512* @execution Synchronous.
1513* @sideeffect None.
1514*
1515* @note This function must not suspend and must not invoke any blocking system
1516* calls. It should probably just send a message to a driver event handler task.
1517*
1518*/
1519INT wifi_reset()
1520{
developer17038e62023-03-02 14:43:43 +08001521
1522 wifi_BringDownInterfaces();
1523 sleep(2);
1524
developer96b38512023-02-22 11:17:45 +08001525 //TODO: resets the wifi subsystem, deletes all APs
1526 system("systemctl stop hostapd.service");
1527 sleep(2);
developer17038e62023-03-02 14:43:43 +08001528
developer96b38512023-02-22 11:17:45 +08001529 system("systemctl start hostapd.service");
1530 sleep(5);
developer17038e62023-03-02 14:43:43 +08001531
1532 wifi_PrepareDefaultHostapdConfigs();
1533 sleep(2);
developer8a3bbbf2023-03-15 17:47:23 +08001534
1535 wifi_vap_status_reset();
1536
developer17038e62023-03-02 14:43:43 +08001537 wifi_BringUpInterfaces();
1538
developer72fb0bb2023-01-11 09:46:29 +08001539 return RETURN_OK;
1540}
1541
1542/* wifi_down() function */
1543/**
1544* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
developer69b61b02023-03-07 17:17:44 +08001545* Implementation specifics may dictate some functionality since
developer72fb0bb2023-01-11 09:46:29 +08001546* different hardware implementations may have different requirements.
1547*
1548* @param None
1549*
1550* @return The status of the operation
1551* @retval RETURN_OK if successful
1552* @retval RETURN_ERR if any error is detected
1553*
1554* @execution Synchronous
1555* @sideeffect None
1556*
1557* @note This function must not suspend and must not invoke any blocking system
1558* calls. It should probably just send a message to a driver event handler task.
1559*
1560*/
1561INT wifi_down()
1562{
developer96b38512023-02-22 11:17:45 +08001563 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developer17038e62023-03-02 14:43:43 +08001564 wifi_BringDownInterfaces();
1565 sleep(2);
1566
developer96b38512023-02-22 11:17:45 +08001567 system("systemctl stop hostapd.service");
1568 sleep(2);
developer72fb0bb2023-01-11 09:46:29 +08001569 return RETURN_OK;
1570}
1571
1572
1573/* wifi_createInitialConfigFiles() function */
1574/**
1575* @description This function creates wifi configuration files. The format
developer69b61b02023-03-07 17:17:44 +08001576* and content of these files are implementation dependent. This function call is
1577* used to trigger this task if necessary. Some implementations may not need this
1578* function. If an implementation does not need to create config files the function call can
developer72fb0bb2023-01-11 09:46:29 +08001579* do nothing and return RETURN_OK.
1580*
1581* @param None
1582*
1583* @return The status of the operation
1584* @retval RETURN_OK if successful
1585* @retval RETURN_ERR if any error is detected
1586*
1587* @execution Synchronous
1588* @sideeffect None
1589*
1590* @note This function must not suspend and must not invoke any blocking system
1591* calls. It should probably just send a message to a driver event handler task.
1592*
1593*/
1594INT wifi_createInitialConfigFiles()
1595{
1596 //TODO: creates initial implementation dependent configuration files that are later used for variable storage. Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
1597 return RETURN_OK;
1598}
1599
developer7e4a2a62023-04-06 19:56:03 +08001600/* outputs the country code to a max 64 character string */
developer72fb0bb2023-01-11 09:46:29 +08001601INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1602{
developer7e4a2a62023-04-06 19:56:03 +08001603 char interface_name[IF_NAME_SIZE] = {0};
1604 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer72fb0bb2023-01-11 09:46:29 +08001605
developer7e4a2a62023-04-06 19:56:03 +08001606 if (!output_string || (radioIndex >= MAX_NUM_RADIOS)) {
1607 printf("%s: input para error!!!\n", __func__);
1608 return RETURN_ERR;
1609 }
developer72fb0bb2023-01-11 09:46:29 +08001610
developer7e4a2a62023-04-06 19:56:03 +08001611 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK) {
1612 printf("%s: get inf_name error!!!\n", __func__);
1613 return RETURN_ERR;
1614 }
1615
1616 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i %s status driver | grep country | cut -d '=' -f2 | tr -d '\\n'",
1617 interface_name);
1618 _syscmd(cmd, buf, sizeof(buf));
1619
1620 if(strlen(buf))
1621 snprintf(output_string, 64, "%s", buf);
1622 else
1623 return RETURN_ERR;
1624
1625 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08001626}
1627
1628INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1629{
developer7e4a2a62023-04-06 19:56:03 +08001630 /*Set wifi config. Wait for wifi reset to apply*/
1631 char str[MAX_BUF_SIZE] = {0};
1632 char cmd[MAX_CMD_SIZE] = {0};
1633 struct params params;
1634 char config_file[MAX_BUF_SIZE] = {0};
1635 int ret = 0;
developer72fb0bb2023-01-11 09:46:29 +08001636
developer7e4a2a62023-04-06 19:56:03 +08001637 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08001638
developer7e4a2a62023-04-06 19:56:03 +08001639 if(NULL == CountryCode || strlen(CountryCode) >= 32 ) {
1640 printf("%s: input para error!!!\n", __func__);
1641 return RETURN_ERR;
1642 }
developer72fb0bb2023-01-11 09:46:29 +08001643
developer7e4a2a62023-04-06 19:56:03 +08001644 if (!strlen(CountryCode))
1645 strncpy(CountryCode, "US", sizeof("US")); /*default set the code to US*/
developer72fb0bb2023-01-11 09:46:29 +08001646
developer7e4a2a62023-04-06 19:56:03 +08001647 params.name = "country_code";
1648 params.value = CountryCode;
developer72fb0bb2023-01-11 09:46:29 +08001649
developer7e4a2a62023-04-06 19:56:03 +08001650 snprintf(config_file, MAX_BUF_SIZE, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1651 ret = wifi_hostapdWrite(config_file, &params, 1);
1652
1653 if (ret) {
1654 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n",
1655 __func__, ret);
1656 }
1657
1658 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1659
1660 if (ret) {
1661 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n",
1662 __func__, ret);
1663 }
1664
1665 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
1666
1667 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08001668}
1669
1670INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1671{
1672 char interface_name[16] = {0};
1673 char channel_util_file[64] = {0};
1674 char cmd[128] = {0};
1675 char buf[128] = {0};
1676 char line[128] = {0};
1677 char *param = NULL, *value = NULL;
1678 int read = 0;
1679 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1680 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1681 size_t len = 0;
1682 FILE *f = NULL;
1683
1684 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1685
1686 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
1687 return RETURN_ERR;
1688 snprintf(cmd, sizeof(cmd), "iw %s scan | grep signal | awk '{print $2}' | sort -n | tail -n1", interface_name);
1689 _syscmd(cmd, buf, sizeof(buf));
1690 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1691
1692 memset(cmd, 0, sizeof(cmd));
1693 memset(buf, 0, sizeof(buf));
1694 snprintf(cmd, sizeof(cmd), "iw %s survey dump | grep 'in use' -A6", interface_name);
1695 if ((f = popen(cmd, "r")) == NULL) {
1696 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1697 return RETURN_ERR;
1698 }
1699
1700 read = getline(&line, &len, f);
1701 while (read != -1) {
1702 param = strtok(line, ":\t");
1703 value = strtok(NULL, " ");
1704 if(strstr(param, "frequency") != NULL) {
1705 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1706 }
1707 if(strstr(param, "noise") != NULL) {
1708 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1709 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1710 }
1711 if(strstr(param, "channel active time") != NULL) {
1712 ActiveTime = strtol(value, NULL, 10);
1713 }
1714 if(strstr(param, "channel busy time") != NULL) {
1715 BusyTime = strtol(value, NULL, 10);
1716 }
1717 if(strstr(param, "channel transmit time") != NULL) {
1718 TransmitTime = strtol(value, NULL, 10);
1719 }
1720 read = getline(&line, &len, f);
1721 }
1722 pclose(f);
1723
1724 // The file should store the last active, busy and transmit time
1725 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1726 f = fopen(channel_util_file, "r");
1727 if (f != NULL) {
1728 read = getline(&line, &len, f);
1729 preActiveTime = strtol(line, NULL, 10);
1730 read = getline(&line, &len, f);
1731 preBusyTime = strtol(line, NULL, 10);
1732 read = getline(&line, &len, f);
1733 preTransmitTime = strtol(line, NULL, 10);
1734 fclose(f);
1735 }
1736
1737 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1738 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1739
1740 f = fopen(channel_util_file, "w");
1741 if (f != NULL) {
1742 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1743 fclose(f);
1744 }
1745 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1746 return RETURN_OK;
1747}
1748
1749/**********************************************************************************
1750 *
1751 * Wifi radio level function prototypes
1752 *
1753**********************************************************************************/
1754
1755//Get the total number of radios in this wifi subsystem
1756INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1757{
1758 if (NULL == output)
1759 return RETURN_ERR;
1760 *output = MAX_NUM_RADIOS;
1761
1762 return RETURN_OK;
1763}
1764
developer69b61b02023-03-07 17:17:44 +08001765//Get the total number of SSID entries in this wifi subsystem
developer72fb0bb2023-01-11 09:46:29 +08001766INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1767{
1768 if (NULL == output)
1769 return RETURN_ERR;
1770 *output = MAX_APS;
1771
1772 return RETURN_OK;
1773}
1774
1775//Get the Radio enable config parameter
1776INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1777{
1778 char interface_name[16] = {0};
1779 char buf[128] = {0}, cmd[128] = {0};
1780
1781 if (NULL == output_bool)
1782 return RETURN_ERR;
1783
1784 *output_bool = FALSE;
1785 if (radioIndex >= MAX_NUM_RADIOS)// Target has two wifi radios
1786 return RETURN_ERR;
1787
1788 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
1789 return RETURN_ERR;
1790 sprintf(cmd, "hostapd_cli -i %s status | grep state | cut -d '=' -f2", interface_name);
1791 _syscmd(cmd, buf, sizeof(buf));
1792
1793 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 || strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0)
1794 *output_bool = TRUE;
1795 return RETURN_OK;
1796}
1797
developere82c0ca2023-05-10 16:25:35 +08001798typedef long time_t;
1799static time_t radio_up_time[MAX_NUM_RADIOS];
1800
developer72fb0bb2023-01-11 09:46:29 +08001801INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1802{
1803 char interface_name[16] = {0};
1804 char cmd[MAX_CMD_SIZE] = {0};
developer8a3bbbf2023-03-15 17:47:23 +08001805 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08001806 int apIndex, ret;
developer69b61b02023-03-07 17:17:44 +08001807 int max_radio_num = 0;
developer72fb0bb2023-01-11 09:46:29 +08001808 int phyId = 0;
1809
1810 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1811
1812 phyId = radio_index_to_phy(radioIndex);
1813
1814 wifi_getMaxRadioNumber(&max_radio_num);
1815
developer8a3bbbf2023-03-15 17:47:23 +08001816 if(enable == FALSE) {
developere82c0ca2023-05-10 16:25:35 +08001817 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s", main_prefix[radioIndex]);
developer8a3bbbf2023-03-15 17:47:23 +08001818 _syscmd(cmd, buf, sizeof(buf));
developere82c0ca2023-05-10 16:25:35 +08001819 if(strncmp(buf, "OK", 2))
1820 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
developer8a3bbbf2023-03-15 17:47:23 +08001821 } else {
developere82c0ca2023-05-10 16:25:35 +08001822 for (apIndex = radioIndex; apIndex < MAX_APS; apIndex += max_radio_num) {
developer72fb0bb2023-01-11 09:46:29 +08001823 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
1824 return RETURN_ERR;
1825
developer8a3bbbf2023-03-15 17:47:23 +08001826 memset(cmd, 0, MAX_CMD_SIZE);
1827 memset(buf, 0, MAX_BUF_SIZE);
1828
developer72fb0bb2023-01-11 09:46:29 +08001829 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
1830 _syscmd(cmd, buf, sizeof(buf));
developer8a3bbbf2023-03-15 17:47:23 +08001831
1832 if(*buf == '1') {
1833
1834 memset(cmd, 0, MAX_CMD_SIZE);
1835 memset(buf, 0, MAX_BUF_SIZE);
1836
developer72fb0bb2023-01-11 09:46:29 +08001837 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
1838 phyId, apIndex);
1839 _syscmd(cmd, buf, sizeof(buf));
developer8a3bbbf2023-03-15 17:47:23 +08001840
developer72fb0bb2023-01-11 09:46:29 +08001841 }
1842 }
developere82c0ca2023-05-10 16:25:35 +08001843 time(&radio_up_time[radioIndex]);
developer72fb0bb2023-01-11 09:46:29 +08001844 }
1845
1846 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1847 return RETURN_OK;
1848}
1849
1850//Get the Radio enable status
1851INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1852{
1853 if (NULL == output_bool)
1854 return RETURN_ERR;
1855
1856 return wifi_getRadioEnable(radioIndex, output_bool);
1857}
1858
1859//Get the Radio Interface name from platform, eg "wlan0"
1860INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1861{
1862 if (NULL == output_string || radioIndex>=MAX_NUM_RADIOS || radioIndex<0)
1863 return RETURN_ERR;
1864 return wifi_GetInterfaceName(radioIndex, output_string);
1865}
1866
1867//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1868//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.
1869INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1870{
1871 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
1872 // For max bit rate, we should always choose the best MCS
1873 char mode[64] = {0};
1874 char channel_bandwidth_str[64] = {0};
1875 char *tmp = NULL;
1876 UINT mode_map = 0;
1877 UINT num_subcarrier = 0;
1878 UINT code_bits = 0;
1879 float code_rate = 0; // use max code rate
1880 int NSS = 0;
1881 UINT Symbol_duration = 0;
developer69b61b02023-03-07 17:17:44 +08001882 UINT GI_duration = 0;
developer72fb0bb2023-01-11 09:46:29 +08001883 wifi_band band = band_invalid;
1884 wifi_guard_interval_t gi = wifi_guard_interval_auto;
1885 BOOL enable = FALSE;
1886 float bit_rate = 0;
developera1255e42023-05-13 17:45:02 +08001887 int ant_bitmap = 0;
developer72fb0bb2023-01-11 09:46:29 +08001888
1889 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1890 if (NULL == output_string)
1891 return RETURN_ERR;
1892
1893 wifi_getRadioEnable(radioIndex, &enable);
1894 if (enable == FALSE) {
1895 snprintf(output_string, 64, "0 Mb/s");
1896 return RETURN_OK;
1897 }
1898
1899 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
1900 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
1901 return RETURN_ERR;
1902 }
1903
1904 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
1905 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
1906 return RETURN_ERR;
1907 }
1908
1909 if (gi == wifi_guard_interval_3200)
1910 GI_duration = 32;
1911 else if (gi == wifi_guard_interval_1600)
1912 GI_duration = 16;
1913 else if (gi == wifi_guard_interval_800)
1914 GI_duration = 8;
1915 else // auto, 400
1916 GI_duration = 4;
1917
1918 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
1919 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
1920 return RETURN_ERR;
1921 }
1922
1923 if (strstr(channel_bandwidth_str, "80+80") != NULL)
1924 strcpy(channel_bandwidth_str, "160");
1925
1926 if (mode_map & WIFI_MODE_AX) {
1927 if (strstr(channel_bandwidth_str, "160") != NULL)
1928 num_subcarrier = 1960;
1929 else if (strstr(channel_bandwidth_str, "80") != NULL)
1930 num_subcarrier = 980;
1931 else if (strstr(channel_bandwidth_str, "40") != NULL)
1932 num_subcarrier = 468;
1933 else if (strstr(channel_bandwidth_str, "20") != NULL)
1934 num_subcarrier = 234;
1935 code_bits = 10;
1936 code_rate = (float)5/6;
1937 Symbol_duration = 128;
developera1255e42023-05-13 17:45:02 +08001938 GI_duration = 8;/*HE no GI 400ns*/
developer72fb0bb2023-01-11 09:46:29 +08001939 } else if (mode_map & WIFI_MODE_AC) {
1940 if (strstr(channel_bandwidth_str, "160") != NULL)
1941 num_subcarrier = 468;
1942 else if (strstr(channel_bandwidth_str, "80") != NULL)
1943 num_subcarrier = 234;
1944 else if (strstr(channel_bandwidth_str, "40") != NULL)
1945 num_subcarrier = 108;
1946 else if (strstr(channel_bandwidth_str, "20") != NULL)
1947 num_subcarrier = 52;
1948 code_bits = 8;
1949 code_rate = (float)5/6;
1950 Symbol_duration = 32;
1951 } else if (mode_map & WIFI_MODE_N) {
1952 if (strstr(channel_bandwidth_str, "160") != NULL)
1953 num_subcarrier = 468;
1954 else if (strstr(channel_bandwidth_str, "80") != NULL)
1955 num_subcarrier = 234;
1956 else if (strstr(channel_bandwidth_str, "40") != NULL)
1957 num_subcarrier = 108;
1958 else if (strstr(channel_bandwidth_str, "20") != NULL)
1959 num_subcarrier = 52;
1960 code_bits = 6;
1961 code_rate = (float)3/4;
1962 Symbol_duration = 32;
1963 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
1964 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
1965 snprintf(output_string, 64, "65 Mb/s");
1966 return RETURN_OK;
1967 } else {
1968 snprintf(output_string, 64, "0 Mb/s");
1969 return RETURN_OK;
1970 }
1971
1972 // Spatial streams
developera1255e42023-05-13 17:45:02 +08001973 if (wifi_getRadioTxChainMask(radioIndex, &ant_bitmap) != RETURN_OK) {
developer72fb0bb2023-01-11 09:46:29 +08001974 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
1975 return RETURN_ERR;
1976 }
developera1255e42023-05-13 17:45:02 +08001977 for (; ant_bitmap > 0; ant_bitmap >>= 1)
1978 NSS += ant_bitmap & 1;
developer72fb0bb2023-01-11 09:46:29 +08001979
1980 // multiple 10 is to align duration unit (0.1 us)
1981 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
1982 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
developera1255e42023-05-13 17:45:02 +08001983 WIFI_ENTRY_EXIT_DEBUG("%s:num_subcarrier=%d, code_bits=%d, code_rate=%.3f, nss=%d, symbol time=%u, %.1f Mb/s\n",
1984 __func__, num_subcarrier, code_bits, code_rate, NSS, Symbol_duration + GI_duration, bit_rate);
developer72fb0bb2023-01-11 09:46:29 +08001985 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1986
1987 return RETURN_OK;
1988}
1989#if 0
1990INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1991{
1992 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1993 char cmd[64];
1994 char buf[1024];
1995 int apIndex;
1996
developer69b61b02023-03-07 17:17:44 +08001997 if (NULL == output_string)
developer72fb0bb2023-01-11 09:46:29 +08001998 return RETURN_ERR;
1999
2000 apIndex=(radioIndex==0)?0:1;
2001
2002 snprintf(cmd, sizeof(cmd), "iwconfig %s | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", interface_name);
2003 _syscmd(cmd,buf, sizeof(buf));
2004
2005 snprintf(output_string, 64, "%s", buf);
2006 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2007 return RETURN_OK;
2008}
2009#endif
2010
2011
2012//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
2013//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.
2014INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
2015{
2016 wifi_band band = band_invalid;
2017
2018 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2019 if (NULL == output_string)
2020 return RETURN_ERR;
2021
2022 band = wifi_index_to_band(radioIndex);
2023
2024 memset(output_string, 0, 10);
2025 if (band == band_2_4)
2026 strcpy(output_string, "2.4GHz");
2027 else if (band == band_5)
2028 strcpy(output_string, "5GHz");
2029 else if (band == band_6)
2030 strcpy(output_string, "6GHz");
2031 else
2032 return RETURN_ERR;
2033 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2034
2035 return RETURN_OK;
2036#if 0
2037 char buf[MAX_BUF_SIZE]={'\0'};
2038 char str[MAX_BUF_SIZE]={'\0'};
2039 char cmd[MAX_CMD_SIZE]={'\0'};
2040 char *ch=NULL;
2041 char *ch2=NULL;
2042
2043 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2044 if (NULL == output_string)
2045 return RETURN_ERR;
2046
2047
2048 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2049
2050 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
2051 {
2052 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2053 return RETURN_ERR;
2054 }
2055 ch=strchr(buf,'\n');
2056 *ch='\0';
2057 ch=strchr(buf,'=');
2058 if(ch==NULL)
2059 return RETURN_ERR;
2060
2061
2062 ch++;
2063
2064 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
2065 strcpy(buf,"0");
2066 if(strlen(ch) == 1)
2067 ch=strcat(buf,ch);
2068
2069
2070 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2071
2072 if(_syscmd(cmd,str,64) == RETURN_ERR)
2073 {
2074 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2075 return RETURN_ERR;
2076 }
2077
2078
2079 ch2=strchr(str,'\n');
2080 //replace \n with \0
2081 *ch2='\0';
2082 ch2=strchr(str,'=');
2083 if(ch2==NULL)
2084 {
2085 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2086 return RETURN_ERR;
2087 }
2088 else
2089 wifi_dbg_printf("%s",ch2+1);
2090
2091
2092 ch2++;
2093
2094
2095 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
2096
2097 memset(buf,'\0',sizeof(buf));
2098 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
2099 {
2100 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2101 return RETURN_ERR;
2102 }
2103 if (strstr(buf,"2.4") != NULL )
2104 strcpy(output_string,"2.4GHz");
2105 else if(strstr(buf,"5.") != NULL )
2106 strcpy(output_string,"5GHz");
2107 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2108
2109 return RETURN_OK;
2110#endif
2111}
2112
2113//Get the frequency band at which the radio is operating, eg: "2.4GHz"
2114//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.
2115INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
2116{
2117 wifi_band band = band_invalid;
2118 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2119 if (NULL == output_string)
2120 return RETURN_ERR;
2121 band = wifi_index_to_band(radioIndex);
2122
developer69b61b02023-03-07 17:17:44 +08002123 if (band == band_2_4)
developer72fb0bb2023-01-11 09:46:29 +08002124 snprintf(output_string, 64, "2.4GHz");
2125 else if (band == band_5)
developer69b61b02023-03-07 17:17:44 +08002126 snprintf(output_string, 64, "5GHz");
developer72fb0bb2023-01-11 09:46:29 +08002127 else if (band == band_6)
2128 snprintf(output_string, 64, "6GHz");
2129
2130 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2131
2132 return RETURN_OK;
2133#if 0
2134 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2135 char buf[MAX_BUF_SIZE]={'\0'};
2136 char str[MAX_BUF_SIZE]={'\0'};
2137 char cmd[MAX_CMD_SIZE]={'\0'};
2138 char *ch=NULL;
2139 char *ch2=NULL;
2140 char ch1[5]="0";
2141
2142 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2143
2144 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
2145 {
2146 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2147 return RETURN_ERR;
2148 }
2149
2150 ch=strchr(buf,'\n');
2151 *ch='\0';
2152 ch=strchr(buf,'=');
2153 if(ch==NULL)
2154 return RETURN_ERR;
2155 ch++;
2156
2157 if(strlen(ch)==1)
2158 {
2159 strcat(ch1,ch);
2160
2161 }
2162 else
2163 {
2164 strcpy(ch1,ch);
2165 }
2166
2167
2168
2169 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2170 if(_syscmd(cmd,str,64) == RETURN_ERR)
2171 {
2172 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2173 return RETURN_ERR;
2174 }
2175
2176
2177 ch2=strchr(str,'\n');
2178 //replace \n with \0
2179 *ch2='\0';
2180 ch2=strchr(str,'=');
2181 if(ch2==NULL)
2182 {
2183 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2184 return RETURN_ERR;
2185 }
2186 else
2187 wifi_dbg_printf("%s",ch2+1);
2188 ch2++;
2189
2190
2191 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
2192 memset(buf,'\0',sizeof(buf));
2193 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
2194 {
2195 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2196 return RETURN_ERR;
2197 }
2198
2199
2200 if(strstr(buf,"2.4")!=NULL)
2201 {
2202 strcpy(output_string,"2.4GHz");
2203 }
2204 if(strstr(buf,"5.")!=NULL)
2205 {
2206 strcpy(output_string,"5GHz");
2207 }
2208 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2209 return RETURN_OK;
2210#endif
2211}
2212
2213//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
2214//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.
2215INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
2216{
2217 char cmd[128]={0};
2218 char buf[128]={0};
2219 char temp_output[128] = {0};
2220 wifi_band band;
2221 int phyId = 0;
2222
2223 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer69b61b02023-03-07 17:17:44 +08002224 if (NULL == output_string)
developer72fb0bb2023-01-11 09:46:29 +08002225 return RETURN_ERR;
2226
2227 band = wifi_index_to_band(radioIndex);
2228 if (band == band_2_4) {
2229 strcat(temp_output, "b,g,");
2230 } else if (band == band_5) {
2231 strcat(temp_output, "a,");
2232 }
2233 phyId = radio_index_to_phy(radioIndex);
2234 // ht capabilities
2235 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep '[^PHY|MAC|VHT].Capabilities' | head -n 1 | cut -d ':' -f2 | sed 's/^.//' | tr -d '\\n'", phyId);
2236 _syscmd(cmd, buf, sizeof(buf));
2237 if (strlen(buf) >= 4 && strncmp(buf, "0x00", 4) != 0) {
2238 strcat(temp_output, "n,");
2239 }
2240
2241 // vht capabilities
2242 if (band == band_5) {
2243 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'VHT Capabilities' | cut -d '(' -f2 | cut -c1-10 | tr -d '\\n'", phyId);
2244 _syscmd(cmd, buf, sizeof(buf));
2245 if (strlen(buf) >= 10 && strncmp(buf, "0x00000000", 10) != 0) {
2246 strcat(temp_output, "ac,");
2247 }
2248 }
2249
2250 // he capabilities
2251 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'", phyId);
2252 _syscmd(cmd, buf, sizeof(buf));
2253 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
2254 strcat(temp_output, "ax,");
2255 }
2256
developere82c0ca2023-05-10 16:25:35 +08002257 // eht capabilities
2258 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'EHT MAC Capabilities' | head -n 2 | tail -n 1 | cut -d '(' -f2 | cut -c1-6 | tr -d '\\n'", phyId);
2259 _syscmd(cmd, buf, sizeof(buf));
2260 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
2261 strcat(temp_output, "be,");
2262 }
2263
developer72fb0bb2023-01-11 09:46:29 +08002264 // Remove the last comma
2265 if (strlen(temp_output) != 0)
2266 temp_output[strlen(temp_output)-1] = '\0';
2267 strncpy(output_string, temp_output, strlen(temp_output));
2268 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2269 return RETURN_OK;
2270}
2271
2272//Get the radio operating mode, and pure mode flag. eg: "ac"
2273//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.
2274INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
2275{
2276 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2277 if (NULL == output_string)
2278 return RETURN_ERR;
2279
2280 if (radioIndex == 0) {
2281 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
2282 *gOnly = FALSE;
2283 *nOnly = TRUE;
2284 *acOnly = FALSE;
2285 } else {
2286 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
2287 *gOnly = FALSE;
2288 *nOnly = FALSE;
2289 *acOnly = FALSE;
2290 }
2291 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2292
2293 return RETURN_OK;
2294#if 0
2295 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2296 char buf[64] = {0};
2297 char config_file[MAX_BUF_SIZE] = {0};
2298
developer69b61b02023-03-07 17:17:44 +08002299 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
developer72fb0bb2023-01-11 09:46:29 +08002300 return RETURN_ERR;
2301
2302 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2303 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
2304
2305 wifi_dbg_printf("\nhw_mode=%s\n",buf);
developer69b61b02023-03-07 17:17:44 +08002306 if (strlen(buf) == 0)
developer72fb0bb2023-01-11 09:46:29 +08002307 {
2308 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
2309 return RETURN_ERR;
2310 }
2311 if(strcmp(buf,"g")==0)
2312 {
2313 wifi_dbg_printf("\nG\n");
2314 *gOnly=TRUE;
2315 *nOnly=FALSE;
2316 *acOnly=FALSE;
2317 }
2318 else if(strcmp(buf,"n")==0)
2319 {
2320 wifi_dbg_printf("\nN\n");
2321 *gOnly=FALSE;
2322 *nOnly=TRUE;
2323 *acOnly=FALSE;
2324 }
2325 else if(strcmp(buf,"ac")==0)
2326 {
2327 wifi_dbg_printf("\nac\n");
2328 *gOnly=FALSE;
2329 *nOnly=FALSE;
2330 *acOnly=TRUE;
2331 }
2332 /* hostapd-5G.conf has "a" as hw_mode */
2333 else if(strcmp(buf,"a")==0)
2334 {
2335 wifi_dbg_printf("\na\n");
2336 *gOnly=FALSE;
2337 *nOnly=FALSE;
2338 *acOnly=FALSE;
2339 }
2340 else
2341 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
2342
2343 //for a,n mode
2344 if(radioIndex == 1)
2345 {
2346 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
2347 if(strcmp(buf,"1")==0)
2348 {
2349 strncpy(output_string, "n", 1);
2350 *nOnly=FALSE;
2351 }
2352 }
2353
2354 wifi_dbg_printf("\nReturning from getRadioStandard\n");
2355 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2356 return RETURN_OK;
2357#endif
2358}
2359
2360INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
2361{
2362 char cmd[128] = {0};
2363 char buf[64] = {0};
2364 char config_file[64] = {0};
2365 wifi_band band;
2366
2367 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2368 if(NULL == output_string || NULL == pureMode)
2369 return RETURN_ERR;
2370
2371 // grep all of the ieee80211 protocol config set to 1
2372 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developera1255e42023-05-13 17:45:02 +08002373 //snprintf(cmd, sizeof(cmd), "cat %s | grep -E \"ieee.*=1\" | cut -d '=' -f1 | tr -d 'ieee80211'", config_file);
2374 /*tr -d 'ieee80211' return unexpected result, if object is ieee80211be*/
2375 snprintf(cmd, sizeof(cmd), "cat %s | grep -E \"ieee.*=1\" | cut -d '=' -f1 | sed 's/ieee80211//g", config_file);
developer72fb0bb2023-01-11 09:46:29 +08002376 _syscmd(cmd, buf, sizeof(buf));
2377
2378 band = wifi_index_to_band(radioIndex);
2379 // puremode is a bit map
2380 *pureMode = 0;
2381 if (band == band_2_4) {
2382 strcat(output_string, "b,g");
2383 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
2384 if (strstr(buf, "n") != NULL) {
2385 strcat(output_string, ",n");
2386 *pureMode |= WIFI_MODE_N;
2387 }
2388 if (strstr(buf, "ax") != NULL) {
2389 strcat(output_string, ",ax");
2390 *pureMode |= WIFI_MODE_AX;
2391 }
developera1255e42023-05-13 17:45:02 +08002392 if (strstr(buf, "be") != NULL) {
2393 strcat(output_string, ",be");
2394 *pureMode |= WIFI_MODE_BE;
2395 }
developer72fb0bb2023-01-11 09:46:29 +08002396 } else if (band == band_5) {
2397 strcat(output_string, "a");
2398 *pureMode |= WIFI_MODE_A;
2399 if (strstr(buf, "n") != NULL) {
2400 strcat(output_string, ",n");
2401 *pureMode |= WIFI_MODE_N;
2402 }
2403 if (strstr(buf, "ac") != NULL) {
2404 strcat(output_string, ",ac");
2405 *pureMode |= WIFI_MODE_AC;
2406 }
2407 if (strstr(buf, "ax") != NULL) {
2408 strcat(output_string, ",ax");
2409 *pureMode |= WIFI_MODE_AX;
2410 }
developera1255e42023-05-13 17:45:02 +08002411 if (strstr(buf, "be") != NULL) {
2412 strcat(output_string, ",be");
2413 *pureMode |= WIFI_MODE_BE;
2414 }
developer72fb0bb2023-01-11 09:46:29 +08002415 } else if (band == band_6) {
2416 if (strstr(buf, "ax") != NULL) {
2417 strcat(output_string, "ax");
2418 *pureMode |= WIFI_MODE_AX;
2419 }
developera1255e42023-05-13 17:45:02 +08002420 if (strstr(buf, "be") != NULL) {
2421 strcat(output_string, ",be");
2422 *pureMode |= WIFI_MODE_BE;
2423 }
developer72fb0bb2023-01-11 09:46:29 +08002424 }
2425
2426 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2427 return RETURN_OK;
2428}
2429
2430// Set the radio operating mode, and pure mode flag.
2431INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
2432{
developer69b61b02023-03-07 17:17:44 +08002433 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
developer72fb0bb2023-01-11 09:46:29 +08002434 if (strcmp (channelMode,"11A") == 0)
2435 {
2436 writeBandWidth(radioIndex,"20MHz");
2437 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2438 printf("\nChannel Mode is 802.11a (5GHz)\n");
2439 }
2440 else if (strcmp (channelMode,"11NAHT20") == 0)
2441 {
2442 writeBandWidth(radioIndex,"20MHz");
2443 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2444 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
2445 }
2446 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
2447 {
2448 writeBandWidth(radioIndex,"40MHz");
2449 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2450 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
2451 }
2452 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
2453 {
2454 writeBandWidth(radioIndex,"40MHz");
2455 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2456 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
2457 }
2458 else if (strcmp (channelMode,"11ACVHT20") == 0)
2459 {
2460 writeBandWidth(radioIndex,"20MHz");
2461 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2462 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
2463 }
2464 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
2465 {
2466 writeBandWidth(radioIndex,"40MHz");
2467 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2468 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2469 }
2470 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
2471 {
2472 writeBandWidth(radioIndex,"40MHz");
2473 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2474 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2475 }
2476 else if (strcmp (channelMode,"11ACVHT80") == 0)
2477 {
2478 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
2479 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
2480 }
2481 else if (strcmp (channelMode,"11ACVHT160") == 0)
2482 {
2483 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
2484 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
developer69b61b02023-03-07 17:17:44 +08002485 }
developer72fb0bb2023-01-11 09:46:29 +08002486 else if (strcmp (channelMode,"11B") == 0)
2487 {
2488 writeBandWidth(radioIndex,"20MHz");
2489 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2490 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
2491 }
2492 else if (strcmp (channelMode,"11G") == 0)
2493 {
2494 writeBandWidth(radioIndex,"20MHz");
2495 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2496 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
2497 }
2498 else if (strcmp (channelMode,"11NGHT20") == 0)
2499 {
2500 writeBandWidth(radioIndex,"20MHz");
2501 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2502 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
2503 }
2504 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
2505 {
2506 writeBandWidth(radioIndex,"40MHz");
2507 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2508 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2509 }
2510 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
2511 {
2512 writeBandWidth(radioIndex,"40MHz");
2513 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2514 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2515 }
developer69b61b02023-03-07 17:17:44 +08002516 else
developer72fb0bb2023-01-11 09:46:29 +08002517 {
2518 return RETURN_ERR;
2519 }
2520 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2521
2522 return RETURN_OK;
2523}
2524
2525// Set the radio operating mode, and pure mode flag.
2526INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
2527{
2528 int num_hostapd_support_mode = 3; // n, ac, ax
2529 struct params list[num_hostapd_support_mode];
2530 char config_file[64] = {0};
2531 char bandwidth[16] = {0};
2532 int mode_check_bit = 1 << 3; // n mode
developer69b61b02023-03-07 17:17:44 +08002533
developer72fb0bb2023-01-11 09:46:29 +08002534
2535 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
2536 // Set radio mode
2537 list[0].name = "ieee80211n";
2538 list[1].name = "ieee80211ac";
2539 list[2].name = "ieee80211ax";
2540 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2541
2542 // check the bit map from n to ax, and set hostapd config
2543 if (pureMode & WIFI_MODE_N)
2544 list[0].value = "1";
2545 else
2546 list[0].value = "0";
2547 if (pureMode & WIFI_MODE_AC)
2548 list[1].value = "1";
2549 else
2550 list[1].value = "0";
2551 if (pureMode & WIFI_MODE_AX)
2552 list[2].value = "1";
2553 else
2554 list[2].value = "0";
2555 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
2556
2557 if (channelMode == NULL || strlen(channelMode) == 0)
2558 return RETURN_OK;
2559 // Set bandwidth
2560 if (strstr(channelMode, "40") != NULL)
2561 strcpy(bandwidth, "40MHz");
2562 else if (strstr(channelMode, "80") != NULL)
2563 strcpy(bandwidth, "80MHz");
2564 else if (strstr(channelMode, "160") != NULL)
2565 strcpy(bandwidth, "160MHz");
2566 else // 11A, 11B, 11G....
2567 strcpy(bandwidth, "20MHz");
2568
2569 writeBandWidth(radioIndex, bandwidth);
2570 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
2571
2572 wifi_reloadAp(radioIndex);
2573 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2574
2575 return RETURN_OK;
2576}
2577
2578INT wifi_setRadioHwMode(INT radioIndex, CHAR *hw_mode) {
2579
2580 char config_file[64] = {0};
2581 char buf[64] = {0};
2582 struct params params = {0};
2583 wifi_band band = band_invalid;
2584
2585 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2586
2587 band = wifi_index_to_band(radioIndex);
2588
2589 if (strncmp(hw_mode, "a", 1) == 0 && (band != band_5 && band != band_6))
2590 return RETURN_ERR;
2591 else if ((strncmp(hw_mode, "b", 1) == 0 || strncmp(hw_mode, "g", 1) == 0) && band != band_2_4)
2592 return RETURN_ERR;
2593 else if ((strncmp(hw_mode, "a", 1) && strncmp(hw_mode, "b", 1) && strncmp(hw_mode, "g", 1)) || band == band_invalid)
2594 return RETURN_ERR;
2595
2596 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2597 params.name = "hw_mode";
2598 params.value = hw_mode;
2599 wifi_hostapdWrite(config_file, &params, 1);
2600 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2601
2602 if (band == band_2_4) {
2603 if (strncmp(hw_mode, "b", 1) == 0) {
2604 wifi_setRadioMode(radioIndex, "20MHz", WIFI_MODE_B);
2605 snprintf(buf, sizeof(buf), "%s", "1,2,5.5,11");
2606 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2607 snprintf(buf, sizeof(buf), "%s", "1,2");
2608 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2609 } else {
2610 // We don't set mode here, because we don't know whitch mode should be set (g, n or ax?).
2611
2612 snprintf(buf, sizeof(buf), "%s", "6,9,12,18,24,36,48,54");
2613 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2614 snprintf(buf, sizeof(buf), "%s", "6,12,24");
2615 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2616 }
2617 }
2618
2619 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2620 return RETURN_OK;
2621}
2622
2623INT wifi_setNoscan(INT radioIndex, CHAR *noscan)
2624{
2625 char config_file[64] = {0};
2626 struct params params = {0};
2627 wifi_band band = band_invalid;
2628
2629 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2630
2631 band = wifi_index_to_band(radioIndex);
2632 if (band != band_2_4)
2633 return RETURN_OK;
2634
2635 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2636 params.name = "noscan";
2637 params.value = noscan;
2638 wifi_hostapdWrite(config_file, &params, 1);
2639 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2640
2641 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2642 return RETURN_OK;
2643}
2644
2645//Get the list of supported channel. eg: "1-11"
2646//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.
2647INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2648{
2649 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer69b61b02023-03-07 17:17:44 +08002650 if (NULL == output_string)
developer72fb0bb2023-01-11 09:46:29 +08002651 return RETURN_ERR;
2652 char cmd[256] = {0};
2653 char buf[128] = {0};
2654 BOOL dfs_enable = false;
2655 int phyId = 0;
2656
2657 // Parse possible channel number and separate them with commas.
2658 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
2659 phyId = radio_index_to_phy(radioIndex);
2660 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
2661 if (dfs_enable)
2662 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | grep -v 'no IR\\|5340\\|5480' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'", phyId);
developer69b61b02023-03-07 17:17:44 +08002663 else
developer72fb0bb2023-01-11 09:46:29 +08002664 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | grep -v 'radar\\|no IR\\|5340\\|5480' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'", phyId);
2665
2666 _syscmd(cmd,buf,sizeof(buf));
2667 strncpy(output_string, buf, sizeof(buf));
2668
2669 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2670 return RETURN_OK;
2671}
developerf6a87542023-05-16 15:47:28 +08002672
developer72fb0bb2023-01-11 09:46:29 +08002673//Get the list for used channel. eg: "1,6,9,11"
2674//The output_string is a max length 256 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
2675INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2676{
2677 char interface_name[16] = {0};
2678 char cmd[128] = {0};
2679 char buf[128] = {0};
2680 char config_file[64] = {0};
2681 int channel = 0;
2682 int freq = 0;
2683 int bandwidth = 0;
2684 int center_freq = 0;
2685 int center_channel = 0;
2686 int channel_delta = 0;
2687 wifi_band band = band_invalid;
2688
2689 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2690
2691 if (NULL == output_string)
2692 return RETURN_ERR;
2693
2694 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
2695 return RETURN_ERR;
2696 sprintf(cmd, "iw %s info | grep channel | sed -e 's/[^0-9 ]//g'", interface_name);
2697 _syscmd(cmd, buf, sizeof(buf));
2698 if (strlen(buf) == 0) {
2699 fprintf(stderr, "%s: failed to get channel information from iw.\n", __func__);
2700 return RETURN_ERR;
2701 }
2702 sscanf(buf, "%d %d %d %*d %d", &channel, &freq, &bandwidth, &center_freq);
2703
2704 if (bandwidth == 20) {
2705 snprintf(output_string, 256, "%d", channel);
2706 return RETURN_OK;
2707 }
2708
2709 center_channel = ieee80211_frequency_to_channel(center_freq);
2710
2711 band = wifi_index_to_band(radioIndex);
2712 if (band == band_2_4 && bandwidth == 40) {
2713 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2714 memset(buf, 0, sizeof(buf));
2715 wifi_halgetRadioExtChannel(config_file, buf); // read ht_capab for HT40+ or -
2716
2717 if (strncmp(buf, "AboveControlChannel", strlen("AboveControlChannel")) == 0 && channel < 10) {
2718 snprintf(output_string, 256, "%d,%d", channel, channel+4);
2719 } else if (strncmp(buf, "BelowControlChannel", strlen("BelowControlChannel")) == 0 && channel > 4) {
2720 snprintf(output_string, 256, "%d,%d", channel-4, channel);
2721 } else {
2722 fprintf(stderr, "%s: invalid channel %d set with %s\n.", __func__, channel, buf);
2723 return RETURN_ERR;
2724 }
2725 } else if (band == band_5 || band == band_6){
2726 // to minus 20 is an offset, because frequence of a channel have a range. We need to use offset to calculate correct channel.
developer40ba1762023-05-13 11:03:49 +08002727 // example: bandwidth 80: center is 42 (5210), channels are "36,40,44,48" (5170-5250). The delta should be 6.
developer72fb0bb2023-01-11 09:46:29 +08002728 channel_delta = (bandwidth-20)/10;
developer40ba1762023-05-13 11:03:49 +08002729 memset(output_string, 0, 256);
2730 for (int i = center_channel-channel_delta; i <= center_channel+channel_delta; i+=4) {
2731 // If i is not the last channel, we add a comma.
2732 snprintf(buf, sizeof(buf), "%d%s", i, i==center_channel+channel_delta?"":",");
2733 strncat(output_string, buf, strlen(buf));
2734 }
developer72fb0bb2023-01-11 09:46:29 +08002735 } else
2736 return RETURN_ERR;
2737
2738 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
2739 return RETURN_OK;
2740}
2741
developer69b61b02023-03-07 17:17:44 +08002742//Get the running channel number
developer72fb0bb2023-01-11 09:46:29 +08002743INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
2744{
2745 char channel_str[16] = {0};
2746 char config_file[128] = {0};
2747
2748 if (output_ulong == NULL)
2749 return RETURN_ERR;
2750
2751 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2752 wifi_hostapdRead(config_file, "channel", channel_str, sizeof(channel_str));
2753
2754 *output_ulong = strtoul(channel_str, NULL, 10);
2755
2756 return RETURN_OK;
2757}
2758
2759
2760INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2761{
2762 char cmd[1024] = {0}, buf[5] = {0};
2763 char interface_name[16] = {0};
2764
2765 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2766 if (NULL == output_ulong)
2767 return RETURN_ERR;
2768
2769 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
2770 if (wifi_getApName(apIndex,interface_name) != RETURN_OK)
2771 return RETURN_ERR;
2772 _syscmd(cmd,buf,sizeof(buf));
2773 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2774 if (*output_ulong == 0) {
2775 return RETURN_ERR;
2776 }
2777
2778 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2779 return RETURN_OK;
2780}
2781
2782//Storing the previous channel value
2783INT wifi_storeprevchanval(INT radioIndex)
2784{
2785 char buf[256] = {0};
2786 char output[4]={'\0'};
2787 char config_file[MAX_BUF_SIZE] = {0};
2788 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2789 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2790 if(radioIndex == 0)
2791 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2792 else if(radioIndex == 1)
2793 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2794 system(buf);
2795 Radio_flag = FALSE;
2796 return RETURN_OK;
2797}
2798
2799//Set the running channel number
2800INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2801{
2802 // We only write hostapd config here
2803 char str_channel[8]={0};
2804 char *list_channel;
2805 char config_file[128] = {0};
2806 char possible_channels[256] = {0};
2807 int max_radio_num = 0;
2808 struct params list = {0};
2809
2810 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2811
2812 // Check valid
2813 sprintf(str_channel, "%lu", channel);
2814
2815 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
2816 list_channel = strtok(possible_channels, ",");
2817 while(true)
2818 {
2819 if(list_channel == NULL) { // input not in the list
2820 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
2821 return RETURN_ERR;
2822 }
2823 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
2824 break;
2825 list_channel = strtok(NULL, ",");
2826 }
developerf6a87542023-05-16 15:47:28 +08002827
developer72fb0bb2023-01-11 09:46:29 +08002828 list.name = "channel";
2829 list.value = str_channel;
2830 wifi_getMaxRadioNumber(&max_radio_num);
2831 for(int i=0; i<=MAX_APS/max_radio_num;i++)
2832 {
2833 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2834 wifi_hostapdWrite(config_file, &list, 1);
2835 }
developerf6a87542023-05-16 15:47:28 +08002836
developer72fb0bb2023-01-11 09:46:29 +08002837 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
2838 return RETURN_OK;
2839}
2840
2841INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2842{
2843 struct params list[2];
2844 char str_idx[16];
2845 char config_file[64];
2846 int max_num_radios = 0;
2847 wifi_band band = band_invalid;
2848
2849 band = wifi_index_to_band(radioIndex);
2850 if (band == band_2_4)
2851 return RETURN_OK;
2852
2853 snprintf(str_idx, sizeof(str_idx), "%lu", channel);
2854 list[0].name = "vht_oper_centr_freq_seg0_idx";
2855 list[0].value = str_idx;
2856 list[1].name = "he_oper_centr_freq_seg0_idx";
2857 list[1].value = str_idx;
2858
2859 wifi_getMaxRadioNumber(&max_num_radios);
2860 for(int i=0; i<=MAX_APS/max_num_radios; i++)
2861 {
2862 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
2863 if (band == band_6)
2864 wifi_hostapdWrite(config_file, &list[1], 1);
2865 else
2866 wifi_hostapdWrite(config_file, list, 2);
2867 }
2868
2869 return RETURN_OK;
2870}
2871
2872//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2873//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2874INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2875{
2876 //Set to wifi config only. Wait for wifi reset to apply.
2877 char buf[256] = {0};
2878 char str_channel[256] = {0};
2879 int count = 0;
2880 ULONG Value = 0;
2881 FILE *fp = NULL;
2882 if(enable == TRUE)
2883 {
2884 wifi_setRadioChannel(radioIndex,Value);
2885 }
2886 return RETURN_OK;
2887}
2888
2889INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
2890{
2891 if (output_bool == NULL)
2892 return RETURN_ERR;
2893
2894 *output_bool = TRUE;
2895
2896 return RETURN_OK;
2897}
2898
2899INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2900{
developer69b61b02023-03-07 17:17:44 +08002901 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08002902 return RETURN_ERR;
2903 *output_bool=FALSE;
2904 return RETURN_OK;
2905}
2906
2907INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2908{
developer69b61b02023-03-07 17:17:44 +08002909 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08002910 return RETURN_ERR;
2911 *output_bool=FALSE;
2912 return RETURN_OK;
2913}
2914
2915INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2916{
2917 //Set to wifi config only. Wait for wifi reset to apply.
2918 return RETURN_OK;
2919}
2920
2921INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2922{
2923 return RETURN_OK;
2924}
2925
2926INT wifi_factoryResetAP(int apIndex)
2927{
2928 char ap_config_file[64] = {0};
2929 char cmd[128] = {0};
2930
2931 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2932
2933 wifi_setApEnable(apIndex, FALSE);
2934 sprintf(ap_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
2935 sprintf(cmd, "rm %s && sh /lib/rdk/hostapd-init.sh", ap_config_file);
2936 wifi_setApEnable(apIndex, TRUE);
2937
2938 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2939
2940 return RETURN_OK;
2941}
2942
2943//To set Band Steering AP group
2944//To-do
2945INT wifi_setBandSteeringApGroup(char *ApGroup)
2946{
2947 return RETURN_OK;
2948}
2949
2950INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2951{
2952 char config_file[128] = {'\0'};
2953 char buf[128] = {'\0'};
2954
2955 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2956 if (dtimInterval == NULL)
2957 return RETURN_ERR;
2958
2959 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2960 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2961
2962 if (strlen(buf) == 0) {
2963 *dtimInterval = 2;
2964 } else {
2965 *dtimInterval = strtoul(buf, NULL, 10);
2966 }
2967
2968 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2969 return RETURN_OK;
2970}
2971
2972INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2973{
2974 struct params params={0};
2975 char config_file[MAX_BUF_SIZE] = {'\0'};
2976 char buf[MAX_BUF_SIZE] = {'\0'};
2977
2978 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2979 if (dtimInterval < 1 || dtimInterval > 255) {
2980 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
2981 return RETURN_ERR;
2982 }
developer69b61b02023-03-07 17:17:44 +08002983
developer72fb0bb2023-01-11 09:46:29 +08002984 params.name = "dtim_period";
2985 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2986 params.value = buf;
2987
2988 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2989 wifi_hostapdWrite(config_file, &params, 1);
2990 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2991
2992 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2993 return RETURN_OK;
2994}
2995
2996//Check if the driver support the Dfs
2997INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2998{
2999 wifi_band band = band_invalid;
developer69b61b02023-03-07 17:17:44 +08003000 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08003001 return RETURN_ERR;
3002 *output_bool=FALSE;
3003
3004 band = wifi_index_to_band(radioIndex);
3005 if (band == band_5)
3006 *output_bool = TRUE;
3007 return RETURN_OK;
3008}
3009
3010//The output_string is a max length 256 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
3011//The value of this parameter is a comma seperated list of channel number
3012INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
3013{
developer69b61b02023-03-07 17:17:44 +08003014 if (NULL == output_pool)
developer72fb0bb2023-01-11 09:46:29 +08003015 return RETURN_ERR;
3016 if (radioIndex==1)
developer69b61b02023-03-07 17:17:44 +08003017 return RETURN_OK;//TODO need to handle for 5GHz band, i think
developer72fb0bb2023-01-11 09:46:29 +08003018 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
3019
3020 return RETURN_OK;
3021}
3022
3023INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
3024{
3025 //Set to wifi config. And apply instantly.
3026 return RETURN_OK;
3027}
3028
3029INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
3030{
developer69b61b02023-03-07 17:17:44 +08003031 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
developer72fb0bb2023-01-11 09:46:29 +08003032 return RETURN_ERR;
3033 *output_interval_seconds=1800;
3034 *output_dwell_milliseconds=40;
3035
3036 return RETURN_OK;
3037}
3038
3039INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
3040{
3041 //Set to wifi config. And apply instantly.
3042 return RETURN_OK;
3043}
3044
3045INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
3046{
3047 if (output_bool == NULL)
3048 return RETURN_ERR;
developer69b61b02023-03-07 17:17:44 +08003049 *output_bool = true;
3050 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08003051}
3052
3053INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
3054{
3055 return RETURN_OK;
3056}
3057
3058//Get the Dfs enable status
3059INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
3060{
3061 char buf[16] = {0};
3062 FILE *f = NULL;
3063
3064 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3065
3066 if (output_bool == NULL)
3067 return RETURN_ERR;
developer4903e3f2023-05-15 10:04:40 +08003068
developerf6a87542023-05-16 15:47:28 +08003069 *output_bool = TRUE; // default
3070 f = fopen(DFS_ENABLE_FILE, "r");
3071 if (f != NULL) {
3072 fgets(buf, 2, f);
3073 if (strncmp(buf, "0", 1) == 0)
3074 *output_bool = FALSE;
3075 fclose(f);
3076 }
developer72fb0bb2023-01-11 09:46:29 +08003077 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3078 return RETURN_OK;
3079}
3080
3081//Set the Dfs enable status
3082INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
3083{
3084 char config_file[128] = {0};
3085 FILE *f = NULL;
developerf6a87542023-05-16 15:47:28 +08003086 struct params params={0};
developer72fb0bb2023-01-11 09:46:29 +08003087
3088 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3089
3090 f = fopen(DFS_ENABLE_FILE, "w");
3091 if (f == NULL)
3092 return RETURN_ERR;
3093 fprintf(f, "%d", enable);
3094 fclose(f);
3095
3096 params.name = "acs_exclude_dfs";
3097 params.value = enable?"0":"1";
3098 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3099 wifi_hostapdWrite(config_file, &params, 1);
3100 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
developerf6a87542023-05-16 15:47:28 +08003101
developer72fb0bb2023-01-11 09:46:29 +08003102 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
3103
3104 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3105 return RETURN_OK;
3106}
3107
3108//Check if the driver support the AutoChannelRefreshPeriod
3109INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
3110{
developer69b61b02023-03-07 17:17:44 +08003111 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08003112 return RETURN_ERR;
3113 *output_bool=FALSE; //not support
3114
3115 return RETURN_OK;
3116}
3117
3118//Get the ACS refresh period in seconds
3119INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
3120{
developer69b61b02023-03-07 17:17:44 +08003121 if (NULL == output_ulong)
developer72fb0bb2023-01-11 09:46:29 +08003122 return RETURN_ERR;
3123 *output_ulong=300;
3124
3125 return RETURN_OK;
3126}
3127
3128//Set the ACS refresh period in seconds
3129INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
3130{
3131 return RETURN_ERR;
3132}
3133
3134//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
3135//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.
3136INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
3137{
developer8666b312023-03-24 14:05:31 +08003138 char cmd[MAX_CMD_SIZE] = {0}, buf[64] = {0};
developer72fb0bb2023-01-11 09:46:29 +08003139 char extchannel[128] = {0};
developer8666b312023-03-24 14:05:31 +08003140 char interface_name[64] = {0};
3141 int ret = 0, len=0;
developer72fb0bb2023-01-11 09:46:29 +08003142 BOOL radio_enable = FALSE;
3143 wifi_band band;
3144
3145 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3146
3147 if (NULL == output_string)
3148 return RETURN_ERR;
3149
3150 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
3151 return RETURN_ERR;
3152
3153 if (radio_enable != TRUE)
3154 return RETURN_OK;
3155
developer8666b312023-03-24 14:05:31 +08003156 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3157 return RETURN_ERR;
3158 /*IW command get BW320 to do*/
3159 snprintf(cmd, sizeof(cmd),"iw dev %s info | grep 'width' | cut -d ' ' -f6 | tr -d '\\n'", interface_name);
3160 ret = _syscmd(cmd, buf, sizeof(buf));
3161 len = strlen(buf);
3162 if((ret != 0) || (len == 0))
3163 {
3164 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
3165 return RETURN_ERR;
3166 }
3167
developer72fb0bb2023-01-11 09:46:29 +08003168 band = wifi_index_to_band(radioIndex);
developer8666b312023-03-24 14:05:31 +08003169 if (band == band_2_4 && strncmp(buf, "20", 2) == 0) {
developer72fb0bb2023-01-11 09:46:29 +08003170 wifi_getRadioExtChannel(radioIndex, extchannel);
developer8666b312023-03-24 14:05:31 +08003171 if (strncmp(extchannel, "Auto", 4) != 0) // not auto means we have set HT40+/-
3172 snprintf(buf, sizeof(buf), "40");
developer72fb0bb2023-01-11 09:46:29 +08003173 }
developer8666b312023-03-24 14:05:31 +08003174 snprintf(output_string, 64, "%sMHz", buf);
developer72fb0bb2023-01-11 09:46:29 +08003175 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3176
3177 return RETURN_OK;
3178}
developer72fb0bb2023-01-11 09:46:29 +08003179//Set the Operating Channel Bandwidth.
3180INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
3181{
3182 char config_file[128];
3183 char set_value[16];
3184 struct params params[2];
3185 int max_radio_num = 0;
3186
3187 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3188
3189 if(NULL == bandwidth)
3190 return RETURN_ERR;
3191
3192 if(strstr(bandwidth,"160") != NULL)
3193 strcpy(set_value, "2");
3194 else if(strstr(bandwidth,"80") != NULL)
3195 strcpy(set_value, "1");
3196 else if(strstr(bandwidth,"20") != NULL || strstr(bandwidth,"40") != NULL)
3197 strcpy(set_value, "0");
3198 else
3199 {
3200 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
3201 return RETURN_ERR;
3202 }
3203
3204 params[0].name = "vht_oper_chwidth";
3205 params[0].value = set_value;
3206 params[1].name = "he_oper_chwidth";
3207 params[1].value = set_value;
3208
3209 wifi_getMaxRadioNumber(&max_radio_num);
3210 for(int i=0; i<=MAX_APS/max_radio_num; i++)
3211 {
3212 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
3213 wifi_hostapdWrite(config_file, params, 2);
3214 }
3215
3216 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3217 return RETURN_OK;
3218}
3219
developerf6a87542023-05-16 15:47:28 +08003220//Getting current radio extension channel
3221INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
3222{
3223 CHAR buf[150] = {0};
3224 CHAR cmd[150] = {0};
3225 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
3226 _syscmd(cmd, buf, sizeof(buf));
3227 if(NULL != strstr(buf,"HT40+"))
3228 strcpy(Value,"AboveControlChannel");
3229 else if(NULL != strstr(buf,"HT40-"))
3230 strcpy(Value,"BelowControlChannel");
3231 return RETURN_OK;
3232}
developer72fb0bb2023-01-11 09:46:29 +08003233
3234//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
3235//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.
3236INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
3237{
3238 char config_file[64] = {0};
3239 char mode_str[16] = {0};
3240 char buf[64] = {0};
3241 wifi_band band;
developerf6a87542023-05-16 15:47:28 +08003242 int channel = 0, centr_channel = 0;
developer72fb0bb2023-01-11 09:46:29 +08003243 UINT mode_map = 0;
3244
3245 if (output_string == NULL)
3246 return RETURN_ERR;
3247
3248 wifi_getRadioMode(radioIndex, mode_str, &mode_map);
3249
3250 band = wifi_index_to_band(radioIndex);
3251 if (band == band_invalid)
3252 return RETURN_ERR;
3253
3254 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
3255
3256 snprintf(output_string, 64, "Auto");
developer23e71282023-01-18 10:25:19 +08003257 if (band == band_2_4 || (!(mode_map&WIFI_MODE_AC) && !(mode_map&WIFI_MODE_AX))) {
developer72fb0bb2023-01-11 09:46:29 +08003258 // 2G band or ac and ax mode is disable, we will check ht_capab
3259 wifi_halgetRadioExtChannel(config_file, output_string);
developer23e71282023-01-18 10:25:19 +08003260 if (!(mode_map&WIFI_MODE_N))
developer72fb0bb2023-01-11 09:46:29 +08003261 snprintf(output_string, 64, "Auto");
3262 } else {
3263 // 5G and 6G band with ac or ax mode.
3264 wifi_getRadioChannel(radioIndex, &channel);
3265 if (mode_map&WIFI_MODE_AX)
3266 wifi_hostapdRead(config_file, "he_oper_centr_freq_seg0_idx", buf, sizeof(buf));
3267 else
3268 wifi_hostapdRead(config_file, "vht_oper_centr_freq_seg0_idx", buf, sizeof(buf));
3269 centr_channel = strtol(buf, NULL, 10);
3270 if (centr_channel > channel)
3271 snprintf(output_string, 64, "AboveControlChannel");
3272 else
3273 snprintf(output_string, 64, "BelowControlChannel");
3274 }
3275
3276 return RETURN_OK;
3277}
3278
3279//Set the extension channel.
3280INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
developer69b61b02023-03-07 17:17:44 +08003281{
developer72fb0bb2023-01-11 09:46:29 +08003282 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3283 struct params params={0};
3284 char config_file[64] = {0};
3285 char ext_channel[128]={0};
3286 char buf[128] = {0};
3287 char cmd[128] = {0};
3288 int max_radio_num =0, ret = 0, bandwidth = 0;
3289 unsigned long channel = 0, centr_channel = 0;
3290 bool stbcEnable = FALSE;
3291 params.name = "ht_capab";
3292 wifi_band band;
3293
3294 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3295 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
3296 _syscmd(cmd, buf, sizeof(buf));
3297 if (strlen(buf) != 0)
3298 stbcEnable = TRUE;
3299 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, buf) != RETURN_OK)
3300 return RETURN_ERR;
3301 bandwidth = strtol(buf, NULL, 10);
3302 // TDK expected to get error with 20MHz
3303 if (bandwidth == 20 || strstr(buf, "80+80") != NULL)
3304 return RETURN_ERR;
3305
3306 band = wifi_index_to_band(radioIndex);
3307 if (band == band_invalid)
3308 return RETURN_ERR;
3309
3310 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK)
3311 return RETURN_ERR;
3312
3313 if (band == band_5) {
3314 snprintf(buf, sizeof(buf), "HT%d", bandwidth);
3315 centr_channel = util_unii_5g_centerfreq(buf, channel);
3316 if (centr_channel == 0)
3317 return RETURN_ERR;
3318 }
3319
3320 if(NULL!= strstr(string,"Above")) {
3321 if ((band == band_2_4 && channel > 9) || (band == band_5 && channel > centr_channel))
3322 return RETURN_ERR;
3323 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
3324 } else if(NULL!= strstr(string,"Below")) {
3325 if ((band == band_2_4 && channel < 5) || (band == band_5 && channel < centr_channel))
3326 return RETURN_ERR;
3327 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
3328 } else {
3329 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
3330 }
3331
3332 params.value = ext_channel;
3333
3334 wifi_getMaxRadioNumber(&max_radio_num);
3335 for(int i=0; i<=MAX_APS/max_radio_num; i++)
3336 {
3337 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(max_radio_num*i));
3338 wifi_hostapdWrite(config_file, &params, 1);
3339 wifi_setRadioSTBCEnable(radioIndex+(max_radio_num*i), stbcEnable);
3340 }
3341
3342 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
3343 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3344 return RETURN_OK;
3345}
3346
3347//Get the guard interval value. eg "400nsec" or "800nsec"
3348//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.
3349INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
3350{
3351 wifi_guard_interval_t GI;
3352
3353 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3354
3355 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
3356 return RETURN_ERR;
3357
3358 if (GI == wifi_guard_interval_400)
3359 strcpy(output_string, "400nsec");
3360 else if (GI == wifi_guard_interval_800)
3361 strcpy(output_string, "800nsec");
3362 else if (GI == wifi_guard_interval_1600)
3363 strcpy(output_string, "1600nsec");
3364 else if (GI == wifi_guard_interval_3200)
3365 strcpy(output_string, "3200nsec");
3366 else
3367 strcpy(output_string, "Auto");
3368
3369 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3370 return RETURN_OK;
3371}
3372
3373//Set the guard interval value.
3374INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
3375{
3376 wifi_guard_interval_t GI;
3377 int ret = 0;
3378
3379 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3380
3381 if (strcmp(string, "400nsec") == 0)
3382 GI = wifi_guard_interval_400;
3383 else if (strcmp(string , "800nsec") == 0)
3384 GI = wifi_guard_interval_800;
3385 else if (strcmp(string , "1600nsec") == 0)
3386 GI = wifi_guard_interval_1600;
3387 else if (strcmp(string , "3200nsec") == 0)
3388 GI = wifi_guard_interval_3200;
3389 else
3390 GI = wifi_guard_interval_auto;
3391
3392 ret = wifi_setGuardInterval(radioIndex, GI);
3393
3394 if (ret == RETURN_ERR) {
3395 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
3396 return RETURN_ERR;
3397 }
3398
3399 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3400 return RETURN_OK;
3401}
3402
3403//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
3404INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
3405{
3406 char buf[32]={0};
3407 char mcs_file[64] = {0};
3408 char cmd[64] = {0};
3409 int mode_bitmap = 0;
3410
3411 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3412 if(output_int == NULL)
3413 return RETURN_ERR;
3414 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
3415
3416 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
3417 _syscmd(cmd, buf, sizeof(buf));
3418 if (strlen(buf) > 0)
3419 *output_int = strtol(buf, NULL, 10);
3420 else {
3421 // output the max MCS for the current radio mode
3422 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
3423 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
3424 return RETURN_ERR;
3425 }
3426 if (mode_bitmap & WIFI_MODE_AX) {
3427 *output_int = 11;
3428 } else if (mode_bitmap & WIFI_MODE_AC) {
3429 *output_int = 9;
3430 } else if (mode_bitmap & WIFI_MODE_N) {
3431 *output_int = 7;
3432 }
3433 }
3434 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3435
3436 return RETURN_OK;
3437}
3438
3439//Set the Modulation Coding Scheme index
3440INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
3441{
developera1255e42023-05-13 17:45:02 +08003442 /*Only HE mode can specify MCS capability. We don't support MCS in HT mode,
3443 because that would be ambiguous (MCS code 8~11 refer to 2 NSS in HT but 1 NSS in HE adn VHT).*/
developer72fb0bb2023-01-11 09:46:29 +08003444 char config_file[64] = {0};
3445 char set_value[16] = {0};
3446 char mcs_file[32] = {0};
developer72fb0bb2023-01-11 09:46:29 +08003447 struct params set_config = {0};
3448 FILE *f = NULL;
developera1255e42023-05-13 17:45:02 +08003449 INT nss = 0;
3450 int ant_bitmap = 0;
3451 unsigned short cal_value = 0;
3452 UCHAR tval = 0, i = 0;
developer72fb0bb2023-01-11 09:46:29 +08003453
3454 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3455
3456 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
3457
3458 // -1 means auto
3459 if (MCS > 15 || MCS < -1) {
3460 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
3461 return RETURN_ERR;
3462 }
developera1255e42023-05-13 17:45:02 +08003463 wifi_getRadioTxChainMask(radioIndex, &ant_bitmap);/*nss is a bit map value,1111*/
3464 for(; ant_bitmap > 0; ant_bitmap >>= 1)
3465 nss += 1;
3466 //printf("%s:nss = %d\n", __func__, nss);
3467 /*16-bit combination of 2-bit values of Max HE-MCS For 1..8 SS;each 2-bit value have following meaning:
3468 0 = HE-MCS 0-7, 1 = HE-MCS 0-9, 2 = HE-MCS 0-11, 3 = not supported*/
developer72fb0bb2023-01-11 09:46:29 +08003469 if (MCS > 9 || MCS == -1)
developera1255e42023-05-13 17:45:02 +08003470 tval = 2;/*one stream value*/
developer72fb0bb2023-01-11 09:46:29 +08003471 else if (MCS > 7)
developera1255e42023-05-13 17:45:02 +08003472 tval = 1;
developer72fb0bb2023-01-11 09:46:29 +08003473 else
developera1255e42023-05-13 17:45:02 +08003474 tval = 0;
3475 for (i = 0; i < nss; i++)
3476 cal_value |= (tval << (2*i));
3477 snprintf(set_value, sizeof(set_value), "%x", cal_value);
3478 WIFI_ENTRY_EXIT_DEBUG("%s:set=%s, cal=%x\n", __func__, set_value, cal_value);
3479 set_config.name = "he_basic_mcs_nss_set";/*He capability in beacon or response*/
developer72fb0bb2023-01-11 09:46:29 +08003480 set_config.value = set_value;
3481
3482 wifi_hostapdWrite(config_file, &set_config, 1);
3483 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
3484
3485 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
3486 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
3487 f = fopen(mcs_file, "w");
3488 if (f == NULL) {
3489 fprintf(stderr, "%s: fopen failed\n", __func__);
3490 return RETURN_ERR;
3491 }
3492 fprintf(f, "%d", MCS);
3493 fclose(f);
3494
3495 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3496 return RETURN_OK;
3497}
3498
3499//Get supported Transmit Power list, eg : "0,25,50,75,100"
3500//The output_list is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
3501INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
3502{
3503 if (NULL == output_list)
3504 return RETURN_ERR;
3505 snprintf(output_list, 64,"0,25,50,75,100");
3506 return RETURN_OK;
3507}
3508
3509//Get current Transmit Power in dBm units.
3510//The transmite power level is in units of full power for this radio.
3511INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
3512{
3513 char interface_name[16] = {0};
3514 char cmd[128]={0};
3515 char buf[16]={0};
developera1255e42023-05-13 17:45:02 +08003516 char pwr_file[128]={0};
3517
developer72fb0bb2023-01-11 09:46:29 +08003518 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3519
3520 if(output_ulong == NULL)
3521 return RETURN_ERR;
3522
3523 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3524 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +08003525/*
developer72fb0bb2023-01-11 09:46:29 +08003526 snprintf(cmd, sizeof(cmd), "iw %s info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", interface_name);
3527 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08003528 *output_ulong = strtol(buf, NULL, 10);
developera1255e42023-05-13 17:45:02 +08003529*/
3530 snprintf(pwr_file, sizeof(pwr_file), "%s%d.txt", POWER_PERCENTAGE, radioIndex);
3531 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", pwr_file);
3532 _syscmd(cmd, buf, sizeof(buf));
3533 if (strlen(buf) > 0)
3534 *output_ulong = strtol(buf, NULL, 10);
3535 else
3536 *output_ulong = 100;
developer72fb0bb2023-01-11 09:46:29 +08003537 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3538 return RETURN_OK;
3539}
3540
3541//Set Transmit Power
3542//The transmite power level is in units of full power for this radio.
3543INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
3544{
3545 char interface_name[16] = {0};
3546 char *support;
3547 char cmd[128]={0};
3548 char buf[128]={0};
3549 char txpower_str[64] = {0};
developera1255e42023-05-13 17:45:02 +08003550 char pwr_file[128]={0};
3551 FILE *f = NULL;
developer72fb0bb2023-01-11 09:46:29 +08003552
3553 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3554
3555 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3556 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +08003557 // Get the Tx power supported list and check that is the input in the list
3558 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
3559 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
3560 support = strtok(buf, ",");
3561 while(true)
3562 {
3563 if(support == NULL) { // input not in the list
3564 wifi_dbg_printf("Input value is invalid.\n");
3565 return RETURN_ERR;
3566 }
3567 if (strncmp(txpower_str, support, strlen(support)) == 0) {
3568 break;
3569 }
3570 support = strtok(NULL, ",");
3571 }
3572 snprintf(cmd, sizeof(cmd), "mwctl dev %s set pwr PercentageCtrl=1\n", interface_name);
3573 _syscmd(cmd, buf, sizeof(buf));
3574 snprintf(cmd, sizeof(cmd), "mwctl dev %s set pwr PowerDropCtrl=%lu\n", interface_name, TransmitPower);
3575 _syscmd(cmd, buf, sizeof(buf));
3576 snprintf(pwr_file, sizeof(pwr_file), "%s%d.txt", POWER_PERCENTAGE, radioIndex);
3577 f = fopen(pwr_file, "w");
3578 if (f == NULL) {
3579 fprintf(stderr, "%s: fopen failed\n", __func__);
3580 return RETURN_ERR;
3581 }
3582 fprintf(f, "%d", TransmitPower);
3583 fclose(f);
3584/* snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", interface_name);
developer72fb0bb2023-01-11 09:46:29 +08003585 _syscmd(cmd, buf, sizeof(buf));
3586 maximum_tx = strtol(buf, NULL, 10);
3587
3588 // Get the Tx power supported list and check that is the input in the list
3589 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
3590 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
3591 support = strtok(buf, ",");
3592 while(true)
3593 {
3594 if(support == NULL) { // input not in the list
3595 wifi_dbg_printf("Input value is invalid.\n");
3596 return RETURN_ERR;
3597 }
3598 if (strncmp(txpower_str, support, strlen(support)) == 0) {
3599 break;
3600 }
3601 support = strtok(NULL, ",");
3602 }
3603 txpower = TransmitPower*maximum_tx/100;
3604 phyId = radio_index_to_phy(radioIndex);
3605 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", phyId, txpower);
3606 _syscmd(cmd, buf, sizeof(buf));
3607 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera1255e42023-05-13 17:45:02 +08003608*/
3609 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08003610}
3611
3612//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
3613INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
3614{
developer69b61b02023-03-07 17:17:44 +08003615 if (NULL == Supported)
developer72fb0bb2023-01-11 09:46:29 +08003616 return RETURN_ERR;
3617 *Supported = TRUE;
3618
3619 return RETURN_OK;
3620}
3621
3622//Get 80211h feature enable
3623INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
3624{
3625 char buf[64]={'\0'};
3626 char config_file[64] = {'\0'};
3627
3628 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3629 if(enable == NULL)
3630 return RETURN_ERR;
3631
3632 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3633 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
3634
3635 if (strncmp(buf, "1", 1) == 0)
3636 *enable = TRUE;
3637 else
3638 *enable = FALSE;
3639
3640 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3641 return RETURN_OK;
3642}
3643
3644//Set 80211h feature enable
3645INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
3646{
3647 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3648 struct params params={'\0'};
3649 char config_file[MAX_BUF_SIZE] = {0};
3650
3651 params.name = "ieee80211h";
3652
3653 if (enable) {
3654 params.value = "1";
3655 } else {
3656 params.value = "0";
3657 }
3658
3659 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3660 wifi_hostapdWrite(config_file, &params, 1);
developer69b61b02023-03-07 17:17:44 +08003661
developer72fb0bb2023-01-11 09:46:29 +08003662 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3663 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3664 return RETURN_OK;
3665}
3666
3667//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.
3668INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
3669{
3670 if (NULL == output)
3671 return RETURN_ERR;
3672 *output=100;
3673
3674 return RETURN_OK;
3675}
3676
3677//The RSSI signal level at which CS/CCA detects a busy condition. This attribute enables APs to increase minimum sensitivity to avoid detecting busy condition from multiple/weak Wi-Fi sources in dense Wi-Fi environments. It is measured in dBm. Refer section A.2.3.2 of CableLabs Wi-Fi MGMT Specification.
3678INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
3679{
3680 if (NULL == output)
3681 return RETURN_ERR;
3682 *output = -99;
3683
3684 return RETURN_OK;
3685}
3686
3687INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
3688{
3689 return RETURN_ERR;
3690}
3691
3692
3693//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
3694INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
3695{
3696 char interface_name[16] = {0};
3697 char cmd[MAX_BUF_SIZE]={'\0'};
3698 char buf[MAX_CMD_SIZE]={'\0'};
3699
3700 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3701 if(output == NULL)
3702 return RETURN_ERR;
3703
3704 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3705 return RETURN_ERR;
3706 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", interface_name);
3707 _syscmd(cmd, buf, sizeof(buf));
3708 *output = atoi(buf);
3709
3710 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3711 return RETURN_OK;
3712}
developer69b61b02023-03-07 17:17:44 +08003713
developer72fb0bb2023-01-11 09:46:29 +08003714INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
3715{
3716 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3717 struct params params={'\0'};
3718 char buf[MAX_BUF_SIZE] = {'\0'};
3719 char config_file[MAX_BUF_SIZE] = {'\0'};
3720
3721 if (BeaconPeriod < 15 || BeaconPeriod > 65535)
3722 return RETURN_ERR;
3723
3724 params.name = "beacon_int";
3725 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
3726 params.value = buf;
3727
3728 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3729 wifi_hostapdWrite(config_file, &params, 1);
developer69b61b02023-03-07 17:17:44 +08003730
developer72fb0bb2023-01-11 09:46:29 +08003731 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3732 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3733 return RETURN_OK;
3734}
3735
3736//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.
3737INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
3738{
3739 //TODO: need to revisit below implementation
3740 char *temp;
3741 char temp_output[128] = {0};
3742 char temp_TransmitRates[64] = {0};
3743 char config_file[64] = {0};
3744
3745 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3746 if (NULL == output)
3747 return RETURN_ERR;
3748 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3749 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
developer69b61b02023-03-07 17:17:44 +08003750
developer72fb0bb2023-01-11 09:46:29 +08003751 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
3752 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
3753 } else {
3754 temp = strtok(temp_TransmitRates," ");
3755 while(temp!=NULL)
3756 {
3757 // Convert 100 kbps to Mbps
3758 temp[strlen(temp)-1]=0;
3759 if((temp[0]=='5') && (temp[1]=='\0'))
3760 {
3761 temp="5.5";
3762 }
3763 strcat(temp_output,temp);
3764 temp = strtok(NULL," ");
3765 if(temp!=NULL)
3766 {
3767 strcat(temp_output,",");
3768 }
3769 }
3770 strcpy(output,temp_output);
3771 }
3772 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3773 return RETURN_OK;
3774}
3775
3776INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
3777{
3778 char *temp;
3779 char temp1[128];
3780 char temp_output[128];
3781 char temp_TransmitRates[128];
3782 char set[128];
3783 char sub_set[128];
3784 int set_count=0,subset_count=0;
3785 int set_index=0,subset_index=0;
3786 char *token;
3787 int flag=0, i=0;
3788 struct params params={'\0'};
3789 char config_file[MAX_BUF_SIZE] = {0};
3790 wifi_band band = wifi_index_to_band(radioIndex);
3791
3792 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3793 if(NULL == TransmitRates)
3794 return RETURN_ERR;
3795 strcpy(sub_set,TransmitRates);
3796
3797 //Allow only supported Data transmit rate to be set
3798 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3799 token = strtok(sub_set,",");
3800 while( token != NULL ) /* split the basic rate to be set, by comma */
3801 {
3802 sub_set[subset_count]=atoi(token);
3803 subset_count++;
3804 token=strtok(NULL,",");
3805 }
3806 token=strtok(set,",");
3807 while(token!=NULL) /* split the supported rate by comma */
3808 {
3809 set[set_count]=atoi(token);
3810 set_count++;
3811 token=strtok(NULL,",");
3812 }
3813 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3814 {
3815 for(set_index=0;set_index < set_count;set_index++)
3816 {
3817 flag=0;
3818 if(sub_set[subset_index]==set[set_index])
3819 break;
3820 else
3821 flag=1; /* No match found */
3822 }
3823 if(flag==1)
3824 return RETURN_ERR; //If value not found return Error
3825 }
3826 strcpy(temp_TransmitRates,TransmitRates);
3827
3828 for(i=0;i<strlen(temp_TransmitRates);i++)
3829 {
3830 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
3831 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
3832 {
3833 continue;
3834 }
3835 else
3836 {
3837 return RETURN_ERR;
3838 }
3839 }
3840 strcpy(temp_output,"");
3841 temp = strtok(temp_TransmitRates,",");
3842 while(temp!=NULL)
3843 {
3844 strcpy(temp1,temp);
3845 if(band == band_5)
3846 {
3847 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
3848 {
3849 return RETURN_ERR;
3850 }
3851 }
3852
3853 if(strcmp(temp,"5.5")==0)
3854 {
3855 strcpy(temp1,"55");
3856 }
3857 else
3858 {
3859 strcat(temp1,"0");
3860 }
3861 strcat(temp_output,temp1);
3862 temp = strtok(NULL,",");
3863 if(temp!=NULL)
3864 {
3865 strcat(temp_output," ");
3866 }
3867 }
3868 strcpy(TransmitRates,temp_output);
3869
3870 params.name= "basic_rates";
3871 params.value =TransmitRates;
3872
3873 wifi_dbg_printf("\n%s:",__func__);
3874 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3875 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3876 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3877 wifi_hostapdWrite(config_file,&params,1);
3878 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3879 return RETURN_OK;
3880}
3881
3882//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
3883INT wifi_GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
3884{
3885 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3886 FILE *fp = NULL;
3887 char path[256] = {0}, output_string[256] = {0};
3888 int count = 0;
3889 char *interface = NULL;
3890
3891 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3892 if (fp == NULL)
3893 {
3894 printf("Failed to run command in Function %s\n", __FUNCTION__);
3895 return RETURN_ERR;
3896 }
3897 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3898 {
3899 interface = strchr(path, '=');
3900
3901 if (interface != NULL)
3902 {
3903 strcpy(output_string, interface + 1);
3904 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
3905 interface_name[count] = output_string[count];
3906
3907 interface_name[count] = '\0';
3908 }
3909 }
3910 pclose(fp);
3911 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3912 return RETURN_OK;
3913}
3914
3915INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3916{
3917 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3918 output_struct->radio_BytesSent = 0;
3919 output_struct->radio_BytesReceived = 0;
3920 output_struct->radio_PacketsSent = 0;
3921 output_struct->radio_PacketsReceived = 0;
3922 output_struct->radio_ErrorsSent = 0;
3923 output_struct->radio_ErrorsReceived = 0;
3924 output_struct->radio_DiscardPacketsSent = 0;
3925 output_struct->radio_DiscardPacketsReceived = 0;
3926 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3927 return RETURN_OK;
3928}
3929
3930
3931INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3932{
3933 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3934 CHAR buf[MAX_CMD_SIZE] = {0};
3935 CHAR Value[MAX_BUF_SIZE] = {0};
3936 FILE *fp = NULL;
3937
3938 if (ifname == NULL || strlen(ifname) <= 1)
3939 return RETURN_OK;
3940
3941 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
3942 system(buf);
3943
3944 fp = fopen("/tmp/Radio_Stats.txt", "r");
3945 if(fp == NULL)
3946 {
3947 printf("/tmp/Radio_Stats.txt not exists \n");
3948 return RETURN_ERR;
3949 }
3950 fclose(fp);
3951
3952 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3953 File_Reading(buf, Value);
3954 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
3955
3956 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3957 File_Reading(buf, Value);
3958 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
3959
3960 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3961 File_Reading(buf, Value);
3962 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
3963
3964 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3965 File_Reading(buf, Value);
3966 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
3967
3968 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3969 File_Reading(buf, Value);
3970 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
3971
3972 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3973 File_Reading(buf, Value);
3974 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
3975
3976 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3977 File_Reading(buf, Value);
3978 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
3979
3980 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3981 File_Reading(buf, Value);
3982 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
3983
3984 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3985 return RETURN_OK;
3986}
3987
3988INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3989{
developer7e4a2a62023-04-06 19:56:03 +08003990 CHAR buf[MAX_CMD_SIZE] = {0};
3991 INT count = 0;
developer72fb0bb2023-01-11 09:46:29 +08003992
developer7e4a2a62023-04-06 19:56:03 +08003993 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3994
3995 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL) {
3996 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3997 File_Reading(buf, status);
3998 }
3999
4000 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
4001 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08004002}
4003
4004//Get detail radio traffic static info
4005INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
4006{
4007
developer69b61b02023-03-07 17:17:44 +08004008#if 0
4009 //ifconfig radio_x
developer72fb0bb2023-01-11 09:46:29 +08004010 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
4011 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
4012 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
4013 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
4014
4015 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
4016 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
4017 output_struct->radio_DiscardPacketsSent=0; //The total number of outbound packets which were chosen to be discarded even though no errors had been detected to prevent their being transmitted. One possible reason for discarding such a packet could be to free up buffer space.
4018 output_struct->radio_DiscardPacketsReceived=0; //The total number of inbound packets which were chosen to be discarded even though no errors had been detected to prevent their being delivered. One possible reason for discarding such a packet could be to free up buffer space.
4019
developer69b61b02023-03-07 17:17:44 +08004020 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
developer72fb0bb2023-01-11 09:46:29 +08004021 output_struct->radio_FCSErrorCount=0; //The number of packets that were received with a detected FCS error. This parameter is based on dot11FCSErrorCount from [Annex C/802.11-2012].
4022 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
4023 output_struct->radio_PacketsOtherReceived=0; //The number of packets that were received, but which were destined for a MAC address that is not associated with this interface.
4024 output_struct->radio_NoiseFloor=-99; //The noise floor for this radio channel where a recoverable signal can be obtained. Expressed as a signed integer in the range (-110:0). Measurement should capture all energy (in dBm) from sources other than Wi-Fi devices as well as interference from Wi-Fi devices too weak to be decoded. Measured in dBm
4025 output_struct->radio_ChannelUtilization=35; //Percentage of time the channel was occupied by the radios own activity (Activity Factor) or the activity of other radios. Channel utilization MUST cover all user traffic, management traffic, and time the radio was unavailable for CSMA activities, including DIFS intervals, etc. The metric is calculated and updated in this parameter at the end of the interval defined by "Radio Statistics Measuring Interval". The calculation of this metric MUST only use the data collected from the just completed interval. If this metric is queried before it has been updated with an initial calculation, it MUST return -1. Units in Percentage
4026 output_struct->radio_ActivityFactor=2; //Percentage of time that the radio was transmitting or receiving Wi-Fi packets to/from associated clients. Activity factor MUST include all traffic that deals with communication between the radio and clients associated to the radio as well as management overhead for the radio, including NAV timers, beacons, probe responses,time for receiving devices to send an ACK, SIFC intervals, etc. The metric is calculated and updated in this parameter at the end of the interval defined by "Radio Statistics Measuring Interval". The calculation of this metric MUST only use the data collected from the just completed interval. If this metric is queried before it has been updated with an initial calculation, it MUST return -1. Units in Percentage
4027 output_struct->radio_CarrierSenseThreshold_Exceeded=20; //Percentage of time that the radio was unable to transmit or receive Wi-Fi packets to/from associated clients due to energy detection (ED) on the channel or clear channel assessment (CCA). The metric is calculated and updated in this Parameter at the end of the interval defined by "Radio Statistics Measuring Interval". The calculation of this metric MUST only use the data collected from the just completed interval. If this metric is queried before it has been updated with an initial calculation, it MUST return -1. Units in Percentage
4028 output_struct->radio_RetransmissionMetirc=0; //Percentage of packets that had to be re-transmitted. Multiple re-transmissions of the same packet count as one. The metric is calculated and updated in this parameter at the end of the interval defined by "Radio Statistics Measuring Interval". The calculation of this metric MUST only use the data collected from the just completed interval. If this metric is queried before it has been updated with an initial calculation, it MUST return -1. Units in percentage
4029
4030 output_struct->radio_MaximumNoiseFloorOnChannel=-1; //Maximum Noise on the channel during the measuring interval. The metric is updated in this parameter at the end of the interval defined by "Radio Statistics Measuring Interval". The calculation of this metric MUST only use the data collected in the just completed interval. If this metric is queried before it has been updated with an initial calculation, it MUST return -1. Units in dBm
4031 output_struct->radio_MinimumNoiseFloorOnChannel=-1; //Minimum Noise on the channel. The metric is updated in this Parameter at the end of the interval defined by "Radio Statistics Measuring Interval". The calculation of this metric MUST only use the data collected in the just completed interval. If this metric is queried before it has been updated with an initial calculation, it MUST return -1. Units in dBm
4032 output_struct->radio_MedianNoiseFloorOnChannel=-1; //Median Noise on the channel during the measuring interval. The metric is updated in this parameter at the end of the interval defined by "Radio Statistics Measuring Interval". The calculation of this metric MUST only use the data collected in the just completed interval. If this metric is queried before it has been updated with an initial calculation, it MUST return -1. Units in dBm
4033 output_struct->radio_StatisticsStartTime=0; //The date and time at which the collection of the current set of statistics started. This time must be updated whenever the radio statistics are reset.
4034
4035 return RETURN_OK;
4036#endif
4037
4038 CHAR interface_name[64] = {0};
4039 BOOL iface_status = FALSE;
4040 wifi_radioTrafficStats2_t radioTrafficStats = {0};
4041
4042 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
4043 if (NULL == output_struct)
4044 return RETURN_ERR;
4045
4046 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4047 return RETURN_ERR;
4048
4049 wifi_getApEnable(radioIndex, &iface_status);
4050
4051 if (iface_status == TRUE)
4052 wifi_halGetIfStats(interface_name, &radioTrafficStats);
4053 else
4054 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
4055
4056 output_struct->radio_BytesSent = radioTrafficStats.radio_BytesSent;
4057 output_struct->radio_BytesReceived = radioTrafficStats.radio_BytesReceived;
4058 output_struct->radio_PacketsSent = radioTrafficStats.radio_PacketsSent;
4059 output_struct->radio_PacketsReceived = radioTrafficStats.radio_PacketsReceived;
4060 output_struct->radio_ErrorsSent = radioTrafficStats.radio_ErrorsSent;
4061 output_struct->radio_ErrorsReceived = radioTrafficStats.radio_ErrorsReceived;
4062 output_struct->radio_DiscardPacketsSent = radioTrafficStats.radio_DiscardPacketsSent;
4063 output_struct->radio_DiscardPacketsReceived = radioTrafficStats.radio_DiscardPacketsReceived;
4064
4065 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
4066 output_struct->radio_FCSErrorCount = 0; //The number of packets that were received with a detected FCS error. This parameter is based on dot11FCSErrorCount from [Annex C/802.11-2012].
4067 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
4068 output_struct->radio_PacketsOtherReceived = 0; //The number of packets that were received, but which were destined for a MAC address that is not associated with this interface.
4069 output_struct->radio_NoiseFloor = -99; //The noise floor for this radio channel where a recoverable signal can be obtained. Expressed as a signed integer in the range (-110:0). Measurement should capture all energy (in dBm) from sources other than Wi-Fi devices as well as interference from Wi-Fi devices too weak to be decoded. Measured in dBm
4070 output_struct->radio_ChannelUtilization = 35; //Percentage of time the channel was occupied by the radio\92s own activity (Activity Factor) or the activity of other radios. Channel utilization MUST cover all user traffic, management traffic, and time the radio was unavailable for CSMA activities, including DIFS intervals, etc. The metric is calculated and updated in this parameter at the end of the interval defined by "Radio Statistics Measuring Interval". The calculation of this metric MUST only use the data collected from the just completed interval. If this metric is queried before it has been updated with an initial calculation, it MUST return -1. Units in Percentage
4071 output_struct->radio_ActivityFactor = 2; //Percentage of time that the radio was transmitting or receiving Wi-Fi packets to/from associated clients. Activity factor MUST include all traffic that deals with communication between the radio and clients associated to the radio as well as management overhead for the radio, including NAV timers, beacons, probe responses,time for receiving devices to send an ACK, SIFC intervals, etc. The metric is calculated and updated in this parameter at the end of the interval defined by "Radio Statistics Measuring Interval". The calculation of this metric MUST only use the data collected from the just completed interval. If this metric is queried before it has been updated with an initial calculation, it MUST return -1. Units in Percentage
4072 output_struct->radio_CarrierSenseThreshold_Exceeded = 20; //Percentage of time that the radio was unable to transmit or receive Wi-Fi packets to/from associated clients due to energy detection (ED) on the channel or clear channel assessment (CCA). The metric is calculated and updated in this Parameter at the end of the interval defined by "Radio Statistics Measuring Interval". The calculation of this metric MUST only use the data collected from the just completed interval. If this metric is queried before it has been updated with an initial calculation, it MUST return -1. Units in Percentage
4073 output_struct->radio_RetransmissionMetirc = 0; //Percentage of packets that had to be re-transmitted. Multiple re-transmissions of the same packet count as one. The metric is calculated and updated in this parameter at the end of the interval defined by "Radio Statistics Measuring Interval". The calculation of this metric MUST only use the data collected from the just completed interval. If this metric is queried before it has been updated with an initial calculation, it MUST return -1. Units in percentage
4074
4075 output_struct->radio_MaximumNoiseFloorOnChannel = -1; //Maximum Noise on the channel during the measuring interval. The metric is updated in this parameter at the end of the interval defined by "Radio Statistics Measuring Interval". The calculation of this metric MUST only use the data collected in the just completed interval. If this metric is queried before it has been updated with an initial calculation, it MUST return -1. Units in dBm
4076 output_struct->radio_MinimumNoiseFloorOnChannel = -1; //Minimum Noise on the channel. The metric is updated in this Parameter at the end of the interval defined by "Radio Statistics Measuring Interval". The calculation of this metric MUST only use the data collected in the just completed interval. If this metric is queried before it has been updated with an initial calculation, it MUST return -1. Units in dBm
4077 output_struct->radio_MedianNoiseFloorOnChannel = -1; //Median Noise on the channel during the measuring interval. The metric is updated in this parameter at the end of the interval defined by "Radio Statistics Measuring Interval". The calculation of this metric MUST only use the data collected in the just completed interval. If this metric is queried before it has been updated with an initial calculation, it MUST return -1. Units in dBm
4078 output_struct->radio_StatisticsStartTime = 0; //The date and time at which the collection of the current set of statistics started. This time must be updated whenever the radio statistics are reset.
4079
4080 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
4081
4082 return RETURN_OK;
4083}
4084
4085//Set radio traffic static Measureing rules
4086INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
4087{
4088 //zqiu: If the RadioTrafficStats process running, and the new value is different from old value, the process needs to be reset. The Statistics date, such as MaximumNoiseFloorOnChannel, MinimumNoiseFloorOnChannel and MedianNoiseFloorOnChannel need to be reset. And the "StatisticsStartTime" must be reset to the current time. Units in Seconds
4089 // Else, save the MeasuringRate and MeasuringInterval for future usage
4090
4091 return RETURN_OK;
4092}
4093
4094//To start or stop RadioTrafficStats
4095INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
4096{
4097 //zqiu: If the RadioTrafficStats process running
4098 // if(enable)
4099 // return RETURN_OK.
4100 // else
4101 // Stop RadioTrafficStats process
developer69b61b02023-03-07 17:17:44 +08004102 // Else
developer72fb0bb2023-01-11 09:46:29 +08004103 // if(enable)
4104 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
4105 // else
4106 // return RETURN_OK.
4107
4108 return RETURN_OK;
4109}
4110
4111//Clients associated with the AP over a specific interval. The histogram MUST have a range from -110to 0 dBm and MUST be divided in bins of 3 dBM, with bins aligning on the -110 dBm end of the range. Received signal levels equal to or greater than the smaller boundary of a bin and less than the larger boundary are included in the respective bin. The bin associated with the client?s current received signal level MUST be incremented when a client associates with the AP. Additionally, the respective bins associated with each connected client?s current received signal level MUST be incremented at the interval defined by "Radio Statistics Measuring Rate". The histogram?s bins MUST NOT be incremented at any other time. The histogram data collected during the interval MUST be published to the parameter only at the end of the interval defined by "Radio Statistics Measuring Interval". The underlying histogram data MUST be cleared at the start of each interval defined by "Radio Statistics Measuring Interval?. If any of the parameter's representing this histogram is queried before the histogram has been updated with an initial set of data, it MUST return -1. Units dBm
4112INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
4113{
4114 //zqiu: Please ignor signalIndex.
developer69b61b02023-03-07 17:17:44 +08004115 if (NULL == SignalLevel)
developer72fb0bb2023-01-11 09:46:29 +08004116 return RETURN_ERR;
4117 *SignalLevel=(radioIndex==0)?-19:-19;
4118
4119 return RETURN_OK;
4120}
4121
4122//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
4123INT wifi_applyRadioSettings(INT radioIndex)
4124{
4125 return RETURN_OK;
4126}
4127
4128//Get the radio index assocated with this SSID entry
4129INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
4130{
4131 if(NULL == radioIndex)
4132 return RETURN_ERR;
4133 int max_radio_num = 0;
4134 wifi_getMaxRadioNumber(&max_radio_num);
4135 *radioIndex = ssidIndex%max_radio_num;
4136 return RETURN_OK;
4137}
4138
4139//Device.WiFi.SSID.{i}.Enable
4140//Get SSID enable configuration parameters (not the SSID enable status)
4141INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
4142{
developer69b61b02023-03-07 17:17:44 +08004143 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08004144 return RETURN_ERR;
4145
4146 return wifi_getApEnable(ssidIndex, output_bool);
4147}
4148
4149//Device.WiFi.SSID.{i}.Enable
4150//Set SSID enable configuration parameters
4151INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
4152{
4153 return wifi_setApEnable(ssidIndex, enable);
4154}
4155
4156//Device.WiFi.SSID.{i}.Status
4157//Get the SSID enable status
4158INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
4159{
4160 char cmd[MAX_CMD_SIZE]={0};
4161 char buf[MAX_BUF_SIZE]={0};
4162 BOOL output_bool;
4163
4164 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4165 if (NULL == output_string)
4166 return RETURN_ERR;
developer69b61b02023-03-07 17:17:44 +08004167
developer72fb0bb2023-01-11 09:46:29 +08004168 wifi_getApEnable(ssidIndex,&output_bool);
4169 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
4170
4171 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4172 return RETURN_OK;
4173}
4174
4175// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
4176INT wifi_getSSIDName(INT apIndex, CHAR *output)
4177{
4178 char config_file[MAX_BUF_SIZE] = {0};
4179
developer69b61b02023-03-07 17:17:44 +08004180 if (NULL == output)
developer72fb0bb2023-01-11 09:46:29 +08004181 return RETURN_ERR;
4182
4183 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4184 wifi_hostapdRead(config_file,"ssid",output,32);
4185
4186 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
4187 return RETURN_OK;
4188}
4189
developer69b61b02023-03-07 17:17:44 +08004190// Set a max 32 byte string and sets an internal variable to the SSID name
developer72fb0bb2023-01-11 09:46:29 +08004191INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
4192{
4193 char str[MAX_BUF_SIZE]={'\0'};
4194 char cmd[MAX_CMD_SIZE]={'\0'};
4195 struct params params;
4196 char config_file[MAX_BUF_SIZE] = {0};
4197
4198 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4199 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
4200 return RETURN_ERR;
4201
4202 params.name = "ssid";
4203 params.value = ssid_string;
4204 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4205 wifi_hostapdWrite(config_file, &params, 1);
4206 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4207 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4208
4209 return RETURN_OK;
4210}
4211
4212//Get the BSSID
4213INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
4214{
developer7e4a2a62023-04-06 19:56:03 +08004215 char cmd[MAX_CMD_SIZE] = {0};
4216 char inf_name[IF_NAME_SIZE] = {0};
4217 char conf_file[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08004218
developer7e4a2a62023-04-06 19:56:03 +08004219 if (!output_string)
developer72fb0bb2023-01-11 09:46:29 +08004220 return RETURN_ERR;
4221
developer7e4a2a62023-04-06 19:56:03 +08004222 wifi_GetInterfaceName(ssidIndex, inf_name);
4223
4224 if(ssidIndex >= 0 && ssidIndex < MAX_APS) {
4225 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep bssid | cut -d '=' -f2 | tr -d '\\n'", inf_name);
developer72fb0bb2023-01-11 09:46:29 +08004226 _syscmd(cmd, output_string, 64);
developer7e4a2a62023-04-06 19:56:03 +08004227 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08004228 }
developer7e4a2a62023-04-06 19:56:03 +08004229
developer72fb0bb2023-01-11 09:46:29 +08004230 strncpy(output_string, "\0", 1);
4231
4232 return RETURN_ERR;
4233}
4234
4235//Get the MAC address associated with this Wifi SSID
4236INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
4237{
4238 wifi_getBaseBSSID(ssidIndex,output_string);
4239 return RETURN_OK;
4240}
4241
4242//Get the basic SSID traffic static info
4243//Apply SSID and AP (in the case of Acess Point devices) to the hardware
4244//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
4245INT wifi_applySSIDSettings(INT ssidIndex)
4246{
4247 char interface_name[16] = {0};
4248 BOOL status = false;
4249 char cmd[MAX_CMD_SIZE] = {0};
4250 char buf[MAX_CMD_SIZE] = {0};
4251 int apIndex, ret;
4252 int max_radio_num = 0;
4253 int radioIndex = 0;
4254
4255 wifi_getMaxRadioNumber(&max_radio_num);
4256
4257 radioIndex = ssidIndex % max_radio_num;
4258
4259 wifi_getApEnable(ssidIndex,&status);
4260 // Do not apply when ssid index is disabled
4261 if (status == false)
4262 return RETURN_OK;
4263
4264 /* Doing full remove and add for ssid Index
4265 * Not all hostapd options are supported with reload
4266 * for example macaddr_acl
4267 */
4268 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
4269 return RETURN_ERR;
4270
4271 ret = wifi_setApEnable(ssidIndex,true);
4272
4273 /* Workaround for hostapd issue with multiple bss definitions
4274 * when first created interface will be removed
4275 * then all vaps other vaps on same phy are removed
4276 * after calling setApEnable to false readd all enabled vaps */
4277 for(int i=0; i < MAX_APS/max_radio_num; i++) {
4278 apIndex = max_radio_num*i+radioIndex;
4279 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4280 return RETURN_ERR;
4281 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
4282 _syscmd(cmd, buf, sizeof(buf));
4283 if(*buf == '1')
4284 wifi_setApEnable(apIndex, true);
4285 }
4286
4287 return ret;
4288}
4289
4290struct channels_noise {
4291 int channel;
4292 int noise;
4293};
4294
4295// Return noise array for each channel
4296int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
4297{
4298 char interface_name[16] = {0};
4299 FILE *f = NULL;
4300 char cmd[128] = {0};
4301 char line[256] = {0};
4302 size_t len = 0;
4303 ssize_t read = 0;
4304 int tmp = 0, arr_index = -1;
4305
4306 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4307 return RETURN_ERR;
4308 sprintf(cmd, "iw dev %s survey dump | grep 'frequency\\|noise' | awk '{print $2}'", interface_name);
4309
4310 if ((f = popen(cmd, "r")) == NULL) {
4311 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
4312 return RETURN_ERR;
4313 }
developer69b61b02023-03-07 17:17:44 +08004314
developer72fb0bb2023-01-11 09:46:29 +08004315 while(fgets(line, sizeof(line), f) != NULL) {
4316 if(arr_index < channels_num){
4317 sscanf(line, "%d", &tmp);
4318 if (tmp > 0) { // channel frequency, the first line must be frequency
4319 arr_index++;
4320 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
4321 } else { // noise
4322 channels_noise_arr[arr_index].noise = tmp;
4323 }
4324 }else{
4325 break;
4326 }
4327 }
4328 pclose(f);
4329 return RETURN_OK;
4330}
4331
4332//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
4333//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
developer69b61b02023-03-07 17:17:44 +08004334INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
developer72fb0bb2023-01-11 09:46:29 +08004335{
4336 int index = -1;
4337 wifi_neighbor_ap2_t *scan_array = NULL;
4338 char cmd[256]={0};
4339 char buf[128]={0};
4340 char file_name[32] = {0};
4341 char filter_SSID[32] = {0};
4342 char line[256] = {0};
4343 char interface_name[16] = {0};
4344 char *ret = NULL;
4345 int freq=0;
4346 FILE *f = NULL;
4347 size_t len=0;
4348 int channels_num = 0;
4349 int vht_channel_width = 0;
4350 int get_noise_ret = RETURN_ERR;
4351 bool filter_enable = false;
4352 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
4353 int phyId = 0;
4354
4355 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
4356
4357 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4358 return RETURN_ERR;
4359
4360 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
4361 f = fopen(file_name, "r");
4362 if (f != NULL) {
4363 fgets(filter_SSID, sizeof(file_name), f);
4364 if (strlen(filter_SSID) != 0)
4365 filter_enable = true;
4366 fclose(f);
4367 }
4368
4369 phyId = radio_index_to_phy(radioIndex);
4370 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
4371 _syscmd(cmd, buf, sizeof(buf));
4372 channels_num = strtol(buf, NULL, 10);
4373
4374
4375
4376 sprintf(cmd, "iw dev %s scan | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
4377 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", interface_name, interface_name);
4378 fprintf(stderr, "cmd: %s\n", cmd);
4379 if ((f = popen(cmd, "r")) == NULL) {
4380 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
4381 return RETURN_ERR;
4382 }
developer69b61b02023-03-07 17:17:44 +08004383
developer72fb0bb2023-01-11 09:46:29 +08004384 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
4385 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
developer69b61b02023-03-07 17:17:44 +08004386
developer72fb0bb2023-01-11 09:46:29 +08004387 ret = fgets(line, sizeof(line), f);
4388 while (ret != NULL) {
4389 if(strstr(line, "BSS") != NULL) { // new neighbor info
developer69b61b02023-03-07 17:17:44 +08004390 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
developer72fb0bb2023-01-11 09:46:29 +08004391 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
4392 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
4393
4394 if (!filter_BSS) {
4395 index++;
4396 wifi_neighbor_ap2_t *tmp;
4397 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
4398 if (tmp == NULL) { // no more memory to use
4399 index--;
4400 wifi_dbg_printf("%s: realloc failed\n", __func__);
4401 break;
4402 }
4403 scan_array = tmp;
4404 }
4405 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
4406
4407 filter_BSS = false;
4408 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
4409 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
4410 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
4411 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
4412 } else if (strstr(line, "freq") != NULL) {
4413 sscanf(line," freq: %d", &freq);
4414 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
4415
4416 if (freq >= 2412 && freq <= 2484) {
4417 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
4418 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
4419 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
4420 }
4421 else if (freq >= 5160 && freq <= 5805) {
4422 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
4423 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
4424 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
4425 }
4426
4427 scan_array[index].ap_Noise = 0;
4428 if (get_noise_ret == RETURN_OK) {
4429 for (int i = 0; i < channels_num; i++) {
4430 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
4431 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
4432 break;
4433 }
4434 }
4435 }
4436 } else if (strstr(line, "beacon interval") != NULL) {
4437 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
4438 } else if (strstr(line, "signal") != NULL) {
4439 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
4440 } else if (strstr(line,"SSID") != NULL) {
4441 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
4442 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
4443 filter_BSS = true;
4444 }
4445 } else if (strstr(line, "Supported rates") != NULL) {
4446 char SRate[80] = {0}, *tmp = NULL;
4447 memset(buf, 0, sizeof(buf));
4448 strcpy(SRate, line);
4449 tmp = strtok(SRate, ":");
4450 tmp = strtok(NULL, ":");
4451 strcpy(buf, tmp);
4452 memset(SRate, 0, sizeof(SRate));
4453
4454 tmp = strtok(buf, " \n");
4455 while (tmp != NULL) {
4456 strcat(SRate, tmp);
4457 if (SRate[strlen(SRate) - 1] == '*') {
4458 SRate[strlen(SRate) - 1] = '\0';
4459 }
4460 strcat(SRate, ",");
4461
4462 tmp = strtok(NULL, " \n");
4463 }
4464 SRate[strlen(SRate) - 1] = '\0';
4465 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
4466 } else if (strstr(line, "DTIM") != NULL) {
4467 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
4468 } else if (strstr(line, "VHT capabilities") != NULL) {
4469 strcat(scan_array[index].ap_SupportedStandards, ",ac");
4470 strcpy(scan_array[index].ap_OperatingStandards, "ac");
4471 } else if (strstr(line, "HT capabilities") != NULL) {
4472 strcat(scan_array[index].ap_SupportedStandards, ",n");
4473 strcpy(scan_array[index].ap_OperatingStandards, "n");
4474 } else if (strstr(line, "VHT operation") != NULL) {
4475 ret = fgets(line, sizeof(line), f);
4476 sscanf(line," * channel width: %d", &vht_channel_width);
4477 if(vht_channel_width == 1) {
4478 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
4479 } else {
4480 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
4481 }
4482 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
4483 continue;
4484 } else if (strstr(line, "HT operation") != NULL) {
4485 ret = fgets(line, sizeof(line), f);
4486 sscanf(line," * secondary channel offset: %s", &buf);
4487 if (!strcmp(buf, "above")) {
4488 //40Mhz +
4489 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
4490 }
4491 else if (!strcmp(buf, "below")) {
4492 //40Mhz -
4493 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
4494 } else {
4495 //20Mhz
4496 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
4497 }
4498 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
4499 continue;
4500 } else if (strstr(line, "HE capabilities") != NULL) {
4501 strcat(scan_array[index].ap_SupportedStandards, ",ax");
4502 strcpy(scan_array[index].ap_OperatingStandards, "ax");
4503 ret = fgets(line, sizeof(line), f);
4504 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
4505 if (strstr(line, "HE40/2.4GHz") != NULL)
4506 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
4507 else
4508 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
4509 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
4510 if (strstr(line, "HE80/5GHz") != NULL) {
4511 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
4512 ret = fgets(line, sizeof(line), f);
4513 } else
4514 continue;
4515 if (strstr(line, "HE160/5GHz") != NULL)
4516 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
4517 }
4518 continue;
4519 } else if (strstr(line, "WPA") != NULL) {
4520 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
4521 } else if (strstr(line, "RSN") != NULL) {
4522 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
4523 } else if (strstr(line, "Group cipher") != NULL) {
4524 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
4525 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
4526 strcpy(scan_array[index].ap_EncryptionMode, "AES");
4527 }
4528 }
4529 ret = fgets(line, sizeof(line), f);
4530 }
4531
4532 if (!filter_BSS) {
4533 *output_array_size = index + 1;
4534 } else {
4535 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
4536 *output_array_size = index;
4537 }
4538 *neighbor_ap_array = scan_array;
4539 pclose(f);
4540 free(channels_noise_arr);
4541 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4542 return RETURN_OK;
4543}
4544
4545//>> Deprecated: used for old RDKB code.
4546INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
4547{
4548 INT status = RETURN_ERR;
4549
4550 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4551 output_struct->wifi_PLCPErrorCount = 0;
4552 output_struct->wifi_FCSErrorCount = 0;
4553 output_struct->wifi_InvalidMACCount = 0;
4554 output_struct->wifi_PacketsOtherReceived = 0;
4555 output_struct->wifi_Noise = 0;
4556 status = RETURN_OK;
4557 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4558 return status;
4559}
4560
4561INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
4562{
4563 char interface_name[16] = {0};
4564 char cmd[128] = {0};
4565 char buf[1280] = {0};
4566 char *pos = NULL;
4567
4568 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4569 if (NULL == output_struct)
4570 return RETURN_ERR;
4571
4572 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4573 return RETURN_ERR;
4574
4575 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4576
4577 snprintf(cmd, sizeof(cmd), "ifconfig %s", interface_name);
4578 _syscmd(cmd, buf, sizeof(buf));
4579
4580 pos = buf;
4581 if ((pos = strstr(pos, "RX packets:")) == NULL)
4582 return RETURN_ERR;
4583 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
4584
4585 if ((pos = strstr(pos, "TX packets:")) == NULL)
4586 return RETURN_ERR;
4587 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
4588
4589 if ((pos = strstr(pos, "RX bytes:")) == NULL)
4590 return RETURN_ERR;
4591 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
4592
4593 if ((pos = strstr(pos, "TX bytes:")) == NULL)
4594 return RETURN_ERR;
4595 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
4596
4597 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l | tr -d '\n'", interface_name);
4598 _syscmd(cmd, buf, sizeof(buf));
4599 sscanf(buf, "%lu", &output_struct->wifi_Associations);
4600
4601#if 0
4602 //TODO: need to revisit below implementation
4603 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4604 char interface_name[MAX_BUF_SIZE] = {0};
4605 char interface_status[MAX_BUF_SIZE] = {0};
4606 char Value[MAX_BUF_SIZE] = {0};
4607 char buf[MAX_CMD_SIZE] = {0};
4608 char cmd[MAX_CMD_SIZE] = {0};
4609 FILE *fp = NULL;
4610
4611 if (NULL == output_struct) {
4612 return RETURN_ERR;
4613 }
4614
4615 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4616
4617 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
4618 {
4619 if(apIndex == 0) //private_wifi for 2.4G
4620 {
4621 wifi_GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
4622 }
4623 else if(apIndex == 1) //private_wifi for 5G
4624 {
4625 wifi_GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
4626 }
4627 else if(apIndex == 4) //public_wifi for 2.4G
4628 {
4629 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4630 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4631 {
4632 return RETURN_ERR;
4633 }
4634 if(buf[0] == '#')//tp-link
4635 wifi_GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
4636 else//tenda
4637 wifi_GetInterfaceName_virtualInterfaceName_2G(interface_name);
4638 }
4639 else if(apIndex == 5) //public_wifi for 5G
4640 {
4641 wifi_GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
4642 }
4643
4644 GetIfacestatus(interface_name, interface_status);
4645
4646 if(0 != strcmp(interface_status, "1"))
4647 return RETURN_ERR;
4648
4649 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4650 system(cmd);
4651
4652 fp = fopen("/tmp/SSID_Stats.txt", "r");
4653 if(fp == NULL)
4654 {
4655 printf("/tmp/SSID_Stats.txt not exists \n");
4656 return RETURN_ERR;
4657 }
4658 fclose(fp);
4659
4660 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4661 File_Reading(buf, Value);
4662 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
4663
4664 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4665 File_Reading(buf, Value);
4666 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
4667
4668 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4669 File_Reading(buf, Value);
4670 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
4671
4672 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4673 File_Reading(buf, Value);
4674 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
4675
4676 /* There is no specific parameter from caller to associate the value wifi_Associations */
4677 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
4678 //_syscmd(cmd, buf, sizeof(buf));
4679 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
4680 }
4681#endif
4682 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4683 return RETURN_OK;
4684}
4685
4686INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
4687{
4688 char interface_name[MAX_BUF_SIZE] = {0};
4689 char interface_status[MAX_BUF_SIZE] = {0};
4690 char Value[MAX_BUF_SIZE] = {0};
4691 char buf[MAX_CMD_SIZE] = {0};
4692 char cmd[MAX_CMD_SIZE] = {0};
4693 FILE *fp = NULL;
4694
4695 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4696 if (NULL == output_struct)
4697 return RETURN_ERR;
4698
4699 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
4700
4701 if (wifi_GetInterfaceName(apIndex,interface_name) != RETURN_OK)
4702 return RETURN_ERR;
4703 GetIfacestatus(interface_name, interface_status);
4704
4705 if(0 != strcmp(interface_status, "1"))
4706 return RETURN_ERR;
4707
4708 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4709 system(cmd);
4710
4711 fp = fopen("/tmp/SSID_Stats.txt", "r");
4712 if(fp == NULL)
4713 {
4714 printf("/tmp/SSID_Stats.txt not exists \n");
4715 return RETURN_ERR;
4716 }
4717 fclose(fp);
4718
4719 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4720 File_Reading(buf, Value);
4721 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
4722
4723 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4724 File_Reading(buf, Value);
4725 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
4726
4727 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4728 File_Reading(buf, Value);
4729 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
4730
4731 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4732 File_Reading(buf, Value);
4733 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
4734
4735 output_struct->wifi_UnicastPacketsSent = 0;
4736 output_struct->wifi_UnicastPacketsReceived = 0;
4737 output_struct->wifi_MulticastPacketsSent = 0;
4738 output_struct->wifi_MulticastPacketsReceived = 0;
4739 output_struct->wifi_BroadcastPacketsSent = 0;
4740 output_struct->wifi_BroadcastPacketsRecevied = 0;
4741 output_struct->wifi_UnknownPacketsReceived = 0;
4742
4743 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4744 return RETURN_OK;
4745}
4746
4747INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
4748{
4749 INT status = RETURN_ERR;
4750
4751 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4752 //Below values should get updated from hal
4753 output_struct->wifi_RetransCount=0;
4754 output_struct->wifi_FailedRetransCount=0;
4755 output_struct->wifi_RetryCount=0;
4756 output_struct->wifi_MultipleRetryCount=0;
4757 output_struct->wifi_ACKFailureCount=0;
4758 output_struct->wifi_AggregatedPacketCount=0;
4759
4760 status = RETURN_OK;
4761 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4762
4763 return status;
4764}
4765
4766INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4767{
4768 INT status = RETURN_ERR;
4769 UINT index;
4770 wifi_neighbor_ap_t *pt=NULL;
4771
4772 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4773 *output_array_size=2;
4774 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4775 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4776 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4777 strcpy(pt->ap_Radio,"");
4778 strcpy(pt->ap_SSID,"");
4779 strcpy(pt->ap_BSSID,"");
4780 strcpy(pt->ap_Mode,"");
4781 pt->ap_Channel=1;
4782 pt->ap_SignalStrength=0;
4783 strcpy(pt->ap_SecurityModeEnabled,"");
4784 strcpy(pt->ap_EncryptionMode,"");
4785 strcpy(pt->ap_OperatingFrequencyBand,"");
4786 strcpy(pt->ap_SupportedStandards,"");
4787 strcpy(pt->ap_OperatingStandards,"");
4788 strcpy(pt->ap_OperatingChannelBandwidth,"");
4789 pt->ap_BeaconPeriod=1;
4790 pt->ap_Noise=0;
4791 strcpy(pt->ap_BasicDataTransferRates,"");
4792 strcpy(pt->ap_SupportedDataTransferRates,"");
4793 pt->ap_DTIMPeriod=1;
4794 pt->ap_ChannelUtilization = 1;
4795 }
4796
4797 status = RETURN_OK;
4798 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4799
4800 return status;
4801}
4802
4803//----------------- AP HAL -------------------------------
4804
4805//>> Deprecated: used for old RDKB code.
4806INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4807{
4808 if (NULL == output_ulong || NULL == output_struct)
4809 return RETURN_ERR;
4810 *output_ulong = 0;
4811 *output_struct = NULL;
4812 return RETURN_OK;
4813}
4814
4815#ifdef HAL_NETLINK_IMPL
4816static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4817 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4818 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4819 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4820 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4821 char mac_addr[20];
4822 static int count=0;
4823 int rate=0;
4824
4825 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4826
4827 nla_parse(tb,
4828 NL80211_ATTR_MAX,
4829 genlmsg_attrdata(gnlh, 0),
4830 genlmsg_attrlen(gnlh, 0),
4831 NULL);
4832
4833 if(!tb[NL80211_ATTR_STA_INFO]) {
4834 fprintf(stderr, "sta stats missing!\n");
4835 return NL_SKIP;
4836 }
4837
4838
4839 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4840 fprintf(stderr, "failed to parse nested attributes!\n");
4841 return NL_SKIP;
4842 }
4843
4844 //devIndex starts from 1
4845 if( ++count == out->wifi_devIndex )
4846 {
4847 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4848 //Getting the mac addrress
4849 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4850
4851 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4852 fprintf(stderr, "failed to parse nested rate attributes!");
4853 return NL_SKIP;
4854 }
4855
4856 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4857 if(rinfo[NL80211_RATE_INFO_BITRATE])
4858 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4859 out->wifi_devTxRate = rate/10;
4860 }
4861
4862 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4863 fprintf(stderr, "failed to parse nested rate attributes!");
4864 return NL_SKIP;
4865 }
4866
4867 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4868 if(rinfo[NL80211_RATE_INFO_BITRATE])
4869 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4870 out->wifi_devRxRate = rate/10;
4871 }
4872 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4873 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4874
4875 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4876 count = 0; //starts the count for next cycle
4877 return NL_STOP;
4878 }
4879
4880 return NL_SKIP;
4881
4882}
4883#endif
4884
4885INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4886{
4887#ifdef HAL_NETLINK_IMPL
4888 Netlink nl = {0};
4889 char if_name[10] = {0};
4890 char interface_name[16] = {0};
4891
4892 wifi_device_info_t info = {0};
4893 info.wifi_devIndex = devIndex;
4894
4895 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4896 return RETURN_ERR;
4897
4898 snprintf(if_name,sizeof(if_name),"%s", interface_name);
4899
4900 nl.id = initSock80211(&nl);
4901
4902 if (nl.id < 0) {
4903 fprintf(stderr, "Error initializing netlink \n");
4904 return -1;
4905 }
4906
4907 struct nl_msg* msg = nlmsg_alloc();
4908
4909 if (!msg) {
4910 fprintf(stderr, "Failed to allocate netlink message.\n");
4911 nlfree(&nl);
4912 return -2;
4913 }
4914
4915 genlmsg_put(msg,
4916 NL_AUTO_PORT,
4917 NL_AUTO_SEQ,
4918 nl.id,
4919 0,
4920 NLM_F_DUMP,
4921 NL80211_CMD_GET_STATION,
4922 0);
4923
4924 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4925 nl_send_auto(nl.socket, msg);
4926 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4927 nl_recvmsgs(nl.socket, nl.cb);
4928 nlmsg_free(msg);
4929 nlfree(&nl);
4930
4931 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4932 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4933 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4934 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4935 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4936 return RETURN_OK;
4937#else
4938 //iw utility to retrieve station information
4939#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4940#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4941#define MACFILE "/tmp/wifi_AssoMac.txt"
4942#define TXRATEFILE "/tmp/wifi_txrate.txt"
4943#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4944 FILE *file = NULL;
4945 char if_name[10] = {'\0'};
4946 char pipeCmd[256] = {'\0'};
4947 char line[256] = {0};
4948 char interface_name[16] = {0};
4949 int count = 0, device = 0;
4950
4951 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4952 return RETURN_ERR;
4953
4954 snprintf(if_name,sizeof(if_name),"%s", interface_name);
4955
4956 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4957 file = popen(pipeCmd, "r");
4958
4959 if(file == NULL)
4960 return RETURN_ERR; //popen failed
4961
4962 fgets(line, sizeof line, file);
4963 device = atoi(line);
4964 pclose(file);
4965
4966 if(device == 0)
4967 return RETURN_ERR; //No devices are connected
4968
4969 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4970 system(pipeCmd);
4971
4972 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4973
4974 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4975
4976 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4977
4978 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4979
4980 //devIndex starts from 1, ++count
4981 if((file = fopen(SIGNALFILE, "r")) != NULL )
4982 {
4983 for(count =0;fgets(line, sizeof line, file) != NULL;)
4984 {
4985 if (++count == devIndex)
4986 {
4987 output_struct->wifi_devSignalStrength = atoi(line);
4988 break;
4989 }
4990 }
4991 fclose(file);
4992 }
4993 else
4994 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4995
4996 if((file = fopen(MACFILE, "r")) != NULL )
4997 {
4998 for(count =0;fgets(line, sizeof line, file) != NULL;)
4999 {
5000 if (++count == devIndex)
5001 {
5002 sscanf(line, "%02x:%02x:%02x:%02x:%02x:%02x",&output_struct->wifi_devMacAddress[0],&output_struct->wifi_devMacAddress[1],&output_struct->wifi_devMacAddress[2],&output_struct->wifi_devMacAddress[3],&output_struct->wifi_devMacAddress[4],&output_struct->wifi_devMacAddress[5]);
5003 break;
5004 }
5005 }
5006 fclose(file);
5007 }
5008 else
5009 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
5010
5011 if((file = fopen(TXRATEFILE, "r")) != NULL )
5012 {
5013 for(count =0;fgets(line, sizeof line, file) != NULL;)
5014 {
5015 if (++count == devIndex)
5016 {
5017 output_struct->wifi_devTxRate = atoi(line);
5018 break;
5019 }
5020 }
5021 fclose(file);
5022 }
5023 else
5024 fprintf(stderr,"fopen wifi_txrate.txt failed");
5025
5026 if((file = fopen(RXRATEFILE, "r")) != NULL)
5027 {
5028 for(count =0;fgets(line, sizeof line, file) != NULL;)
5029 {
5030 if (++count == devIndex)
5031 {
5032 output_struct->wifi_devRxRate = atoi(line);
5033 break;
5034 }
5035 }
5036 fclose(file);
5037 }
5038 else
5039 fprintf(stderr,"fopen wifi_rxrate.txt failed");
5040
5041 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
5042
5043 return RETURN_OK;
5044#endif
5045}
5046
5047INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
5048{
5049 if (NULL == device)
5050 return RETURN_ERR;
5051 return RETURN_OK;
5052}
5053//<<
5054
5055
5056//--------------wifi_ap_hal-----------------------------
5057//enables CTS protection for the radio used by this AP
5058INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
5059{
5060 //save config and Apply instantly
5061 return RETURN_ERR;
5062}
5063
5064// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
5065INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
5066{
5067 char config_file[64] = {'\0'};
5068 char buf[64] = {'\0'};
5069 struct params list;
5070
5071 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5072 list.name = "ht_coex";
5073 snprintf(buf, sizeof(buf), "%d", enable);
5074 list.value = buf;
5075
5076 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
5077 wifi_hostapdWrite(config_file, &list, 1);
5078 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5079
5080 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5081
5082 return RETURN_OK;
5083}
5084
5085//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
5086INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
5087{
5088 char config_file[MAX_BUF_SIZE] = {'\0'};
5089 char buf[MAX_BUF_SIZE] = {'\0'};
5090 struct params list;
5091
5092 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5093 if (threshold < 256 || threshold > 2346 )
5094 return RETURN_ERR;
5095 list.name = "fragm_threshold";
5096 snprintf(buf, sizeof(buf), "%d", threshold);
5097 list.value = buf;
5098
5099 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
5100 wifi_hostapdWrite(config_file, &list, 1);
5101 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5102
5103 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5104
5105 return RETURN_OK;
5106}
5107
5108// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
5109INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
5110{
5111 char config_file[64] = {'\0'};
5112 char cmd[512] = {'\0'};
5113 char buf[512] = {'\0'};
5114 char stbc_config[16] = {'\0'};
5115 wifi_band band;
5116 int iterator = 0;
5117 BOOL current_stbc = FALSE;
5118 int ant_count = 0;
5119 int ant_bitmap = 0;
5120 struct params list;
developera1255e42023-05-13 17:45:02 +08005121 char dat_file[64] = {'\0'};
developer72fb0bb2023-01-11 09:46:29 +08005122
5123 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5124
5125 band = wifi_index_to_band(radioIndex);
5126 if (band == band_invalid)
5127 return RETURN_ERR;
5128
5129 if (band == band_2_4)
5130 iterator = 1;
developera1255e42023-05-13 17:45:02 +08005131 else if ((band == band_5) || (band == band_6))
developer72fb0bb2023-01-11 09:46:29 +08005132 iterator = 2;
5133 else
5134 return RETURN_OK;
5135
5136 wifi_getRadioTxChainMask(radioIndex, &ant_bitmap);
5137 for (; ant_bitmap > 0; ant_bitmap >>= 1)
5138 ant_count += ant_bitmap & 1;
5139
5140 if (ant_count == 1 && STBC_Enable == TRUE) {
5141 fprintf(stderr, "%s: can not enable STBC when using only one antenna\n", __func__);
5142 return RETURN_OK;
5143 }
5144
5145 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
5146
5147 // set ht and vht config
5148 for (int i = 0; i < iterator; i++) {
5149 memset(stbc_config, 0, sizeof(stbc_config));
5150 memset(cmd, 0, sizeof(cmd));
5151 memset(buf, 0, sizeof(buf));
5152 list.name = (i == 0)?"ht_capab":"vht_capab";
5153 snprintf(stbc_config, sizeof(stbc_config), "%s", list.name);
5154 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
5155 _syscmd(cmd, buf, sizeof(buf));
5156 if (strlen(buf) != 0)
5157 current_stbc = TRUE;
5158 if (current_stbc == STBC_Enable)
5159 continue;
5160
5161 if (STBC_Enable == TRUE) {
5162 // Append the STBC flags in capab config
5163 memset(cmd, 0, sizeof(cmd));
5164 if (i == 0)
5165 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
5166 else
5167 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1][RX-STBC-1]/' %s", config_file);
5168 _syscmd(cmd, buf, sizeof(buf));
5169 } else if (STBC_Enable == FALSE) {
5170 // Remove the STBC flags and remain other flags in capab
5171 memset(cmd, 0, sizeof(cmd));
5172 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
5173 _syscmd(cmd, buf, sizeof(buf));
5174 memset(cmd, 0, sizeof(cmd));
5175 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
5176 _syscmd(cmd, buf, sizeof(buf));
5177 }
5178 wifi_hostapdRead(config_file, list.name, buf, sizeof(buf));
5179 list.value = buf;
5180 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
5181 }
developera1255e42023-05-13 17:45:02 +08005182 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
5183 snprintf(cmd, sizeof(cmd), "sed -r -i 's/^HT_STBC=.*/HT_STBC=%d/g' %s", STBC_Enable, dat_file);
5184 _syscmd(cmd, buf, sizeof(buf));
5185 if ((band == band_5) || (band == band_6)) {
5186 snprintf(cmd, sizeof(cmd), "sed -r -i 's/^VHT_STBC=.*/VHT_STBC=%d/g' %s", STBC_Enable, dat_file);
5187 _syscmd(cmd, buf, sizeof(buf));
5188 }
5189 /*wifi_reloadAp(radioIndex);
5190 the caller do this.*/
developer72fb0bb2023-01-11 09:46:29 +08005191
5192 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5193 return RETURN_OK;
5194}
5195
5196// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
5197INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
5198{
5199 char cmd[128] = {0};
5200 char buf[128] = {0};
5201 char interface_name[16] = {0};
5202
5203 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5204
5205 if(output_bool == NULL)
5206 return RETURN_ERR;
5207
5208 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
5209 return RETURN_ERR;
5210
5211 sprintf(cmd, "hostapd_cli -i %s get_amsdu | awk '{print $3}'", interface_name);
5212 _syscmd(cmd, buf, sizeof(buf));
5213
5214 if (strncmp(buf, "1", 1) == 0)
5215 *output_bool = TRUE;
5216 else
5217 *output_bool = FALSE;
5218
5219 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5220 return RETURN_OK;
5221}
5222
5223// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
5224INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
5225{
5226 char config_file[128] = {0};
5227 struct params list = {0};
5228 BOOL enable;
5229
5230 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5231
5232 if (wifi_getRadioAMSDUEnable(radioIndex, &enable) != RETURN_OK)
5233 return RETURN_ERR;
5234
5235 if (amsduEnable == enable)
5236 return RETURN_OK;
5237
5238 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
5239 list.name = "amsdu";
5240 list.value = amsduEnable? "1":"0";
5241 wifi_hostapdWrite(config_file, &list, 1);
5242 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
5243 wifi_reloadAp(radioIndex);
5244
5245 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5246 return RETURN_OK;
5247}
5248
5249//P2 // outputs the number of Tx streams
5250INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
5251{
5252 char buf[8] = {0};
5253 char cmd[128] = {0};
5254 int phyId = 0;
5255
5256 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5257
5258 phyId = radio_index_to_phy(radioIndex);
5259 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Configured Antennas' | awk '{print $4}'", phyId);
5260 _syscmd(cmd, buf, sizeof(buf));
5261
5262 *output_int = (INT)strtol(buf, NULL, 16);
5263
5264 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5265
5266 return RETURN_OK;
5267}
5268
5269INT fitChainMask(INT radioIndex, int antcount)
5270{
5271 char buf[128] = {0};
5272 char cmd[128] = {0};
5273 char config_file[64] = {0};
5274 wifi_band band;
5275 struct params list[2] = {0};
5276
5277 band = wifi_index_to_band(radioIndex);
5278 if (band == band_invalid)
5279 return RETURN_ERR;
5280
5281 list[0].name = "he_mu_beamformer";
5282 list[1].name = "he_su_beamformer";
5283
5284 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
5285 if (antcount == 1) {
5286 // remove config about multiple antennas
5287 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
5288 _syscmd(cmd, buf, sizeof(buf));
5289
5290 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SOUNDING-DIMENSION-.\\]//' %s", config_file);
5291 _syscmd(cmd, buf, sizeof(buf));
5292
5293 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SU-BEAMFORMER\\]//' %s", config_file);
5294 _syscmd(cmd, buf, sizeof(buf));
5295
5296 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[MU-BEAMFORMER\\]//' %s", config_file);
5297 _syscmd(cmd, buf, sizeof(buf));
5298
5299 list[0].value = "0";
5300 list[1].value = "0";
5301 } else {
5302 // If we only set RX STBC means STBC is enable and TX STBC is disable when last time set one antenna. so we need to add it back.
5303 if (band == band_2_4 || band == band_5) {
5304 snprintf(cmd, sizeof(cmd), "cat %s | grep '^ht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
5305 _syscmd(cmd, buf, sizeof(buf));
5306 if (strlen(buf) > 0) {
5307 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC]/' %s", config_file);
5308 _syscmd(cmd, buf, sizeof(buf));
5309 }
5310 }
5311 if (band == band_5) {
5312 snprintf(cmd, sizeof(cmd), "cat %s | grep '^vht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
5313 _syscmd(cmd, buf, sizeof(buf));
5314 if (strlen(buf) > 0) {
5315 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1]/' %s", config_file);
5316 _syscmd(cmd, buf, sizeof(buf));
5317 }
5318 }
5319
5320 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SU-BEAMFORMER\\]'", config_file);
5321 _syscmd(cmd, buf, sizeof(buf));
5322 if (strlen(buf) == 0) {
5323 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SU-BEAMFORMER]/' %s", config_file);
5324 _syscmd(cmd, buf, sizeof(buf));
5325 }
5326
5327 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[MU-BEAMFORMER\\]'", config_file);
5328 _syscmd(cmd, buf, sizeof(buf));
5329 if (strlen(buf) == 0) {
5330 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[MU-BEAMFORMER]/' %s", config_file);
5331 _syscmd(cmd, buf, sizeof(buf));
5332 }
5333
5334 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SOUNDING-DIMENSION-.\\]'", config_file);
5335 _syscmd(cmd, buf, sizeof(buf));
5336 if (strlen(buf) == 0) {
5337 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SOUNDING-DIMENSION-%d]/' %s", antcount, config_file);
5338 } else {
5339 snprintf(cmd, sizeof(cmd), "sed -r -i 's/(SOUNDING-DIMENSION-)./\\1%d/' %s", antcount, config_file);
5340 }
5341 _syscmd(cmd, buf, sizeof(buf));
5342
5343 list[0].value = "1";
5344 list[1].value = "1";
5345 }
5346 wifi_hostapdWrite(config_file, list, 2);
5347}
5348
5349//P2 // sets the number of Tx streams to an enviornment variable
5350INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
5351{
5352 char cmd[128] = {0};
5353 char buf[128] = {0};
5354 int phyId = 0;
5355 int cur_mask = 0;
developera1255e42023-05-13 17:45:02 +08005356 int antcountmsk = 0;
5357 INT cur_nss = 0;
5358 UCHAR dat_file[64] = {0};
5359 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08005360
5361 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5362
5363 if (numStreams <= 0) {
5364 fprintf(stderr, "%s: chainmask is not supported %d.\n", __func__, numStreams);
5365 return RETURN_ERR;
5366 }
5367
developera1255e42023-05-13 17:45:02 +08005368 wifi_getRadioTxChainMask(radioIndex, &cur_mask);//this is mask value
5369 for(; cur_mask > 0; cur_mask >>= 1)//convert to number of streams.
5370 cur_nss += 1;
5371 WIFI_ENTRY_EXIT_DEBUG("%s:cur_nss=%d, new_nss=%d\n", __func__, cur_nss, numStreams);
5372 if (cur_nss == numStreams)
developer72fb0bb2023-01-11 09:46:29 +08005373 return RETURN_OK;
5374
5375 wifi_setRadioEnable(radioIndex, FALSE);
5376
5377 phyId = radio_index_to_phy(radioIndex);
developera1255e42023-05-13 17:45:02 +08005378 //iw need mask value.
5379 for (;numStreams > 0; numStreams--)
5380 antcountmsk |= 0x1 << (numStreams - 1);
5381 snprintf(cmd, sizeof(cmd), "iw phy%d set antenna 0x%x 2>&1", phyId, antcountmsk);
developer72fb0bb2023-01-11 09:46:29 +08005382 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08005383 if (strlen(buf) > 0) {
5384 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
5385 return RETURN_ERR;
5386 }
developera1255e42023-05-13 17:45:02 +08005387 band = wifi_index_to_band(radioIndex);
5388 if (band == band_invalid) {
5389 printf("%s:Band Error\n", __func__);
5390 return RETURN_ERR;
5391 }
5392 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
5393 snprintf(cmd, sizeof(cmd), "sed -r -i 's/^HT_TxStream=.*/HT_TxStream=%d/g' %s", numStreams, dat_file);
5394 _syscmd(cmd, buf, sizeof(buf));
5395 if (strlen(buf) > 0) {
5396 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
5397 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08005398 }
developera1255e42023-05-13 17:45:02 +08005399 snprintf(cmd, sizeof(cmd), "sed -r -i 's/^HT_RxStream=.*/HT_RxStream=%d/g' %s", numStreams, dat_file);
5400 _syscmd(cmd, buf, sizeof(buf));
5401 if (strlen(buf) > 0) {
5402 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
5403 return RETURN_ERR;
5404 }
5405 fitChainMask(radioIndex, numStreams);
developer72fb0bb2023-01-11 09:46:29 +08005406 wifi_setRadioEnable(radioIndex, TRUE);
5407
5408 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5409 return RETURN_OK;
5410}
5411
5412//P2 // outputs the number of Rx streams
5413INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
5414{
5415 char buf[8] = {0};
5416 char cmd[128] = {0};
5417 int phyId = 0;
5418
5419 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5420
5421 phyId = radio_index_to_phy(radioIndex);
5422 sprintf(cmd, "iw phy%d info | grep 'Configured Antennas' | awk '{print $6}'", phyId);
5423 _syscmd(cmd, buf, sizeof(buf));
5424
5425 *output_int = (INT)strtol(buf, NULL, 16);
5426
5427 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5428
5429 return RETURN_OK;
5430}
5431
5432//P2 // sets the number of Rx streams to an enviornment variable
5433INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
5434{
5435 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5436 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
5437 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
5438 return RETURN_ERR;
5439 }
5440 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5441 return RETURN_ERR;
5442}
5443
5444//Get radio RDG enable setting
5445INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
5446{
5447 if (NULL == output_bool)
5448 return RETURN_ERR;
5449 *output_bool = TRUE;
5450 return RETURN_OK;
5451}
5452
5453//Get radio RDG enable setting
5454INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
5455{
5456 if (NULL == output_bool)
5457 return RETURN_ERR;
5458 *output_bool = TRUE;
5459 return RETURN_OK;
5460}
5461
5462//Set radio RDG enable setting
5463INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
5464{
5465 return RETURN_ERR;
5466}
5467
5468//Get radio ADDBA enable setting
5469INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
5470{
5471 if (NULL == output_bool)
5472 return RETURN_ERR;
5473 *output_bool = TRUE;
5474 return RETURN_OK;
5475}
5476
5477//Set radio ADDBA enable setting
5478INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
5479{
5480 return RETURN_ERR;
5481}
5482
5483//Get radio auto block ack enable setting
5484INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
5485{
5486 if (NULL == output_bool)
5487 return RETURN_ERR;
5488 *output_bool = TRUE;
5489 return RETURN_OK;
5490}
5491
5492//Set radio auto block ack enable setting
5493INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
5494{
5495 return RETURN_ERR;
5496}
5497
5498//Get radio 11n pure mode enable support
5499INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
5500{
5501 if (NULL == output_bool)
5502 return RETURN_ERR;
5503 *output_bool = TRUE;
5504 return RETURN_OK;
5505}
5506
5507//Get radio 11n pure mode enable setting
5508INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
5509{
5510 if (NULL == output_bool)
5511 return RETURN_ERR;
5512 *output_bool = TRUE;
5513 return RETURN_OK;
5514}
5515
5516//Set radio 11n pure mode enable setting
5517INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
5518{
5519 return RETURN_ERR;
5520}
5521
5522//Get radio IGMP snooping enable setting
5523INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
5524{
5525 char interface_name[16] = {0};
5526 char cmd[128]={0};
5527 char buf[4]={0};
5528 bool bridge = FALSE, mac80211 = FALSE;
5529 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5530
5531 if(output_bool == NULL)
5532 return RETURN_ERR;
5533
5534 *output_bool = FALSE;
5535
5536 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
5537 _syscmd(cmd, buf, sizeof(buf));
5538 if (strncmp(buf, "1", 1) == 0)
5539 bridge = TRUE;
5540
5541 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
5542 return RETURN_ERR;
5543 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast", BRIDGE_NAME, interface_name);
5544 _syscmd(cmd, buf, sizeof(buf));
5545 if (strncmp(buf, "1", 1) == 0)
5546 mac80211 = TRUE;
5547
5548 if (bridge && mac80211)
5549 *output_bool = TRUE;
5550
5551 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5552 return RETURN_OK;
5553}
5554
5555//Set radio IGMP snooping enable setting
5556INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
5557{
5558 char interface_name[16] = {0};
5559 char cmd[128]={0};
5560 char buf[4]={0};
5561 int max_num_radios =0;
5562 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5563
5564 // bridge
5565 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
5566 _syscmd(cmd, buf, sizeof(buf));
5567
5568 wifi_getMaxRadioNumber(&max_num_radios);
5569 // mac80211
5570 for (int i = 0; i < max_num_radios; i++) {
5571 if (wifi_GetInterfaceName(i, interface_name) != RETURN_OK)
5572 return RETURN_ERR;
5573 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast", enable, BRIDGE_NAME, interface_name);
5574 _syscmd(cmd, buf, sizeof(buf));
5575 }
5576 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5577 return RETURN_OK;
5578}
5579
5580//Get the Reset count of radio
developer69b61b02023-03-07 17:17:44 +08005581INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
developer72fb0bb2023-01-11 09:46:29 +08005582{
developer69b61b02023-03-07 17:17:44 +08005583 if (NULL == output_int)
developer72fb0bb2023-01-11 09:46:29 +08005584 return RETURN_ERR;
5585 *output_int = (radioIndex==0)? 1: 3;
5586
5587 return RETURN_OK;
5588}
5589
5590
5591//---------------------------------------------------------------------------------------------------
5592//
5593// Additional Wifi AP level APIs used for Access Point devices
5594//
5595//---------------------------------------------------------------------------------------------------
5596
5597// creates a new ap and pushes these parameters to the hardware
5598INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
5599{
5600 // Deprecated when use hal version 3, use wifi_createVap() instead.
5601 return RETURN_OK;
5602}
5603
5604// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
5605INT wifi_deleteAp(INT apIndex)
5606{
developer7e4a2a62023-04-06 19:56:03 +08005607 char interface_name[16] = {0};
5608 char buf[MAX_BUF_SIZE];
5609 char cmd[MAX_CMD_SIZE];
developer72fb0bb2023-01-11 09:46:29 +08005610
developer7e4a2a62023-04-06 19:56:03 +08005611 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5612 return RETURN_ERR;
developer8a3bbbf2023-03-15 17:47:23 +08005613
developer7e4a2a62023-04-06 19:56:03 +08005614 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw REMOVE %s", interface_name);
5615 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08005616
developer7e4a2a62023-04-06 19:56:03 +08005617 wifi_removeApSecVaribles(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08005618
developer7e4a2a62023-04-06 19:56:03 +08005619 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08005620}
5621
5622// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
5623INT wifi_getApName(INT apIndex, CHAR *output_string)
5624{
developer7e4a2a62023-04-06 19:56:03 +08005625 char interface_name[IF_NAME_SIZE] = {0};
5626 char radio_idx = 0;
5627 char bss_idx = 0;
developer72fb0bb2023-01-11 09:46:29 +08005628
developer7e4a2a62023-04-06 19:56:03 +08005629 if(!output_string)
5630 return RETURN_ERR;
5631
5632 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
5633 vap_index_to_array_index(apIndex, &radio_idx, &bss_idx);
5634
5635 snprintf(output_string, IF_NAME_SIZE, "%s%d", ext_prefix[radio_idx], bss_idx); // For wifiagent generating data model.
5636 } else
5637 snprintf(output_string, IF_NAME_SIZE, "%s", interface_name);
5638
5639 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08005640}
5641
5642// Outputs the index number in that corresponds to the SSID string
5643INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
5644{
developer7e4a2a62023-04-06 19:56:03 +08005645 char cmd [128] = {0};
5646 char buf[32] = {0};
5647 char ap_idx = 0;
5648 char *apIndex_str = NULL;
5649 char radio_idx = 0;
5650 char bss_idx = 0;
developer72fb0bb2023-01-11 09:46:29 +08005651
developer7e4a2a62023-04-06 19:56:03 +08005652 snprintf(cmd, sizeof(cmd), "grep -rn ^interface=%s$ /nvram/hostapd*.conf | cut -d '.' -f1 | cut -d 'd' -f2 | tr -d '\\n'",
5653 inputSsidString);
5654 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08005655
developer7e4a2a62023-04-06 19:56:03 +08005656 if (strlen(buf)) {
5657 apIndex_str = strtok(buf, "\n");
5658 *output_int = strtoul(apIndex_str, NULL, 10);
5659 return RETURN_OK;
5660 }
developer72fb0bb2023-01-11 09:46:29 +08005661
developer7e4a2a62023-04-06 19:56:03 +08005662 /* If interface name is not in hostapd config, the caller maybe wifi agent to generate data model.*/
5663 if (strstr(inputSsidString, PREFIX_WIFI6G)) {
5664 bss_idx = atoi(inputSsidString + strlen(PREFIX_WIFI6G));
5665 radio_idx = 2;
5666 } else if (strstr(inputSsidString, PREFIX_WIFI5G)) {
5667 bss_idx = atoi(inputSsidString + strlen(PREFIX_WIFI5G));
5668 radio_idx = 1;
5669 } else if (strstr(inputSsidString, PREFIX_WIFI2G)) {
5670 bss_idx = atoi(inputSsidString + strlen(PREFIX_WIFI2G));
5671 radio_idx = 0;
5672 } else {
5673 printf("%s: hostapd conf not find, unknow inf(%s), return ERROR!!!(%d).\n",
5674 __func__, inputSsidString, ap_idx);
5675 *output_int = -1;
5676 return RETURN_ERR;
5677 }
5678
5679 ap_idx = array_index_to_vap_index(radio_idx, bss_idx);
5680
5681 if (ap_idx >= 0 && ap_idx < MAX_VAP) {
5682 printf("%s: hostapd conf not find, inf(%s), use inf idx(%d).\n",
5683 __func__, inputSsidString, ap_idx);
5684 *output_int = ap_idx;
5685 return RETURN_OK;
5686 }
5687
5688 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08005689}
5690
5691INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
5692{
5693 return wifi_getIndexFromName(inputSsidString, output_int);
5694}
5695
5696// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
5697INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
5698{
5699 char buf[MAX_BUF_SIZE] = {0};
5700 char cmd[MAX_CMD_SIZE] = {0};
5701 char config_file[MAX_BUF_SIZE] = {0};
5702
5703 if(NULL == output_string)
5704 return RETURN_ERR;
5705
5706 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5707 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
5708 if((strcmp(buf,"3")==0))
5709 snprintf(output_string, 32, "WPAand11i");
5710 else if((strcmp(buf,"2")==0))
5711 snprintf(output_string, 32, "11i");
5712 else if((strcmp(buf,"1")==0))
5713 snprintf(output_string, 32, "WPA");
5714 else
5715 snprintf(output_string, 32, "None");
5716
5717 return RETURN_OK;
5718}
5719
5720// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
5721INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
5722{
5723 char config_file[MAX_BUF_SIZE] = {0};
5724 struct params list;
5725
5726 if (NULL == beaconTypeString)
5727 return RETURN_ERR;
5728 list.name = "wpa";
5729 list.value = "0";
5730
5731 if((strcmp(beaconTypeString,"WPAand11i")==0))
5732 list.value="3";
5733 else if((strcmp(beaconTypeString,"11i")==0))
5734 list.value="2";
5735 else if((strcmp(beaconTypeString,"WPA")==0))
5736 list.value="1";
5737
5738 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5739 wifi_hostapdWrite(config_file, &list, 1);
5740 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5741 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
5742 return RETURN_OK;
5743}
5744
5745// sets the beacon interval on the hardware for this AP
5746INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
5747{
5748 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5749 struct params params={'\0'};
5750 char buf[MAX_BUF_SIZE] = {'\0'};
5751 char config_file[MAX_BUF_SIZE] = {'\0'};
5752
5753 params.name = "beacon_int";
5754 snprintf(buf, sizeof(buf), "%u", beaconInterval);
5755 params.value = buf;
5756
5757 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5758 wifi_hostapdWrite(config_file, &params, 1);
developer69b61b02023-03-07 17:17:44 +08005759
developer72fb0bb2023-01-11 09:46:29 +08005760 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5761 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5762 return RETURN_OK;
5763}
5764
5765INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
5766{
5767 if (wifi_setApDTIMInterval(apIndex, dtimInterval) != RETURN_OK)
5768 return RETURN_ERR;
5769 return RETURN_OK;
5770}
5771
5772// Get the packet size threshold supported.
5773INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
5774{
5775 //save config and apply instantly
5776 if (NULL == output_bool)
5777 return RETURN_ERR;
5778 *output_bool = TRUE;
5779 return RETURN_OK;
5780}
5781
5782// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
5783INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
5784{
developer72fb0bb2023-01-11 09:46:29 +08005785 char buf[16] = {0};
5786 char config_file[128] = {0};
5787 struct params param = {0};
5788
5789 if (threshold > 65535) {
5790 fprintf(stderr, "%s: rts threshold %u is too big.\n", __func__, threshold);
5791 return RETURN_ERR;
5792 }
5793
developer23e71282023-01-18 10:25:19 +08005794 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developer72fb0bb2023-01-11 09:46:29 +08005795 snprintf(buf, sizeof(buf), "%u", threshold);
5796 param.name = "rts_threshold";
5797 param.value = buf;
5798 wifi_hostapdWrite(config_file, &param, 1);
5799 wifi_hostapdProcessUpdate(apIndex, &param, 1);
5800 wifi_reloadAp(apIndex);
5801
5802 return RETURN_OK;
5803}
5804
5805// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5806INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
5807{
5808 if (NULL == output_string)
5809 return RETURN_ERR;
5810 snprintf(output_string, 32, "TKIPandAESEncryption");
5811 return RETURN_OK;
5812
5813}
5814
5815// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5816INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
5817{
5818 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5819 char *param_name = NULL;
5820 char buf[32] = {0}, config_file[MAX_BUF_SIZE] = {0};
5821
5822 if(NULL == output_string)
5823 return RETURN_ERR;
5824
5825 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5826 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5827
5828 if(strcmp(buf,"0")==0)
5829 {
5830 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
5831 snprintf(output_string, 32, "None");
5832 return RETURN_OK;
5833 }
5834 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
5835 param_name = "rsn_pairwise";
5836 else if((strcmp(buf,"1")==0))
5837 param_name = "wpa_pairwise";
5838 else
5839 return RETURN_ERR;
5840 memset(output_string,'\0',32);
5841 wifi_hostapdRead(config_file,param_name,output_string,32);
5842 if (strlen(output_string) == 0) { // rsn_pairwise is optional. When it is empty use wpa_pairwise instead.
5843 param_name = "wpa_pairwise";
5844 memset(output_string, '\0', 32);
5845 wifi_hostapdRead(config_file, param_name, output_string, 32);
5846 }
5847 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
5848
5849 if(strcmp(output_string,"TKIP") == 0)
5850 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
5851 else if(strcmp(output_string,"CCMP") == 0)
5852 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
5853 else if(strcmp(output_string,"TKIP CCMP") == 0)
5854 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
5855
5856 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5857 return RETURN_OK;
5858}
5859
5860// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5861INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
5862{
5863 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5864 struct params params={'\0'};
5865 char output_string[32];
5866 char config_file[MAX_BUF_SIZE] = {0};
5867
5868 memset(output_string,'\0',32);
5869 wifi_getApWpaEncryptionMode(apIndex,output_string);
5870
5871 if(strcmp(encMode, "TKIPEncryption") == 0)
5872 params.value = "TKIP";
5873 else if(strcmp(encMode,"AESEncryption") == 0)
5874 params.value = "CCMP";
5875 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
5876 params.value = "TKIP CCMP";
5877
5878 if((strcmp(output_string,"WPAand11i")==0))
5879 {
5880 params.name = "wpa_pairwise";
5881 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5882 wifi_hostapdWrite(config_file, &params, 1);
5883 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5884
5885 params.name = "rsn_pairwise";
5886 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5887 wifi_hostapdWrite(config_file, &params, 1);
5888 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5889
5890 return RETURN_OK;
5891 }
5892 else if((strcmp(output_string,"11i")==0))
5893 {
5894 params.name = "rsn_pairwise";
5895 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5896 wifi_hostapdWrite(config_file, &params, 1);
5897 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5898 return RETURN_OK;
5899 }
5900 else if((strcmp(output_string,"WPA")==0))
5901 {
5902 params.name = "wpa_pairwise";
5903 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5904 wifi_hostapdWrite(config_file, &params, 1);
5905 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5906 return RETURN_OK;
5907 }
5908
5909 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5910 return RETURN_OK;
5911}
5912
5913// deletes internal security varable settings for this ap
5914INT wifi_removeApSecVaribles(INT apIndex)
5915{
5916 //TODO: remove the entry in hostapd config file
5917 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s.conf//g' /tmp/conf_filename", interface_name);
5918 //_syscmd(cmd, buf, sizeof(buf));
5919
5920 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s//g' /tmp/conf_filename", interface_name);
5921 //_syscmd(cmd, buf, sizeof(buf));
5922 return RETURN_ERR;
5923}
5924
5925// changes the hardware settings to disable encryption on this ap
5926INT wifi_disableApEncryption(INT apIndex)
5927{
5928 //Apply instantly
5929 return RETURN_ERR;
5930}
5931
5932// set the authorization mode on this ap
5933// mode mapping as: 1: open, 2: shared, 4:auto
5934INT wifi_setApAuthMode(INT apIndex, INT mode)
5935{
5936 struct params params={0};
5937 char config_file[64] = {0};
5938 int ret;
5939
5940 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5941
5942 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
5943 params.name = "auth_algs";
5944
5945 if (mode & 1 && mode & 2)
5946 params.value = "3";
5947 else if (mode & 2)
5948 params.value = "2";
5949 else if (mode & 1)
5950 params.value = "1";
5951 else
5952 params.value = "0";
5953
5954 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5955 wifi_hostapdWrite(config_file, &params, 1);
5956 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5957 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5958
5959 return RETURN_OK;
5960}
5961
5962// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5963INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5964{
5965 //save to wifi config, and wait for wifi restart to apply
5966 struct params params={'\0'};
5967 char config_file[MAX_BUF_SIZE] = {0};
5968 int ret;
5969
5970 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5971 if(authMode == NULL)
5972 return RETURN_ERR;
5973
5974 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5975 params.name = "wpa_key_mgmt";
5976
5977 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5978 params.value = "WPA-PSK";
5979 else if(strcmp(authMode,"EAPAuthentication") == 0)
5980 params.value = "WPA-EAP";
5981 else if (strcmp(authMode, "SAEAuthentication") == 0)
5982 params.value = "SAE";
5983 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5984 params.value = "WPA-EAP-SUITE-B-192";
5985 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
5986 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer3086e2f2023-01-17 09:40:01 +08005987 else if (strcmp(authMode, "Enhanced_Open") == 0)
5988 params.value = "OWE";
developer72fb0bb2023-01-11 09:46:29 +08005989 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5990 return RETURN_OK; //This is taken careof in beaconType
5991
5992 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5993 ret=wifi_hostapdWrite(config_file,&params,1);
5994 if(!ret)
5995 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
5996 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5997
5998 return ret;
5999}
6000
6001// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
6002INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
6003{
6004 //save to wifi config, and wait for wifi restart to apply
6005 char BeaconType[50] = {0};
6006 char config_file[MAX_BUF_SIZE] = {0};
6007
6008 *authMode = 0;
6009 wifi_getApBeaconType(apIndex,BeaconType);
6010 printf("%s____%s \n",__FUNCTION__,BeaconType);
6011
6012 if(strcmp(BeaconType,"None") == 0)
6013 strcpy(authMode,"None");
6014 else
6015 {
6016 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6017 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
6018 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
6019 if(strcmp(authMode,"WPA-PSK") == 0)
6020 strcpy(authMode,"SharedAuthentication");
6021 else if(strcmp(authMode,"WPA-EAP") == 0)
6022 strcpy(authMode,"EAPAuthentication");
6023 }
6024
6025 return RETURN_OK;
6026}
6027
6028// Outputs the number of stations associated per AP
6029INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
6030{
6031 char interface_name[16] = {0};
6032 char cmd[128]={0};
6033 char buf[128]={0};
6034 BOOL status = false;
6035
6036 if(apIndex > MAX_APS)
6037 return RETURN_ERR;
6038
6039 wifi_getApEnable(apIndex,&status);
6040 if (!status)
6041 return RETURN_OK;
6042
6043 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);//alternate method
6044 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6045 return RETURN_ERR;
6046 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l", interface_name);
6047 _syscmd(cmd, buf, sizeof(buf));
6048 sscanf(buf,"%lu", output_ulong);
6049
6050 return RETURN_OK;
6051}
6052
6053// manually removes any active wi-fi association with the device specified on this ap
6054INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
6055{
developer7e4a2a62023-04-06 19:56:03 +08006056 char inf_name[16] = {0};
6057 char cmd[MAX_CMD_SIZE] = {0};
6058 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08006059
developer7e4a2a62023-04-06 19:56:03 +08006060 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
developer72fb0bb2023-01-11 09:46:29 +08006061 return RETURN_ERR;
developer7e4a2a62023-04-06 19:56:03 +08006062
6063 snprintf(cmd, sizeof(cmd),"hostapd_cli -i %s disassociate %s", inf_name, client_mac);
6064 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006065
6066 return RETURN_OK;
6067}
6068
6069// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
6070INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
6071{
developer7e4a2a62023-04-06 19:56:03 +08006072 int max_radio_num = 0;
6073
6074 if(NULL == output_int)
6075 return RETURN_ERR;
6076
6077 wifi_getMaxRadioNumber(&max_radio_num);
6078 *output_int = apIndex % max_radio_num;
6079
6080 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006081}
6082
6083// sets the radio index for the specific ap
6084INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
6085{
6086 //set to config only and wait for wifi reset to apply settings
6087 return RETURN_ERR;
6088}
6089
6090// Get the ACL MAC list per AP
6091INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
6092{
developer7e4a2a62023-04-06 19:56:03 +08006093 char cmd[MAX_CMD_SIZE] = {0};
6094 char buf[MAX_BUF_SIZE] = {0};
6095 char inf_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08006096
developer7e4a2a62023-04-06 19:56:03 +08006097 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
6098 return RETURN_ERR;
6099
6100 /* mwctl acl del sta */
6101 snprintf(cmd, sizeof(cmd), "mwctl %s acl show_all | grep ':'", inf_name);
6102 _syscmd(cmd, buf, sizeof(buf));
6103
6104 memcpy(macArray, buf, buf_size);
developer72fb0bb2023-01-11 09:46:29 +08006105
6106 return RETURN_OK;
6107}
6108
6109INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
6110{
developer72fb0bb2023-01-11 09:46:29 +08006111
developer7e4a2a62023-04-06 19:56:03 +08006112 wifi_getApAclDevices(apIndex, macArray, buf_size);
developer72fb0bb2023-01-11 09:46:29 +08006113
6114 return RETURN_OK;
6115}
6116
6117
6118// Get the list of stations associated per AP
6119INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
6120{
developer7e4a2a62023-04-06 19:56:03 +08006121 char interface_name[IF_NAME_SIZE] = {0};
6122 char cmd[MAX_CMD_SIZE];
developer72fb0bb2023-01-11 09:46:29 +08006123
developer7e4a2a62023-04-06 19:56:03 +08006124 if(apIndex > 3) //Currently supporting apIndex upto 3
6125 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006126
developer7e4a2a62023-04-06 19:56:03 +08006127 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6128 return RETURN_ERR;
6129
6130 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s list_sta", interface_name);
6131 _syscmd(cmd, macArray, buf_size);
6132 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006133}
6134
6135// adds the mac address to the filter list
6136//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
6137INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
6138{
developer7e4a2a62023-04-06 19:56:03 +08006139 char cmd[MAX_CMD_SIZE] = {0};
6140 char buf[MAX_BUF_SIZE] = {0};
6141 char inf_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08006142
developer7e4a2a62023-04-06 19:56:03 +08006143 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
6144 return RETURN_ERR;
6145
6146 if (!DeviceMacAddress)
6147 return RETURN_ERR;
6148
6149 /* mwctl acl add sta */
6150 snprintf(cmd, sizeof(cmd), "mwctl %s acl add=%s", inf_name, DeviceMacAddress);
6151 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006152
6153 return RETURN_OK;
6154}
6155
6156// deletes the mac address from the filter list
6157//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
6158INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
6159{
developer7e4a2a62023-04-06 19:56:03 +08006160 char cmd[MAX_CMD_SIZE] = {0};
6161 char buf[MAX_BUF_SIZE] = {0};
6162 char inf_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08006163
developer7e4a2a62023-04-06 19:56:03 +08006164 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
6165 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006166
developer7e4a2a62023-04-06 19:56:03 +08006167 if (!DeviceMacAddress)
6168 return RETURN_ERR;
6169
6170 /* mwctl acl del sta */
6171 snprintf(cmd, sizeof(cmd), "mwctl %s acl del=%s", inf_name, DeviceMacAddress);
6172 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006173
6174 return RETURN_OK;
6175}
6176
6177// outputs the number of devices in the filter list
6178INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
6179{
developer7e4a2a62023-04-06 19:56:03 +08006180 char cmd[MAX_CMD_SIZE] = {0};
6181 char buf[MAX_BUF_SIZE] = {0};
6182 char inf_name[IF_NAME_SIZE] = {0};
6183 char sta_num = 0;
developer72fb0bb2023-01-11 09:46:29 +08006184
developer72fb0bb2023-01-11 09:46:29 +08006185 if(output_uint == NULL)
6186 return RETURN_ERR;
6187
developer7e4a2a62023-04-06 19:56:03 +08006188 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
6189 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006190
developer7e4a2a62023-04-06 19:56:03 +08006191 /* mwctl acl get sta num */
6192 snprintf(cmd, sizeof(cmd), "mwctl %s acl show_all | wc -l | tr -d '\\n'", inf_name);
6193 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006194
developer7e4a2a62023-04-06 19:56:03 +08006195 if (atoi(buf) > 1)
6196 *output_uint = atoi(buf) - 1; /*except the line of acl_policy*/
6197 else {
6198 *output_uint = 0;
6199 printf("%s: acl get wrong return content!!!\n", __func__);
6200 }
6201
6202 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006203}
6204
6205INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
6206{
6207 char cmd[128]={'\0'};
6208 char buf[128]={'\0'};
6209
6210 if(strcmp(action,"DENY")==0)
6211 {
6212 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
6213 system(buf);
6214 return RETURN_OK;
6215 }
6216
6217 if(strcmp(action,"ALLOW")==0)
6218 {
6219 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
6220 system(buf);
6221 return RETURN_OK;
6222 }
6223
6224 return RETURN_ERR;
6225
6226}
6227
6228// enable kick for devices on acl black list
6229INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
6230{
6231 char aclArray[512] = {0}, *acl = NULL;
6232 char assocArray[512] = {0}, *asso = NULL;
6233
6234 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
6235 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
6236
developer7e4a2a62023-04-06 19:56:03 +08006237 /* if there are no devices connected there is nothing to do */
developer72fb0bb2023-01-11 09:46:29 +08006238 if (strlen(assocArray) < 17)
6239 return RETURN_OK;
6240
developer7e4a2a62023-04-06 19:56:03 +08006241 if (enable == TRUE) {
6242 /* kick off the MAC which is in ACL array (deny list) */
6243 acl = strtok(aclArray, "\n");
developer72fb0bb2023-01-11 09:46:29 +08006244 while (acl != NULL) {
6245 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
6246 wifi_kickApAssociatedDevice(apIndex, acl);
6247
developer7e4a2a62023-04-06 19:56:03 +08006248 acl = strtok(NULL, "\n");
developer72fb0bb2023-01-11 09:46:29 +08006249 }
6250 wifi_setApMacAddressControlMode(apIndex, 2);
developer7e4a2a62023-04-06 19:56:03 +08006251 } else
developer72fb0bb2023-01-11 09:46:29 +08006252 wifi_setApMacAddressControlMode(apIndex, 0);
developer72fb0bb2023-01-11 09:46:29 +08006253
developer72fb0bb2023-01-11 09:46:29 +08006254 return RETURN_OK;
6255}
6256
6257INT wifi_setPreferPrivateConnection(BOOL enable)
6258{
6259 return RETURN_OK;
6260}
6261
6262// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
6263INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
6264{
developer7e4a2a62023-04-06 19:56:03 +08006265 char inf_name[IF_NAME_SIZE] = {0};
6266 char cmd[MAX_CMD_SIZE] = {0};
6267 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08006268
developer7e4a2a62023-04-06 19:56:03 +08006269 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
6270 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006271
developer7e4a2a62023-04-06 19:56:03 +08006272 /*mwctl set acl policy*/
6273 snprintf(cmd, sizeof(cmd), "mwctl %s acl policy=%d", inf_name, filterMode);
6274 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006275
developer7e4a2a62023-04-06 19:56:03 +08006276 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006277}
6278
6279// enables internal gateway VLAN mode. In this mode a Vlan tag is added to upstream (received) data packets before exiting the Wifi driver. VLAN tags in downstream data are stripped from data packets before transmission. Default is FALSE.
6280INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
6281{
6282 return RETURN_ERR;
6283}
6284
6285// gets the vlan ID for this ap from an internal enviornment variable
6286INT wifi_getApVlanID(INT apIndex, INT *output_int)
6287{
6288 if(apIndex==0)
6289 {
6290 *output_int=100;
6291 return RETURN_OK;
6292 }
6293
6294 return RETURN_ERR;
6295}
6296
6297// sets the vlan ID for this ap to an internal enviornment variable
6298INT wifi_setApVlanID(INT apIndex, INT vlanId)
6299{
6300 //save the vlanID to config and wait for wifi reset to apply (wifi up module would read this parameters and tag the AP with vlan id)
6301 return RETURN_ERR;
6302}
6303
6304// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
6305INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
6306{
6307 snprintf(bridgeName, 32, "brlan0");
6308 snprintf(IP, 32, "10.0.0.1");
6309 snprintf(subnet, 32, "255.255.255.0");
6310
6311 return RETURN_OK;
6312}
6313
6314//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
6315INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
6316{
6317 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
6318 return RETURN_ERR;
6319}
6320
6321// reset the vlan configuration for this ap
6322INT wifi_resetApVlanCfg(INT apIndex)
6323{
6324 char original_config_file[64] = {0};
6325 char current_config_file[64] = {0};
6326 char buf[64] = {0};
6327 char cmd[64] = {0};
6328 char vlan_file[64] = {0};
6329 char vlan_tagged_interface[16] = {0};
6330 char vlan_bridge[16] = {0};
6331 char vlan_naming[16] = {0};
6332 struct params list[4] = {0};
6333 wifi_band band;
developera1255e42023-05-13 17:45:02 +08006334 char interface_name[16] = {0};
developer72fb0bb2023-01-11 09:46:29 +08006335
6336 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08006337 band = wifi_index_to_band(apIndex);
6338 if (band == band_2_4)
developera1255e42023-05-13 17:45:02 +08006339 snprintf(original_config_file, sizeof(original_config_file), "/etc/hostapd-2G.conf");
developer72fb0bb2023-01-11 09:46:29 +08006340 else if (band == band_5)
developera1255e42023-05-13 17:45:02 +08006341 snprintf(original_config_file, sizeof(original_config_file), "/etc/hostapd-5G.conf");
developer72fb0bb2023-01-11 09:46:29 +08006342 else if (band == band_6)
developera1255e42023-05-13 17:45:02 +08006343 snprintf(original_config_file, sizeof(original_config_file), "/etc/hostapd-6G.conf");
developer72fb0bb2023-01-11 09:46:29 +08006344
6345 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
6346
6347 if (strlen(vlan_file) == 0)
6348 strcpy(vlan_file, VLAN_FILE);
6349
6350 // The file should exist or this vap would not work.
6351 if (access(vlan_file, F_OK) != 0) {
developera1255e42023-05-13 17:45:02 +08006352 snprintf(cmd, sizeof(cmd), "touch %s", vlan_file);
developer72fb0bb2023-01-11 09:46:29 +08006353 _syscmd(cmd, buf, sizeof(buf));
6354 }
6355 list[0].name = "vlan_file";
6356 list[0].value = vlan_file;
6357
6358 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
6359 list[1].name = "vlan_tagged_interface";
6360 list[1].value = vlan_tagged_interface;
6361
6362 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
6363 list[2].name = "vlan_bridge";
6364 list[2].value = vlan_bridge;
6365
6366 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
6367 list[3].name = "vlan_naming";
6368 list[3].value = vlan_naming;
6369
developera1255e42023-05-13 17:45:02 +08006370 snprintf(current_config_file, sizeof(current_config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developer72fb0bb2023-01-11 09:46:29 +08006371 wifi_hostapdWrite(current_config_file, list, 4);
6372 //Reapply vlan settings
6373 // wifi_pushBridgeInfo(apIndex);
6374
6375 // restart this ap
6376 wifi_setApEnable(apIndex, FALSE);
6377 wifi_setApEnable(apIndex, TRUE);
developera1255e42023-05-13 17:45:02 +08006378 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6379 return RETURN_ERR;
6380 snprintf(cmd, sizeof(cmd), "mwctl dev %s set vlan_tag 0\n", interface_name);
6381 _syscmd(cmd, buf, sizeof(buf));
6382 snprintf(cmd, sizeof(cmd), "mwctl dev %s set vlan_priority 0\n", interface_name);
6383 _syscmd(cmd, buf, sizeof(buf));
6384 snprintf(cmd, sizeof(cmd), "mwctl dev %s set vlan_id 0\n", interface_name);
6385 _syscmd(cmd, buf, sizeof(buf));
6386 snprintf(cmd, sizeof(cmd), "mwctl dev %s set vlan_en 0\n", interface_name);
6387 _syscmd(cmd, buf, sizeof(buf));
6388 snprintf(cmd, sizeof(cmd), "mwctl dev %s set vlan_policy 0:4\n", interface_name);
6389 _syscmd(cmd, buf, sizeof(buf));
6390 snprintf(cmd, sizeof(cmd), "mwctl dev %s set vlan_policy 1:0\n", interface_name);
6391 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006392 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6393
6394 return RETURN_OK;
6395}
6396
6397// 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.
6398INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
6399{
6400 return RETURN_ERR;
6401}
6402
6403// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
6404INT wifi_startHostApd()
6405{
6406 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6407 system("systemctl start hostapd.service");
6408 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6409 return RETURN_OK;
6410 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
6411}
6412
6413// stops hostapd
developer69b61b02023-03-07 17:17:44 +08006414INT wifi_stopHostApd()
developer72fb0bb2023-01-11 09:46:29 +08006415{
6416 char cmd[128] = {0};
6417 char buf[128] = {0};
6418
6419 sprintf(cmd,"systemctl stop hostapd");
6420 _syscmd(cmd, buf, sizeof(buf));
6421
6422 return RETURN_OK;
6423}
6424
6425// restart hostapd dummy function
6426INT wifi_restartHostApd()
6427{
6428 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6429 system("systemctl restart hostapd-global");
6430 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6431
6432 return RETURN_OK;
6433}
6434
6435static int align_hostapd_config(int index)
6436{
6437 ULONG lval;
6438 wifi_getRadioChannel(index%2, &lval);
6439 wifi_setRadioChannel(index%2, lval);
6440 return RETURN_OK;
6441}
6442
6443// sets the AP enable status variable for the specified ap.
6444INT wifi_setApEnable(INT apIndex, BOOL enable)
6445{
developer7e4a2a62023-04-06 19:56:03 +08006446 char interface_name[16] = {0};
6447 char config_file[MAX_BUF_SIZE] = {0};
6448 char cmd[MAX_CMD_SIZE] = {0};
6449 char buf[MAX_BUF_SIZE] = {0};
6450 BOOL status;
6451 int max_radio_num = 0;
6452 int phyId = 0;
developer72fb0bb2023-01-11 09:46:29 +08006453
developer7e4a2a62023-04-06 19:56:03 +08006454 wifi_getApEnable(apIndex, &status);
developer72fb0bb2023-01-11 09:46:29 +08006455
developer7e4a2a62023-04-06 19:56:03 +08006456 wifi_getMaxRadioNumber(&max_radio_num);
6457 if (enable == status)
6458 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006459
developer7e4a2a62023-04-06 19:56:03 +08006460 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6461 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006462
developer7e4a2a62023-04-06 19:56:03 +08006463 if (enable == TRUE) {
6464 int radioIndex = apIndex % max_radio_num;
6465 phyId = radio_index_to_phy(radioIndex);
developer8a3bbbf2023-03-15 17:47:23 +08006466
developer7e4a2a62023-04-06 19:56:03 +08006467 snprintf(config_file, MAX_BUF_SIZE, "%s%d.conf", CONFIG_PREFIX, apIndex);
6468 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyId, config_file);
6469 _syscmd(cmd, buf, sizeof(buf));
6470 } else {
6471 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw REMOVE %s", interface_name);
6472 _syscmd(cmd, buf, sizeof(buf));
6473 }
6474 snprintf(cmd, MAX_CMD_SIZE, "sed -i -n -e '/^%s=/!p' -e '$a%s=%d' %s",
6475 interface_name, interface_name, enable, VAP_STATUS_FILE);
6476 _syscmd(cmd, buf, sizeof(buf));
6477 //Wait for wifi up/down to apply
6478 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006479}
6480
6481// Outputs the setting of the internal variable that is set by wifi_setApEnable().
6482INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
6483{
developer7e4a2a62023-04-06 19:56:03 +08006484 char interface_name[IF_NAME_SIZE] = {0};
6485 char cmd[MAX_CMD_SIZE] = {0};
6486 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08006487
developer7e4a2a62023-04-06 19:56:03 +08006488 if ((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
6489 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006490
developer7e4a2a62023-04-06 19:56:03 +08006491 *output_bool = 0;
developer72fb0bb2023-01-11 09:46:29 +08006492
developer7e4a2a62023-04-06 19:56:03 +08006493 if ((apIndex >= 0) && (apIndex < MAX_APS)) {
6494 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
6495 *output_bool = FALSE;
6496 return RETURN_OK;
6497 }
6498 snprintf(cmd, MAX_CMD_SIZE, "ifconfig %s 2> /dev/null | grep UP", interface_name);
6499 *output_bool = _syscmd(cmd, buf, sizeof(buf)) ? 0 : 1;
6500 }
developer72fb0bb2023-01-11 09:46:29 +08006501
developer7e4a2a62023-04-06 19:56:03 +08006502 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006503}
6504
developer69b61b02023-03-07 17:17:44 +08006505// Outputs the AP "Enabled" "Disabled" status from driver
6506INT wifi_getApStatus(INT apIndex, CHAR *output_string)
developer72fb0bb2023-01-11 09:46:29 +08006507{
developer7e4a2a62023-04-06 19:56:03 +08006508 char cmd[128] = {0};
6509 char buf[128] = {0};
6510 BOOL output_bool;
developer72fb0bb2023-01-11 09:46:29 +08006511
developer7e4a2a62023-04-06 19:56:03 +08006512 if (!output_string) {
6513 printf("%s: null pointer!", __func__);
6514 return RETURN_ERR;
6515 }
developer72fb0bb2023-01-11 09:46:29 +08006516
developer7e4a2a62023-04-06 19:56:03 +08006517 wifi_getApEnable(apIndex, &output_bool);
developer72fb0bb2023-01-11 09:46:29 +08006518
developer7e4a2a62023-04-06 19:56:03 +08006519 if(output_bool == 1)
6520 snprintf(output_string, 32, "Up");
6521 else
6522 snprintf(output_string, 32, "Disable");
6523
6524 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006525}
6526
6527//Indicates whether or not beacons include the SSID name.
6528// outputs a 1 if SSID on the AP is enabled, else outputs 0
6529INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
6530{
6531 //get the running status
6532 char config_file[MAX_BUF_SIZE] = {0};
6533 char buf[16] = {0};
6534
6535 if (!output)
6536 return RETURN_ERR;
6537
6538 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6539 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
6540 // default is enable
6541 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
6542 *output = TRUE;
6543
6544 return RETURN_OK;
6545}
6546
6547// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
6548INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
6549{
6550 //store the config, apply instantly
6551 char config_file[MAX_BUF_SIZE] = {0};
6552 struct params list;
6553
6554 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6555 list.name = "ignore_broadcast_ssid";
6556 list.value = enable?"0":"1";
6557
6558 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6559 wifi_hostapdWrite(config_file, &list, 1);
6560 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6561 //TODO: call hostapd_cli for dynamic_config_control
6562 wifi_reloadAp(apIndex);
6563 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6564
6565 return RETURN_OK;
6566}
6567
6568//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
6569INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
6570{
6571 //get the running status
6572 if(!output_uint)
6573 return RETURN_ERR;
6574 *output_uint=16;
6575 return RETURN_OK;
6576}
6577
6578INT wifi_setApRetryLimit(INT apIndex, UINT number)
6579{
6580 //apply instantly
6581 return RETURN_ERR;
6582}
6583
6584//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
6585INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
6586{
6587 if(!output)
6588 return RETURN_ERR;
6589 *output=TRUE;
6590 return RETURN_OK;
6591}
6592
6593//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
6594INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
6595{
6596 //get the running status from driver
6597 char cmd[128] = {0};
6598 char buf[128] = {0};
6599 int max_radio_num = 0, radioIndex = 0;
6600 int phyId = 0;
6601
6602 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6603
6604 wifi_getMaxRadioNumber(&max_radio_num);
6605 radioIndex = apIndex % max_radio_num;
6606 phyId = radio_index_to_phy(radioIndex);
6607 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", phyId);
6608 _syscmd(cmd,buf, sizeof(buf));
6609
6610 if (strlen(buf) > 0)
6611 *output = true;
6612
6613 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6614
6615 return RETURN_OK;
6616}
6617
6618//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
6619INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
6620{
6621 //get the running status from driver
6622 if(!output)
6623 return RETURN_ERR;
6624
6625 char config_file[MAX_BUF_SIZE] = {0};
6626 char buf[16] = {0};
6627
6628 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6629 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
6630 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
6631 *output = TRUE;
6632 else
6633 *output = FALSE;
6634
6635 return RETURN_OK;
6636}
6637
6638// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
6639INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
6640{
6641 //Save config and apply instantly.
6642 char config_file[MAX_BUF_SIZE] = {0};
6643 struct params list;
6644
6645 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6646 list.name = "wmm_enabled";
6647 list.value = enable?"1":"0";
6648
6649 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6650 wifi_hostapdWrite(config_file, &list, 1);
6651 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6652 wifi_reloadAp(apIndex);
6653 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6654
6655 return RETURN_OK;
6656}
6657
6658//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.
6659INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
6660{
6661 //get the running status from driver
6662 if(!output)
6663 return RETURN_ERR;
6664
6665 char config_file[128] = {0};
6666 char buf[16] = {0};
6667
6668 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6669 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
6670 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
6671 *output = TRUE;
6672 else
6673 *output = FALSE;
6674
6675 return RETURN_OK;
6676}
6677
6678// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
6679INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
6680{
6681 //save config and apply instantly.
6682 char config_file[MAX_BUF_SIZE] = {0};
6683 struct params list;
6684
6685 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6686 list.name = "uapsd_advertisement_enabled";
6687 list.value = enable?"1":"0";
6688
6689 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6690 wifi_hostapdWrite(config_file, &list, 1);
6691 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developere82c0ca2023-05-10 16:25:35 +08006692 wifi_quick_reload_ap(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08006693 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6694
6695 return RETURN_OK;
6696}
6697
6698// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
6699INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
6700{
6701 char interface_name[16] = {0};
6702 // assume class 0->BE, 1->BK, 2->VI, 3->VO
6703 char cmd[128] = {0};
6704 char buf[128] = {0};
6705 char ack_filepath[128] = {0};
6706 uint16_t bitmap = 0;
6707 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
6708 FILE *f = NULL;
6709
6710 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
6711
6712 // Get current setting
6713 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
6714 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
6715 _syscmd(cmd, buf, sizeof(buf));
6716 if (strlen(buf) > 0)
6717 bitmap = strtoul(buf, NULL, 10);
6718
6719 bitmap = strtoul(buf, NULL, 10);
6720
6721 if (ackPolicy == TRUE) { // True, unset this class
6722 bitmap &= ~class_map[class];
6723 } else { // False, set this class
6724 bitmap |= class_map[class];
6725 }
6726
6727 f = fopen(ack_filepath, "w");
6728 if (f == NULL) {
6729 fprintf(stderr, "%s: fopen failed\n", __func__);
6730 return RETURN_ERR;
6731 }
6732 fprintf(f, "%hu", bitmap);
6733 fclose(f);
6734
6735 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6736 return RETURN_ERR;
6737 snprintf(cmd, sizeof(cmd), "iw dev %s set noack_map 0x%04x\n", interface_name, bitmap);
6738 _syscmd(cmd, buf, sizeof(buf));
6739
6740 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
6741 return RETURN_OK;
6742}
6743
6744//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.
6745INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
6746{
6747 //get the running status from driver
6748 if(!output_uint)
6749 return RETURN_ERR;
6750
6751 char output[16]={'\0'};
6752 char config_file[MAX_BUF_SIZE] = {0};
6753
6754 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6755 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
6756 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
6757 else {
6758 int device_num = atoi(output);
6759 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
6760 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
6761 return RETURN_ERR;
6762 }
6763 else {
6764 *output_uint = device_num;
6765 }
6766 }
6767
6768 return RETURN_OK;
6769}
6770
6771INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
6772{
6773 //store to wifi config, apply instantly
6774 char str[MAX_BUF_SIZE]={'\0'};
6775 char cmd[MAX_CMD_SIZE]={'\0'};
6776 struct params params;
6777 char config_file[MAX_BUF_SIZE] = {0};
6778
6779 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6780 if (number > MAX_ASSOCIATED_STA_NUM) {
6781 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
6782 return RETURN_ERR;
6783 }
6784 sprintf(str, "%d", number);
6785 params.name = "max_num_sta";
6786 params.value = str;
6787
6788 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
6789 int ret = wifi_hostapdWrite(config_file, &params, 1);
6790 if (ret) {
6791 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
6792 ,__func__, ret);
6793 }
6794
6795 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6796 if (ret) {
6797 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
6798 ,__func__, ret);
6799 }
6800 wifi_reloadAp(apIndex);
6801 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6802
6803 return RETURN_OK;
6804}
6805
6806//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.
6807INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
6808{
6809 //get the current threshold
6810 if(!output_uint)
6811 return RETURN_ERR;
6812 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
6813 if (*output_uint == 0)
6814 *output_uint = 50;
6815 return RETURN_OK;
6816}
6817
6818INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6819{
6820 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
6821 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6822 return RETURN_OK;
6823 return RETURN_ERR;
6824}
6825
6826//Number of times the current total number of associated device has reached the HighWatermarkThreshold value. This calculation can be based on the parameter AssociatedDeviceNumberOfEntries as well. Implementation specifics about this parameter are left to the product group and the device vendors. It can be updated whenever there is a new client association request to the access point.
6827INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6828{
6829 if(!output_uint)
6830 return RETURN_ERR;
6831 *output_uint = 3;
6832 return RETURN_OK;
6833}
6834
6835//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6836INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6837{
6838 if(!output_uint)
6839 return RETURN_ERR;
6840 *output_uint = 3;
6841 return RETURN_OK;
6842}
6843
6844//Date and Time at which the maximum number of associated devices ever associated with the access point concurrenlty since the last reset of the device or WiFi module (or in short when was X_COMCAST-COM_AssociatedDevicesHighWatermark updated). This dateTime value is in UTC.
6845INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6846{
6847 if(!output_in_seconds)
6848 return RETURN_ERR;
6849 *output_in_seconds = 0;
6850 return RETURN_OK;
6851}
6852
6853//Comma-separated list of strings. Indicates which security modes this AccessPoint instance is capable of supporting. Each list item is an enumeration of: None,WEP-64,WEP-128,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise
6854INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6855{
6856 if(!output || apIndex>=MAX_APS)
6857 return RETURN_ERR;
6858 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
6859 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
6860 return RETURN_OK;
developer69b61b02023-03-07 17:17:44 +08006861}
developer72fb0bb2023-01-11 09:46:29 +08006862
6863//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6864INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6865{
6866 char config_file[128] = {0};
6867 char wpa[16] = {0};
6868 char key_mgmt[64] = {0};
6869 char buf[16] = {0};
6870 if (!output)
6871 return RETURN_ERR;
6872
6873 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6874 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
6875
6876 strcpy(output, "None");//Copying "None" to output string for default case
6877 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
6878 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
6879 if (!strcmp(wpa, "1"))
6880 snprintf(output, 32, "WPA-Personal");
6881 else if (!strcmp(wpa, "2"))
6882 snprintf(output, 32, "WPA2-Personal");
6883 else if (!strcmp(wpa, "3"))
6884 snprintf(output, 32, "WPA-WPA2-Personal");
6885
6886 } else if (strstr(key_mgmt, "WPA-EAP")) {
6887 if (!strcmp(wpa, "1"))
6888 snprintf(output, 32, "WPA-Enterprise");
6889 else if (!strcmp(wpa, "2"))
6890 snprintf(output, 32, "WPA2-Enterprise");
6891 else if (!strcmp(wpa, "3"))
6892 snprintf(output, 32, "WPA-WPA2-Enterprise");
6893 } else if (strstr(key_mgmt, "SAE")) {
6894 if (strstr(key_mgmt, "WPA-PSK") == NULL)
6895 snprintf(output, 32, "WPA3-Personal");
6896 else
6897 snprintf(output, 32, "WPA3-Personal-Transition");
6898 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6899 snprintf(output, 32, "WPA3-Enterprise");
6900 }
6901
6902 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6903 return RETURN_OK;
6904#if 0
6905 //TODO: need to revisit below implementation
6906 char securityType[32], authMode[32];
6907 int enterpriseMode=0;
6908
6909 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6910 if(!output)
6911 return RETURN_ERR;
6912
6913 wifi_getApBeaconType(apIndex, securityType);
6914 strcpy(output,"None");//By default, copying "None" to output string
6915 if (strncmp(securityType,"None", strlen("None")) == 0)
6916 return RETURN_OK;
6917
6918 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6919 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6920
6921 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6922 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6923 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6924 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6925 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6926 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6927 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6928
6929 return RETURN_OK;
6930#endif
6931}
developer69b61b02023-03-07 17:17:44 +08006932
developer72fb0bb2023-01-11 09:46:29 +08006933INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6934{
6935 char securityType[32];
6936 char authMode[32];
6937
6938 //store settings and wait for wifi up to apply
6939 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6940 if(!encMode)
6941 return RETURN_ERR;
6942
6943 if (strcmp(encMode, "None")==0)
6944 {
6945 strcpy(securityType,"None");
6946 strcpy(authMode,"None");
6947 }
6948 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6949 {
6950 strcpy(securityType,"WPAand11i");
6951 strcpy(authMode,"PSKAuthentication");
6952 }
6953 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6954 {
6955 strcpy(securityType,"WPAand11i");
6956 strcpy(authMode,"EAPAuthentication");
6957 }
6958 else if (strcmp(encMode, "WPA-Personal")==0)
6959 {
6960 strcpy(securityType,"WPA");
6961 strcpy(authMode,"PSKAuthentication");
6962 }
6963 else if (strcmp(encMode, "WPA-Enterprise")==0)
6964 {
6965 strcpy(securityType,"WPA");
6966 strcpy(authMode,"EAPAuthentication");
6967 }
6968 else if (strcmp(encMode, "WPA2-Personal")==0)
6969 {
6970 strcpy(securityType,"11i");
6971 strcpy(authMode,"PSKAuthentication");
6972 }
6973 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6974 {
6975 strcpy(securityType,"11i");
6976 strcpy(authMode,"EAPAuthentication");
6977 }
6978 else if (strcmp(encMode, "WPA3-Personal") == 0)
6979 {
6980 strcpy(securityType,"11i");
6981 strcpy(authMode,"SAEAuthentication");
6982 }
6983 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
6984 {
6985 strcpy(securityType, "11i");
6986 strcpy(authMode, "PSK-SAEAuthentication");
6987 }
6988 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6989 {
6990 strcpy(securityType,"11i");
6991 strcpy(authMode,"EAP_192-bit_Authentication");
6992 }
developer3086e2f2023-01-17 09:40:01 +08006993 else if (strcmp(encMode, "OWE") == 0)
6994 {
6995 strcpy(securityType,"11i");
6996 strcpy(authMode,"Enhanced_Open");
6997 }
developer72fb0bb2023-01-11 09:46:29 +08006998 else
6999 {
7000 strcpy(securityType,"None");
7001 strcpy(authMode,"None");
7002 }
7003 wifi_setApBeaconType(apIndex, securityType);
7004 wifi_setApBasicAuthenticationMode(apIndex, authMode);
7005 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7006
7007 return RETURN_OK;
developer69b61b02023-03-07 17:17:44 +08007008}
developer72fb0bb2023-01-11 09:46:29 +08007009
7010
7011//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
7012// output_string must be pre-allocated as 64 character string by caller
7013// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
7014INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
7015{
7016 char buf[16] = {0};
7017 char config_file[MAX_BUF_SIZE] = {0};
7018
7019 if(output_string==NULL)
7020 return RETURN_ERR;
7021
7022 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7023 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
7024
7025 if(strcmp(buf,"0")==0)
7026 {
7027 printf("wpa_mode is %s ......... \n",buf);
7028 return RETURN_ERR;
7029 }
7030
7031 wifi_dbg_printf("\nFunc=%s\n",__func__);
7032 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7033 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
7034 wifi_dbg_printf("\noutput_string=%s\n",output_string);
7035
7036 return RETURN_OK;
7037}
7038
7039// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
7040// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
7041INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
7042{
7043 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
7044 struct params params={'\0'};
7045 int ret;
7046 char config_file[MAX_BUF_SIZE] = {0};
7047
7048 if(NULL == preSharedKey)
7049 return RETURN_ERR;
7050
7051 params.name = "wpa_passphrase";
7052
7053 if(strlen(preSharedKey)<8 || strlen(preSharedKey)>63)
7054 {
7055 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
7056 return RETURN_ERR;
7057 }
7058 params.value = preSharedKey;
7059 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7060 ret = wifi_hostapdWrite(config_file, &params, 1);
7061 if(!ret)
7062 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
7063 return ret;
7064 //TODO: call hostapd_cli for dynamic_config_control
7065}
7066
7067//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
7068// outputs the passphrase, maximum 63 characters
7069INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
7070{
7071 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
7072
7073 wifi_dbg_printf("\nFunc=%s\n",__func__);
7074 if (NULL == output_string)
7075 return RETURN_ERR;
7076
7077 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7078 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
7079 if(strcmp(buf,"0")==0)
7080 {
7081 printf("wpa_mode is %s ......... \n",buf);
7082 return RETURN_ERR;
7083 }
7084
7085 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
7086 wifi_dbg_printf("\noutput_string=%s\n",output_string);
7087
7088 return RETURN_OK;
7089}
7090
7091// sets the passphrase enviornment variable, max 63 characters
7092INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
7093{
7094 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
7095 struct params params={'\0'};
7096 char config_file[MAX_BUF_SIZE] = {0};
7097 int ret;
7098
7099 if(NULL == passPhrase)
7100 return RETURN_ERR;
7101
7102 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
7103 {
7104 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
7105 return RETURN_ERR;
7106 }
7107 params.name = "wpa_passphrase";
7108 params.value = passPhrase;
7109 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7110 ret=wifi_hostapdWrite(config_file,&params,1);
7111 if(!ret)
7112 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7113
7114 return ret;
7115}
7116
7117//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.
7118INT wifi_setApSecurityReset(INT apIndex)
7119{
7120 char original_config_file[64] = {0};
7121 char current_config_file[64] = {0};
7122 char buf[64] = {0};
7123 char cmd[64] = {0};
7124 char wpa[4] = {0};
7125 char wpa_psk[64] = {0};
7126 char wpa_passphrase[64] = {0};
7127 char wpa_psk_file[128] = {0};
7128 char wpa_key_mgmt[64] = {0};
7129 char wpa_pairwise[32] = {0};
7130 wifi_band band;
7131 struct params list[6];
7132
7133 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7134
7135 band = wifi_index_to_band(apIndex);
7136 if (band == band_2_4)
7137 sprintf(original_config_file, "/etc/hostapd-2G.conf");
7138 else if (band == band_5)
7139 sprintf(original_config_file, "/etc/hostapd-5G.conf");
7140 else if (band == band_6)
7141 sprintf(original_config_file, "/etc/hostapd-6G.conf");
7142 else
7143 return RETURN_ERR;
7144
7145 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
7146 list[0].name = "wpa";
7147 list[0].value = wpa;
developer69b61b02023-03-07 17:17:44 +08007148
developer72fb0bb2023-01-11 09:46:29 +08007149 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
7150 list[1].name = "wpa_psk";
7151 list[1].value = wpa_psk;
7152
7153 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
7154 list[2].name = "wpa_passphrase";
7155 list[2].value = wpa_passphrase;
7156
7157 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
7158
7159 if (strlen(wpa_psk_file) == 0)
7160 strcpy(wpa_psk_file, PSK_FILE);
7161
7162 if (access(wpa_psk_file, F_OK) != 0) {
7163 sprintf(cmd, "touch %s", wpa_psk_file);
7164 _syscmd(cmd, buf, sizeof(buf));
7165 }
7166 list[3].name = "wpa_psk_file";
7167 list[3].value = wpa_psk_file;
7168
7169 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
7170 list[4].name = "wpa_key_mgmt";
7171 list[4].value = wpa_key_mgmt;
7172
7173 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
7174 list[5].name = "wpa_pairwise";
7175 list[5].value = wpa_pairwise;
7176
7177 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7178 wifi_hostapdWrite(current_config_file, list, 6);
7179
7180 wifi_setApEnable(apIndex, FALSE);
7181 wifi_setApEnable(apIndex, TRUE);
7182
7183 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7184 return RETURN_OK;
7185}
7186
7187//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).
7188INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
7189{
7190 char config_file[64] = {0};
7191 char buf[64] = {0};
7192 char cmd[256] = {0};
7193
7194 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7195
7196 if(!IP_output || !Port_output || !RadiusSecret_output)
7197 return RETURN_ERR;
7198
7199 // Read the first matched config
7200 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7201 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7202 _syscmd(cmd, buf, sizeof(buf));
7203 strncpy(IP_output, buf, 64);
7204
7205 memset(buf, 0, sizeof(buf));
7206 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7207 _syscmd(cmd, buf, sizeof(buf));
7208 *Port_output = atoi(buf);
7209
7210 memset(buf, 0, sizeof(buf));
7211 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7212 _syscmd(cmd, buf, sizeof(buf));
7213 strncpy(RadiusSecret_output, buf, 64);
7214
7215 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7216 return RETURN_OK;
7217}
7218
7219INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
7220{
7221 char config_file[64] = {0};
7222 char port_str[8] = {0};
7223 char cmd[256] = {0};
7224 char buf[128] = {0};
7225
7226 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7227
7228 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7229
7230 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
7231 _syscmd(cmd, buf, sizeof(buf));
7232 memset(cmd, 0, sizeof(cmd));
7233
7234 snprintf(port_str, sizeof(port_str), "%d", port);
7235 if (strlen(buf) == 0)
7236 // Append
7237 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
7238 "auth_server_addr=%s\\n"
7239 "auth_server_port=%s\\n"
7240 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
7241 else {
7242 // Delete the three lines setting after the "# radius 1" comment
7243 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
7244 _syscmd(cmd, buf, sizeof(buf));
7245 memset(cmd, 0, sizeof(cmd));
7246 // Use "# radius 1" comment to find the location to insert the radius setting
7247 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
7248 "# radius 1\\n"
7249 "auth_server_addr=%s\\n"
7250 "auth_server_port=%s\\n"
7251 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
7252 }
7253 if(_syscmd(cmd, buf, sizeof(buf))) {
7254 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
7255 return RETURN_ERR;
7256 }
7257
7258 wifi_reloadAp(apIndex);
7259 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7260 return RETURN_OK;
7261}
7262
7263INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
7264{
7265 char config_file[64] = {0};
7266 char buf[64] = {0};
7267 char cmd[256] = {0};
7268
7269 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7270
7271 if(!IP_output || !Port_output || !RadiusSecret_output)
7272 return RETURN_ERR;
7273
7274 // Read the second matched config
7275 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7276 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7277 _syscmd(cmd, buf, sizeof(buf));
7278 strncpy(IP_output, buf, 64);
7279
7280 memset(buf, 0, sizeof(buf));
7281 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7282 _syscmd(cmd, buf, sizeof(buf));
7283 *Port_output = atoi(buf);
7284
7285 memset(buf, 0, sizeof(buf));
7286 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7287 _syscmd(cmd, buf, sizeof(buf));
7288 strncpy(RadiusSecret_output, buf, 64);
7289
7290 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7291 return RETURN_OK;
7292}
7293
7294INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
7295{
7296 char config_file[64] = {0};
7297 char port_str[8] = {0};
7298 char cmd[256] = {0};
7299 char buf[128] = {0};
7300
7301 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7302
7303 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7304
7305 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
7306 _syscmd(cmd, buf, sizeof(buf));
7307 memset(cmd, 0, sizeof(cmd));
7308
7309 snprintf(port_str, sizeof(port_str), "%d", port);
7310 if (strlen(buf) == 0)
7311 // Append
7312 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
7313 "auth_server_addr=%s\\n"
7314 "auth_server_port=%s\\n"
7315 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
7316 else {
7317 // Delete the three lines setting after the "# radius 2" comment
7318 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
7319 _syscmd(cmd, buf, sizeof(buf));
7320 memset(cmd, 0, sizeof(cmd));
7321 // Use "# radius 2" comment to find the location to insert the radius setting
7322 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
7323 "# radius 2\\n"
7324 "auth_server_addr=%s\\n"
7325 "auth_server_port=%s\\n"
7326 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
7327 }
7328 if(_syscmd(cmd, buf, sizeof(buf))) {
7329 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
7330 return RETURN_ERR;
7331 }
7332
7333 wifi_reloadAp(apIndex);
7334 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7335 return RETURN_OK;
7336}
7337
7338//RadiusSettings
7339INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
7340{
7341 if(!output)
7342 return RETURN_ERR;
7343
7344 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
developer69b61b02023-03-07 17:17:44 +08007345 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
7346 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
7347 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
7348 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
developer72fb0bb2023-01-11 09:46:29 +08007349 output->MaxAuthenticationAttempts = 3; //Indicates the # of time, a client can attempt to login with incorrect credentials. When this limit is reached, the client is blacklisted and not allowed to attempt loging into the network. Settings this parameter to 0 (zero) disables the blacklisting feature.
developer69b61b02023-03-07 17:17:44 +08007350 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
7351 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
7352 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
developer72fb0bb2023-01-11 09:46:29 +08007353 //snprintf(output->RadiusSecret, 64, "12345678"); //The secret used for handshaking with the RADIUS server [RFC2865]. When read, this parameter returns an empty string, regardless of the actual value.
7354
7355 return RETURN_OK;
7356}
7357
7358INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
7359{
7360 //store the paramters, and apply instantly
7361 return RETURN_ERR;
7362}
7363
7364//Device.WiFi.AccessPoint.{i}.WPS.Enable
7365//Enables or disables WPS functionality for this access point.
7366// outputs the WPS enable state of this ap in output_bool
7367INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
7368{
7369 char interface_name[16] = {0};
7370 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
7371 if(!output_bool)
7372 return RETURN_ERR;
7373 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7374 return RETURN_ERR;
7375 sprintf(cmd,"hostapd_cli -i %s get_config | grep wps_state | cut -d '=' -f2", interface_name);
7376 _syscmd(cmd, buf, sizeof(buf));
7377 if(strstr(buf, "configured"))
7378 *output_bool=TRUE;
7379 else
7380 *output_bool=FALSE;
7381
7382 return RETURN_OK;
developer69b61b02023-03-07 17:17:44 +08007383}
developer72fb0bb2023-01-11 09:46:29 +08007384
7385//Device.WiFi.AccessPoint.{i}.WPS.Enable
7386// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
7387INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
7388{
7389 char config_file[MAX_BUF_SIZE] = {0};
7390 struct params params;
7391
7392 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7393 //store the paramters, and wait for wifi up to apply
7394 params.name = "wps_state";
7395 params.value = enable ? "2":"0";
7396
7397 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7398 wifi_hostapdWrite(config_file, &params, 1);
7399 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7400 wifi_reloadAp(apIndex);
7401
7402 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7403 return RETURN_OK;
7404}
7405
7406//Comma-separated list of strings. Indicates WPS configuration methods supported by the device. Each list item is an enumeration of: USBFlashDrive,Ethernet,ExternalNFCToken,IntegratedNFCToken,NFCInterface,PushButton,PIN
7407INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
7408{
7409 if(!output)
7410 return RETURN_ERR;
7411 snprintf(output, 128, "PushButton,PIN");
7412 return RETURN_OK;
7413}
7414
7415//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
7416//Comma-separated list of strings. Each list item MUST be a member of the list reported by the ConfigMethodsSupported parameter. Indicates WPS configuration methods enabled on the device.
7417// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
7418INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
7419{
7420 if(!output)
7421 return RETURN_ERR;
7422 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
7423
7424 return RETURN_OK;
7425}
7426
7427//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
7428// sets an enviornment variable that specifies the WPS configuration method(s). methodString is a comma separated list of methods USBFlashDrive,Ethernet,ExternalNFCToken,IntegratedNFCToken,NFCInterface,PushButton,PIN
7429INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
7430{
7431 //apply instantly. No setting need to be stored.
7432 char methods[MAX_BUF_SIZE], *token, *next_token;
7433 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
7434 struct params params;
7435
7436 if(!methodString)
7437 return RETURN_ERR;
7438 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7439 //store the paramters, and wait for wifi up to apply
7440
7441 snprintf(methods, sizeof(methods), "%s", methodString);
7442 for(token=methods; *token; token=next_token)
7443 {
7444 strtok_r(token, ",", &next_token);
7445 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
7446 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
7447 else if(*token=='E')
7448 {
7449 if(!strcmp(methods, "Ethernet"))
7450 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
7451 else if(!strcmp(methods, "ExternalNFCToken"))
7452 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
7453 else
7454 printf("%s: Unknown WpsConfigMethod\n", __func__);
7455 }
7456 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
7457 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
7458 else if(*token=='N' && !strcmp(token, "NFCInterface"))
7459 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
7460 else if(*token=='P' )
7461 {
7462 if(!strcmp(token, "PushButton"))
7463 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
7464 else if(!strcmp(token, "PIN"))
7465 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
7466 else
7467 printf("%s: Unknown WpsConfigMethod\n", __func__);
7468 }
7469 else
7470 printf("%s: Unknown WpsConfigMethod\n", __func__);
7471 }
7472 params.name = "config_methods";
7473 params.value = config_methods;
7474 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7475 wifi_hostapdWrite(config_file, &params, 1);
7476 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7477 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7478
7479 return RETURN_OK;
7480}
7481
7482// outputs the pin value, ulong_pin must be allocated by the caller
7483INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
7484{
7485 char buf[MAX_BUF_SIZE] = {0};
7486 char cmd[MAX_CMD_SIZE] = {0};
7487
7488 if(!output_ulong)
7489 return RETURN_ERR;
7490 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
7491 _syscmd(cmd, buf, sizeof(buf));
7492 if(strlen(buf) > 0)
7493 *output_ulong=strtoul(buf, NULL, 10);
7494
7495 return RETURN_OK;
7496}
7497
7498// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
7499INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
7500{
7501 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
7502 char ap_pin[16] = {0};
7503 char buf[MAX_BUF_SIZE] = {0};
7504 char config_file[MAX_BUF_SIZE] = {0};
7505 ULONG prev_pin = 0;
7506 struct params params;
7507
7508 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7509 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
7510 params.name = "ap_pin";
7511 params.value = ap_pin;
7512 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7513 wifi_hostapdWrite(config_file, &params, 1);
7514 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7515 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7516
7517 return RETURN_OK;
7518}
7519
7520// Output string is either Not configured or Configured, max 32 characters
7521INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
7522{
7523 char interface_name[16] = {0};
7524 char cmd[MAX_CMD_SIZE];
7525 char buf[MAX_BUF_SIZE]={0};
7526
7527 if(!output_string)
7528 return RETURN_ERR;
7529 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7530 snprintf(output_string, 32, "Not configured");
7531 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7532 return RETURN_ERR;
7533 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep wps_state | cut -d'=' -f2", interface_name);
7534 _syscmd(cmd, buf, sizeof(buf));
7535
7536 if(!strncmp(buf, "configured", 10))
7537 snprintf(output_string, 32, "Configured");
7538 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7539
7540 return RETURN_OK;
7541}
7542
7543// sets the WPS pin for this AP
7544INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
7545{
7546 char interface_name[16] = {0};
7547 char cmd[MAX_CMD_SIZE];
7548 char buf[MAX_BUF_SIZE]={0};
7549 BOOL enable;
7550
7551 wifi_getApEnable(apIndex, &enable);
7552 if (!enable)
7553 return RETURN_ERR;
7554 wifi_getApWpsEnable(apIndex, &enable);
7555 if (!enable)
7556 return RETURN_ERR;
7557
7558 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7559 return RETURN_ERR;
7560 snprintf(cmd, 64, "hostapd_cli -i%s wps_pin any %s", interface_name, pin);
7561 _syscmd(cmd, buf, sizeof(buf));
7562 if((strstr(buf, "OK"))!=NULL)
7563 return RETURN_OK;
7564
7565 return RETURN_ERR;
7566}
7567
7568// This function is called when the WPS push button has been pressed for this AP
7569INT wifi_setApWpsButtonPush(INT apIndex)
7570{
7571 char cmd[MAX_CMD_SIZE];
7572 char buf[MAX_BUF_SIZE]={0};
7573 char interface_name[16] = {0};
7574 BOOL enable=FALSE;
7575
7576 wifi_getApEnable(apIndex, &enable);
7577 if (!enable)
7578 return RETURN_ERR;
7579
7580 wifi_getApWpsEnable(apIndex, &enable);
7581 if (!enable)
7582 return RETURN_ERR;
7583
7584 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7585 return RETURN_ERR;
7586
7587 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel; hostapd_cli -i%s wps_pbc", interface_name, interface_name);
7588 _syscmd(cmd, buf, sizeof(buf));
7589
7590 if((strstr(buf, "OK"))!=NULL)
7591 return RETURN_OK;
7592 return RETURN_ERR;
7593}
7594
7595// cancels WPS mode for this AP
7596INT wifi_cancelApWPS(INT apIndex)
7597{
7598 char interface_name[16] = {0};
7599 char cmd[MAX_CMD_SIZE];
7600 char buf[MAX_BUF_SIZE]={0};
7601
7602 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7603 return RETURN_ERR;
7604 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel", interface_name);
7605 _syscmd(cmd,buf, sizeof(buf));
7606
7607 if((strstr(buf, "OK"))!=NULL)
7608 return RETURN_OK;
7609 return RETURN_ERR;
7610}
7611
7612//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
7613//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
7614INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
7615{
7616 char interface_name[16] = {0};
7617 FILE *f = NULL;
7618 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7619 char cmd[256] = {0}, buf[2048] = {0};
7620 char *param = NULL, *value = NULL, *line=NULL;
7621 size_t len = 0;
7622 ssize_t nread = 0;
7623 wifi_associated_dev_t *dev=NULL;
7624
7625 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7626 *associated_dev_array = NULL;
7627 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7628 return RETURN_ERR;
7629 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
7630 _syscmd(cmd,buf,sizeof(buf));
7631 *output_array_size = atoi(buf);
7632
7633 if (*output_array_size <= 0)
7634 return RETURN_OK;
7635
7636 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
7637 *associated_dev_array = dev;
7638 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt" , interface_name);
7639 _syscmd(cmd,buf,sizeof(buf));
7640 f = fopen("/tmp/connected_devices.txt", "r");
7641 if (f==NULL)
7642 {
7643 *output_array_size=0;
7644 return RETURN_ERR;
7645 }
7646 while ((getline(&line, &len, f)) != -1)
7647 {
7648 param = strtok(line,"=");
7649 value = strtok(NULL,"=");
7650
7651 if( strcmp("flags",param) == 0 )
7652 {
7653 value[strlen(value)-1]='\0';
7654 if(strstr (value,"AUTHORIZED") != NULL )
7655 {
7656 dev[auth_temp].cli_AuthenticationState = 1;
7657 dev[auth_temp].cli_Active = 1;
7658 auth_temp++;
7659 read_flag=1;
7660 }
7661 }
7662 if(read_flag==1)
7663 {
7664 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7665 {
7666 value[strlen(value)-1]='\0';
7667 sscanf(value, "%x:%x:%x:%x:%x:%x",
7668 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7669 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7670 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7671 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7672 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7673 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7674 mac_temp++;
7675 read_flag=0;
7676 }
7677 }
7678 }
7679 *output_array_size = auth_temp;
7680 auth_temp=0;
7681 mac_temp=0;
7682 free(line);
7683 fclose(f);
7684 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7685 return RETURN_OK;
7686}
7687
7688#define MACADDRESS_SIZE 6
7689
7690INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7691{
7692 FILE *fp = NULL;
7693 char str[MAX_BUF_SIZE] = {0};
7694 int wificlientindex = 0 ;
7695 int count = 0;
7696 int signalstrength = 0;
7697 int arr[MACADDRESS_SIZE] = {0};
7698 unsigned char mac[MACADDRESS_SIZE] = {0};
7699 UINT wifi_count = 0;
7700 char virtual_interface_name[MAX_BUF_SIZE] = {0};
7701 char pipeCmd[MAX_CMD_SIZE] = {0};
7702
7703 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7704 *output_array_size = 0;
7705 *associated_dev_array = NULL;
7706
7707 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
7708 fp = popen(pipeCmd, "r");
developer69b61b02023-03-07 17:17:44 +08007709 if (fp == NULL)
developer72fb0bb2023-01-11 09:46:29 +08007710 {
7711 printf("Failed to run command inside function %s\n",__FUNCTION__ );
7712 return RETURN_ERR;
7713 }
7714
7715 /* Read the output a line at a time - output it. */
7716 fgets(str, sizeof(str)-1, fp);
7717 wifi_count = (unsigned int) atoi ( str );
7718 *output_array_size = wifi_count;
7719 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
7720 pclose(fp);
7721
7722 if(wifi_count == 0)
7723 {
7724 return RETURN_OK;
7725 }
7726 else
7727 {
7728 wifi_associated_dev3_t* temp = NULL;
7729 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
7730 if(temp == NULL)
7731 {
7732 printf("Error Statement. Insufficient memory \n");
7733 return RETURN_ERR;
7734 }
7735
7736 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
7737 system(pipeCmd);
7738 memset(pipeCmd,0,sizeof(pipeCmd));
7739 if(apIndex == 0)
7740 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
7741 else if(apIndex == 1)
7742 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
7743 system(pipeCmd);
7744
7745 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
7746 if(fp == NULL)
7747 {
7748 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
7749 free(temp);
7750 return RETURN_ERR;
7751 }
7752 fclose(fp);
7753
7754 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
7755 fp = popen(pipeCmd, "r");
7756 if(fp)
7757 {
7758 for(count =0 ; count < wifi_count; count++)
7759 {
7760 fgets(str, MAX_BUF_SIZE, fp);
7761 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7762 {
7763 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7764 {
7765 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7766
7767 }
7768 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7769 printf("MAC %d = %X:%X:%X:%X:%X:%X \n", count, temp[count].cli_MACAddress[0],temp[count].cli_MACAddress[1], temp[count].cli_MACAddress[2], temp[count].cli_MACAddress[3], temp[count].cli_MACAddress[4], temp[count].cli_MACAddress[5]);
7770 }
7771 temp[count].cli_AuthenticationState = 1; //TODO
7772 temp[count].cli_Active = 1; //TODO
7773 }
7774 pclose(fp);
7775 }
7776
7777 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt");
7778 fp = popen(pipeCmd, "r");
7779 if(fp)
developer69b61b02023-03-07 17:17:44 +08007780 {
developer72fb0bb2023-01-11 09:46:29 +08007781 pclose(fp);
7782 }
7783 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
7784 if(fp)
7785 {
7786 for(count =0 ; count < wifi_count ;count++)
7787 {
7788 fgets(str, MAX_BUF_SIZE, fp);
7789 signalstrength = atoi(str);
7790 temp[count].cli_SignalStrength = signalstrength;
7791 temp[count].cli_RSSI = signalstrength;
7792 temp[count].cli_SNR = signalstrength + 95;
7793 }
7794 pclose(fp);
7795 }
7796
7797
7798 if((apIndex == 0) || (apIndex == 4))
7799 {
7800 for(count =0 ; count < wifi_count ;count++)
developer69b61b02023-03-07 17:17:44 +08007801 {
developer72fb0bb2023-01-11 09:46:29 +08007802 strcpy(temp[count].cli_OperatingStandard,"g");
7803 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
7804 }
7805
7806 //BytesSent
7807 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt");
7808 fp = popen(pipeCmd, "r");
7809 if(fp)
developer69b61b02023-03-07 17:17:44 +08007810 {
developer72fb0bb2023-01-11 09:46:29 +08007811 pclose(fp);
7812 }
7813 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
7814 if(fp)
7815 {
7816 for (count = 0; count < wifi_count; count++)
7817 {
7818 fgets(str, MAX_BUF_SIZE, fp);
7819 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
7820 }
7821 pclose(fp);
7822 }
7823
7824 //BytesReceived
7825 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt");
7826 fp = popen(pipeCmd, "r");
7827 if (fp)
7828 {
7829 pclose(fp);
7830 }
7831 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
7832 if (fp)
7833 {
7834 for (count = 0; count < wifi_count; count++)
7835 {
7836 fgets(str, MAX_BUF_SIZE, fp);
7837 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7838 }
7839 pclose(fp);
7840 }
7841
7842 //PacketsSent
7843 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt");
7844 fp = popen(pipeCmd, "r");
7845 if (fp)
7846 {
7847 pclose(fp);
7848 }
7849
7850 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7851 if (fp)
7852 {
7853 for (count = 0; count < wifi_count; count++)
7854 {
7855 fgets(str, MAX_BUF_SIZE, fp);
7856 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7857 }
7858 pclose(fp);
7859 }
7860
7861 //PacketsReceived
7862 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt");
7863 fp = popen(pipeCmd, "r");
7864 if (fp)
7865 {
7866 pclose(fp);
7867 }
7868 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7869 if (fp)
7870 {
7871 for (count = 0; count < wifi_count; count++)
7872 {
7873 fgets(str, MAX_BUF_SIZE, fp);
7874 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7875 }
7876 pclose(fp);
7877 }
7878
7879 //ErrorsSent
7880 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt");
7881 fp = popen(pipeCmd, "r");
7882 if (fp)
7883 {
7884 pclose(fp);
7885 }
7886 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7887 if (fp)
7888 {
7889 for (count = 0; count < wifi_count; count++)
7890 {
7891 fgets(str, MAX_BUF_SIZE, fp);
7892 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7893 }
7894 pclose(fp);
7895 }
7896
7897 //ErrorsSent
7898 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt");
7899 fp = popen(pipeCmd, "r");
7900 if (fp)
7901 {
7902 pclose(fp);
7903 }
7904 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7905 if (fp)
7906 {
7907 for (count = 0; count < wifi_count; count++)
7908 {
7909 fgets(str, MAX_BUF_SIZE, fp);
7910 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7911 }
7912 pclose(fp);
7913 }
7914
7915 //LastDataDownlinkRate
7916 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt");
7917 fp = popen(pipeCmd, "r");
7918 if (fp)
7919 {
7920 pclose(fp);
7921 }
7922 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7923 if (fp)
7924 {
7925 for (count = 0; count < wifi_count; count++)
7926 {
7927 fgets(str, MAX_BUF_SIZE, fp);
7928 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7929 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7930 }
7931 pclose(fp);
7932 }
7933
7934 //LastDataUplinkRate
7935 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt");
7936 fp = popen(pipeCmd, "r");
7937 if (fp)
7938 {
7939 pclose(fp);
7940 }
7941 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7942 if (fp)
7943 {
7944 for (count = 0; count < wifi_count; count++)
7945 {
7946 fgets(str, MAX_BUF_SIZE, fp);
7947 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7948 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7949 }
7950 pclose(fp);
7951 }
7952
7953 }
7954 else if ((apIndex == 1) || (apIndex == 5))
7955 {
7956 for (count = 0; count < wifi_count; count++)
7957 {
7958 strcpy(temp[count].cli_OperatingStandard, "a");
7959 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7960 temp[count].cli_BytesSent = 0;
7961 temp[count].cli_BytesReceived = 0;
7962 temp[count].cli_LastDataUplinkRate = 0;
7963 temp[count].cli_LastDataDownlinkRate = 0;
7964 temp[count].cli_PacketsSent = 0;
7965 temp[count].cli_PacketsReceived = 0;
7966 temp[count].cli_ErrorsSent = 0;
7967 }
7968 }
7969
7970 for (count = 0; count < wifi_count; count++)
7971 {
7972 temp[count].cli_Retransmissions = 0;
7973 temp[count].cli_DataFramesSentAck = 0;
7974 temp[count].cli_DataFramesSentNoAck = 0;
7975 temp[count].cli_MinRSSI = 0;
7976 temp[count].cli_MaxRSSI = 0;
7977 strncpy(temp[count].cli_InterferenceSources, "", 64);
7978 memset(temp[count].cli_IPAddress, 0, 64);
7979 temp[count].cli_RetransCount = 0;
7980 temp[count].cli_FailedRetransCount = 0;
7981 temp[count].cli_RetryCount = 0;
7982 temp[count].cli_MultipleRetryCount = 0;
7983 }
7984 *associated_dev_array = temp;
7985 }
7986 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7987 return RETURN_OK;
7988}
7989
developer7e4a2a62023-04-06 19:56:03 +08007990int wifihal_interfacestatus(CHAR *wifi_status, CHAR *interface_name)
developer72fb0bb2023-01-11 09:46:29 +08007991{
developer7e4a2a62023-04-06 19:56:03 +08007992 char cmd[MAX_CMD_SIZE] = {0};
7993 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08007994
developer7e4a2a62023-04-06 19:56:03 +08007995 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
7996
7997 snprintf(cmd, MAX_CMD_SIZE, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4 | tr -d '\\n'",
7998 interface_name);
7999 _syscmd(cmd, buf, MAX_BUF_SIZE);
8000
8001 strcpy(wifi_status, buf); /* TBD: check wifi_status mem lenth and replace with strcpy later */
8002
8003 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08008004 return RETURN_OK;
8005}
8006
8007/* #define HOSTAPD_STA_PARAM_ENTRIES 29
8008struct hostapd_sta_param {
8009 char key[50];
8010 char value[100];
8011}
8012
8013static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
8014 int i = 0;
8015
8016 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
8017 if (strncmp(params[i].key,key,50) == 0){
8018 return &params[i].value;
8019 }
8020 i++;
8021 }
8022 return NULL;
8023
8024} */
8025
8026static unsigned int count_occurences(const char *buf, const char *word)
8027{
8028 unsigned int n = 0;
8029 char *ptr = strstr(buf, word);
8030
8031 while (ptr++) {
8032 n++;
8033 ptr = strstr(ptr, word);
8034 }
8035
8036 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
8037 return n;
8038}
8039
8040static const char *get_line_from_str_buf(const char *buf, char *line)
8041{
8042 int i;
8043 int n = strlen(buf);
8044
8045 for (i = 0; i < n; i++) {
8046 line[i] = buf[i];
8047 if (buf[i] == '\n') {
8048 line[i] = '\0';
8049 return &buf[i + 1];
8050 }
8051 }
8052
8053 return NULL;
8054}
8055
8056INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8057{
8058 unsigned int assoc_cnt = 0;
8059 char interface_name[50] = {0};
8060 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
8061 char cmd[MAX_CMD_SIZE] = {'\0'};
8062 char line[256] = {'\0'};
8063 int i = 0;
8064 int ret = 0;
8065 const char *ptr = NULL;
8066 char *key = NULL;
8067 char *val = NULL;
8068 wifi_associated_dev3_t *temp = NULL;
8069 int rssi;
8070
8071 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8072
8073 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8074 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8075 return RETURN_ERR;
8076 }
8077
8078 // Example filtered output of 'iw dev' command:
8079 // Station 0a:69:72:10:d2:fa (on wifi0)
8080 // signal avg:-67 [-71, -71] dBm
8081 // Station 28:c2:1f:25:5f:99 (on wifi0)
8082 // signal avg:-67 [-71, -70] dBm
8083 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
8084 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
8085 return RETURN_ERR;
8086 }
8087
8088 ret = _syscmd(cmd, buf, sizeof(buf));
8089 if (ret == RETURN_ERR) {
8090 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
8091 return RETURN_ERR;
8092 }
8093
8094 *output_array_size = count_occurences(buf, "Station");
8095 if (*output_array_size == 0) return RETURN_OK;
8096
8097 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
8098 if (temp == NULL) {
8099 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
8100 return RETURN_ERR;
8101 }
8102 *associated_dev_array = temp;
8103
8104 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
8105 ptr = get_line_from_str_buf(buf, line);
8106 i = -1;
8107 while (ptr) {
8108 if (strstr(line, "Station")) {
8109 i++;
8110 key = strtok(line, " ");
8111 val = strtok(NULL, " ");
8112 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
8113 &temp[i].cli_MACAddress[0],
8114 &temp[i].cli_MACAddress[1],
8115 &temp[i].cli_MACAddress[2],
8116 &temp[i].cli_MACAddress[3],
8117 &temp[i].cli_MACAddress[4],
8118 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
8119 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
8120 free(*associated_dev_array);
8121 return RETURN_ERR;
8122 }
8123 }
8124 else if (i < 0) {
8125 ptr = get_line_from_str_buf(ptr, line);
8126 continue; // We didn't detect 'station' entry yet
8127 }
8128 else if (strstr(line, "signal avg")) {
8129 key = strtok(line, ":");
8130 val = strtok(NULL, " ");
8131 if (sscanf(val, "%d", &rssi) <= 0 ) {
8132 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
8133 free(*associated_dev_array);
8134 return RETURN_ERR;
8135 }
8136 temp[i].cli_RSSI = rssi;
8137 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
8138 }
8139 // Here other fields can be parsed if added to filter of 'iw dev' command
8140
8141 ptr = get_line_from_str_buf(ptr, line);
8142 };
8143
8144 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8145
8146 return RETURN_OK;
8147}
8148
8149#if 0
8150//To-do
8151INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8152{
8153 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8154
8155 //Using different approach to get required WiFi Parameters from system available commands
developer69b61b02023-03-07 17:17:44 +08008156#if 0
developer72fb0bb2023-01-11 09:46:29 +08008157 FILE *f;
8158 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
8159 char cmd[256], buf[2048];
8160 char *param , *value, *line=NULL;
8161 size_t len = 0;
8162 ssize_t nread;
8163 wifi_associated_dev3_t *dev=NULL;
8164 *associated_dev_array = NULL;
8165 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
8166 _syscmd(cmd,buf,sizeof(buf));
8167 *output_array_size = atoi(buf);
8168
8169 if (*output_array_size <= 0)
8170 return RETURN_OK;
8171
8172 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
8173 *associated_dev_array = dev;
8174 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt", interface_name);
8175 _syscmd(cmd,buf,sizeof(buf));
8176 f = fopen("/tmp/connected_devices.txt", "r");
8177 if (f==NULL)
8178 {
8179 *output_array_size=0;
8180 return RETURN_ERR;
8181 }
8182 while ((nread = getline(&line, &len, f)) != -1)
8183 {
8184 param = strtok(line,"=");
8185 value = strtok(NULL,"=");
8186
8187 if( strcmp("flags",param) == 0 )
8188 {
8189 value[strlen(value)-1]='\0';
8190 if(strstr (value,"AUTHORIZED") != NULL )
8191 {
8192 dev[auth_temp].cli_AuthenticationState = 1;
8193 dev[auth_temp].cli_Active = 1;
8194 auth_temp++;
8195 read_flag=1;
8196 }
8197 }
8198 if(read_flag==1)
8199 {
8200 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
8201 {
8202 value[strlen(value)-1]='\0';
8203 sscanf(value, "%x:%x:%x:%x:%x:%x",
8204 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
8205 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
8206 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
8207 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
8208 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
8209 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
8210
8211 }
8212 else if( strcmp("rx_packets",param) == 0 )
8213 {
8214 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
8215 }
8216
8217 else if( strcmp("tx_packets",param) == 0 )
8218 {
developer69b61b02023-03-07 17:17:44 +08008219 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
developer72fb0bb2023-01-11 09:46:29 +08008220 }
8221
8222 else if( strcmp("rx_bytes",param) == 0 )
8223 {
8224 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
8225 }
8226
8227 else if( strcmp("tx_bytes",param) == 0 )
8228 {
developer69b61b02023-03-07 17:17:44 +08008229 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
developer72fb0bb2023-01-11 09:46:29 +08008230 mac_temp++;
8231 read_flag=0;
developer69b61b02023-03-07 17:17:44 +08008232 }
developer72fb0bb2023-01-11 09:46:29 +08008233 }
8234 }
8235
8236 *output_array_size = auth_temp;
8237 auth_temp=0;
8238 mac_temp=0;
8239 free(line);
8240 fclose(f);
8241#endif
8242 char interface_name[MAX_BUF_SIZE] = {0};
8243 char wifi_status[MAX_BUF_SIZE] = {0};
8244 char hostapdconf[MAX_BUF_SIZE] = {0};
8245
8246 wifi_associated_dev3_t *dev_array = NULL;
8247 ULONG wifi_count = 0;
8248
8249 *associated_dev_array = NULL;
8250 *output_array_size = 0;
8251
8252 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
8253 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
8254 {
8255 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
8256
8257 wifi_GetInterfaceName(interface_name, hostapdconf);
8258
8259 if(strlen(interface_name) > 1)
8260 {
8261 wifihal_interfacestatus(wifi_status,interface_name);
8262 if(strcmp(wifi_status,"RUNNING") == 0)
8263 {
8264 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
8265
8266 *associated_dev_array = dev_array;
developer69b61b02023-03-07 17:17:44 +08008267 *output_array_size = wifi_count;
developer72fb0bb2023-01-11 09:46:29 +08008268 }
8269 else
8270 {
8271 *associated_dev_array = NULL;
8272 }
8273 }
8274 }
8275
8276 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8277 return RETURN_OK;
8278}
8279#endif
8280
8281/* getIPAddress function */
8282/**
8283* @description Returning IpAddress of the Matched String
8284*
developer69b61b02023-03-07 17:17:44 +08008285* @param
developer72fb0bb2023-01-11 09:46:29 +08008286* @str Having MacAddress
developer69b61b02023-03-07 17:17:44 +08008287* @ipaddr Having ipaddr
developer72fb0bb2023-01-11 09:46:29 +08008288* @return The status of the operation
8289* @retval RETURN_OK if successful
8290* @retval RETURN_ERR if any error is detected
8291*
8292*/
8293
8294INT getIPAddress(char *str,char *ipaddr)
8295{
8296 FILE *fp = NULL;
8297 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
8298 int LeaseTime = 0,ret = 0;
8299 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
8300 {
8301 return RETURN_ERR;
8302 }
8303
8304 while ( fgets(buf, sizeof(buf), fp)!= NULL )
8305 {
8306 /*
8307 Sample:sss
8308 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
8309 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
8310 */
8311 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
8312 &(LeaseTime),
8313 phyAddr,
8314 ipAddr,
8315 hostName
8316 );
8317 if(ret != 4)
8318 continue;
8319 if(strcmp(str,phyAddr) == 0)
8320 strcpy(ipaddr,ipAddr);
8321 }
8322 fclose(fp);
8323 return RETURN_OK;
8324}
8325
8326/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
8327/**
8328* @description Returning Inactive wireless connected clients informations
8329*
developer69b61b02023-03-07 17:17:44 +08008330* @param
developer72fb0bb2023-01-11 09:46:29 +08008331* @filename Holding private_wifi 2g/5g content files
8332* @associated_dev_array Having inactiv wireless clients informations
8333* @output_array_size Returning Inactive wireless counts
8334* @return The status of the operation
8335* @retval RETURN_OK if successful
8336* @retval RETURN_ERR if any error is detected
8337*
8338*/
8339
8340INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8341{
8342 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8343 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
8344 FILE *fp = NULL;
8345 int arr[MACADDRESS_SIZE] = {0};
8346 unsigned char mac[MACADDRESS_SIZE] = {0};
8347 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
8348 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
8349 fp = popen(buf,"r");
8350 if(fp == NULL)
8351 return RETURN_ERR;
8352 else
8353 {
8354 fgets(path,sizeof(path),fp);
8355 maccount = atoi(path);
8356 }
8357 pclose(fp);
8358 *output_array_size = maccount;
8359 wifi_associated_dev3_t* temp = NULL;
8360 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
8361 *associated_dev_array = temp;
8362 if(temp == NULL)
8363 {
8364 printf("Error Statement. Insufficient memory \n");
8365 return RETURN_ERR;
8366 }
8367 memset(buf,0,sizeof(buf));
8368 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
8369 fp = popen(buf,"r");
8370 if (fp == NULL) {
8371 fprintf(stderr, "%s: failed pipe command %s.\n", __func__, buf);
8372 return RETURN_ERR;
8373 }
8374 for(count = 0; count < maccount ; count++)
8375 {
8376 fgets(path,sizeof(path),fp);
8377 for(i = 0; path[i]!='\n';i++)
8378 str[i]=path[i];
8379 str[i]='\0';
8380 getIPAddress(str,ipaddr);
8381 memset(buf,0,sizeof(buf));
8382 if(strlen(ipaddr) > 0)
8383 {
8384 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
8385 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
8386 {
8387 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8388 {
8389 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8390 {
8391 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8392
8393 }
8394 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8395 fprintf(stderr,"%sMAC %d = %X:%X:%X:%X:%X:%X \n", __FUNCTION__,count, temp[count].cli_MACAddress[0],temp[count].cli_MACAddress[1], temp[count].cli_MACAddress[2], temp[count].cli_MACAddress[3], temp[count].cli_MACAddress[4], temp[count].cli_MACAddress[5]);
8396 }
8397 temp[count].cli_AuthenticationState = 0; //TODO
developer69b61b02023-03-07 17:17:44 +08008398 temp[count].cli_Active = 0; //TODO
developer72fb0bb2023-01-11 09:46:29 +08008399 temp[count].cli_SignalStrength = 0;
8400 }
8401 else //Active wireless clients info
8402 {
8403 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8404 {
8405 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8406 {
8407 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8408
8409 }
8410 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8411 fprintf(stderr,"%sMAC %d = %X:%X:%X:%X:%X:%X \n", __FUNCTION__,count, temp[count].cli_MACAddress[0],temp[count].cli_MACAddress[1], temp[count].cli_MACAddress[2], temp[count].cli_MACAddress[3], temp[count].cli_MACAddress[4], temp[count].cli_MACAddress[5]);
8412 }
8413 temp[count].cli_Active = 1;
8414 }
8415 }
8416 memset(ipaddr,0,sizeof(ipaddr));
8417 }
8418 pclose(fp);
8419 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8420 return RETURN_OK;
8421}
8422//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
8423//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
8424//To get Band Steering Capability
8425INT wifi_getBandSteeringCapability(BOOL *support)
8426{
8427 *support = FALSE;
8428 return RETURN_OK;
8429}
8430
8431
8432//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
8433//To get Band Steering enable status
8434INT wifi_getBandSteeringEnable(BOOL *enable)
8435{
8436 *enable = FALSE;
8437 return RETURN_OK;
8438}
8439
8440//To turn on/off Band steering
8441INT wifi_setBandSteeringEnable(BOOL enable)
8442{
8443 return RETURN_OK;
8444}
8445
8446//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
8447//To get Band Steering AP group
8448INT wifi_getBandSteeringApGroup(char *output_ApGroup)
8449{
8450 if (NULL == output_ApGroup)
8451 return RETURN_ERR;
8452
8453 strcpy(output_ApGroup, "1,2");
8454 return RETURN_OK;
8455}
8456
8457//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
8458//to set and read the band steering BandUtilizationThreshold parameters
8459INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
8460{
8461 return RETURN_ERR;
8462}
8463
8464INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
8465{
8466 return RETURN_ERR;
8467}
8468
8469//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
8470//to set and read the band steering RSSIThreshold parameters
8471INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
8472{
8473 return RETURN_ERR;
8474}
8475
8476INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
8477{
8478 return RETURN_ERR;
8479}
8480
8481
8482//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
8483//to set and read the band steering physical modulation rate threshold parameters
8484INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
8485{
8486 //If chip is not support, return -1
8487 return RETURN_ERR;
8488}
8489
8490INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
8491{
8492 //If chip is not support, return -1
8493 return RETURN_ERR;
8494}
8495
8496//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
8497//to set and read the inactivity time (in seconds) for steering under overload condition
8498INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
8499{
8500 return RETURN_ERR;
8501}
8502
8503INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
8504{
8505 return RETURN_ERR;
8506}
8507
8508//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
8509//to set and read the inactivity time (in seconds) for steering under Idle condition
8510INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
8511{
8512 return RETURN_ERR;
8513}
8514
8515INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
8516{
8517 return RETURN_ERR;
8518}
8519
8520//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
8521//pClientMAC[64]
8522//pSourceSSIDIndex[64]
8523//pDestSSIDIndex[64]
8524//pSteeringReason[256]
8525INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
8526{
8527 //if no steering or redord_index is out of boundary, return -1. pSteeringTime returns the UTC time in seconds. pClientMAC is pre allocated as 64bytes. pSteeringReason returns the predefined steering trigger reason
8528 *pSteeringTime=time(NULL);
8529 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
8530 return RETURN_OK;
8531}
8532
8533INT wifi_ifConfigDown(INT apIndex)
8534{
8535 INT status = RETURN_OK;
8536 char cmd[64];
8537
8538 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
8539 printf("%s: %s\n", __func__, cmd);
8540 system(cmd);
8541
8542 return status;
8543}
8544
8545INT wifi_ifConfigUp(INT apIndex)
8546{
8547 char interface_name[16] = {0};
8548 char cmd[128];
8549 char buf[1024];
8550
8551 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8552 return RETURN_ERR;
8553 snprintf(cmd, sizeof(cmd), "ifconfig %s up 2>/dev/null", interface_name);
8554 _syscmd(cmd, buf, sizeof(buf));
8555 return 0;
8556}
8557
8558//>> Deprecated. Replace with wifi_applyRadioSettings
8559INT wifi_pushBridgeInfo(INT apIndex)
8560{
8561 char interface_name[16] = {0};
8562 char ip[32] = {0};
8563 char subnet[32] = {0};
8564 char bridge[32] = {0};
8565 int vlanId = 0;
8566 char cmd[128] = {0};
8567 char buf[1024] = {0};
8568
8569 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
8570 wifi_getApVlanID(apIndex,&vlanId);
8571
8572 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8573 return RETURN_ERR;
8574 snprintf(cmd, sizeof(cmd), "cfgVlan %s %s %d %s ", interface_name, bridge, vlanId, ip);
8575 _syscmd(cmd,buf, sizeof(buf));
8576
8577 return 0;
8578}
8579
8580INT wifi_pushChannel(INT radioIndex, UINT channel)
8581{
8582 char interface_name[16] = {0};
8583 char cmd[128];
8584 char buf[1024];
8585 int apIndex;
8586
developer69b61b02023-03-07 17:17:44 +08008587 apIndex=(radioIndex==0)?0:1;
developer72fb0bb2023-01-11 09:46:29 +08008588 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
8589 return RETURN_ERR;
8590 snprintf(cmd, sizeof(cmd), "iwconfig %s freq %d",interface_name,channel);
8591 _syscmd(cmd,buf, sizeof(buf));
8592
8593 return 0;
8594}
8595
8596INT wifi_pushChannelMode(INT radioIndex)
8597{
8598 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
8599 return RETURN_ERR;
8600}
8601
8602INT wifi_pushDefaultValues(INT radioIndex)
8603{
8604 //Apply Comcast specified default radio settings instantly
8605 //AMPDU=1
8606 //AMPDUFrames=32
8607 //AMPDULim=50000
8608 //txqueuelen=1000
8609
8610 return RETURN_ERR;
8611}
8612
8613INT wifi_pushTxChainMask(INT radioIndex)
8614{
8615 //Apply default TxChainMask instantly
8616 return RETURN_ERR;
8617}
8618
8619INT wifi_pushRxChainMask(INT radioIndex)
8620{
8621 //Apply default RxChainMask instantly
8622 return RETURN_ERR;
8623}
8624
8625INT wifi_pushSSID(INT apIndex, CHAR *ssid)
8626{
developer7e4a2a62023-04-06 19:56:03 +08008627 INT status;
developer72fb0bb2023-01-11 09:46:29 +08008628
developer7e4a2a62023-04-06 19:56:03 +08008629 status = wifi_setSSIDName(apIndex, ssid);
8630 wifi_quick_reload_ap(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08008631
developer7e4a2a62023-04-06 19:56:03 +08008632 return status;
developer72fb0bb2023-01-11 09:46:29 +08008633}
8634
8635INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
8636{
8637 //Apply default Ssid Advertisement instantly
8638 return RETURN_ERR;
8639}
8640
8641INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
8642{
developere82c0ca2023-05-10 16:25:35 +08008643 time_t now;
8644
8645 time(&now);
8646 if (now > radio_up_time[radioIndex])
8647 *output = now - radio_up_time[radioIndex];
8648 else {
8649 *output = 0;
8650 return RETURN_ERR;
8651 }
8652
8653 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08008654}
8655
8656INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
8657{
8658 return RETURN_OK;
8659}
8660
8661INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
8662{
8663 return RETURN_OK;
8664}
8665
8666//To-do
8667INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
8668{
8669 char output[16]={'\0'};
8670 char config_file[MAX_BUF_SIZE] = {0};
8671
8672 if (!output_string)
8673 return RETURN_ERR;
8674
8675 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8676 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
8677
8678 if (strlen(output) == 0)
8679 snprintf(output_string, 64, "Disabled");
8680 else if (strncmp(output, "0", 1) == 0)
8681 snprintf(output_string, 64, "Disabled");
8682 else if (strncmp(output, "1", 1) == 0)
8683 snprintf(output_string, 64, "Optional");
8684 else if (strncmp(output, "2", 1) == 0)
8685 snprintf(output_string, 64, "Required");
8686 else {
8687 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
8688 return RETURN_ERR;
8689 }
8690
8691 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
8692 return RETURN_OK;
8693}
8694INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
8695{
8696 char str[MAX_BUF_SIZE]={'\0'};
8697 char cmd[MAX_CMD_SIZE]={'\0'};
8698 struct params params;
8699 char config_file[MAX_BUF_SIZE] = {0};
8700
8701 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8702 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
8703 return RETURN_ERR;
8704
8705 params.name = "ieee80211w";
8706 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
8707 params.value = "0";
8708 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
8709 params.value = "1";
8710 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
8711 params.value = "2";
8712 else{
8713 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
8714 return RETURN_ERR;
8715 }
8716 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8717 wifi_hostapdWrite(config_file, &params, 1);
8718 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
8719 return RETURN_OK;
8720}
8721INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
8722{
8723 char output[16]={'\0'};
8724 char config_file[MAX_BUF_SIZE] = {0};
8725
8726 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8727 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
8728 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
8729
8730 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
8731 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8732
8733 return RETURN_OK;
8734}
8735
8736INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
8737{
8738 return RETURN_OK;
8739}
8740
8741INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
8742{
8743 return RETURN_OK;
8744}
8745
8746INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
8747{
8748 return RETURN_OK;
8749}
8750
8751INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8752{
8753 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8754 char config_file[MAX_BUF_SIZE] = {0};
8755
8756 if (NULL == output)
8757 return RETURN_ERR;
8758 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8759 wifi_hostapdRead(config_file,"hw_mode",output,64);
8760
8761 if(strcmp(output,"b")==0)
8762 sprintf(output, "%s", "1,2,5.5,11");
8763 else if (strcmp(output,"a")==0)
8764 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
8765 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
8766 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
8767
8768 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8769 return RETURN_OK;
8770}
8771
8772INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8773{
8774 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8775 char *temp;
8776 char temp_output[128];
8777 char temp_TransmitRates[128];
8778 char config_file[MAX_BUF_SIZE] = {0};
8779
8780 if (NULL == output)
8781 return RETURN_ERR;
8782
8783 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8784 wifi_hostapdRead(config_file,"supported_rates",output,64);
8785
8786 if (strlen(output) == 0) {
8787 wifi_getRadioSupportedDataTransmitRates(wlanIndex, output);
8788 return RETURN_OK;
8789 }
8790 strcpy(temp_TransmitRates,output);
8791 strcpy(temp_output,"");
8792 temp = strtok(temp_TransmitRates," ");
8793 while(temp!=NULL)
8794 {
8795 temp[strlen(temp)-1]=0;
8796 if((temp[0]=='5') && (temp[1]=='\0'))
8797 {
8798 temp="5.5";
8799 }
8800 strcat(temp_output,temp);
8801 temp = strtok(NULL," ");
8802 if(temp!=NULL)
8803 {
8804 strcat(temp_output,",");
8805 }
8806 }
8807 strcpy(output,temp_output);
8808 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8809
8810 return RETURN_OK;
8811}
8812
8813INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8814{
8815 return RETURN_OK;
8816}
8817
8818
8819INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8820{
8821 int i=0;
8822 char *temp;
8823 char temp1[128] = {0};
8824 char temp_output[128] = {0};
8825 char temp_TransmitRates[128] = {0};
8826 struct params params={'\0'};
8827 char config_file[MAX_BUF_SIZE] = {0};
8828 wifi_band band = wifi_index_to_band(wlanIndex);
8829
8830 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8831 if(NULL == output)
8832 return RETURN_ERR;
8833 strcpy(temp_TransmitRates,output);
8834
8835 for(i=0;i<strlen(temp_TransmitRates);i++)
8836 {
8837 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
8838 {
8839 continue;
8840 }
8841 else
8842 {
8843 return RETURN_ERR;
8844 }
8845 }
8846 strcpy(temp_output,"");
8847 temp = strtok(temp_TransmitRates,",");
8848 while(temp!=NULL)
8849 {
8850 strcpy(temp1,temp);
8851 if(band == band_5)
8852 {
8853 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
8854 {
8855 return RETURN_ERR;
8856 }
8857 }
8858
8859 if(strcmp(temp,"5.5")==0)
8860 {
8861 strcpy(temp1,"55");
8862 }
8863 else
8864 {
8865 strcat(temp1,"0");
8866 }
8867 strcat(temp_output,temp1);
8868 temp = strtok(NULL,",");
8869 if(temp!=NULL)
8870 {
8871 strcat(temp_output," ");
8872 }
8873 }
8874 strcpy(output,temp_output);
8875
8876 params.name = "supported_rates";
8877 params.value = output;
8878
8879 wifi_dbg_printf("\n%s:",__func__);
8880 wifi_dbg_printf("params.value=%s\n",params.value);
8881 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8882 wifi_hostapdWrite(config_file,&params,1);
8883 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8884
8885 return RETURN_OK;
8886}
8887
8888
8889static char *sncopy(char *dst, int dst_sz, const char *src)
8890{
8891 if (src && dst && dst_sz > 0) {
8892 strncpy(dst, src, dst_sz);
8893 dst[dst_sz - 1] = '\0';
8894 }
8895 return dst;
8896}
8897
8898static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8899{
8900 if (0 == strcmp(ht_mode, "HT40") ||
8901 0 == strcmp(ht_mode, "HT80") ||
8902 0 == strcmp(ht_mode, "HT160")) {
8903 switch (channel) {
8904 case 1 ... 7:
8905 case 36:
8906 case 44:
8907 case 52:
8908 case 60:
8909 case 100:
8910 case 108:
8911 case 116:
8912 case 124:
8913 case 132:
8914 case 140:
8915 case 149:
8916 case 157:
8917 return 1;
8918 case 8 ... 13:
8919 case 40:
8920 case 48:
8921 case 56:
8922 case 64:
8923 case 104:
8924 case 112:
8925 case 120:
8926 case 128:
8927 case 136:
8928 case 144:
8929 case 153:
8930 case 161:
8931 return -1;
8932 default:
8933 return -EINVAL;
8934 }
8935 }
8936
8937 return -EINVAL;
8938}
8939
8940static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
8941{
8942 int idx = channel%8;
8943 if (0 == strcmp(ht_mode, "HT40") ||
8944 0 == strcmp(ht_mode, "HT80") ||
8945 0 == strcmp(ht_mode, "HT160")) {
8946 switch (idx) {
8947 case 1:
8948 return 1;
8949 case 5:
8950 return -1;
8951 default:
8952 return -EINVAL;
8953 }
8954 }
8955
8956 return -EINVAL;
8957}
8958static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8959{
8960 if (NULL == hw_mode) return;
8961
8962 if (0 == strcmp(hw_mode, "ac"))
8963 sncopy(bw_mode, bw_mode_len, "ht vht");
8964
8965 if (0 == strcmp(hw_mode, "n"))
8966 sncopy(bw_mode, bw_mode_len, "ht");
8967
8968 return;
8969}
8970
8971static int util_chan_to_freq(int chan)
8972{
8973 if (chan == 14)
8974 return 2484;
8975 else if (chan < 14)
8976 return 2407 + chan * 5;
8977 else if (chan >= 182 && chan <= 196)
8978 return 4000 + chan * 5;
8979 else
8980 return 5000 + chan * 5;
8981 return 0;
8982}
8983
8984static int util_6G_chan_to_freq(int chan)
8985{
8986 if (chan)
8987 return 5950 + chan * 5;
8988 else
8989 return 0;
developer69b61b02023-03-07 17:17:44 +08008990
developer72fb0bb2023-01-11 09:46:29 +08008991}
8992const int *util_unii_5g_chan2list(int chan, int width)
8993{
8994 static const int lists[] = {
8995 // <width>, <chan1>, <chan2>..., 0,
8996 20, 36, 0,
8997 20, 40, 0,
8998 20, 44, 0,
8999 20, 48, 0,
9000 20, 52, 0,
9001 20, 56, 0,
9002 20, 60, 0,
9003 20, 64, 0,
9004 20, 100, 0,
9005 20, 104, 0,
9006 20, 108, 0,
9007 20, 112, 0,
9008 20, 116, 0,
9009 20, 120, 0,
9010 20, 124, 0,
9011 20, 128, 0,
9012 20, 132, 0,
9013 20, 136, 0,
9014 20, 140, 0,
9015 20, 144, 0,
9016 20, 149, 0,
9017 20, 153, 0,
9018 20, 157, 0,
9019 20, 161, 0,
9020 20, 165, 0,
9021 40, 36, 40, 0,
9022 40, 44, 48, 0,
9023 40, 52, 56, 0,
9024 40, 60, 64, 0,
9025 40, 100, 104, 0,
9026 40, 108, 112, 0,
9027 40, 116, 120, 0,
9028 40, 124, 128, 0,
9029 40, 132, 136, 0,
9030 40, 140, 144, 0,
9031 40, 149, 153, 0,
9032 40, 157, 161, 0,
9033 80, 36, 40, 44, 48, 0,
9034 80, 52, 56, 60, 64, 0,
9035 80, 100, 104, 108, 112, 0,
9036 80, 116, 120, 124, 128, 0,
9037 80, 132, 136, 140, 144, 0,
9038 80, 149, 153, 157, 161, 0,
9039 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
9040 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
9041 -1 // final delimiter
9042 };
9043 const int *start;
9044 const int *p;
9045
9046 for (p = lists; *p != -1; p++) {
9047 if (*p == width) {
9048 for (start = ++p; *p != 0; p++) {
9049 if (*p == chan)
9050 return start;
9051 }
9052 }
9053 // move to the end of channel list of given width
9054 while (*p != 0) {
9055 p++;
9056 }
9057 }
9058
9059 return NULL;
9060}
9061
9062static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
9063{
9064 if (NULL == ht_mode)
9065 return 0;
9066
9067 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
9068 const int *chans = util_unii_5g_chan2list(channel, width);
9069 int sum = 0;
9070 int cnt = 0;
9071
9072 if (NULL == chans)
9073 return 0;
9074
9075 while (*chans) {
9076 sum += *chans;
9077 cnt++;
9078 chans++;
9079 }
9080 if (cnt == 0)
9081 return 0;
9082 return sum / cnt;
9083}
9084
9085static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
9086{
9087 if (NULL == ht_mode)
9088 return 0;
9089
9090 int width = strtol((ht_mode + 2), NULL, 10);
9091
9092 int idx = 0 ;
9093 int centerchan = 0;
9094 int chan_ofs = 1;
9095
9096 if (width == 40){
9097 idx = ((channel/4) + chan_ofs)%2;
9098 switch (idx) {
9099 case 0:
9100 centerchan = (channel - 2);
9101 break;
9102 case 1:
9103 centerchan = (channel + 2);
developer69b61b02023-03-07 17:17:44 +08009104 break;
developer72fb0bb2023-01-11 09:46:29 +08009105 default:
9106 return -EINVAL;
9107 }
9108 }else if (width == 80){
developer69b61b02023-03-07 17:17:44 +08009109 idx = ((channel/4) + chan_ofs)%4;
developer72fb0bb2023-01-11 09:46:29 +08009110 switch (idx) {
9111 case 0:
9112 centerchan = (channel - 6);
9113 break;
9114 case 1:
9115 centerchan = (channel + 6);
9116 break;
9117 case 2:
9118 centerchan = (channel + 2);
9119 break;
9120 case 3:
9121 centerchan = (channel - 2);
9122 break;
9123 default:
9124 return -EINVAL;
developer69b61b02023-03-07 17:17:44 +08009125 }
developer72fb0bb2023-01-11 09:46:29 +08009126 }else if (width == 160){
9127 switch (channel) {
9128 case 1 ... 29:
9129 centerchan = 15;
9130 break;
9131 case 33 ... 61:
9132 centerchan = 47;
9133 break;
9134 case 65 ... 93:
9135 centerchan = 79;
9136 break;
9137 case 97 ... 125:
9138 centerchan = 111;
9139 break;
9140 case 129 ... 157:
9141 centerchan = 143;
9142 break;
9143 case 161 ... 189:
9144 centerchan = 175;
9145 break;
9146 case 193 ... 221:
9147 centerchan = 207;
9148 break;
9149 default:
9150 return -EINVAL;
developer69b61b02023-03-07 17:17:44 +08009151 }
developer72fb0bb2023-01-11 09:46:29 +08009152 }
9153 return centerchan;
9154}
9155static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
9156{
9157 BOOL onlyG, onlyN, onlyA;
9158 CHAR tmp[64];
9159 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
9160 if (ret == RETURN_OK) {
9161 sncopy(hw_mode, hw_mode_size, tmp);
9162 }
9163 return ret;
9164}
9165
9166INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
9167{
9168 // Sample commands:
9169 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
9170 // hostapd_cli -i wifi0 chan_switch 30 2437
9171 char cmd[MAX_CMD_SIZE] = {0};
9172 char buf[MAX_BUF_SIZE] = {0};
9173 int freq = 0, ret = 0;
9174 char center_freq1_str[32] = ""; // center_freq1=%d
9175 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
9176 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
9177 char hw_mode[16] = ""; // n|ac
9178 char bw_mode[16] = ""; // ht|ht vht
9179 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
9180 char interface_name[16] = {0};
9181 int sec_chan_offset;
9182 int width;
9183 char config_file[64] = {0};
9184 BOOL stbcEnable = FALSE;
9185 char *ext_str = "None";
9186 wifi_band band = band_invalid;
9187 int center_chan = 0;
9188 int center_freq1 = 0;
9189
9190 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
9191
9192 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
9193 return RETURN_ERR;
9194
9195 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9196
9197 band = wifi_index_to_band(radioIndex);
9198
9199 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
9200
9201 // Get radio mode HT20|HT40|HT80 etc.
9202 if (channel){
9203 if (band == band_6){
9204 freq = util_6G_chan_to_freq(channel);
9205 }else{
9206 freq = util_chan_to_freq(channel);
9207 }
9208 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
9209
9210 // Provide bandwith if specified
9211 if (channel_width_MHz > 20) {
9212 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
9213 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
9214 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
9215
9216 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
9217 }else if (channel_width_MHz == 20){
9218 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
9219 }
9220
9221
9222 if (channel_width_MHz > 20) {
9223 if (band == band_6){
9224 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
9225 if(center_chan){
9226 center_freq1 = util_6G_chan_to_freq(center_chan);
9227 }
9228 }else{
9229 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
9230 if(center_chan){
9231 center_freq1 = util_chan_to_freq(center_chan);
9232 }
9233 }
developer69b61b02023-03-07 17:17:44 +08009234
developer72fb0bb2023-01-11 09:46:29 +08009235 if (center_freq1)
9236 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
developer69b61b02023-03-07 17:17:44 +08009237
developer72fb0bb2023-01-11 09:46:29 +08009238 }
9239
9240 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
9241 if (band == band_6){
9242 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
9243 }else{
9244 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
9245 }
9246 if (sec_chan_offset != -EINVAL)
9247 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
9248
9249 // Only the first AP, other are hanging on the same radio
9250 int apIndex = radioIndex;
developerf6a87542023-05-16 15:47:28 +08009251 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s chan_switch %d %d %s %s %s",
developer72fb0bb2023-01-11 09:46:29 +08009252 interface_name, csa_beacon_count, freq,
developerf6a87542023-05-16 15:47:28 +08009253 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
9254 wifi_dbg_printf("execute: '%s'\n", cmd);
9255 ret = _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08009256 wifi_reloadAp(radioIndex);
9257
9258 ret = wifi_setRadioChannel(radioIndex, channel);
9259 if (ret != RETURN_OK) {
9260 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
9261 return RETURN_ERR;
9262 }
9263
9264 if (sec_chan_offset == 1) ext_str = "Above";
9265 else if (sec_chan_offset == -1) ext_str = "Below";
9266
9267 wifi_setRadioCenterChannel(radioIndex, center_chan);
9268
9269 } else {
9270 if (channel_width_MHz > 20)
9271 ext_str = "Above";
9272 }
9273
9274 wifi_setRadioExtChannel(radioIndex, ext_str);
9275
9276 char mhz_str[16];
9277 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
9278 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
9279
9280 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9281
9282 return RETURN_OK;
9283}
9284
9285INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
9286{
9287 int index = -1;
9288 wifi_neighbor_ap2_t *scan_array = NULL;
9289 char cmd[256]={0};
9290 char buf[128]={0};
9291 char file_name[32] = {0};
9292 char filter_SSID[32] = {0};
9293 char line[256] = {0};
9294 char interface_name[16] = {0};
9295 char *ret = NULL;
9296 int freq=0;
9297 FILE *f = NULL;
9298 size_t len=0;
9299 int channels_num = 0;
9300 int vht_channel_width = 0;
9301 int get_noise_ret = RETURN_ERR;
9302 bool filter_enable = false;
9303 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
9304 int phyId = 0;
9305
9306 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
9307
9308 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
9309 f = fopen(file_name, "r");
9310 if (f != NULL) {
9311 fgets(filter_SSID, sizeof(file_name), f);
9312 if (strlen(filter_SSID) != 0)
9313 filter_enable = true;
9314 fclose(f);
9315 }
9316
9317 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
9318 return RETURN_ERR;
9319
9320 phyId = radio_index_to_phy(radio_index);
9321
9322 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
9323 _syscmd(cmd, buf, sizeof(buf));
9324 channels_num = strtol(buf, NULL, 10);
9325
9326 sprintf(cmd, "iw dev %s scan dump | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
9327 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", interface_name, interface_name);
9328 fprintf(stderr, "cmd: %s\n", cmd);
9329 if ((f = popen(cmd, "r")) == NULL) {
9330 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9331 return RETURN_ERR;
9332 }
developer69b61b02023-03-07 17:17:44 +08009333
developer72fb0bb2023-01-11 09:46:29 +08009334 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
9335 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
developer69b61b02023-03-07 17:17:44 +08009336
developer72fb0bb2023-01-11 09:46:29 +08009337 ret = fgets(line, sizeof(line), f);
9338 while (ret != NULL) {
9339 if(strstr(line, "BSS") != NULL) { // new neighbor info
developer69b61b02023-03-07 17:17:44 +08009340 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
developer72fb0bb2023-01-11 09:46:29 +08009341 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
9342 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
9343
9344 if (!filter_BSS) {
9345 index++;
9346 wifi_neighbor_ap2_t *tmp;
9347 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
9348 if (tmp == NULL) { // no more memory to use
9349 index--;
9350 wifi_dbg_printf("%s: realloc failed\n", __func__);
9351 break;
9352 }
9353 scan_array = tmp;
9354 }
9355 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
9356
9357 filter_BSS = false;
9358 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
9359 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
9360 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
9361 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
9362 } else if (strstr(line, "freq") != NULL) {
9363 sscanf(line," freq: %d", &freq);
9364 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
9365
9366 if (freq >= 2412 && freq <= 2484) {
9367 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
9368 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
9369 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
9370 }
9371 else if (freq >= 5160 && freq <= 5805) {
9372 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
9373 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
9374 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
9375 }
9376
9377 scan_array[index].ap_Noise = 0;
9378 if (get_noise_ret == RETURN_OK) {
9379 for (int i = 0; i < channels_num; i++) {
9380 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
9381 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
9382 break;
9383 }
9384 }
9385 }
9386 } else if (strstr(line, "beacon interval") != NULL) {
9387 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
9388 } else if (strstr(line, "signal") != NULL) {
9389 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
9390 } else if (strstr(line,"SSID") != NULL) {
9391 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
9392 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
9393 filter_BSS = true;
9394 }
9395 } else if (strstr(line, "Supported rates") != NULL) {
9396 char SRate[80] = {0}, *tmp = NULL;
9397 memset(buf, 0, sizeof(buf));
9398 strcpy(SRate, line);
9399 tmp = strtok(SRate, ":");
9400 tmp = strtok(NULL, ":");
9401 strcpy(buf, tmp);
9402 memset(SRate, 0, sizeof(SRate));
9403
9404 tmp = strtok(buf, " \n");
9405 while (tmp != NULL) {
9406 strcat(SRate, tmp);
9407 if (SRate[strlen(SRate) - 1] == '*') {
9408 SRate[strlen(SRate) - 1] = '\0';
9409 }
9410 strcat(SRate, ",");
9411
9412 tmp = strtok(NULL, " \n");
9413 }
9414 SRate[strlen(SRate) - 1] = '\0';
9415 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
9416 } else if (strstr(line, "DTIM") != NULL) {
9417 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
9418 } else if (strstr(line, "VHT capabilities") != NULL) {
9419 strcat(scan_array[index].ap_SupportedStandards, ",ac");
9420 strcpy(scan_array[index].ap_OperatingStandards, "ac");
9421 } else if (strstr(line, "HT capabilities") != NULL) {
9422 strcat(scan_array[index].ap_SupportedStandards, ",n");
9423 strcpy(scan_array[index].ap_OperatingStandards, "n");
9424 } else if (strstr(line, "VHT operation") != NULL) {
9425 ret = fgets(line, sizeof(line), f);
9426 sscanf(line," * channel width: %d", &vht_channel_width);
9427 if(vht_channel_width == 1) {
9428 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
9429 } else {
9430 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
9431 }
9432 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
9433 continue;
9434 } else if (strstr(line, "HT operation") != NULL) {
9435 ret = fgets(line, sizeof(line), f);
9436 sscanf(line," * secondary channel offset: %s", &buf);
9437 if (!strcmp(buf, "above")) {
9438 //40Mhz +
9439 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radio_index%1 ? "A": "G");
9440 }
9441 else if (!strcmp(buf, "below")) {
9442 //40Mhz -
9443 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
9444 } else {
9445 //20Mhz
9446 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radio_index%1 ? "A": "G");
9447 }
9448 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
9449 continue;
9450 } else if (strstr(line, "HE capabilities") != NULL) {
9451 strcat(scan_array[index].ap_SupportedStandards, ",ax");
9452 strcpy(scan_array[index].ap_OperatingStandards, "ax");
9453 ret = fgets(line, sizeof(line), f);
9454 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
9455 if (strstr(line, "HE40/2.4GHz") != NULL)
9456 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
9457 else
9458 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
9459 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
9460 if (strstr(line, "HE80/5GHz") != NULL) {
9461 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
9462 ret = fgets(line, sizeof(line), f);
9463 } else
9464 continue;
9465 if (strstr(line, "HE160/5GHz") != NULL)
9466 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
9467 }
9468 continue;
9469 } else if (strstr(line, "WPA") != NULL) {
9470 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
9471 } else if (strstr(line, "RSN") != NULL) {
9472 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
9473 } else if (strstr(line, "Group cipher") != NULL) {
9474 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
9475 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
9476 strcpy(scan_array[index].ap_EncryptionMode, "AES");
9477 }
9478 }
9479 ret = fgets(line, sizeof(line), f);
9480 }
9481
9482 if (!filter_BSS) {
9483 *output_array_size = index + 1;
9484 } else {
9485 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
9486 *output_array_size = index;
9487 }
9488 *neighbor_ap_array = scan_array;
9489 pclose(f);
9490 free(channels_noise_arr);
9491 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9492 return RETURN_OK;
9493}
9494
9495INT wifi_getApAssociatedDeviceStats(
9496 INT apIndex,
9497 mac_address_t *clientMacAddress,
9498 wifi_associated_dev_stats_t *associated_dev_stats,
9499 u64 *handle)
9500{
9501 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
9502 char interface_name[50] = {0};
9503 char cmd[1024] = {0};
9504 char mac_str[18] = {0};
9505 char *key = NULL;
9506 char *val = NULL;
9507 FILE *f = NULL;
9508 char *line = NULL;
9509 size_t len = 0;
9510
9511 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9512 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9513 return RETURN_ERR;
9514 }
9515
9516 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
9517 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
9518 if((f = popen(cmd, "r")) == NULL) {
9519 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9520 return RETURN_ERR;
9521 }
9522
9523 while ((getline(&line, &len, f)) != -1) {
9524 key = strtok(line,":");
9525 val = strtok(NULL,":");
9526
9527 if(!strncmp(key,"rx bytes",8))
9528 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
9529 if(!strncmp(key,"tx bytes",8))
9530 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
9531 if(!strncmp(key,"rx packets",10))
9532 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9533 if(!strncmp(key,"tx packets",10))
9534 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9535 if(!strncmp(key,"tx retries",10))
9536 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
9537 if(!strncmp(key,"tx failed",9))
9538 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
9539 if(!strncmp(key,"rx drop misc",13))
9540 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
9541 if(!strncmp(key,"rx bitrate",10)) {
9542 val = strtok(val, " ");
9543 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
9544 }
9545 if(!strncmp(key,"tx bitrate",10)) {
9546 val = strtok(val, " ");
9547 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
9548 }
9549 }
9550 free(line);
9551 pclose(f);
9552 return RETURN_OK;
9553}
9554
9555INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
9556{
developer7e4a2a62023-04-06 19:56:03 +08009557 char interface_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08009558 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
9559
developer7e4a2a62023-04-06 19:56:03 +08009560 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
9561
developer72fb0bb2023-01-11 09:46:29 +08009562 if (NULL == output_string)
9563 return RETURN_ERR;
9564
9565 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9566 return RETURN_ERR;
developer7e4a2a62023-04-06 19:56:03 +08009567
9568 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep ^ssid | cut -d '=' -f2 | tr -d '\\n'", interface_name);
developer72fb0bb2023-01-11 09:46:29 +08009569 _syscmd(cmd, buf, sizeof(buf));
9570
9571 //size of SSID name restricted to value less than 32 bytes
9572 snprintf(output_string, 32, "%s", buf);
developer7e4a2a62023-04-06 19:56:03 +08009573 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08009574
9575 return RETURN_OK;
9576}
9577
9578INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
9579{
developer7e4a2a62023-04-06 19:56:03 +08009580 char cmd[MAX_CMD_SIZE] = {0};
9581 char buf[MAX_BUF_SIZE] = {0};
9582 char inf_name[IF_NAME_SIZE] = {0};
9583 char policy = 0;
developer72fb0bb2023-01-11 09:46:29 +08009584
9585 if (!output_filterMode)
9586 return RETURN_ERR;
9587
developer7e4a2a62023-04-06 19:56:03 +08009588 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
9589 return RETURN_ERR;
9590
9591 /* mwctl get acl policy */
9592 snprintf(cmd, sizeof(cmd), "mwctl %s acl show_all | grep policy | cut -d '=' -f2 | tr -d '\\n'", inf_name);
9593 _syscmd(cmd, buf, sizeof(buf));
9594
9595
9596 policy = atoi(buf);
9597
9598 if (policy < 0 || policy > 2) {
9599 printf("%s:get wrong acl policy!!!\n", __func__);
9600 *output_filterMode = 0;
9601 return RETURN_ERR;
9602 } else
9603 *output_filterMode = policy;
9604
developer72fb0bb2023-01-11 09:46:29 +08009605
9606 return RETURN_OK;
9607}
9608
9609INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
9610{
9611 FILE *fp = NULL;
9612 char str[MAX_BUF_SIZE] = {0};
9613 int wificlientindex = 0 ;
9614 int count = 0;
9615 int signalstrength = 0;
9616 int arr[MACADDRESS_SIZE] = {0};
9617 unsigned char mac[MACADDRESS_SIZE] = {0};
9618 UINT wifi_count = 0;
9619 char virtual_interface_name[MAX_BUF_SIZE] = {0};
9620 char pipeCmd[MAX_CMD_SIZE] = {0};
9621
9622 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9623 *output_array_size = 0;
9624 *associated_dev_array = NULL;
9625 char interface_name[50] = {0};
9626
9627 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9628 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9629 return RETURN_ERR;
9630 }
9631
9632 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
9633 fp = popen(pipeCmd, "r");
9634 if (fp == NULL)
9635 {
9636 printf("Failed to run command inside function %s\n",__FUNCTION__ );
9637 return RETURN_ERR;
9638 }
9639
9640 /* Read the output a line at a time - output it. */
9641 fgets(str, sizeof(str)-1, fp);
9642 wifi_count = (unsigned int) atoi ( str );
9643 *output_array_size = wifi_count;
9644 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
9645 pclose(fp);
9646
9647 if(wifi_count == 0)
9648 {
9649 return RETURN_OK;
9650 }
9651 else
9652 {
9653 wifi_associated_dev2_t* temp = NULL;
9654 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
9655 *associated_dev_array = temp;
9656 if(temp == NULL)
9657 {
9658 printf("Error Statement. Insufficient memory \n");
9659 return RETURN_ERR;
9660 }
9661
9662 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
9663 system(pipeCmd);
9664
9665 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
9666 if(fp == NULL)
9667 {
9668 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
9669 return RETURN_ERR;
9670 }
9671 fclose(fp);
9672
9673 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
9674 fp = popen(pipeCmd, "r");
9675 if(fp)
9676 {
9677 for(count =0 ; count < wifi_count; count++)
9678 {
9679 fgets(str, MAX_BUF_SIZE, fp);
9680 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
9681 {
9682 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
9683 {
9684 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
9685
9686 }
9687 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
9688 wifi_dbg_printf("MAC %d = %X:%X:%X:%X:%X:%X \n", count, temp[count].cli_MACAddress[0],temp[count].cli_MACAddress[1], temp[count].cli_MACAddress[2], temp[count].cli_MACAddress[3], temp[count].cli_MACAddress[4], temp[count].cli_MACAddress[5]);
9689 }
9690 temp[count].cli_AuthenticationState = 1; //TODO
9691 temp[count].cli_Active = 1; //TODO
9692 }
9693 pclose(fp);
9694 }
9695
9696 //Updating RSSI per client
9697 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt");
9698 fp = popen(pipeCmd, "r");
9699 if(fp)
9700 {
9701 pclose(fp);
9702 }
9703 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
9704 if(fp)
9705 {
9706 for(count =0 ; count < wifi_count ;count++)
9707 {
9708 fgets(str, MAX_BUF_SIZE, fp);
9709 signalstrength = atoi(str);
9710 temp[count].cli_RSSI = signalstrength;
9711 }
9712 pclose(fp);
9713 }
9714
9715
9716 //LastDataDownlinkRate
9717 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt");
9718 fp = popen(pipeCmd, "r");
9719 if (fp)
9720 {
9721 pclose(fp);
9722 }
9723 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
9724 if (fp)
9725 {
9726 for (count = 0; count < wifi_count; count++)
9727 {
9728 fgets(str, MAX_BUF_SIZE, fp);
9729 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
9730 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
9731 }
9732 pclose(fp);
9733 }
9734
9735 //LastDataUplinkRate
9736 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt");
9737 fp = popen(pipeCmd, "r");
9738 if (fp)
9739 {
9740 pclose(fp);
9741 }
9742 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
9743 if (fp)
9744 {
9745 for (count = 0; count < wifi_count; count++)
9746 {
9747 fgets(str, MAX_BUF_SIZE, fp);
9748 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
9749 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
9750 }
9751 pclose(fp);
9752 }
9753 }
9754 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9755 return RETURN_OK;
9756
9757}
9758
9759INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
9760{
9761#if 0
9762 /*char buf[1024] = {0};
9763 sprintf(cmd, "ifconfig %s ", interface_name);
9764 _syscmd(cmd, buf, sizeof(buf));*/
9765
9766 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
9767 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
9768 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
9769 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
9770
9771 output_struct->ssid_RetransCount = 0; //The total number of transmitted packets which were retransmissions. Two retransmissions of the same packet results in this counter incrementing by two.
9772 output_struct->ssid_FailedRetransCount = 0; //The number of packets that were not transmitted successfully due to the number of retransmission attempts exceeding an 802.11 retry limit. This parameter is based on dot11FailedCount from [802.11-2012].
9773 output_struct->ssid_RetryCount = 0; //The number of packets that were successfully transmitted after one or more retransmissions. This parameter is based on dot11RetryCount from [802.11-2012].
9774 output_struct->ssid_MultipleRetryCount = 0; //The number of packets that were successfully transmitted after more than one retransmission. This parameter is based on dot11MultipleRetryCount from [802.11-2012].
9775 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
9776 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
9777
9778 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
9779 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9780 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9781 output_struct->ssid_UnicastPacketsReceived = 2; //The total number of received packets, delivered by this layer to a higher layer, which were not addressed to a multicast or broadcast address at this layer.
9782 output_struct->ssid_DiscardedPacketsSent = 1; //The total number of outbound packets which were chosen to be discarded even though no errors had been detected to prevent their being transmitted. One possible reason for discarding such a packet could be to free up buffer space.
9783 output_struct->ssid_DiscardedPacketsReceived = 1; //The total number of inbound packets which were chosen to be discarded even though no errors had been detected to prevent their being delivered. One possible reason for discarding such a packet could be to free up buffer space.
9784 output_struct->ssid_MulticastPacketsSent = 10; //The total number of packets that higher-level protocols requested for transmission and which were addressed to a multicast address at this layer, including those that were discarded or not sent.
9785 output_struct->ssid_MulticastPacketsReceived = 0; //The total number of received packets, delivered by this layer to a higher layer, which were addressed to a multicast address at this layer.
9786 output_struct->ssid_BroadcastPacketsSent = 0; //The total number of packets that higher-level protocols requested for transmission and which were addressed to a broadcast address at this layer, including those that were discarded or not sent.
9787 output_struct->ssid_BroadcastPacketsRecevied = 1; //The total number of packets that higher-level protocols requested for transmission and which were addressed to a broadcast address at this layer, including those that were discarded or not sent.
9788 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
9789#endif
9790
9791 FILE *fp = NULL;
9792 char interface_name[50] = {0};
9793 char pipeCmd[128] = {0};
9794 char str[256] = {0};
9795 wifi_ssidTrafficStats2_t *out = output_struct;
9796
9797 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
9798 if (!output_struct)
9799 return RETURN_ERR;
9800
9801 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
9802 if (wifi_GetInterfaceName(ssidIndex, interface_name) != RETURN_OK)
9803 return RETURN_ERR;
9804 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
9805
9806 fp = popen(pipeCmd, "r");
9807 if (fp == NULL) {
9808 fprintf(stderr, "%s: popen failed\n", __func__);
9809 return RETURN_ERR;
9810 }
9811 fgets(str, sizeof(str), fp);
9812 pclose(fp);
9813
9814 if (strlen(str) == 0) // interface not exist
9815 return RETURN_OK;
9816
9817 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
9818 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
9819
9820 memset(str, 0, sizeof(str));
9821 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
9822 fp = popen(pipeCmd, "r");
9823 if (fp == NULL) {
9824 fprintf(stderr, "%s: popen failed\n", __func__);
9825 return RETURN_ERR;
9826 }
9827 fgets(str, sizeof(str), fp);
9828
9829 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
9830 &out->ssid_BroadcastPacketsSent);
9831 pclose(fp);
9832
9833 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
9834 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
9835
9836 // Not supported
9837 output_struct->ssid_RetransCount = 0;
9838 output_struct->ssid_FailedRetransCount = 0;
9839 output_struct->ssid_RetryCount = 0;
9840 output_struct->ssid_MultipleRetryCount = 0;
9841 output_struct->ssid_ACKFailureCount = 0;
9842 output_struct->ssid_AggregatedPacketCount = 0;
9843
9844 return RETURN_OK;
9845}
9846
9847//Enables or disables device isolation. A value of true means that the devices connected to the Access Point are isolated from all other devices within the home network (as is typically the case for a Wireless Hotspot).
9848INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
9849{
9850 char output_val[16]={'\0'};
9851 char config_file[MAX_BUF_SIZE] = {0};
9852
9853 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9854 if (!output)
9855 return RETURN_ERR;
9856 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9857 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
9858
9859 if( strcmp(output_val,"1") == 0 )
9860 *output = TRUE;
9861 else
9862 *output = FALSE;
9863 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9864
9865 return RETURN_OK;
9866}
9867
9868INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
9869{
9870 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9871 char str[MAX_BUF_SIZE]={'\0'};
9872 char string[MAX_BUF_SIZE]={'\0'};
9873 char cmd[MAX_CMD_SIZE]={'\0'};
9874 char *ch;
9875 char config_file[MAX_BUF_SIZE] = {0};
9876 struct params params;
9877
9878 if(enable == TRUE)
9879 strcpy(string,"1");
9880 else
9881 strcpy(string,"0");
9882
9883 params.name = "ap_isolate";
9884 params.value = string;
9885
9886 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9887 wifi_hostapdWrite(config_file,&params,1);
9888 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9889
9890 return RETURN_OK;
9891}
9892
9893INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
9894{
developera1255e42023-05-13 17:45:02 +08009895 char mgmtpwr_file[32] = {0};
9896 char cmd[64] = {0};
9897 char buf[32]={0};
9898
developer72fb0bb2023-01-11 09:46:29 +08009899 if (NULL == output_dBm)
9900 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +08009901 snprintf(mgmtpwr_file, sizeof(mgmtpwr_file), "%s%d.txt", MGMT_POWER_CTRL, apIndex);
9902 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mgmtpwr_file);
9903 _syscmd(cmd, buf, sizeof(buf));
9904 if (strlen(buf) > 0)
9905 *output_dBm = strtol(buf, NULL, 10);
9906 else
9907 *output_dBm = 23;
developer72fb0bb2023-01-11 09:46:29 +08009908 return RETURN_OK;
9909}
9910
9911INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
9912{
developera1255e42023-05-13 17:45:02 +08009913 char interface_name[16] = {0};
9914 char cmd[128]={0};
9915 char buf[128]={0};
9916 char mgmt_pwr_file[128]={0};
9917 FILE *f = NULL;
9918
9919 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9920
9921 if (wifi_GetInterfaceName(wlanIndex, interface_name) != RETURN_OK)
9922 return RETURN_ERR;
9923 snprintf(cmd, sizeof(cmd), "mwctl dev %s set pwr mgmt_frame_pwr=%d", interface_name, dBm);
9924 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR) {
9925 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
9926 return RETURN_ERR;
9927 }
9928 snprintf(mgmt_pwr_file, sizeof(mgmt_pwr_file), "%s%d.txt", MGMT_POWER_CTRL, wlanIndex);
9929 f = fopen(mgmt_pwr_file, "w");
9930 if (f == NULL) {
9931 fprintf(stderr, "%s: fopen failed\n", __func__);
9932 return RETURN_ERR;
9933 }
9934 fprintf(f, "%d", dBm);
9935 fclose(f);
developer72fb0bb2023-01-11 09:46:29 +08009936 return RETURN_OK;
9937}
9938INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
9939{
9940 return RETURN_OK;
9941}
9942INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
9943{
9944 return RETURN_OK;
9945}
9946INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
9947{
9948 return RETURN_OK;
9949}
9950INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
9951{
9952 return RETURN_OK;
9953}
9954INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
9955{
9956 char config_file[MAX_BUF_SIZE] = {0};
9957 struct params list;
9958
9959 list.name = "bss_transition";
9960 list.value = activate?"1":"0";
9961 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
9962 wifi_hostapdWrite(config_file, &list, 1);
9963
9964 return RETURN_OK;
9965}
9966wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
9967
9968void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
9969{
9970 return;
9971}
9972
9973INT wifi_setApCsaDeauth(INT apIndex, INT mode)
9974{
9975 // TODO Implement me!
9976 return RETURN_OK;
9977}
9978
9979INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
9980{
9981 char file_name[128] = {0};
9982 char buf[128] = {0};
9983 FILE *f = NULL;
9984 int max_num_radios = 0;
9985
9986 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9987
9988 wifi_getMaxRadioNumber(&max_num_radios);
9989 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
9990 for (int index = 0; index < max_num_radios; index++) {
9991 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
9992 f = fopen(file_name, "w");
9993 if (f == NULL)
9994 return RETURN_ERR;
9995 // For mode == 0 is to disable filter, just don't write to the file.
9996 if (mode)
9997 fprintf(f, "%s", essid);
9998
9999 fclose(f);
10000 }
10001 } else { // special case, need to set AP's SSID as filter for each radio.
10002 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
10003 f = fopen(file_name, "w");
10004 if (f == NULL)
10005 return RETURN_ERR;
10006
10007 // For mode == 0 is to disable filter, just don't write to the file.
10008 if (mode)
10009 fprintf(f, "%s", essid);
10010
10011 fclose(f);
10012 }
10013
10014 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10015 return RETURN_OK;
10016}
10017
10018INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
10019{
10020 // TODO Implement me!
10021 //Apply wifi_pushRadioChannel() instantly
10022 return RETURN_ERR;
10023}
10024
10025INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
10026{
10027 // TODO Implement me!
10028 return RETURN_OK;
10029}
10030
10031#ifdef HAL_NETLINK_IMPL
10032static int tidStats_callback(struct nl_msg *msg, void *arg) {
10033 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10034 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10035 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10036 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
10037 int rem , tid_index = 0;
10038
10039 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
10040 wifi_associated_dev_tid_entry_t *stats_entry;
10041
10042 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
10043 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
10044 };
10045 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
10046 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
10047 };
10048
10049 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
10050 genlmsg_attrlen(gnlh, 0), NULL);
10051
10052
10053 if (!tb[NL80211_ATTR_STA_INFO]) {
10054 fprintf(stderr, "station stats missing!\n");
10055 return NL_SKIP;
10056 }
10057
10058 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
10059 tb[NL80211_ATTR_STA_INFO],
10060 stats_policy)) {
10061 fprintf(stderr, "failed to parse nested attributes!\n");
10062 return NL_SKIP;
10063 }
10064
10065 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
10066 {
10067 stats_entry = &out->tid_array[tid_index];
10068
10069 stats_entry->tid = tid_index;
10070 stats_entry->ac = _tid_ac_index_get[tid_index];
10071
10072 if(sinfo[NL80211_STA_INFO_TID_STATS])
10073 {
10074 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
10075 printf("failed to parse nested stats attributes!");
10076 return NL_SKIP;
10077 }
10078 }
10079 if(stats_info[NL80211_TID_STATS_TX_MSDU])
10080 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
10081
10082 if(tid_index < (PS_MAX_TID - 1))
10083 tid_index++;
10084 }
10085 //ToDo: sum_time_ms, ewma_time_ms
10086 return NL_SKIP;
10087}
10088#endif
10089
10090INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
10091{
10092#ifdef HAL_NETLINK_IMPL
10093 Netlink nl;
10094 char if_name[10];
10095 char interface_name[16] = {0};
10096
10097 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
10098 return RETURN_ERR;
10099
10100 snprintf(if_name, sizeof(if_name), "%s", interface_name);
10101
10102 nl.id = initSock80211(&nl);
10103
10104 if (nl.id < 0) {
10105 fprintf(stderr, "Error initializing netlink \n");
10106 return -1;
10107 }
10108
10109 struct nl_msg* msg = nlmsg_alloc();
10110
10111 if (!msg) {
10112 fprintf(stderr, "Failed to allocate netlink message.\n");
10113 nlfree(&nl);
10114 return -2;
10115 }
10116
10117 genlmsg_put(msg,
10118 NL_AUTO_PORT,
10119 NL_AUTO_SEQ,
10120 nl.id,
10121 0,
10122 0,
10123 NL80211_CMD_GET_STATION,
10124 0);
10125
10126 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
10127 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10128 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
10129 nl_send_auto(nl.socket, msg);
10130 nl_recvmsgs(nl.socket, nl.cb);
10131 nlmsg_free(msg);
10132 nlfree(&nl);
10133 return RETURN_OK;
10134#else
10135//iw implementation
10136#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
10137#define TOTAL_MAX_LINES 50
10138
10139 char buf[256] = {'\0'}; /* or other suitable maximum line size */
10140 char if_name[32] = {0};
10141 FILE *fp=NULL;
10142 char pipeCmd[1024]= {'\0'};
10143 int lines,tid_index=0;
10144 char mac_addr[20] = {'\0'};
10145
10146 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
10147 return RETURN_ERR;
10148
10149 wifi_associated_dev_tid_entry_t *stats_entry;
10150
10151 strcpy(mac_addr,clientMacAddress);
10152
10153 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
10154 fp= popen(pipeCmd,"r");
10155 if(fp == NULL)
10156 {
10157 perror("popen for station dump failed\n");
10158 return RETURN_ERR;
10159 }
10160 pclose(fp);
10161
10162 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
10163 fp=popen(pipeCmd,"r");
10164 if(fp == NULL)
10165 {
10166 perror("popen for grep station failed\n");
10167 return RETURN_ERR;
10168 }
10169 else if(fgets(buf,sizeof(buf),fp) != NULL)
10170 lines=atoi(buf);
10171 else
10172 {
10173 pclose(fp);
10174 fprintf(stderr,"No devices are connected \n");
10175 return RETURN_ERR;
10176 }
10177 pclose(fp);
10178
10179 if(lines == 1)
10180 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
10181
10182 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
10183 {
10184 stats_entry = &tid_stats->tid_array[tid_index];
10185 stats_entry->tid = tid_index;
10186
10187 snprintf(pipeCmd, sizeof(pipeCmd),"cat "TID_STATS_FILE" | awk '/%s/ {for(i=0; i<=%d; i++) {getline; print}}' | grep -F -A%d 'MSDU' | awk '{print $3}' | tail -1",mac_addr,lines,tid_index+2);
10188
10189 fp=popen(pipeCmd,"r");
10190 if(fp ==NULL)
10191 {
10192 perror("Failed to read from tid file \n");
10193 return RETURN_ERR;
10194 }
10195 else if(fgets(buf,sizeof(buf),fp) != NULL)
10196 stats_entry->num_msdus = atol(buf);
10197
10198 pclose(fp);
10199 stats_entry->ac = _tid_ac_index_get[tid_index];
10200// TODO:
10201// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
10202// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
10203 }
10204 return RETURN_OK;
10205#endif
10206}
10207
10208
10209INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
10210{
10211 char interface_name[16] = {0};
10212 char cmd[128]={0};
10213 char buf[128]={0};
10214 int freq = 0;
10215
10216 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10217
10218 // full mode is used to scan all channels.
10219 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
10220 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
10221 ieee80211_channel_to_frequency(chan_list[0], &freq);
10222
10223 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
10224 return RETURN_ERR;
10225
10226 if (freq)
10227 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d freq %d", interface_name, dwell_time, freq);
10228 else
10229 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d", interface_name, dwell_time);
10230
10231 _syscmd(cmd, buf, sizeof(buf));
10232 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10233
10234 return RETURN_OK;
10235}
10236
10237
10238INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
10239{
10240 // TODO Implement me!
10241 return RETURN_ERR;
10242}
10243
10244INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
10245{
10246 // TODO Implement me!
10247 return RETURN_ERR;
10248}
10249
10250INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
10251{
10252 // TODO Implement me!
10253 return RETURN_ERR;
10254}
10255
10256INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
10257{
10258 // TODO Implement me!
10259 return RETURN_ERR;
10260}
10261
10262INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
10263{
10264 // TODO Implement me!
10265 return RETURN_ERR;
10266}
10267
10268INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
10269{
10270 // TODO Implement me!
10271 return RETURN_ERR;
10272}
10273
10274INT wifi_steering_eventUnregister(void)
10275{
10276 // TODO Implement me!
10277 return RETURN_ERR;
10278}
10279
10280INT wifi_delApAclDevices(INT apIndex)
10281{
developer7e4a2a62023-04-06 19:56:03 +080010282 char cmd[MAX_CMD_SIZE] = {0};
10283 char buf[MAX_BUF_SIZE] = {0};
10284 char inf_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +080010285
developer7e4a2a62023-04-06 19:56:03 +080010286 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
10287 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +080010288
developer7e4a2a62023-04-06 19:56:03 +080010289 /* mwctl acl clear all stas */
10290 snprintf(cmd, sizeof(cmd), "mwctl %s acl clear_all", inf_name);
10291 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +080010292
10293 return RETURN_OK;
10294}
10295
10296#ifdef HAL_NETLINK_IMPL
10297static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
10298 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10299 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10300 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10301 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
10302 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
10303 char mac_addr[20],dev[20];
10304
10305 nla_parse(tb,
10306 NL80211_ATTR_MAX,
10307 genlmsg_attrdata(gnlh, 0),
10308 genlmsg_attrlen(gnlh, 0),
10309 NULL);
10310
10311 if(!tb[NL80211_ATTR_STA_INFO]) {
10312 fprintf(stderr, "sta stats missing!\n");
10313 return NL_SKIP;
10314 }
10315
10316 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
10317 fprintf(stderr, "failed to parse nested attributes!\n");
10318 return NL_SKIP;
10319 }
10320 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
10321
10322 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10323
10324 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
10325 fprintf(stderr, "failed to parse nested rate attributes!");
10326 return NL_SKIP;
10327 }
10328
10329 if(sinfo[NL80211_STA_INFO_TID_STATS])
10330 {
10331 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
10332 printf("failed to parse nested stats attributes!");
10333 return NL_SKIP;
10334 }
10335 }
10336
10337 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
10338 {
10339 printf("Type is VHT\n");
10340 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
10341 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
10342
10343 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
10344 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
10345 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
10346 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10347 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
10348 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10349 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
10350 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10351 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
10352 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
10353 }
10354 else
10355 {
10356 printf(" OFDM or CCK \n");
10357 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
10358 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
10359 }
10360
10361 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
10362 if(rinfo[NL80211_RATE_INFO_MCS])
10363 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
10364 }
10365 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
10366 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
10367 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
10368 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
10369
10370 if(stats_info[NL80211_TID_STATS_RX_MSDU])
10371 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
10372
10373 if (sinfo[NL80211_STA_INFO_SIGNAL])
10374 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
10375 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
10376 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
10377 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
10378 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
10379 //rssi_array need to be filled
10380 return NL_SKIP;
10381}
10382#endif
10383
10384INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10385{
10386#ifdef HAL_NETLINK_IMPL
10387 Netlink nl;
10388 char if_name[32];
10389 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
10390 return RETURN_ERR;
10391
10392 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
10393
10394 if (*output_array_size <= 0)
10395 return RETURN_OK;
10396
10397 nl.id = initSock80211(&nl);
10398
10399 if (nl.id < 0) {
10400 fprintf(stderr, "Error initializing netlink \n");
10401 return 0;
10402 }
10403
10404 struct nl_msg* msg = nlmsg_alloc();
10405
10406 if (!msg) {
10407 fprintf(stderr, "Failed to allocate netlink message.\n");
10408 nlfree(&nl);
10409 return 0;
10410 }
10411
10412 genlmsg_put(msg,
10413 NL_AUTO_PORT,
10414 NL_AUTO_SEQ,
10415 nl.id,
10416 0,
10417 0,
10418 NL80211_CMD_GET_STATION,
10419 0);
10420
10421 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
10422 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10423 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
10424 nl_send_auto(nl.socket, msg);
10425 nl_recvmsgs(nl.socket, nl.cb);
10426 nlmsg_free(msg);
10427 nlfree(&nl);
10428 return RETURN_OK;
10429#else
10430 //TODO Implement me
10431 return RETURN_OK;
10432#endif
10433}
10434
10435#ifdef HAL_NETLINK_IMPL
10436static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
10437 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10438 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10439 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10440 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
10441 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
10442 char mac_addr[20],dev[20];
10443
10444 nla_parse(tb,
10445 NL80211_ATTR_MAX,
10446 genlmsg_attrdata(gnlh, 0),
10447 genlmsg_attrlen(gnlh, 0),
10448 NULL);
10449
10450 if(!tb[NL80211_ATTR_STA_INFO]) {
10451 fprintf(stderr, "sta stats missing!\n");
10452 return NL_SKIP;
10453 }
10454
10455 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
10456 fprintf(stderr, "failed to parse nested attributes!\n");
10457 return NL_SKIP;
10458 }
10459
10460 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
10461
10462 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10463
10464 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
10465 fprintf(stderr, "failed to parse nested rate attributes!");
10466 return NL_SKIP;
10467 }
10468
10469 if(sinfo[NL80211_STA_INFO_TID_STATS])
10470 {
10471 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
10472 printf("failed to parse nested stats attributes!");
10473 return NL_SKIP;
10474 }
10475 }
10476 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
10477 {
10478 printf("Type is VHT\n");
10479 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
10480 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
10481
10482 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
10483 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
10484 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
10485 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10486 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
10487 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10488 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
10489 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10490 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
10491 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
10492 }
10493 else
10494 {
10495 printf(" OFDM or CCK \n");
10496 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
10497 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
10498 }
10499
10500 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
10501 if(rinfo[NL80211_RATE_INFO_MCS])
10502 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
10503 }
10504
10505 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
10506 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
10507 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
10508 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
10509
10510 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
10511 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10512 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10513
10514 if(stats_info[NL80211_TID_STATS_TX_MSDU])
10515 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
10516
10517 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
10518 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
10519
10520 if(sinfo[NL80211_STA_INFO_TX_FAILED])
10521 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->attempts = nla_get_u32(sinfo[NL80211_STA_INFO_TX_PACKETS]) + nla_get_u32(sinfo[NL80211_STA_INFO_TX_FAILED]);
10522
10523 return NL_SKIP;
10524}
10525#endif
10526
10527INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10528{
10529#ifdef HAL_NETLINK_IMPL
10530 Netlink nl;
10531 char if_name[10];
10532 char interface_name[16] = {0};
10533 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
10534 return RETURN_ERR;
10535
10536 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
10537
10538 if (*output_array_size <= 0)
10539 return RETURN_OK;
10540
10541 snprintf(if_name, sizeof(if_name), "%s", interface_name);
10542
10543 nl.id = initSock80211(&nl);
10544
10545 if(nl.id < 0) {
10546 fprintf(stderr, "Error initializing netlink \n");
10547 return 0;
10548 }
10549
10550 struct nl_msg* msg = nlmsg_alloc();
10551
10552 if(!msg) {
10553 fprintf(stderr, "Failed to allocate netlink message.\n");
10554 nlfree(&nl);
10555 return 0;
10556 }
10557
10558 genlmsg_put(msg,
10559 NL_AUTO_PORT,
10560 NL_AUTO_SEQ,
10561 nl.id,
10562 0,
10563 0,
10564 NL80211_CMD_GET_STATION,
10565 0);
10566
10567 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
10568 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10569 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
10570 nl_send_auto(nl.socket, msg);
10571 nl_recvmsgs(nl.socket, nl.cb);
10572 nlmsg_free(msg);
10573 nlfree(&nl);
10574 return RETURN_OK;
10575#else
10576 //TODO Implement me
10577 return RETURN_OK;
10578#endif
10579}
10580
10581INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
10582{
10583 // TODO Implement me!
10584 char buf[MAX_BUF_SIZE] = {0};
10585 char config_file[MAX_BUF_SIZE] = {0};
10586
10587 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
10588 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
10589 *activate = (strncmp("1",buf,1) == 0);
10590
10591 return RETURN_OK;
10592}
10593
10594INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
10595{
10596 char config_file[MAX_BUF_SIZE] = {0};
10597 struct params list;
10598
10599 list.name = "rrm_neighbor_report";
10600 list.value = activate?"1":"0";
10601 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10602 wifi_hostapdWrite(config_file, &list, 1);
10603
10604 return RETURN_OK;
10605}
10606
10607INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
10608{
10609 char buf[32] = {0};
10610 char config_file[MAX_BUF_SIZE] = {0};
10611
10612 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10613 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
10614 *activate = (strncmp("1",buf,1) == 0);
10615
10616 return RETURN_OK;
10617}
10618#undef HAL_NETLINK_IMPL
10619#ifdef HAL_NETLINK_IMPL
10620static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
10621 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10622 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10623 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
10624 char dev[20];
10625 int freq =0 ;
10626 static int i=0;
10627
10628 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
10629
10630 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
10631 };
10632
10633 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
10634
10635 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10636
10637 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
10638 fprintf(stderr, "survey data missing!\n");
10639 return NL_SKIP;
10640 }
10641
10642 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
10643 {
10644 fprintf(stderr, "failed to parse nested attributes!\n");
10645 return NL_SKIP;
10646 }
10647
10648
10649 if(out[0].array_size == 1 )
10650 {
10651 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
10652 {
10653 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10654 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10655 out[0].ch_number = ieee80211_frequency_to_channel(freq);
10656
10657 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10658 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10659 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10660 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10661 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10662 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10663 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10664 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10665 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10666 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10667 if (sinfo[NL80211_SURVEY_INFO_TIME])
10668 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10669 return NL_STOP;
10670 }
10671 }
10672 else
10673 {
10674 if ( i <= out[0].array_size )
10675 {
10676 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10677 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10678 out[i].ch_number = ieee80211_frequency_to_channel(freq);
10679
10680 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10681 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10682 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10683 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10684 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10685 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10686 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10687 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10688 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10689 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10690 if (sinfo[NL80211_SURVEY_INFO_TIME])
10691 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10692 }
10693 }
10694
10695 i++;
10696 return NL_SKIP;
10697}
10698#endif
10699
10700static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
10701{
10702 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
10703 FILE *fp;
10704
10705 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
10706 {
10707 printf("Creating Frequency-Channel Map\n");
10708 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
10709 }
10710 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
10711 if((fp = popen(command, "r")))
10712 {
10713 fgets(output, sizeof(output), fp);
10714 *freqMHz = atoi(output);
10715 pclose(fp);
10716 }
10717
10718 return 0;
10719}
10720
10721static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
10722{
10723 int freqMHz = -1;
10724 char cmd[MAX_CMD_SIZE] = {'\0'};
10725 char interface_name[16] = {0};
10726
10727 ieee80211_channel_to_frequency(channel, &freqMHz);
10728 if (freqMHz == -1) {
10729 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
10730 return -1;
10731 }
10732
10733 wifi_GetInterfaceName(radioIndex, interface_name);
10734 if (sprintf(cmd,"iw dev %s survey dump | grep -A5 %d | tr -d '\\t'", interface_name, freqMHz) < 0) {
10735 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
10736 radioIndex, freqMHz);
10737 return -1;
10738 }
10739
10740 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
10741 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
10742 return -1;
10743 }
10744
10745 return 0;
10746}
10747
10748static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
10749{
10750 const char *ptr = buf;
10751 char *key = NULL;
10752 char *val = NULL;
10753 char line[256] = { '\0' };
10754
10755 while (ptr = get_line_from_str_buf(ptr, line)) {
10756 if (strstr(line, "Frequency")) continue;
10757
10758 key = strtok(line, ":");
10759 val = strtok(NULL, " ");
10760 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
10761
10762 if (!strcmp(key, "noise")) {
10763 sscanf(val, "%d", &stats->ch_noise);
10764 if (stats->ch_noise == 0) {
10765 // Workaround for missing noise information.
10766 // Assume -95 for 2.4G and -103 for 5G
10767 if (radioIndex == 0) stats->ch_noise = -95;
10768 if (radioIndex == 1) stats->ch_noise = -103;
10769 }
10770 }
10771 else if (!strcmp(key, "channel active time")) {
10772 sscanf(val, "%llu", &stats->ch_utilization_total);
10773 }
10774 else if (!strcmp(key, "channel busy time")) {
10775 sscanf(val, "%llu", &stats->ch_utilization_busy);
10776 }
10777 else if (!strcmp(key, "channel receive time")) {
10778 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
10779 }
10780 else if (!strcmp(key, "channel transmit time")) {
10781 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
10782 }
10783 };
10784
10785 return 0;
10786}
10787
10788INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
10789{
10790 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10791#ifdef HAL_NETLINK_IMPL
10792 Netlink nl;
10793 wifi_channelStats_t_loc local[array_size];
10794 char if_name[32];
10795
10796 local[0].array_size = array_size;
10797
10798 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
10799 return RETURN_ERR;
10800
10801 nl.id = initSock80211(&nl);
10802
10803 if (nl.id < 0) {
10804 fprintf(stderr, "Error initializing netlink \n");
10805 return -1;
10806 }
10807
10808 struct nl_msg* msg = nlmsg_alloc();
10809
10810 if (!msg) {
10811 fprintf(stderr, "Failed to allocate netlink message.\n");
10812 nlfree(&nl);
10813 return -2;
10814 }
10815
10816 genlmsg_put(msg,
10817 NL_AUTO_PORT,
10818 NL_AUTO_SEQ,
10819 nl.id,
10820 0,
10821 NLM_F_DUMP,
10822 NL80211_CMD_GET_SURVEY,
10823 0);
10824
10825 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10826 nl_send_auto(nl.socket, msg);
10827 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
10828 nl_recvmsgs(nl.socket, nl.cb);
10829 nlmsg_free(msg);
10830 nlfree(&nl);
10831 //Copying the Values
10832 for(int i=0;i<array_size;i++)
10833 {
10834 input_output_channelStats_array[i].ch_number = local[i].ch_number;
10835 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
10836 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
10837 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
10838 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
10839 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
10840 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
10841 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
10842 }
10843#else
10844 ULONG channel = 0;
10845 int i;
10846 int number_of_channels = array_size;
10847 char buf[512];
10848 INT ret;
10849 wifi_channelStats_t tmp_stats;
10850
10851 if (number_of_channels == 0) {
10852 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
10853 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
10854 return RETURN_ERR;
10855 }
10856 number_of_channels = 1;
10857 input_output_channelStats_array[0].ch_number = channel;
10858 }
10859
10860 for (i = 0; i < number_of_channels; i++) {
10861
10862 input_output_channelStats_array[i].ch_noise = 0;
10863 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
10864 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
10865 input_output_channelStats_array[i].ch_utilization_busy = 0;
10866 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
10867 input_output_channelStats_array[i].ch_utilization_total = 0;
10868
10869 memset(buf, 0, sizeof(buf));
10870 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
10871 return RETURN_ERR;
10872 }
10873 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
10874 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
10875 return RETURN_ERR;
10876 }
10877
10878 // XXX: fake missing 'self' counter which is not available in iw survey output
10879 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
10880 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
10881
10882 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
10883 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
10884 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
10885 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
10886 input_output_channelStats_array[i].ch_utilization_total *= 1000;
10887
10888 wifi_dbg_printf("%s: ch_number=%d ch_noise=%d total=%llu busy=%llu busy_rx=%llu busy_tx=%llu busy_self=%llu busy_ext=%llu\n",
10889 __func__,
10890 input_output_channelStats_array[i].ch_number,
10891 input_output_channelStats_array[i].ch_noise,
10892 input_output_channelStats_array[i].ch_utilization_total,
10893 input_output_channelStats_array[i].ch_utilization_busy,
10894 input_output_channelStats_array[i].ch_utilization_busy_rx,
10895 input_output_channelStats_array[i].ch_utilization_busy_tx,
10896 input_output_channelStats_array[i].ch_utilization_busy_self,
10897 input_output_channelStats_array[i].ch_utilization_busy_ext);
10898 }
10899#endif
10900 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10901 return RETURN_OK;
10902}
10903#define HAL_NETLINK_IMPL
10904
10905/* Hostapd events */
10906
10907#ifndef container_of
10908#define offset_of(st, m) ((size_t)&(((st *)0)->m))
10909#define container_of(ptr, type, member) \
10910 ((type *)((char *)ptr - offset_of(type, member)))
10911#endif /* container_of */
10912
10913struct ctrl {
10914 char sockpath[128];
10915 char sockdir[128];
10916 char bss[IFNAMSIZ];
10917 char reply[4096];
10918 int ssid_index;
10919 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
10920 void (*overrun)(struct ctrl *ctrl);
10921 struct wpa_ctrl *wpa;
10922 unsigned int ovfl;
10923 size_t reply_len;
10924 int initialized;
10925 ev_timer retry;
10926 ev_timer watchdog;
10927 ev_stat stat;
10928 ev_io io;
10929};
10930static wifi_newApAssociatedDevice_callback clients_connect_cb;
10931static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
10932static struct ctrl wpa_ctrl[MAX_APS];
10933static int initialized;
10934
10935static unsigned int ctrl_get_drops(struct ctrl *ctrl)
10936{
10937 char cbuf[256] = {};
10938 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
10939 struct cmsghdr *cmsg;
10940 unsigned int ovfl = ctrl->ovfl;
10941 unsigned int drop;
10942
10943 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
10944 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
10945 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
10946 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
10947
10948 drop = ovfl - ctrl->ovfl;
10949 ctrl->ovfl = ovfl;
10950
10951 return drop;
10952}
10953
10954static void ctrl_close(struct ctrl *ctrl)
10955{
10956 if (ctrl->io.cb)
10957 ev_io_stop(EV_DEFAULT_ &ctrl->io);
10958 if (ctrl->retry.cb)
10959 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10960 if (!ctrl->wpa)
10961 return;
10962
10963 wpa_ctrl_detach(ctrl->wpa);
10964 wpa_ctrl_close(ctrl->wpa);
10965 ctrl->wpa = NULL;
10966 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
10967}
10968
10969static void ctrl_process(struct ctrl *ctrl)
10970{
10971 const char *str;
10972 int drops;
10973 int level;
10974 int err;
10975
10976 /* Example events:
10977 *
10978 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
10979 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
10980 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
10981 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
10982 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
10983 */
10984 if (!(str = index(ctrl->reply, '>')))
10985 return;
10986 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
10987 return;
10988
10989 str++;
10990
10991 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
10992 if (!(str = index(ctrl->reply, ' ')))
10993 return;
10994 wifi_associated_dev_t sta;
10995 memset(&sta, 0, sizeof(sta));
10996
10997 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10998 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
10999 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
11000
11001 sta.cli_Active=true;
11002
11003 (clients_connect_cb)(ctrl->ssid_index, &sta);
11004 goto handled;
11005 }
11006
11007 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
11008 if (!(str = index(ctrl->reply, ' ')))
11009 return;
11010
11011 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
11012 goto handled;
11013 }
11014
11015 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
11016 printf("CTRL_WPA: handle TERMINATING event\n");
11017 goto retry;
11018 }
11019
11020 if (strncmp("AP-DISABLED", str, 11) == 0) {
11021 printf("CTRL_WPA: handle AP-DISABLED\n");
11022 goto retry;
11023 }
11024
11025 printf("Event not supported!!\n");
11026
11027handled:
11028
11029 if ((drops = ctrl_get_drops(ctrl))) {
11030 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
11031 if (ctrl->overrun)
11032 ctrl->overrun(ctrl);
11033 }
11034
11035 return;
11036
11037retry:
11038 printf("WPA_CTRL: closing\n");
11039 ctrl_close(ctrl);
11040 printf("WPA_CTRL: retrying from ctrl prcoess\n");
11041 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
11042}
11043
11044static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
11045{
11046 struct ctrl *ctrl = container_of(io, struct ctrl, io);
11047 int err;
11048
11049 memset(ctrl->reply, 0, sizeof(ctrl->reply));
11050 ctrl->reply_len = sizeof(ctrl->reply) - 1;
11051 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
11052 ctrl->reply[ctrl->reply_len] = 0;
11053 if (err < 0) {
11054 if (errno == EAGAIN || errno == EWOULDBLOCK)
11055 return;
11056 ctrl_close(ctrl);
11057 ev_timer_again(EV_A_ &ctrl->retry);
11058 return;
11059 }
11060
11061 ctrl_process(ctrl);
11062}
11063
11064static int ctrl_open(struct ctrl *ctrl)
11065{
11066 int fd;
11067
11068 if (ctrl->wpa)
11069 return 0;
11070
11071 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
11072 if (!ctrl->wpa)
11073 goto err;
11074
11075 if (wpa_ctrl_attach(ctrl->wpa) < 0)
11076 goto err_close;
11077
11078 fd = wpa_ctrl_get_fd(ctrl->wpa);
11079 if (fd < 0)
11080 goto err_detach;
11081
11082 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
11083 goto err_detach;
11084
11085 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
11086 ev_io_start(EV_DEFAULT_ &ctrl->io);
11087
11088 return 0;
11089
11090err_detach:
11091 wpa_ctrl_detach(ctrl->wpa);
11092err_close:
11093 wpa_ctrl_close(ctrl->wpa);
11094err:
11095 ctrl->wpa = NULL;
11096 return -1;
11097}
11098
11099static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
11100{
11101 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
11102
11103 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
11104 ctrl_open(ctrl);
11105}
11106
11107static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
11108{
11109 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
11110
11111 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
11112 if (ctrl_open(ctrl) == 0) {
11113 printf("WPA_CTRL: retry successful\n");
11114 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
11115 }
11116}
11117
11118int ctrl_enable(struct ctrl *ctrl)
11119{
11120 if (ctrl->wpa)
11121 return 0;
11122
11123 if (!ctrl->stat.cb) {
11124 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
11125 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
11126 }
11127
11128 if (!ctrl->retry.cb) {
11129 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
11130 }
11131
11132 return ctrl_open(ctrl);
11133}
11134
11135static void
11136ctrl_msg_cb(char *buf, size_t len)
11137{
11138 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
11139
11140 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
11141 ctrl_process(ctrl);
11142}
11143
11144static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
11145{
11146 int err;
11147
11148 if (!ctrl->wpa)
11149 return -1;
11150 if (*reply_len < 2)
11151 return -1;
11152
11153 (*reply_len)--;
11154 ctrl->reply_len = sizeof(ctrl->reply);
11155 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
11156 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
11157 if (err < 0)
11158 return err;
11159
11160 if (ctrl->reply_len > *reply_len)
11161 ctrl->reply_len = *reply_len;
11162
11163 *reply_len = ctrl->reply_len;
11164 memcpy(reply, ctrl->reply, *reply_len);
11165 reply[*reply_len - 1] = 0;
11166 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
11167 return 0;
11168}
11169
11170static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
11171{
11172 const char *pong = "PONG";
11173 const char *ping = "PING";
11174 char reply[1024];
11175 size_t len = sizeof(reply);
11176 int err;
11177 ULONG s, snum;
11178 INT ret;
11179 BOOL status;
11180
11181 printf("WPA_CTRL: watchdog cb\n");
11182
11183 ret = wifi_getSSIDNumberOfEntries(&snum);
11184 if (ret != RETURN_OK) {
11185 printf("%s: failed to get SSID count", __func__);
11186 return;
11187 }
11188
11189 if (snum > MAX_APS) {
11190 printf("more ssid than supported! %lu\n", snum);
11191 return;
11192 }
11193
11194 for (s = 0; s < snum; s++) {
11195 if (wifi_getApEnable(s, &status) != RETURN_OK) {
11196 printf("%s: failed to get AP Enable for index: %lu\n", __func__, s);
11197 continue;
11198 }
11199 if (status == false) continue;
11200
11201 memset(reply, 0, sizeof(reply));
11202 len = sizeof(reply);
11203 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
11204 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
11205 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
11206 continue;
11207
11208 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
11209 ctrl_close(&wpa_ctrl[s]);
11210 printf("WPA_CTRL: ev_timer_again %lu\n", s);
11211 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
11212 }
11213}
11214
11215static int init_wpa()
11216{
11217 int ret = 0, i = 0;
11218 ULONG s, snum;
11219
11220 ret = wifi_getSSIDNumberOfEntries(&snum);
11221 if (ret != RETURN_OK) {
11222 printf("%s: failed to get SSID count", __func__);
11223 return RETURN_ERR;
11224 }
11225
11226 if (snum > MAX_APS) {
11227 printf("more ssid than supported! %lu\n", snum);
11228 return RETURN_ERR;
11229 }
11230
11231 for (s = 0; s < snum; s++) {
11232 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
11233 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
11234 wpa_ctrl[s].ssid_index = s;
11235 ctrl_enable(&wpa_ctrl[s]);
11236 }
11237
11238 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
11239 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
11240
11241 initialized = 1;
11242 printf("WPA_CTRL: initialized\n");
11243
11244 return RETURN_OK;
11245}
11246
11247void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
11248{
11249 clients_connect_cb = callback_proc;
11250 if (!initialized)
11251 init_wpa();
11252}
11253
11254void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
11255{
11256 clients_disconnect_cb = callback_proc;
11257 if (!initialized)
11258 init_wpa();
11259}
11260
11261INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
11262{
11263 // TODO Implement me!
11264 return RETURN_ERR;
11265}
11266
11267INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
11268{
11269 // TODO Implement me!
11270 return RETURN_ERR;
11271}
11272
11273INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
11274{
11275 int i;
developer40ba1762023-05-13 11:03:49 +080011276 int phyId = -1;
11277 char cmd[256] = {0};
11278 char channel_numbers_buf[256] = {0};
11279 char dfs_state_buf[256] = {0};
11280 char line[256] = {0};
developer72fb0bb2023-01-11 09:46:29 +080011281 const char *ptr;
developer40ba1762023-05-13 11:03:49 +080011282 BOOL dfs_enable = false;
developer72fb0bb2023-01-11 09:46:29 +080011283
developer40ba1762023-05-13 11:03:49 +080011284 memset(outputMap, 0, outputMapSize*sizeof(wifi_channelMap_t)); // all unused entries should be zero
developer72fb0bb2023-01-11 09:46:29 +080011285
developer40ba1762023-05-13 11:03:49 +080011286 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
11287 phyId = radio_index_to_phy(radioIndex);
developer72fb0bb2023-01-11 09:46:29 +080011288
developer40ba1762023-05-13 11:03:49 +080011289 snprintf(cmd, sizeof (cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | grep -v '%sno IR\\|5340\\|5480' | awk '{print $4}' | tr -d '[]'", phyId, dfs_enable?"":"radar\\|");
developer72fb0bb2023-01-11 09:46:29 +080011290
developer40ba1762023-05-13 11:03:49 +080011291 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
11292 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
11293 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +080011294 }
11295
developer40ba1762023-05-13 11:03:49 +080011296 ptr = channel_numbers_buf;
11297 i = 0;
11298 while (ptr = get_line_from_str_buf(ptr, line)) {
11299 if (i >= outputMapSize) {
11300 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
11301 return RETURN_ERR;
11302 }
11303 sscanf(line, "%d", &outputMap[i].ch_number);
11304
11305 memset(cmd, 0, sizeof(cmd));
11306 // Below command should fetch string for DFS state (usable, available or unavailable)
11307 // Example line: "DFS state: usable (for 78930 sec)"
11308 if (sprintf(cmd,"iw list | grep -A 2 '\\[%d\\]' | tr -d '\\t' | grep 'DFS state' | awk '{print $3}' | tr -d '\\n'", outputMap[i].ch_number) < 0) {
11309 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
developer72fb0bb2023-01-11 09:46:29 +080011310 return RETURN_ERR;
11311 }
11312
developer40ba1762023-05-13 11:03:49 +080011313 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
11314 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
developer72fb0bb2023-01-11 09:46:29 +080011315 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
11316 return RETURN_ERR;
11317 }
11318
developer40ba1762023-05-13 11:03:49 +080011319 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
developer72fb0bb2023-01-11 09:46:29 +080011320
developer40ba1762023-05-13 11:03:49 +080011321 if (!strcmp(dfs_state_buf, "usable")) {
11322 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
11323 } else if (!strcmp(dfs_state_buf, "available")) {
11324 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
11325 } else if (!strcmp(dfs_state_buf, "unavailable")) {
11326 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
11327 } else {
11328 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
developer72fb0bb2023-01-11 09:46:29 +080011329 }
developer40ba1762023-05-13 11:03:49 +080011330 i++;
developer72fb0bb2023-01-11 09:46:29 +080011331 }
11332
developer40ba1762023-05-13 11:03:49 +080011333 return RETURN_OK;
11334
developer72fb0bb2023-01-11 09:46:29 +080011335 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
11336 return RETURN_ERR;
11337}
11338
11339INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
11340{
11341 // TODO Implement me!
11342 return RETURN_ERR;
11343}
11344
11345INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
11346{
11347 return RETURN_OK;
11348}
11349
11350INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
11351{
11352 // TODO Implement me!
11353 return RETURN_ERR;
11354}
11355
11356INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
11357{
11358 // TODO API refrence Implementaion is present on RPI hal
11359 return RETURN_ERR;
11360}
11361
11362INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
11363{
developera1255e42023-05-13 17:45:02 +080011364/*
developer72fb0bb2023-01-11 09:46:29 +080011365 char interface_name[16] = {0};
11366 char cmd[128]={'\0'};
11367 char buf[128]={'\0'};
11368 char *support;
11369 int maximum_tx = 0, current_tx = 0;
developera1255e42023-05-13 17:45:02 +080011370*/ ULONG pwr_percentage = 0;
developer72fb0bb2023-01-11 09:46:29 +080011371
11372 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11373 if(txpwr_pcntg == NULL)
11374 return RETURN_ERR;
11375
developera1255e42023-05-13 17:45:02 +080011376 wifi_getRadioTransmitPower(apIndex, &pwr_percentage);
11377 *txpwr_pcntg = pwr_percentage;
11378/* if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72fb0bb2023-01-11 09:46:29 +080011379 return RETURN_ERR;
11380
11381 // Get the maximum tx power of the device
11382 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", interface_name);
11383 _syscmd(cmd, buf, sizeof(buf));
11384 maximum_tx = strtol(buf, NULL, 10);
11385
11386 // Get the current tx power
11387 memset(cmd, 0, sizeof(cmd));
11388 memset(buf, 0, sizeof(buf));
11389 snprintf(cmd, sizeof(cmd), "iw %s info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", interface_name);
11390 _syscmd(cmd, buf, sizeof(buf));
11391 current_tx = strtol(buf, NULL, 10);
11392
11393 // Get the power supported list and find the current power percentage in supported list
11394 memset(buf, 0, sizeof(buf));
11395 wifi_getRadioTransmitPowerSupported(apIndex, buf);
11396 support = strtok(buf, ",");
11397 while(true)
11398 {
11399 if(support == NULL) { // current power is not in supported list, this should not happen if the power is set by hal.
11400 *txpwr_pcntg = 100;
11401 wifi_dbg_printf("current power is not in supported list\n");
11402 return RETURN_OK;
11403 }
11404 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
11405 if (tmp == current_tx) {
11406 *txpwr_pcntg = strtol(support, NULL, 10);
11407 break;
11408 }
11409 support = strtok(NULL, ",");
11410 }
developera1255e42023-05-13 17:45:02 +080011411*/
developer72fb0bb2023-01-11 09:46:29 +080011412 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11413 return RETURN_OK;
11414}
11415
11416INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
11417{
11418 // TODO precac feature.
11419 struct params params = {0};
11420 char config_file[128] = {0};
11421
11422 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11423
11424 params.name = "enable_background_radar";
11425 params.value = enable?"1":"0";
11426 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
11427 wifi_hostapdWrite(config_file, &params, 1);
11428 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
11429
11430 /* TODO precac feature */
11431
11432 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11433 return RETURN_OK;
11434}
11435
11436INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
11437{
11438 char config_file[128] = {0};
11439 char buf[64] = {0};
11440
11441 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11442 if (NULL == enable || NULL == precac)
11443 return RETURN_ERR;
11444
11445 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
11446 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
11447 if (strncmp(enable, "1", 1) == 0)
11448 *enable = true;
11449 else
11450 *enable = false;
11451
11452 /* TODO precac feature */
11453
11454 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11455 return RETURN_OK;
11456}
11457
11458INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
11459{
11460 *supported = TRUE;
11461 return RETURN_OK;
11462}
11463
11464INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
11465{
developera1255e42023-05-13 17:45:02 +080011466 UCHAR dat_file[64] = {0};
11467 wifi_band band = band_invalid;
11468 char cmd[128] = {0};
11469 char buf[256] = {0};
11470 char ofdmabuf[32] = {'\0'};
11471 char mimobuf[32] = {'\0'};
11472 char new_ofdmabuf[32] = {'\0'};
11473 char new_mimobuf[32] = {'\0'};
11474 struct params params[2];
11475 char *str_zero = "0;0;0;0;0;0;0;0;0;0;0;0;0;0;0";/*default 15bss per band.*/
11476 char *str_one = "1;1;1;1;1;1;1;1;1;1;1;1;1;1;1";
11477 UCHAR bss_cnt = 0;
11478 UCHAR val_cnt = 0;
11479 char *token = NULL;
developer72fb0bb2023-01-11 09:46:29 +080011480
developera1255e42023-05-13 17:45:02 +080011481 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11482 if ((mu_type < WIFI_DL_MU_TYPE_NONE)
11483 || (mu_type > WIFI_DL_MU_TYPE_OFDMA_MIMO)) {
11484 printf("%s:mu_type input Error", __func__);
11485 return RETURN_ERR;
11486 }
11487 band = wifi_index_to_band(radio_index);
11488 if (band == band_invalid) {
11489 printf("%s:Band Error\n", __func__);
11490 return RETURN_ERR;
11491 }
11492 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
11493 /*get current value in dat file*/
11494 wifi_datfileRead(dat_file, "MuOfdmaDlEnable", ofdmabuf, sizeof(ofdmabuf));
11495 wifi_datfileRead(dat_file, "MuMimoDlEnable", mimobuf, sizeof(mimobuf));
11496 WIFI_ENTRY_EXIT_DEBUG("%s:ofdma-%s, mimo-%s\n", __func__, ofdmabuf, mimobuf);
11497 get_bssnum_byindex(radio_index, &bss_cnt);
11498 val_cnt = 2*bss_cnt - 1;
11499 WIFI_ENTRY_EXIT_DEBUG("bss number: %d\n", bss_cnt);
11500 if ((val_cnt >= sizeof(new_ofdmabuf))
11501 || (val_cnt >= sizeof(new_mimobuf))) {
11502 printf("%s:bss cnt Error", __func__, bss_cnt);
11503 return RETURN_ERR;
11504 }
11505 /*translate set value*/
11506 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
11507 strncpy(new_ofdmabuf, str_zero, val_cnt);
11508 strncpy(new_mimobuf, str_zero, val_cnt);
developer72fb0bb2023-01-11 09:46:29 +080011509 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
developera1255e42023-05-13 17:45:02 +080011510 strncpy(new_ofdmabuf, str_one, val_cnt);
11511 strncpy(new_mimobuf, str_zero, val_cnt);
developer72fb0bb2023-01-11 09:46:29 +080011512 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
developera1255e42023-05-13 17:45:02 +080011513 strncpy(new_ofdmabuf, str_zero, val_cnt);
11514 strncpy(new_mimobuf, str_one, val_cnt);
11515 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO) {
11516 strncpy(new_ofdmabuf, str_one, val_cnt);
11517 strncpy(new_mimobuf, str_one, val_cnt);
developer72fb0bb2023-01-11 09:46:29 +080011518 }
developera1255e42023-05-13 17:45:02 +080011519 WIFI_ENTRY_EXIT_DEBUG("%s:new_ofdmabuf-%s, new_mimobuf-%s\n", __func__, new_ofdmabuf, new_mimobuf);
11520 /*same value, not operation*/
11521 if ((strncmp(new_mimobuf, mimobuf, 1) ==0)
11522 && (strncmp(new_ofdmabuf, ofdmabuf, 1) ==0)) {
11523 printf("%s:Reduntant value\n", __func__);
11524 return RETURN_OK;
11525 }
11526 /*modify dat file to new file*/
11527 params[0].name="MuOfdmaDlEnable";
11528 params[0].value=new_ofdmabuf;
11529 params[1].name="MuMimoDlEnable";
11530 params[1].value=new_mimobuf;
11531 wifi_datfileWrite(dat_file, params, 2);
11532 /*hostapd control restarp ap to take effect on these new value*/
11533 wifi_reloadAp(radio_index);
developer72fb0bb2023-01-11 09:46:29 +080011534 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11535 return RETURN_OK;
11536}
11537
11538INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
11539{
11540 struct params params={0};
11541 char config_file[64] = {0};
11542 char buf[64] = {0};
11543 unsigned int get_mu_type = 0;
developera1255e42023-05-13 17:45:02 +080011544 UCHAR dat_file[64] = {0};
11545 wifi_band band = band_invalid;
11546 char ofdmabuf[32] = {'\0'};
11547 char mimobuf[32] = {'\0'};
11548 char *token = NULL;
11549 UCHAR ofdma = 0;
11550 UCHAR mimo = 0;
developer72fb0bb2023-01-11 09:46:29 +080011551
11552 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11553
11554 if (mu_type == NULL)
11555 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +080011556 band = wifi_index_to_band(radio_index);
11557 if (band == band_invalid) {
11558 printf("%s:Band Error\n", __func__);
11559 return RETURN_ERR;
11560 }
11561 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
11562 /*get current value in dat file*/
11563 wifi_datfileRead(dat_file, "MuOfdmaDlEnable", ofdmabuf, sizeof(ofdmabuf));
11564 wifi_datfileRead(dat_file, "MuMimoDlEnable", mimobuf, sizeof(mimobuf));
developer72fb0bb2023-01-11 09:46:29 +080011565
developera1255e42023-05-13 17:45:02 +080011566 token = strtok(ofdmabuf, ";");
11567 ofdma = strtol(token, NULL, 10);
11568 token = strtok(mimobuf, ";");
11569 mimo = strtol(token, NULL, 10);
11570 WIFI_ENTRY_EXIT_DEBUG("%s:ofdma=%d,mimo=%d\n", __func__, ofdma, mimo);
11571 if ((ofdma == 1) && (mimo == 1))
11572 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
11573 else if ((ofdma == 0) && (mimo == 1))
11574 *mu_type = WIFI_DL_MU_TYPE_MIMO;
11575 else if ((ofdma == 1) && (mimo == 0))
11576 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11577 else
11578 *mu_type = WIFI_DL_MU_TYPE_NONE;
developer72fb0bb2023-01-11 09:46:29 +080011579 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11580 return RETURN_OK;
11581}
11582
11583INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
11584{
11585 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
developera1255e42023-05-13 17:45:02 +080011586 UCHAR dat_file[64] = {0};
11587 wifi_band band = band_invalid;
11588 char cmd[128] = {0};
11589 char buf[256] = {0};
11590 char ofdmabuf[32] = {'\0'};
11591 char mimobuf[32] = {'\0'};
11592 char new_ofdmabuf[32] = {'\0'};
11593 char new_mimobuf[32] = {'\0'};
11594 struct params params[2];
11595 char *str_zero = "0;0;0;0;0;0;0;0;0;0;0;0;0;0;0";/*default 15bss per band.*/
11596 char *str_one = "1;1;1;1;1;1;1;1;1;1;1;1;1;1;1";
11597 UCHAR bss_cnt = 0;
11598 UCHAR val_cnt = 0;
developer72fb0bb2023-01-11 09:46:29 +080011599
developera1255e42023-05-13 17:45:02 +080011600 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11601 band = wifi_index_to_band(radio_index);
11602 if (band == band_invalid) {
11603 printf("%s:Band Error\n", __func__);
11604 return RETURN_ERR;
11605 }
11606 if ((mu_type < WIFI_UL_MU_TYPE_NONE)
11607 || (mu_type > WIFI_UL_MU_TYPE_OFDMA)) {
11608 printf("%s:mu_type input Error\n", __func__);
11609 return RETURN_ERR;
11610 }
11611 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
11612 /*get current value in dat file*/
11613 wifi_datfileRead(dat_file, "MuOfdmaUlEnable", ofdmabuf, sizeof(ofdmabuf));
11614 wifi_datfileRead(dat_file, "MuMimoUlEnable", mimobuf, sizeof(mimobuf));
11615 WIFI_ENTRY_EXIT_DEBUG("%s:ofdma-%s, mimo-%s\n", __func__, ofdmabuf, mimobuf);
11616 get_bssnum_byindex(radio_index, &bss_cnt);
11617 val_cnt = 2*bss_cnt - 1;
11618 printf("bssNumber:%d,ValCnt:%d\n", bss_cnt, val_cnt);
11619 if ((val_cnt >= sizeof(new_ofdmabuf))
11620 || (val_cnt >= sizeof(new_mimobuf))) {
11621 printf("%s:bss cnt Error\n", __func__, val_cnt);
11622 return RETURN_ERR;
11623 }
11624 /*translate set value*/
11625 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
11626 strncpy(new_ofdmabuf, str_zero, val_cnt);
11627 strncpy(new_mimobuf, str_zero, val_cnt);
developer72fb0bb2023-01-11 09:46:29 +080011628 }
developera1255e42023-05-13 17:45:02 +080011629 if (mu_type == WIFI_UL_MU_TYPE_OFDMA) {
11630 strncpy(new_ofdmabuf, str_one, val_cnt);
11631 strncpy(new_mimobuf, str_zero, val_cnt);
11632 }
11633 printf("%s:new_ofdmabuf-%s, new_mimobuf-%s\n", __func__, new_ofdmabuf, new_mimobuf);
11634 /*same value, not operation*/
11635 if ((strncmp(new_mimobuf, mimobuf, 1) ==0)
11636 && (strncmp(new_ofdmabuf, ofdmabuf, 1) ==0)) {
11637 printf("%s:Reduntant value\n", __func__);
11638 return RETURN_OK;
11639 }
11640 /*modify dat file to new file*/
11641 params[0].name="MuOfdmaUlEnable";
11642 params[0].value=new_ofdmabuf;
11643 params[1].name="MuMimoUlEnable";
11644 params[1].value=new_mimobuf;
11645 wifi_datfileWrite(dat_file, params, 2);
11646 wifi_reloadAp(radio_index);
developer72fb0bb2023-01-11 09:46:29 +080011647 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11648 return RETURN_OK;
11649}
11650
11651INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
11652{
11653 struct params params={0};
11654 char config_file[64] = {0};
11655 char buf[64] = {0};
11656 unsigned int get_mu_type = 0;
developera1255e42023-05-13 17:45:02 +080011657 UCHAR dat_file[64] = {0};
11658 wifi_band band = band_invalid;
11659 char ofdmabuf[32] = {'\0'};
11660 char mimobuf[32] = {'\0'};
11661 char *token = NULL;
11662 UCHAR ofdma = 0;
11663 UCHAR mimo = 0;
developer72fb0bb2023-01-11 09:46:29 +080011664
11665 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11666
11667 if (mu_type == NULL)
11668 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +080011669 band = wifi_index_to_band(radio_index);
11670 if (band == band_invalid) {
11671 printf("%s:Band Error", __func__);
11672 return RETURN_ERR;
11673 }
11674 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
11675 /*get current value in dat file*/
11676 wifi_datfileRead(dat_file, "MuOfdmaUlEnable", ofdmabuf, sizeof(ofdmabuf));
11677 wifi_datfileRead(dat_file, "MuMimoUlEnable", mimobuf, sizeof(mimobuf));
developer72fb0bb2023-01-11 09:46:29 +080011678
developera1255e42023-05-13 17:45:02 +080011679 token = strtok(ofdmabuf, ";");
11680 ofdma = strtol(token, NULL, 10);
11681 token = strtok(mimobuf, ";");
11682 mimo = strtol(token, NULL, 10);
11683 WIFI_ENTRY_EXIT_DEBUG("%s:ofdma=%d, mimo=%d\n", __func__, ofdma, mimo);
11684 if ((ofdma == 1) && (mimo == 0))
11685 *mu_type = WIFI_UL_MU_TYPE_OFDMA;
11686 else
11687 *mu_type = WIFI_UL_MU_TYPE_NONE;
developer72fb0bb2023-01-11 09:46:29 +080011688 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11689 return RETURN_OK;
11690}
11691
11692
11693INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
11694{
11695 char cmd[128] = {0};
11696 char buf[256] = {0};
11697 char config_file[64] = {0};
11698 char GI[8] = {0};
11699 int mode_map = 0;
11700 FILE *f = NULL;
11701 wifi_band band = band_invalid;
developera1255e42023-05-13 17:45:02 +080011702 char dat_file[64] = {'\0'};
11703 struct params params[3];
developer72fb0bb2023-01-11 09:46:29 +080011704
11705 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11706
11707 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
11708 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
11709 return RETURN_ERR;
11710 }
developera1255e42023-05-13 17:45:02 +080011711 /*sanity check*/
11712 if (((guard_interval == wifi_guard_interval_1600)
11713 || (guard_interval == wifi_guard_interval_3200))
11714 && (mode_map & (WIFI_MODE_BE | WIFI_MODE_AX) == 0)) {
11715 wifi_dbg_printf("%s: N/AC Mode not support 1600/3200ns GI\n", __func__);
11716 return RETURN_ERR;
11717 }
developer72fb0bb2023-01-11 09:46:29 +080011718 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
11719 band = wifi_index_to_band(radio_index);
11720
11721 // Hostapd are not supported HE mode GI 1600, 3200 ns.
11722 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
11723 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
11724 _syscmd(cmd, buf, sizeof(buf));
11725 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
11726 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
11727 if (strstr(buf, "[SHORT-GI-") == NULL) {
11728 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[SHORT-GI-20][SHORT-GI-40]/' %s", config_file);
11729 _syscmd(cmd, buf, sizeof(buf));
11730 }
11731 if (band == band_5) {
11732 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
11733 if (strstr(buf, "[SHORT-GI-") == NULL) {
11734 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SHORT-GI-80][SHORT-GI-160]/' %s", config_file);
11735 _syscmd(cmd, buf, sizeof(buf));
11736 }
11737 }
11738 }
developera1255e42023-05-13 17:45:02 +080011739 /*wifi_reloadAp(radio_index);
11740 caller "wifi_setRadioOperatingParameters" have done this step.
11741 */
11742 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
11743 if (guard_interval == wifi_guard_interval_400) {
11744 params[0].name = "HT_GI";
11745 params[0].value = "1";
11746 params[1].name = "VHT_SGI";
11747 params[1].value = "1";
11748 wifi_datfileWrite(dat_file, params, 2);
developer72fb0bb2023-01-11 09:46:29 +080011749 strcpy(GI, "0.4");
developera1255e42023-05-13 17:45:02 +080011750 } else {
11751 params[0].name = "HT_GI";
11752 params[0].value = "0";
11753 params[1].name = "VHT_SGI";
11754 params[1].value = "0";
11755 /*should enable FIXED_HE_GI_SUPPORT in driver*/
11756 params[2].name = "FgiFltf";
11757 if (guard_interval == wifi_guard_interval_800) {
11758 params[2].value = "800";
11759 strcpy(GI, "0.8");
11760 } else if (guard_interval == wifi_guard_interval_1600) {
11761 params[2].value = "1600";
11762 strcpy(GI, "1.6");
11763 } else if (guard_interval == wifi_guard_interval_3200) {
11764 params[2].value = "3200";
11765 strcpy(GI, "3.2");
11766 } else if (guard_interval == wifi_guard_interval_auto) {
11767 params[2].value = "0";
11768 strcpy(GI, "auto");
11769 }
11770 wifi_datfileWrite(dat_file, params, 3);
11771 }
developer72fb0bb2023-01-11 09:46:29 +080011772 // Record GI for get GI function
11773 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11774 f = fopen(buf, "w");
11775 if (f == NULL)
11776 return RETURN_ERR;
11777 fprintf(f, "%s", GI);
11778 fclose(f);
11779 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11780 return RETURN_OK;
11781}
11782
11783INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
11784{
11785 char buf[32] = {0};
11786 char cmd[64] = {0};
11787
11788 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11789
11790 if (guard_interval == NULL)
11791 return RETURN_ERR;
11792
developera1255e42023-05-13 17:45:02 +080011793 snprintf(cmd, sizeof(cmd), "cat %s%d.txt 2> /dev/null", GUARD_INTERVAL_FILE, radio_index);
developer72fb0bb2023-01-11 09:46:29 +080011794 _syscmd(cmd, buf, sizeof(buf));
11795
11796 if (strncmp(buf, "0.4", 3) == 0)
11797 *guard_interval = wifi_guard_interval_400;
11798 else if (strncmp(buf, "0.8", 3) == 0)
11799 *guard_interval = wifi_guard_interval_800;
11800 else if (strncmp(buf, "1.6", 3) == 0)
11801 *guard_interval = wifi_guard_interval_1600;
11802 else if (strncmp(buf, "3.2", 3) == 0)
11803 *guard_interval = wifi_guard_interval_3200;
11804 else
11805 *guard_interval = wifi_guard_interval_auto;
11806
11807 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11808 return RETURN_OK;
11809}
11810
11811INT wifi_setBSSColor(INT radio_index, UCHAR color)
11812{
11813 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11814 struct params params = {0};
11815 char config_file[128] = {0};
11816 char bss_color[4] ={0};
11817
developera1255e42023-05-13 17:45:02 +080011818 if (color < 1 || color > 63) {
11819 wifi_dbg_printf("color value is err:%d.\n", color);
11820 return RETURN_ERR;
11821 }
developer72fb0bb2023-01-11 09:46:29 +080011822 params.name = "he_bss_color";
11823 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
11824 params.value = bss_color;
11825 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11826 wifi_hostapdWrite(config_file, &params, 1);
developera1255e42023-05-13 17:45:02 +080011827 //wifi_hostapdProcessUpdate(radio_index, &params, 1);
11828 wifi_reloadAp(radio_index);
developer69b61b02023-03-07 17:17:44 +080011829
developer72fb0bb2023-01-11 09:46:29 +080011830 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11831 return RETURN_OK;
11832}
11833
11834INT wifi_getBSSColor(INT radio_index, UCHAR *color)
11835{
11836 char config_file[128] = {0};
11837 char buf[64] = {0};
11838 char temp_output[128] = {'\0'};
11839
11840 wifi_dbg_printf("\nFunc=%s\n", __func__);
11841 if (NULL == color)
11842 return RETURN_ERR;
11843
11844 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11845 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
11846
11847 if(strlen(buf) > 0) {
11848 snprintf(temp_output, sizeof(temp_output), "%s", buf);
11849 } else {
11850 snprintf(temp_output, sizeof(temp_output), "1"); // default value
11851 }
11852
11853 *color = (UCHAR)strtoul(temp_output, NULL, 10);
11854 wifi_dbg_printf("\noutput_string=%s\n", color);
11855
11856 return RETURN_OK;
11857}
11858
11859/* multi-psk support */
11860INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
11861{
11862 char cmd[256];
11863 char interface_name[16] = {0};
11864
11865 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
11866 return RETURN_ERR;
11867
11868 sprintf(cmd, "hostapd_cli -i %s sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
11869 interface_name,
11870 mac[0],
11871 mac[1],
11872 mac[2],
11873 mac[3],
11874 mac[4],
11875 mac[5]
11876 );
11877 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
11878 _syscmd(cmd, key->wifi_keyId, 64);
11879
11880
11881 return RETURN_OK;
11882}
11883
11884INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11885{
11886 char interface_name[16] = {0};
11887 FILE *fd = NULL;
11888 char fname[100];
11889 char cmd[128] = {0};
11890 char out[64] = {0};
11891 wifi_key_multi_psk_t * key = NULL;
11892 if(keysNumber < 0)
11893 return RETURN_ERR;
11894
11895 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
11896 fd = fopen(fname, "w");
11897 if (!fd) {
11898 return RETURN_ERR;
11899 }
11900 key= (wifi_key_multi_psk_t *) keys;
11901 for(int i=0; i<keysNumber; ++i, key++) {
11902 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
11903 }
11904 fclose(fd);
11905
11906 //reload file
11907 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
11908 return RETURN_ERR;
11909 sprintf(cmd, "hostapd_cli -i%s raw RELOAD_WPA_PSK", interface_name);
11910 _syscmd(cmd, out, 64);
11911 return RETURN_OK;
11912}
11913
11914INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11915{
11916 FILE *fd = NULL;
11917 char fname[100];
11918 char * line = NULL;
11919 char * pos = NULL;
11920 size_t len = 0;
11921 ssize_t read = 0;
11922 INT ret = RETURN_OK;
11923 wifi_key_multi_psk_t *keys_it = NULL;
11924
11925 if (keysNumber < 1) {
11926 return RETURN_ERR;
11927 }
11928
11929 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
11930 fd = fopen(fname, "r");
11931 if (!fd) {
11932 return RETURN_ERR;
11933 }
11934
11935 if (keys == NULL) {
11936 ret = RETURN_ERR;
11937 goto close;
11938 }
11939
11940 keys_it = keys;
11941 while ((read = getline(&line, &len, fd)) != -1) {
11942 //Strip trailing new line if present
11943 if (read > 0 && line[read-1] == '\n') {
11944 line[read-1] = '\0';
11945 }
11946
11947 if(strcmp(line,"keyid=")) {
11948 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
11949 if (!(pos = index(line, ' '))) {
11950 ret = RETURN_ERR;
11951 goto close;
11952 }
11953 pos++;
11954 //Here should be 00:00:00:00:00:00
11955 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
11956 printf("Not supported MAC: %s\n", pos);
11957 }
11958 if (!(pos = index(pos, ' '))) {
11959 ret = RETURN_ERR;
11960 goto close;
11961 }
11962 pos++;
11963
11964 //The rest is PSK
11965 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
11966 keys_it++;
11967
11968 if(--keysNumber <= 0)
11969 break;
11970 }
11971 }
11972
11973close:
11974 free(line);
11975 fclose(fd);
11976 return ret;
11977}
11978/* end of multi-psk support */
11979
11980INT wifi_setNeighborReports(UINT apIndex,
11981 UINT numNeighborReports,
11982 wifi_NeighborReport_t *neighborReports)
11983{
11984 char cmd[256] = { 0 };
11985 char hex_bssid[13] = { 0 };
11986 char bssid[18] = { 0 };
11987 char nr[256] = { 0 };
11988 char ssid[256];
11989 char hex_ssid[256];
11990 char interface_name[16] = {0};
11991 INT ret;
11992
11993 /*rmeove all neighbors*/
11994 wifi_dbg_printf("\n[%s]: removing all neighbors from %s\n", __func__, interface_name);
11995 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
11996 return RETURN_ERR;
11997 sprintf(cmd, "hostapd_cli show_neighbor -i %s | awk '{print $1 \" \" $2}' | xargs -n2 -r hostapd_cli remove_neighbor -i %s",interface_name,interface_name);
11998 system(cmd);
11999
12000 for(unsigned int i = 0; i < numNeighborReports; i++)
12001 {
12002 memset(ssid, 0, sizeof(ssid));
12003 ret = wifi_getSSIDName(apIndex, ssid);
12004 if (ret != RETURN_OK)
12005 return RETURN_ERR;
12006
12007 memset(hex_ssid, 0, sizeof(hex_ssid));
12008 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
12009 sprintf(hex_ssid + k,"%02x", ssid[j]);
12010
12011 snprintf(hex_bssid, sizeof(hex_bssid),
12012 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
12013 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
12014 snprintf(bssid, sizeof(bssid),
12015 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
12016 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
12017
12018 snprintf(nr, sizeof(nr),
12019 "%s" // bssid
12020 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
12021 "%02hhx" // operclass
12022 "%02hhx" // channel
12023 "%02hhx", // phy_mode
12024 hex_bssid,
12025 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
12026 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
12027 neighborReports[i].opClass,
12028 neighborReports[i].channel,
12029 neighborReports[i].phyTable);
12030
12031 snprintf(cmd, sizeof(cmd),
12032 "hostapd_cli set_neighbor "
12033 "%s " // bssid
12034 "ssid=%s " // ssid
12035 "nr=%s " // nr
12036 "-i %s",
12037 bssid,hex_ssid,nr, interface_name);
12038
12039 if (WEXITSTATUS(system(cmd)) != 0)
12040 {
12041 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
12042 }
12043 }
12044
12045 return RETURN_OK;
12046}
12047
12048INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
12049{
12050 return RETURN_OK;
12051}
12052
12053#ifdef _WIFI_HAL_TEST_
12054int main(int argc,char **argv)
12055{
12056 int index;
12057 INT ret=0;
12058 char buf[1024]="";
12059
12060 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12061 if(argc<3)
12062 {
12063 if(argc==2)
12064 {
12065 if(!strcmp(argv[1], "init"))
12066 return wifi_init();
12067 if(!strcmp(argv[1], "reset"))
12068 return wifi_reset();
12069 if(!strcmp(argv[1], "wifi_getHalVersion"))
12070 {
12071 char buffer[64];
12072 if(wifi_getHalVersion(buffer)==RETURN_OK)
12073 printf("Version: %s\n", buffer);
12074 else
12075 printf("Error in wifi_getHalVersion\n");
12076 return RETURN_OK;
12077 }
12078 }
12079 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
12080 exit(-1);
12081 }
12082
12083 index = atoi(argv[2]);
12084 if(strstr(argv[1], "wifi_getApName")!=NULL)
12085 {
12086 wifi_getApName(index,buf);
12087 printf("Ap name is %s \n",buf);
12088 return 0;
12089 }
12090 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
12091 {
12092 BOOL b = FALSE;
12093 BOOL *output_bool = &b;
12094 wifi_getRadioAutoChannelEnable(index,output_bool);
12095 printf("Channel enabled = %d \n",b);
12096 return 0;
12097 }
12098 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
12099 {
12100 wifi_getApWpaEncryptionMode(index,buf);
12101 printf("encryption enabled = %s\n",buf);
12102 return 0;
12103 }
12104 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
12105 {
12106 BOOL b = FALSE;
12107 BOOL *output_bool = &b;
12108 wifi_getApSsidAdvertisementEnable(index,output_bool);
12109 printf("advertisment enabled = %d\n",b);
12110 return 0;
12111 }
12112 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
12113 {
12114 if(argc <= 3 )
12115 {
12116 printf("Insufficient arguments \n");
12117 exit(-1);
12118 }
12119
12120 char sta[20] = {'\0'};
12121 ULLONG handle= 0;
12122 strcpy(sta,argv[3]);
12123 mac_address_t st;
12124 mac_addr_aton(st,sta);
12125
12126 wifi_associated_dev_tid_stats_t tid_stats;
12127 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
12128 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
12129 printf(" tid=%d \t ac=%d \t num_msdus=%lld \n" ,tid_stats.tid_array[tid_index].tid,tid_stats.tid_array[tid_index].ac,tid_stats.tid_array[tid_index].num_msdus);
12130 }
12131
12132 if(strstr(argv[1], "getApEnable")!=NULL) {
12133 BOOL enable;
12134 ret=wifi_getApEnable(index, &enable);
12135 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
12136 }
12137 else if(strstr(argv[1], "setApEnable")!=NULL) {
12138 BOOL enable = atoi(argv[3]);
12139 ret=wifi_setApEnable(index, enable);
12140 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
12141 }
12142 else if(strstr(argv[1], "getApStatus")!=NULL) {
developer69b61b02023-03-07 17:17:44 +080012143 char status[64];
developer72fb0bb2023-01-11 09:46:29 +080012144 ret=wifi_getApStatus(index, status);
12145 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
12146 }
12147 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
12148 {
12149 wifi_getSSIDNameStatus(index,buf);
12150 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
12151 return 0;
12152 }
12153 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
12154 wifi_ssidTrafficStats2_t stats={0};
12155 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
12156 printf("%s %d: returns %d\n", argv[1], index, ret);
12157 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
12158 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
12159 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
12160 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
12161 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
12162 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
12163 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
12164 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
12165 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
12166 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
12167 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
12168 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
12169 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
12170 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
12171 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
12172 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
12173 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
12174 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
12175 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
12176 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
12177 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
12178 }
12179 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
12180 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
12181 UINT array_size=0;
12182 UINT i=0;
12183 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
12184 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
developer69b61b02023-03-07 17:17:44 +080012185 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
developer72fb0bb2023-01-11 09:46:29 +080012186 printf(" neighbor %d:\n", i);
12187 printf(" ap_SSID =%s\n", pt->ap_SSID);
12188 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
12189 printf(" ap_Mode =%s\n", pt->ap_Mode);
12190 printf(" ap_Channel =%d\n", pt->ap_Channel);
12191 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
12192 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
12193 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
12194 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
12195 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
12196 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
12197 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
12198 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
12199 printf(" ap_Noise =%d\n", pt->ap_Noise);
12200 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
12201 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
12202 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
developer69b61b02023-03-07 17:17:44 +080012203 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
developer72fb0bb2023-01-11 09:46:29 +080012204 }
12205 if(neighbor_ap_array)
12206 free(neighbor_ap_array); //make sure to free the list
12207 }
12208 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
12209 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
12210 UINT array_size=0;
12211 UINT i=0;
12212 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
12213 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
developer69b61b02023-03-07 17:17:44 +080012214 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
developer72fb0bb2023-01-11 09:46:29 +080012215 printf(" associated_dev %d:\n", i);
12216 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
12217 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
12218 printf(" cli_SNR =%d\n", pt->cli_SNR);
12219 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
12220 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
12221 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
12222 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
12223 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
12224 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
12225 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
12226 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
12227 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
12228 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
12229 }
12230 if(associated_dev_array)
12231 free(associated_dev_array); //make sure to free the list
12232 }
12233
12234 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
12235 {
12236#define MAX_ARRAY_SIZE 64
12237 int i, array_size;
12238 char *p, *ch_str;
12239 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
12240
12241 if(argc != 5)
12242 {
12243 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
12244 exit(-1);
12245 }
12246 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
12247
12248 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
12249 {
12250 strtok_r(ch_str, ",", &p);
12251 input_output_channelStats_array[i].ch_number = atoi(ch_str);
12252 }
12253 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
12254 if(!array_size)
12255 array_size=1;//Need to print current channel statistics
12256 for(i=0; i<array_size; i++)
12257 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
12258 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
12259 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
12260 input_output_channelStats_array[i].ch_number,\
12261 input_output_channelStats_array[i].ch_noise,\
12262 input_output_channelStats_array[i].ch_utilization_busy_rx,\
12263 input_output_channelStats_array[i].ch_utilization_busy_tx,\
12264 input_output_channelStats_array[i].ch_utilization_busy,\
12265 input_output_channelStats_array[i].ch_utilization_busy_ext,\
12266 input_output_channelStats_array[i].ch_utilization_total);
12267 }
12268
12269 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
12270 {
12271 if(argc <= 3 )
12272 {
12273 printf("Insufficient arguments \n");
12274 exit(-1);
12275 }
12276 char mac_addr[20] = {'\0'};
12277 wifi_device_t output_struct;
12278 int dev_index = atoi(argv[3]);
12279
12280 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
12281 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
12282 printf("wifi_devMacAddress=%s \t wifi_devAssociatedDeviceAuthentiationState=%d \t, wifi_devSignalStrength=%d \t,wifi_devTxRate=%d \t, wifi_devRxRate =%d \t\n ", mac_addr,output_struct.wifi_devAssociatedDeviceAuthentiationState,output_struct.wifi_devSignalStrength,output_struct.wifi_devTxRate,output_struct.wifi_devRxRate);
12283 }
12284
12285 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
12286 {
12287 if (argc <= 3)
12288 {
12289 printf("Insufficient arguments\n");
12290 exit(-1);
12291 }
12292 char args[256];
12293 wifi_NeighborReport_t *neighborReports;
12294
12295 neighborReports = calloc(argc - 2, sizeof(neighborReports));
12296 if (!neighborReports)
12297 {
12298 printf("Failed to allocate memory");
12299 exit(-1);
12300 }
12301
12302 for (int i = 3; i < argc; ++i)
12303 {
12304 char *val;
12305 int j = 0;
12306 memset(args, 0, sizeof(args));
12307 strncpy(args, argv[i], sizeof(args));
12308 val = strtok(args, ";");
12309 while (val != NULL)
12310 {
12311 if (j == 0)
12312 {
12313 mac_addr_aton(neighborReports[i - 3].bssid, val);
12314 } else if (j == 1)
12315 {
12316 neighborReports[i - 3].info = strtol(val, NULL, 16);
12317 } else if (j == 2)
12318 {
12319 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
12320 } else if (j == 3)
12321 {
12322 neighborReports[i - 3].channel = strtol(val, NULL, 16);
12323 } else if (j == 4)
12324 {
12325 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
12326 } else {
12327 printf("Insufficient arguments]n\n");
12328 exit(-1);
12329 }
12330 val = strtok(NULL, ";");
12331 j++;
12332 }
12333 }
12334
12335 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
12336 if (ret != RETURN_OK)
12337 {
12338 printf("wifi_setNeighborReports ret = %d", ret);
12339 exit(-1);
12340 }
12341 }
12342 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
12343 {
12344 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
12345 printf("%s.\n", buf);
12346 else
12347 printf("Error returned\n");
12348 }
12349 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
12350 {
12351 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
12352 printf("%s.\n", buf);
12353 else
12354 printf("Error returned\n");
12355 }
12356 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
12357 {
12358 if (argc <= 2)
12359 {
12360 printf("Insufficient arguments\n");
12361 exit(-1);
12362 }
12363 char buf[64]= {'\0'};
12364 wifi_getRadioOperatingChannelBandwidth(index,buf);
12365 printf("Current bandwidth is %s \n",buf);
12366 return 0;
12367 }
12368 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
12369 {
12370 if (argc <= 5)
12371 {
12372 printf("Insufficient arguments\n");
12373 exit(-1);
12374 }
12375 UINT channel = atoi(argv[3]);
12376 UINT width = atoi(argv[4]);
12377 UINT beacon = atoi(argv[5]);
12378 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
12379 printf("Result = %d", ret);
12380 }
12381
12382 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12383 return 0;
12384}
12385
12386#endif
12387
12388#ifdef WIFI_HAL_VERSION_3
12389
12390INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
12391{
12392 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12393 if (bitMap & WIFI_BITRATE_1MBPS)
12394 strcat(BasicRate, "1,");
12395 if (bitMap & WIFI_BITRATE_2MBPS)
12396 strcat(BasicRate, "2,");
12397 if (bitMap & WIFI_BITRATE_5_5MBPS)
12398 strcat(BasicRate, "5.5,");
12399 if (bitMap & WIFI_BITRATE_6MBPS)
12400 strcat(BasicRate, "6,");
12401 if (bitMap & WIFI_BITRATE_9MBPS)
12402 strcat(BasicRate, "9,");
12403 if (bitMap & WIFI_BITRATE_11MBPS)
12404 strcat(BasicRate, "11,");
12405 if (bitMap & WIFI_BITRATE_12MBPS)
12406 strcat(BasicRate, "12,");
12407 if (bitMap & WIFI_BITRATE_18MBPS)
12408 strcat(BasicRate, "18,");
12409 if (bitMap & WIFI_BITRATE_24MBPS)
12410 strcat(BasicRate, "24,");
12411 if (bitMap & WIFI_BITRATE_36MBPS)
12412 strcat(BasicRate, "36,");
12413 if (bitMap & WIFI_BITRATE_48MBPS)
12414 strcat(BasicRate, "48,");
12415 if (bitMap & WIFI_BITRATE_54MBPS)
12416 strcat(BasicRate, "54,");
12417 if (strlen(BasicRate) != 0) // remove last comma
12418 BasicRate[strlen(BasicRate) - 1] = '\0';
12419 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12420 return RETURN_OK;
12421}
12422
12423INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
12424{
12425 UINT BitMap = 0;
12426 char *rate;
12427
12428 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12429 rate = strtok(BasicRatesList, ",");
12430 while(rate != NULL)
12431 {
12432 if (strcmp(rate, "1") == 0)
12433 BitMap |= WIFI_BITRATE_1MBPS;
12434 else if (strcmp(rate, "2") == 0)
12435 BitMap |= WIFI_BITRATE_2MBPS;
12436 else if (strcmp(rate, "5.5") == 0)
12437 BitMap |= WIFI_BITRATE_5_5MBPS;
12438 else if (strcmp(rate, "6") == 0)
12439 BitMap |= WIFI_BITRATE_6MBPS;
12440 else if (strcmp(rate, "9") == 0)
12441 BitMap |= WIFI_BITRATE_9MBPS;
12442 else if (strcmp(rate, "11") == 0)
12443 BitMap |= WIFI_BITRATE_11MBPS;
12444 else if (strcmp(rate, "12") == 0)
12445 BitMap |= WIFI_BITRATE_12MBPS;
12446 else if (strcmp(rate, "18") == 0)
12447 BitMap |= WIFI_BITRATE_18MBPS;
12448 else if (strcmp(rate, "24") == 0)
12449 BitMap |= WIFI_BITRATE_24MBPS;
12450 else if (strcmp(rate, "36") == 0)
12451 BitMap |= WIFI_BITRATE_36MBPS;
12452 else if (strcmp(rate, "48") == 0)
12453 BitMap |= WIFI_BITRATE_48MBPS;
12454 else if (strcmp(rate, "54") == 0)
12455 BitMap |= WIFI_BITRATE_54MBPS;
12456 rate = strtok(NULL, ",");
12457 }
12458 *basicRateBitMap = BitMap;
12459 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12460 return RETURN_OK;
12461}
12462
12463// This API is used to configured all radio operation parameter in a single set. it includes channel number, channelWidth, mode and auto chammel configuration.
12464INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
12465{
12466 char buf[128] = {0};
12467 char cmd[128] = {0};
12468 char config_file[64] = {0};
12469 int bandwidth;
12470 int set_mode = 0;
12471 wifi_radio_operationParam_t current_param;
12472
12473 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12474
12475 multiple_set = TRUE;
12476 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
12477 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
12478 return RETURN_ERR;
12479 }
12480 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
12481 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
12482 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
12483 return RETURN_ERR;
12484 }
12485 }
12486
12487 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
12488 bandwidth = 20;
12489 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
12490 bandwidth = 40;
12491 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
12492 bandwidth = 80;
12493 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
12494 bandwidth = 160;
12495 if (operationParam->autoChannelEnabled){
12496 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
12497 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
12498 return RETURN_ERR;
12499 }
developer69b61b02023-03-07 17:17:44 +080012500 }else{
developer72fb0bb2023-01-11 09:46:29 +080012501 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
12502 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
12503 return RETURN_ERR;
12504 }
12505 }
12506
12507 if (current_param.variant != operationParam->variant) {
12508 // Two different definition bit map, so need to check every bit.
12509 if (operationParam->variant & WIFI_80211_VARIANT_A)
12510 set_mode |= WIFI_MODE_A;
12511 if (operationParam->variant & WIFI_80211_VARIANT_B)
12512 set_mode |= WIFI_MODE_B;
12513 if (operationParam->variant & WIFI_80211_VARIANT_G)
12514 set_mode |= WIFI_MODE_G;
12515 if (operationParam->variant & WIFI_80211_VARIANT_N)
12516 set_mode |= WIFI_MODE_N;
12517 if (operationParam->variant & WIFI_80211_VARIANT_AC)
12518 set_mode |= WIFI_MODE_AC;
12519 if (operationParam->variant & WIFI_80211_VARIANT_AX)
12520 set_mode |= WIFI_MODE_AX;
12521 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
12522 memset(buf, 0, sizeof(buf));
12523 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
12524 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
12525 return RETURN_ERR;
12526 }
12527 }
12528 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
12529 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
12530 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
12531 return RETURN_ERR;
12532 }
12533 }
12534 if (current_param.beaconInterval != operationParam->beaconInterval) {
12535 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
12536 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
12537 return RETURN_ERR;
12538 }
12539 }
12540 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
12541 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
12542 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12543 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
12544 return RETURN_ERR;
12545 }
12546 }
12547 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
12548 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
12549 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
12550 return RETURN_ERR;
12551 }
12552 }
12553 if (current_param.guardInterval != operationParam->guardInterval) {
12554 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
12555 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
12556 return RETURN_ERR;
12557 }
12558 }
12559 if (current_param.transmitPower != operationParam->transmitPower) {
12560 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
12561 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
12562 return RETURN_ERR;
12563 }
12564 }
12565 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
12566 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
12567 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
12568 return RETURN_ERR;
12569 }
12570 }
12571 if (current_param.obssCoex != operationParam->obssCoex) {
12572 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
12573 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
12574 return RETURN_ERR;
12575 }
12576 }
12577 if (current_param.stbcEnable != operationParam->stbcEnable) {
12578 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
12579 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
12580 return RETURN_ERR;
12581 }
12582 }
12583 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
12584 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
12585 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
12586 return RETURN_ERR;
12587 }
12588 }
12589
12590 // if enable is true, then restart the radio
12591 wifi_setRadioEnable(index, FALSE);
12592 if (operationParam->enable == TRUE)
12593 wifi_setRadioEnable(index, TRUE);
12594 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12595
12596 return RETURN_OK;
12597}
12598
12599INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
12600{
12601 char band[64] = {0};
12602 char buf[256] = {0};
12603 char config_file[64] = {0};
12604 char cmd[128] = {0};
12605 int ret = RETURN_ERR;
12606 int mode = 0;
12607 ULONG channel = 0;
12608 BOOL enabled = FALSE;
12609
12610 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12611 printf("Entering %s index = %d\n", __func__, (int)index);
12612
12613 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
12614 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
12615 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
12616 {
12617 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
12618 return RETURN_ERR;
12619 }
12620 operationParam->enable = enabled;
12621
12622 memset(band, 0, sizeof(band));
12623 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
12624 {
12625 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
12626 return RETURN_ERR;
12627 }
12628
12629 if (!strcmp(band, "2.4GHz"))
12630 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
12631 else if (!strcmp(band, "5GHz"))
12632 operationParam->band = WIFI_FREQUENCY_5_BAND;
12633 else if (!strcmp(band, "6GHz"))
12634 operationParam->band = WIFI_FREQUENCY_6_BAND;
12635 else
12636 {
12637 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
12638 band);
12639 }
12640
12641 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
12642 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
12643 operationParam->channel = 0;
12644 operationParam->autoChannelEnabled = TRUE;
12645 } else {
12646 operationParam->channel = strtol(buf, NULL, 10);
12647 operationParam->autoChannelEnabled = FALSE;
12648 }
12649
12650 memset(buf, 0, sizeof(buf));
12651 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
12652 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
12653 return RETURN_ERR;
12654 }
12655 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
12656 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
12657 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
12658 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
12659 else
12660 {
12661 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
12662 return false;
12663 }
12664
12665 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
12666 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
12667 return RETURN_ERR;
12668 }
12669 // Two different definition bit map, so need to check every bit.
12670 if (mode & WIFI_MODE_A)
12671 operationParam->variant |= WIFI_80211_VARIANT_A;
12672 if (mode & WIFI_MODE_B)
12673 operationParam->variant |= WIFI_80211_VARIANT_B;
12674 if (mode & WIFI_MODE_G)
12675 operationParam->variant |= WIFI_80211_VARIANT_G;
12676 if (mode & WIFI_MODE_N)
12677 operationParam->variant |= WIFI_80211_VARIANT_N;
12678 if (mode & WIFI_MODE_AC)
12679 operationParam->variant |= WIFI_80211_VARIANT_AC;
12680 if (mode & WIFI_MODE_AX)
12681 operationParam->variant |= WIFI_80211_VARIANT_AX;
12682 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
12683 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
12684 return RETURN_ERR;
12685 }
12686 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
12687 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
12688 return RETURN_ERR;
12689 }
12690 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
12691 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
12692 return RETURN_ERR;
12693 }
12694
12695 memset(buf, 0, sizeof(buf));
12696 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
12697 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
12698 return RETURN_ERR;
12699 }
12700 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
12701
12702 memset(buf, 0, sizeof(buf));
12703 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12704 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
12705 return RETURN_ERR;
12706 }
12707 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
12708
12709 memset(buf, 0, sizeof(buf));
12710 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
12711 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
12712
12713 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
12714 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
12715 return RETURN_ERR;
12716 }
developera1255e42023-05-13 17:45:02 +080012717 if (wifi_getRadioPercentageTransmitPower(index, (ULONG *)&operationParam->transmitPower) != RETURN_OK) {
developer72fb0bb2023-01-11 09:46:29 +080012718 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
12719 return RETURN_ERR;
12720 }
12721
12722 memset(buf, 0, sizeof(buf));
12723 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
12724 if (strcmp(buf, "-1") == 0) {
12725 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
12726 operationParam->ctsProtection = FALSE;
12727 } else {
12728 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
12729 operationParam->ctsProtection = TRUE;
12730 }
12731
12732 memset(buf, 0, sizeof(buf));
12733 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
12734 if (strcmp(buf, "0") == 0)
12735 operationParam->obssCoex = FALSE;
12736 else
12737 operationParam->obssCoex = TRUE;
12738
12739 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
12740 _syscmd(cmd, buf, sizeof(buf));
12741 if (strlen(buf) != 0)
12742 operationParam->stbcEnable = TRUE;
12743 else
12744 operationParam->stbcEnable = FALSE;
12745
12746 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
12747 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
12748 return RETURN_ERR;
12749 }
12750
12751 // Below value is hardcoded
12752
12753 operationParam->numSecondaryChannels = 0;
12754 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
12755 operationParam->channelSecondary[i] = 0;
12756 }
12757 operationParam->csa_beacon_count = 15;
12758 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
12759
12760 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12761 return RETURN_OK;
12762}
12763
12764static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
12765{
12766 int max_radio_num = 0;
12767
12768 wifi_getMaxRadioNumber(&max_radio_num);
12769 if (radioIndex >= max_radio_num) {
12770 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
12771 return RETURN_ERR;
12772 }
12773
12774 return (arrayIndex * max_radio_num) + radioIndex;
12775}
12776
developer96b38512023-02-22 11:17:45 +080012777static int vap_index_to_array_index(int vapIndex, int *radioIndex, int *arrayIndex)
12778{
12779 int max_radio_num = 0;
12780
12781 if ((vapIndex < 0) || (vapIndex > MAX_NUM_VAP_PER_RADIO*MAX_NUM_RADIOS))
12782 return -1;
12783
12784 wifi_getMaxRadioNumber(&max_radio_num);
12785
12786 (*radioIndex) = vapIndex % max_radio_num;
12787 (*arrayIndex) = vapIndex / max_radio_num;
12788
12789 return 0;
12790}
12791
12792
developer72fb0bb2023-01-11 09:46:29 +080012793wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
12794 if (strncmp(beaconRate, "1Mbps", 5) == 0)
12795 return WIFI_BITRATE_1MBPS;
12796 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
12797 return WIFI_BITRATE_2MBPS;
12798 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
12799 return WIFI_BITRATE_5_5MBPS;
12800 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
12801 return WIFI_BITRATE_6MBPS;
12802 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
12803 return WIFI_BITRATE_9MBPS;
12804 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
12805 return WIFI_BITRATE_11MBPS;
12806 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
12807 return WIFI_BITRATE_12MBPS;
12808 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
12809 return WIFI_BITRATE_18MBPS;
12810 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
12811 return WIFI_BITRATE_24MBPS;
12812 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
12813 return WIFI_BITRATE_36MBPS;
12814 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
12815 return WIFI_BITRATE_48MBPS;
12816 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
12817 return WIFI_BITRATE_54MBPS;
12818 return WIFI_BITRATE_DEFAULT;
12819}
12820
12821INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
12822{
12823 if (beacon == WIFI_BITRATE_1MBPS)
12824 strcpy(beacon_str, "1Mbps");
12825 else if (beacon == WIFI_BITRATE_2MBPS)
12826 strcpy(beacon_str, "2Mbps");
12827 else if (beacon == WIFI_BITRATE_5_5MBPS)
12828 strcpy(beacon_str, "5.5Mbps");
12829 else if (beacon == WIFI_BITRATE_6MBPS)
12830 strcpy(beacon_str, "6Mbps");
12831 else if (beacon == WIFI_BITRATE_9MBPS)
12832 strcpy(beacon_str, "9Mbps");
12833 else if (beacon == WIFI_BITRATE_11MBPS)
12834 strcpy(beacon_str, "11Mbps");
12835 else if (beacon == WIFI_BITRATE_12MBPS)
12836 strcpy(beacon_str, "12Mbps");
12837 else if (beacon == WIFI_BITRATE_18MBPS)
12838 strcpy(beacon_str, "18Mbps");
12839 else if (beacon == WIFI_BITRATE_24MBPS)
12840 strcpy(beacon_str, "24Mbps");
12841 else if (beacon == WIFI_BITRATE_36MBPS)
12842 strcpy(beacon_str, "36Mbps");
12843 else if (beacon == WIFI_BITRATE_48MBPS)
12844 strcpy(beacon_str, "48Mbps");
12845 else if (beacon == WIFI_BITRATE_54MBPS)
12846 strcpy(beacon_str, "54Mbps");
12847 return RETURN_OK;
12848}
12849
12850INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12851{
12852 INT mode = 0;
12853 INT ret = -1;
12854 INT output = 0;
12855 int i = 0;
12856 int vap_index = 0;
12857 BOOL enabled = FALSE;
12858 char buf[256] = {0};
12859 wifi_vap_security_t security = {0};
12860 map->num_vaps = 5; // Hardcoded
12861
12862 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12863 printf("Entering %s index = %d\n", __func__, (int)index);
12864
12865 for (i = 0; i < 5; i++)
12866 {
12867 map->vap_array[i].radio_index = index;
12868
12869 vap_index = array_index_to_vap_index(index, i);
12870 if (vap_index < 0)
12871 return RETURN_ERR;
12872
12873 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
12874
12875 map->vap_array[i].vap_index = vap_index;
12876
12877 memset(buf, 0, sizeof(buf));
12878 ret = wifi_getApName(vap_index, buf);
12879 if (ret != RETURN_OK) {
12880 printf("%s: wifi_getApName return error\n", __func__);
12881 return RETURN_ERR;
12882 }
12883 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
12884
12885 memset(buf, 0, sizeof(buf));
12886 ret = wifi_getSSIDName(vap_index, buf);
12887 if (ret != RETURN_OK) {
12888 printf("%s: wifi_getSSIDName return error\n", __func__);
12889 return RETURN_ERR;
12890 }
12891 snprintf(map->vap_array[i].u.bss_info.ssid, sizeof(map->vap_array[i].u.bss_info.ssid), "%s", buf);
12892
12893 ret = wifi_getSSIDEnable(vap_index, &enabled);
12894 if (ret != RETURN_OK) {
12895 printf("%s: wifi_getSSIDEnable return error\n", __func__);
12896 return RETURN_ERR;
12897 }
12898 map->vap_array[i].u.bss_info.enabled = enabled;
12899
12900 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
12901 if (ret != RETURN_OK) {
12902 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
12903 return RETURN_ERR;
12904 }
12905 map->vap_array[i].u.bss_info.showSsid = enabled;
developer69b61b02023-03-07 17:17:44 +080012906
developer72fb0bb2023-01-11 09:46:29 +080012907 ret = wifi_getApIsolationEnable(vap_index, &enabled);
12908 if (ret != RETURN_OK) {
12909 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
12910 return RETURN_ERR;
12911 }
12912 map->vap_array[i].u.bss_info.isolation = enabled;
12913
12914 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
12915 if (ret != RETURN_OK) {
12916 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
12917 return RETURN_ERR;
12918 }
12919 map->vap_array[i].u.bss_info.bssMaxSta = output;
12920
12921 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
12922 if (ret != RETURN_OK) {
12923 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
12924 return RETURN_ERR;
12925 }
12926 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
12927
12928 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
12929 if (ret != RETURN_OK) {
12930 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
12931 return RETURN_ERR;
12932 }
12933 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
12934
12935 ret = wifi_getApSecurity(vap_index, &security);
12936 if (ret != RETURN_OK) {
12937 printf("%s: wifi_getApSecurity return error\n", __func__);
12938 return RETURN_ERR;
12939 }
12940 map->vap_array[i].u.bss_info.security = security;
12941
12942 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
12943 if (ret != RETURN_OK) {
12944 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
12945 return RETURN_ERR;
12946 }
developer69b61b02023-03-07 17:17:44 +080012947 if (mode == 0)
developer72fb0bb2023-01-11 09:46:29 +080012948 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
developer69b61b02023-03-07 17:17:44 +080012949 else
developer72fb0bb2023-01-11 09:46:29 +080012950 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
developer69b61b02023-03-07 17:17:44 +080012951 if (mode == 1)
developer72fb0bb2023-01-11 09:46:29 +080012952 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
developer69b61b02023-03-07 17:17:44 +080012953 else if (mode == 2)
developer72fb0bb2023-01-11 09:46:29 +080012954 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
12955
12956 ret = wifi_getApWmmEnable(vap_index, &enabled);
12957 if (ret != RETURN_OK) {
12958 printf("%s: wifi_getApWmmEnable return error\n", __func__);
12959 return RETURN_ERR;
12960 }
12961 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
12962
12963 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
12964 if (ret != RETURN_OK) {
12965 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
12966 return RETURN_ERR;
12967 }
12968 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
12969
12970 memset(buf, 0, sizeof(buf));
12971 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
12972 if (ret != RETURN_OK) {
12973 printf("%s: wifi_getApBeaconRate return error\n", __func__);
12974 return RETURN_ERR;
12975 }
12976 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
12977
12978 memset(buf, 0, sizeof(buf));
12979 ret = wifi_getBaseBSSID(vap_index, buf);
12980 if (ret != RETURN_OK) {
12981 printf("%s: wifi_getBaseBSSID return error\n", __func__);
12982 return RETURN_ERR;
12983 }
12984 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
12985 &map->vap_array[i].u.bss_info.bssid[0],
12986 &map->vap_array[i].u.bss_info.bssid[1],
12987 &map->vap_array[i].u.bss_info.bssid[2],
12988 &map->vap_array[i].u.bss_info.bssid[3],
12989 &map->vap_array[i].u.bss_info.bssid[4],
12990 &map->vap_array[i].u.bss_info.bssid[5]);
12991 // fprintf(stderr, "%s index %d: mac: %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n", __func__, vap_index, map->vap_array[i].u.bss_info.bssid[0], map->vap_array[i].u.bss_info.bssid[1], map->vap_array[i].u.bss_info.bssid[2], map->vap_array[i].u.bss_info.bssid[3], map->vap_array[i].u.bss_info.bssid[4], map->vap_array[i].u.bss_info.bssid[5]);
12992
12993 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
12994 if (ret != RETURN_OK) {
12995 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
12996 return RETURN_ERR;
12997 }
12998 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
12999
13000 // TODO: wps, noack
13001 }
13002 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13003 return RETURN_OK;
13004}
13005
13006void checkVapStatus(int apIndex, bool *enable)
13007{
13008 char if_name[16] = {0};
13009 char cmd[128] = {0};
13010 char buf[128] = {0};
13011
13012 *enable = FALSE;
13013 if (wifi_GetInterfaceName(apIndex, if_name) != RETURN_OK)
13014 return;
13015
13016 snprintf(cmd, sizeof(cmd), "cat %s | grep ^%s=1", VAP_STATUS_FILE, if_name);
13017 _syscmd(cmd, buf, sizeof(buf));
13018 if (strlen(buf) > 0)
13019 *enable = TRUE;
13020 return;
13021}
13022
13023static int prepareInterface(UINT apIndex, char *new_interface)
13024{
13025 char cur_interface[16] = {0};
13026 char config_file[128] = {0};
developer8a3bbbf2023-03-15 17:47:23 +080013027 char cmd[MAX_CMD_SIZE] = {0};
13028 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +080013029 int max_radio_num = 0;
13030 int radioIndex = -1;
13031 int phyIndex = -1;
developer8a3bbbf2023-03-15 17:47:23 +080013032 struct params params;
developer72fb0bb2023-01-11 09:46:29 +080013033
13034 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
13035 wifi_hostapdRead(config_file, "interface", cur_interface, sizeof(cur_interface));
13036
13037 if (strncmp(cur_interface, new_interface, sizeof(cur_interface)) != 0) {
developer8a3bbbf2023-03-15 17:47:23 +080013038 wifi_getMaxRadioNumber(&max_radio_num);
developer72fb0bb2023-01-11 09:46:29 +080013039 radioIndex = apIndex % max_radio_num;
13040 phyIndex = radio_index_to_phy(radioIndex);
13041 // disable and del old interface, then add new interface
13042 wifi_setApEnable(apIndex, FALSE);
developer8a3bbbf2023-03-15 17:47:23 +080013043
13044 params.name = "interface";
13045 params.value = new_interface;
13046 wifi_hostapdWrite(config_file, &params, 1);
13047
13048 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyIndex, config_file);
13049 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +080013050 }
developer8a3bbbf2023-03-15 17:47:23 +080013051
developer72fb0bb2023-01-11 09:46:29 +080013052 // update the vap status file
13053 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=1' %s", cur_interface, new_interface, VAP_STATUS_FILE);
13054 _syscmd(cmd, buf, sizeof(buf));
13055 return RETURN_OK;
13056}
13057
13058INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
13059{
13060 char interface_name[16] = {0};
13061 unsigned int i;
13062 wifi_vap_info_t *vap_info = NULL;
13063 int acl_mode;
13064 int ret = 0;
13065 char *sec_str = NULL;
13066 char buf[256] = {0};
13067 char cmd[128] = {0};
13068 char config_file[64] = {0};
13069 char bssid[32] = {0};
13070 char psk_file[64] = {0};
13071 bool enable = FALSE;
13072
13073 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13074 printf("Entering %s index = %d\n", __func__, (int)index);
13075 for (i = 0; i < map->num_vaps; i++)
13076 {
13077 multiple_set = TRUE;
13078 vap_info = &map->vap_array[i];
13079
13080 // Check vap status file to enable multiple ap if the system boot.
13081 checkVapStatus(vap_info->vap_index, &enable);
13082 if (vap_info->u.bss_info.enabled == FALSE && enable == FALSE)
13083 continue;
13084
13085 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
13086
13087 if (wifi_getApEnable(vap_info->vap_index, &enable) != RETURN_OK)
13088 enable = FALSE;
13089
13090 // multi-ap first up need to copy current radio config
13091 if (vap_info->radio_index != vap_info->vap_index && enable == FALSE) {
13092 snprintf(cmd, sizeof(cmd), "cp %s%d.conf %s%d.conf", CONFIG_PREFIX, vap_info->radio_index, CONFIG_PREFIX, vap_info->vap_index);
13093 _syscmd(cmd, buf, sizeof(buf));
13094 if (strlen(vap_info->vap_name) == 0) // default name of the interface is wifiX
13095 snprintf(vap_info->vap_name, 16, "wifi%d", vap_info->vap_index);
13096 } else {
13097 // Check whether the interface name is valid or this ap change it.
13098 int apIndex = -1;
13099 wifi_getApIndexFromName(vap_info->vap_name, &apIndex);
13100 if (apIndex != -1 && apIndex != vap_info->vap_index)
13101 continue;
13102 prepareInterface(vap_info->vap_index, vap_info->vap_name);
13103 }
13104
13105 struct params params[3];
13106 params[0].name = "interface";
13107 params[0].value = vap_info->vap_name;
13108 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
13109 params[1].name = "bssid";
13110 params[1].value = bssid;
13111 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", vap_info->vap_index);
13112 params[2].name = "wpa_psk_file";
13113 params[2].value = psk_file;
13114
13115 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
13116 wifi_hostapdWrite(config_file, params, 3);
13117
13118 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
13119 _syscmd(cmd, buf, sizeof(buf));
13120
13121 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
13122 if (ret != RETURN_OK) {
13123 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
13124 return RETURN_ERR;
13125 }
13126
13127 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
13128 if (ret != RETURN_OK) {
13129 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
13130 return RETURN_ERR;
13131 }
13132
13133 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
13134 if (ret != RETURN_OK) {
13135 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
13136 return RETURN_ERR;
13137 }
13138
13139 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
13140 if (ret != RETURN_OK) {
13141 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
13142 return RETURN_ERR;
13143 }
13144
13145 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
13146 if (ret != RETURN_OK) {
13147 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
13148 return RETURN_ERR;
13149 }
13150
13151 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
13152 if (ret != RETURN_OK) {
13153 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
13154 return RETURN_ERR;
13155 }
13156
13157 if (vap_info->u.bss_info.mac_filter_enable == false){
13158 acl_mode = 0;
13159 }else {
13160 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
13161 acl_mode = 2;
13162 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
13163 _syscmd(cmd, buf, sizeof(buf));
13164 }else{
13165 acl_mode = 1;
13166 }
13167 }
13168
13169 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
13170 if (ret != RETURN_OK) {
13171 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
13172 return RETURN_ERR;
13173 }
13174
13175 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
13176 if (ret != RETURN_OK) {
13177 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
13178 return RETURN_ERR;
13179 }
13180
developered997d32023-04-18 22:45:39 +080013181 /*TBD: we need refine beacon rate setting flow*/
13182 //memset(buf, 0, sizeof(buf));
13183 //beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
developer72fb0bb2023-01-11 09:46:29 +080013184 // fprintf(stderr, "%s: beaconrate: %d, buf: %s\n", __func__, vap_info->u.bss_info.beaconRate, buf);
developered997d32023-04-18 22:45:39 +080013185 //ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
13186 //if (ret != RETURN_OK) {
13187 // fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
13188 // return RETURN_ERR;
13189 //}
developer72fb0bb2023-01-11 09:46:29 +080013190
13191 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
13192 if (ret != RETURN_OK) {
13193 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable\n", __func__);
13194 return RETURN_ERR;
13195 }
13196
developer72fb0bb2023-01-11 09:46:29 +080013197 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
13198 if (ret != RETURN_OK) {
13199 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
13200 return RETURN_ERR;
13201 }
13202
developer23e71282023-01-18 10:25:19 +080013203 wifi_setApEnable(vap_info->vap_index, FALSE);
13204 wifi_setApEnable(vap_info->vap_index, TRUE);
13205 multiple_set = FALSE;
13206
13207 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
developer72fb0bb2023-01-11 09:46:29 +080013208 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
13209 if (ret != RETURN_OK) {
13210 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
13211 return RETURN_ERR;
13212 }
13213
13214 // TODO mgmtPowerControl, interworking, wps
13215 }
13216 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13217 return RETURN_OK;
13218}
13219
13220int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
13221{
13222 char *token, *next;
13223 const char s[2] = ",";
13224 int count =0;
13225
13226 /* get the first token */
13227 token = strtok_r(pchannels, s, &next);
13228
13229 /* walk through other tokens */
13230 while( token != NULL && count < MAX_CHANNELS) {
13231 chlistptr->channels_list[count++] = atoi(token);
13232 token = strtok_r(NULL, s, &next);
13233 }
13234
13235 return count;
13236}
13237
13238static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
13239{
13240 INT status;
13241 wifi_channels_list_t *chlistp;
13242 CHAR output_string[64];
13243 CHAR pchannels[128];
13244 CHAR interface_name[16] = {0};
13245 wifi_band band;
13246
13247 if(rcap == NULL)
13248 {
13249 return RETURN_ERR;
13250 }
13251
13252 rcap->numSupportedFreqBand = 1;
13253 band = wifi_index_to_band(radioIndex);
13254
13255 if (band == band_2_4)
13256 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
13257 else if (band == band_5)
13258 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
13259 else if (band == band_6)
13260 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
13261
13262 chlistp = &(rcap->channel_list[0]);
13263 memset(pchannels, 0, sizeof(pchannels));
13264
13265 /* possible number of radio channels */
13266 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
13267 {
13268 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
13269 }
13270 /* Number of channels and list*/
13271 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
13272
13273 /* autoChannelSupported */
13274 /* always ON with wifi_getRadioAutoChannelSupported */
13275 rcap->autoChannelSupported = TRUE;
13276
13277 /* DCSSupported */
13278 /* always ON with wifi_getRadioDCSSupported */
13279 rcap->DCSSupported = TRUE;
13280
13281 /* zeroDFSSupported - TBD */
13282 rcap->zeroDFSSupported = FALSE;
13283
13284 /* Supported Country List*/
13285 memset(output_string, 0, sizeof(output_string));
13286 status = wifi_getRadioCountryCode(radioIndex, output_string);
13287 if( status != 0 ) {
13288 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
13289 return RETURN_ERR;
13290 } else {
13291 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
13292 }
13293 if(!strcmp(output_string,"US")){
13294 rcap->countrySupported[0] = wifi_countrycode_US;
13295 rcap->countrySupported[1] = wifi_countrycode_CA;
13296 } else if (!strcmp(output_string,"CA")) {
13297 rcap->countrySupported[0] = wifi_countrycode_CA;
13298 rcap->countrySupported[1] = wifi_countrycode_US;
13299 } else {
13300 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
13301 }
13302
13303 rcap->numcountrySupported = 2;
13304
13305 /* csi */
13306 rcap->csi.maxDevices = 8;
13307 rcap->csi.soudingFrameSupported = TRUE;
13308
13309 wifi_GetInterfaceName(radioIndex, interface_name);
13310 snprintf(rcap->ifaceName, sizeof(interface_name), "%s",interface_name);
13311
13312 /* channelWidth - all supported bandwidths */
13313 int i=0;
13314 rcap->channelWidth[i] = 0;
13315 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
13316 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13317 WIFI_CHANNELBANDWIDTH_40MHZ);
13318
13319 }
13320 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
13321 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13322 WIFI_CHANNELBANDWIDTH_40MHZ |
13323 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
13324 }
13325
13326
13327 /* mode - all supported variants */
13328 // rcap->mode[i] = WIFI_80211_VARIANT_H;
13329 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
13330 rcap->mode[i] = ( WIFI_80211_VARIANT_B | WIFI_80211_VARIANT_G | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AX );
13331 }
13332 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
13333 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
13334 }
13335 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
13336 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
13337 }
13338 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
13339 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
13340
13341 /* supportedBitRate - all supported bitrates */
13342 rcap->supportedBitRate[i] = 0;
13343 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
13344 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13345 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
13346 }
13347 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
13348 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13349 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
13350 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
13351 }
13352
13353
13354 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
13355 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
13356 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
13357 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
13358 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
13359 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
13360 rcap->cipherSupported = 0;
13361 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
13362 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
13363
13364 return RETURN_OK;
13365}
13366
13367INT wifi_getHalCapability(wifi_hal_capability_t *cap)
13368{
13369 INT status = 0, radioIndex = 0;
13370 char cmd[MAX_BUF_SIZE] = {0}, output[MAX_BUF_SIZE] = {0};
13371 int iter = 0;
13372 unsigned int j = 0;
13373 int max_num_radios;
13374 wifi_interface_name_idex_map_t *iface_info = NULL;
13375
13376 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13377
13378 memset(cap, 0, sizeof(wifi_hal_capability_t));
13379
13380 /* version */
13381 cap->version.major = WIFI_HAL_MAJOR_VERSION;
13382 cap->version.minor = WIFI_HAL_MINOR_VERSION;
13383
13384 /* number of radios platform property */
13385 wifi_getMaxRadioNumber(&max_num_radios);
13386 cap->wifi_prop.numRadios = max_num_radios;
13387
13388 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
13389 {
13390 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
13391 if (status != 0) {
13392 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
13393 return RETURN_ERR;
13394 }
13395
13396 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
13397 {
13398 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
13399 {
13400 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
13401 return RETURN_ERR;
13402 }
13403 iface_info = &cap->wifi_prop.interface_map[iter];
13404 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
13405 iface_info->rdk_radio_index = radioIndex;
13406 memset(output, 0, sizeof(output));
13407 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
13408 {
13409 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
13410 }
13411 // TODO: bridge name
13412 // TODO: vlan id
13413 // TODO: primary
13414 iface_info->index = array_index_to_vap_index(radioIndex, j);
13415 memset(output, 0, sizeof(output));
13416 if (wifi_getApName(iface_info->index, output) == RETURN_OK)
13417 {
13418 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
13419 }
13420 iter++;
13421 }
13422 }
13423
13424 cap->BandSteeringSupported = FALSE;
13425 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13426 return RETURN_OK;
13427}
13428
13429INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
13430{
13431 struct params h_config={0};
13432 char config_file[64] = {0};
13433
13434 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13435
13436 h_config.name = "okc";
13437 h_config.value = okc_enable?"1":"0";
13438
13439 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13440 wifi_hostapdWrite(config_file, &h_config, 1);
13441 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13442
13443 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13444 return RETURN_OK;
13445}
13446
13447INT wifi_setSAEMFP(int ap_index, BOOL enable)
13448{
13449 struct params h_config={0};
13450 char config_file[64] = {0};
13451 char buf[128] = {0};
13452
13453 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13454
13455 h_config.name = "sae_require_mfp";
13456 h_config.value = enable?"1":"0";
13457
13458 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13459 wifi_hostapdWrite(config_file, &h_config, 1);
13460 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13461
13462 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13463 return RETURN_OK;
13464}
13465
13466INT wifi_setSAEpwe(int ap_index, int sae_pwe)
13467{
13468 struct params h_config={0};
13469 char config_file[64] = {0};
13470 char buf[128] = {0};
13471
13472 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13473
13474 h_config.name = "sae_pwe";
13475 snprintf(buf, sizeof(buf), "%d", sae_pwe);
13476 h_config.value = buf;
13477
13478 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13479 wifi_hostapdWrite(config_file, &h_config, 1);
13480 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13481
13482 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13483 return RETURN_OK;
13484}
13485
13486INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
13487{
13488 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
13489 struct params h_config={0};
13490 char config_file[64] = {0};
13491
13492 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13493
13494 h_config.name = "wpa_disable_eapol_key_retries";
13495 h_config.value = disable_EAPOL_retries?"1":"0";
13496
13497 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13498 wifi_hostapdWrite(config_file, &h_config, 1);
13499 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13500
13501 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13502 return RETURN_OK;
13503}
13504
13505INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
13506{
13507 char buf[128] = {0};
13508 char config_file[128] = {0};
13509 char password[64] = {0};
13510 char mfp[32] = {0};
13511 char wpa_mode[32] = {0};
13512 BOOL okc_enable = FALSE;
13513 BOOL sae_MFP = FALSE;
13514 BOOL disable_EAPOL_retries = TRUE;
13515 int sae_pwe = 0;
13516 struct params params = {0};
13517 wifi_band band = band_invalid;
13518
13519 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13520
13521 multiple_set = TRUE;
13522 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13523 if (security->mode == wifi_security_mode_none) {
13524 strcpy(wpa_mode, "None");
13525 } else if (security->mode == wifi_security_mode_wpa_personal)
13526 strcpy(wpa_mode, "WPA-Personal");
13527 else if (security->mode == wifi_security_mode_wpa2_personal)
13528 strcpy(wpa_mode, "WPA2-Personal");
13529 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
13530 strcpy(wpa_mode, "WPA-WPA2-Personal");
13531 else if (security->mode == wifi_security_mode_wpa_enterprise)
13532 strcpy(wpa_mode, "WPA-Enterprise");
13533 else if (security->mode == wifi_security_mode_wpa2_enterprise)
13534 strcpy(wpa_mode, "WPA2-Enterprise");
13535 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
13536 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
13537 else if (security->mode == wifi_security_mode_wpa3_personal) {
13538 strcpy(wpa_mode, "WPA3-Personal");
13539 okc_enable = TRUE;
13540 sae_MFP = TRUE;
13541 sae_pwe = 2;
13542 disable_EAPOL_retries = FALSE;
13543 } else if (security->mode == wifi_security_mode_wpa3_transition) {
13544 strcpy(wpa_mode, "WPA3-Personal-Transition");
13545 okc_enable = TRUE;
13546 sae_MFP = TRUE;
13547 sae_pwe = 2;
13548 disable_EAPOL_retries = FALSE;
13549 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
13550 strcpy(wpa_mode, "WPA3-Enterprise");
13551 sae_MFP = TRUE;
13552 sae_pwe = 2;
13553 disable_EAPOL_retries = FALSE;
developerd01e3e82023-04-26 19:10:38 +080013554 } else if (security->mode == wifi_security_mode_enhanced_open) {
developer3086e2f2023-01-17 09:40:01 +080013555 strcpy(wpa_mode, "OWE");
13556 sae_MFP = TRUE;
13557 sae_pwe = 2;
13558 disable_EAPOL_retries = FALSE;
developer72fb0bb2023-01-11 09:46:29 +080013559 }
13560
13561 band = wifi_index_to_band(ap_index);
13562 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
13563 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
13564 return RETURN_ERR;
13565 }
13566
13567 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
13568 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
13569 wifi_setSAEMFP(ap_index, sae_MFP);
13570 wifi_setSAEpwe(ap_index, sae_pwe);
13571 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
13572
developerd01e3e82023-04-26 19:10:38 +080013573 if (security->mode != wifi_security_mode_none && security->mode != wifi_security_mode_enhanced_open) {
developer72fb0bb2023-01-11 09:46:29 +080013574 if (security->u.key.type == wifi_security_key_type_psk || security->u.key.type == wifi_security_key_type_psk_sae) {
13575 strncpy(password, security->u.key.key, 63); // 8 to 63 characters
13576 password[63] = '\0';
13577 wifi_setApSecurityKeyPassphrase(ap_index, password);
13578 }
13579 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
13580 params.name = "sae_password";
13581 params.value = security->u.key.key;
13582 wifi_hostapdWrite(config_file, &params, 1);
13583 }
13584 }
13585
13586 if (security->mode != wifi_security_mode_none) {
13587 memset(&params, 0, sizeof(params));
13588 params.name = "wpa_pairwise";
13589 if (security->encr == wifi_encryption_tkip)
13590 params.value = "TKIP";
13591 else if (security->encr == wifi_encryption_aes)
13592 params.value = "CCMP";
13593 else if (security->encr == wifi_encryption_aes_tkip)
13594 params.value = "TKIP CCMP";
13595 wifi_hostapdWrite(config_file, &params, 1);
13596 }
13597
13598 if (security->mfp == wifi_mfp_cfg_disabled)
13599 strcpy(mfp, "Disabled");
13600 else if (security->mfp == wifi_mfp_cfg_optional)
13601 strcpy(mfp, "Optional");
13602 else if (security->mfp == wifi_mfp_cfg_required)
13603 strcpy(mfp, "Required");
13604 wifi_setApSecurityMFPConfig(ap_index, mfp);
13605
13606 memset(&params, 0, sizeof(params));
13607 params.name = "transition_disable";
13608 if (security->wpa3_transition_disable == TRUE)
13609 params.value = "0x01";
13610 else
13611 params.value = "0x00";
13612 wifi_hostapdWrite(config_file, &params, 1);
13613
13614 memset(&params, 0, sizeof(params));
13615 params.name = "wpa_group_rekey";
13616 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
13617 params.value = buf;
13618 wifi_hostapdWrite(config_file, &params, 1);
13619
13620 memset(&params, 0, sizeof(params));
13621 params.name = "wpa_strict_rekey";
13622 params.value = security->strict_rekey?"1":"0";
13623 wifi_hostapdWrite(config_file, &params, 1);
13624
13625 memset(&params, 0, sizeof(params));
13626 params.name = "wpa_pairwise_update_count";
13627 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
13628 params.value = buf;
13629 wifi_hostapdWrite(config_file, &params, 1);
13630
13631 memset(&params, 0, sizeof(params));
13632 params.name = "disable_pmksa_caching";
13633 params.value = security->disable_pmksa_caching?"1":"0";
13634 wifi_hostapdWrite(config_file, &params, 1);
13635
developer23e71282023-01-18 10:25:19 +080013636 if (multiple_set == FALSE) {
13637 wifi_setApEnable(ap_index, FALSE);
13638 wifi_setApEnable(ap_index, TRUE);
13639 }
developer72fb0bb2023-01-11 09:46:29 +080013640
13641 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13642
13643 return RETURN_OK;
13644}
13645
13646INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
13647{
13648 char buf[256] = {0};
13649 char config_file[128] = {0};
13650 int disable = 0;
13651 // struct params params = {0};
13652
13653 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13654 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13655 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
13656 security->mode = wifi_security_mode_none;
13657 if (strlen(buf) != 0) {
13658 if (!strcmp(buf, "WPA-Personal"))
13659 security->mode = wifi_security_mode_wpa_personal;
13660 else if (!strcmp(buf, "WPA2-Personal"))
13661 security->mode = wifi_security_mode_wpa2_personal;
13662 else if (!strcmp(buf, "WPA-WPA2-Personal"))
13663 security->mode = wifi_security_mode_wpa_wpa2_personal;
13664 else if (!strcmp(buf, "WPA-Enterprise"))
13665 security->mode = wifi_security_mode_wpa_enterprise;
13666 else if (!strcmp(buf, "WPA2-Enterprise"))
13667 security->mode = wifi_security_mode_wpa2_enterprise;
13668 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
13669 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
13670 else if (!strcmp(buf, "WPA3-Personal"))
13671 security->mode = wifi_security_mode_wpa3_personal;
13672 else if (!strcmp(buf, "WPA3-Personal-Transition"))
13673 security->mode = wifi_security_mode_wpa3_transition;
13674 else if (!strcmp(buf, "WPA3-Enterprise"))
13675 security->mode = wifi_security_mode_wpa3_enterprise;
developer3086e2f2023-01-17 09:40:01 +080013676 else if (!strcmp(buf, "OWE"))
developerd01e3e82023-04-26 19:10:38 +080013677 security->mode = wifi_security_mode_enhanced_open;
developer72fb0bb2023-01-11 09:46:29 +080013678 }
13679
13680 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
13681 if (security->mode == wifi_security_mode_none)
13682 security->encr = wifi_encryption_none;
13683 else {
13684 if (strcmp(buf, "TKIP") == 0)
13685 security->encr = wifi_encryption_tkip;
13686 else if (strcmp(buf, "CCMP") == 0)
13687 security->encr = wifi_encryption_aes;
13688 else
13689 security->encr = wifi_encryption_aes_tkip;
13690 }
13691
13692 if (security->mode != wifi_encryption_none) {
13693 memset(buf, 0, sizeof(buf));
13694 // wpa3 can use one or both configs as password, so we check sae_password first.
13695 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
13696 if (security->mode == wifi_security_mode_wpa3_personal && strlen(buf) != 0) {
13697 security->u.key.type = wifi_security_key_type_sae;
13698 } else {
13699 security->u.key.type = wifi_security_key_type_psk;
13700 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
13701 }
13702 strncpy(security->u.key.key, buf, sizeof(buf));
13703 security->u.key.key[255] = '\0';
13704 }
13705
13706 memset(buf, 0, sizeof(buf));
13707 wifi_getApSecurityMFPConfig(ap_index, buf);
13708 if (strcmp(buf, "Disabled") == 0)
13709 security->mfp = wifi_mfp_cfg_disabled;
13710 else if (strcmp(buf, "Optional") == 0)
13711 security->mfp = wifi_mfp_cfg_optional;
13712 else if (strcmp(buf, "Required") == 0)
13713 security->mfp = wifi_mfp_cfg_required;
13714
13715 memset(buf, 0, sizeof(buf));
13716 security->wpa3_transition_disable = FALSE;
13717 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
13718 disable = strtol(buf, NULL, 16);
13719 if (disable != 0)
13720 security->wpa3_transition_disable = TRUE;
13721
13722 memset(buf, 0, sizeof(buf));
13723 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
13724 if (strlen(buf) == 0)
13725 security->rekey_interval = 86400;
13726 else
13727 security->rekey_interval = strtol(buf, NULL, 10);
13728
13729 memset(buf, 0, sizeof(buf));
13730 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
13731 if (strlen(buf) == 0)
13732 security->strict_rekey = 1;
13733 else
13734 security->strict_rekey = strtol(buf, NULL, 10);
13735
13736 memset(buf, 0, sizeof(buf));
13737 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
13738 if (strlen(buf) == 0)
13739 security->eapol_key_retries = 4;
13740 else
13741 security->eapol_key_retries = strtol(buf, NULL, 10);
13742
13743 memset(buf, 0, sizeof(buf));
13744 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
13745 if (strlen(buf) == 0)
13746 security->disable_pmksa_caching = FALSE;
13747 else
13748 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
13749
13750 /* TODO
13751 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
13752 */
13753 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
13754 security->eap_identity_req_timeout = 0;
13755 security->eap_identity_req_retries = 0;
13756 security->eap_req_timeout = 0;
13757 security->eap_req_retries = 0;
13758 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13759 return RETURN_OK;
13760}
13761
13762#endif /* WIFI_HAL_VERSION_3 */
13763
13764#ifdef WIFI_HAL_VERSION_3_PHASE2
13765INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
13766{
13767 char interface_name[16] = {0};
13768 char cmd[128] = {0};
13769 char buf[128] = {0};
13770 char *mac_addr = NULL;
13771 BOOL status = FALSE;
13772 size_t len = 0;
13773
13774 if(ap_index > MAX_APS)
13775 return RETURN_ERR;
13776
13777 *output_numDevices = 0;
13778 wifi_getApEnable(ap_index, &status);
13779 if (status == FALSE)
13780 return RETURN_OK;
13781
13782 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
13783 return RETURN_ERR;
13784 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
13785 _syscmd(cmd, buf, sizeof(buf));
13786
13787 mac_addr = strtok(buf, "\n");
13788 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
13789 *output_numDevices = i + 1;
13790 fprintf(stderr, "mac_addr: %s\n", mac_addr);
13791 addr_ptr = output_deviceMacAddressArray[i];
13792 mac_addr_aton(addr_ptr, mac_addr);
13793 mac_addr = strtok(NULL, "\n");
13794 }
13795
13796 return RETURN_OK;
13797}
13798#else
13799INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
13800{
13801 char interface_name[16] = {0};
13802 char cmd[128];
13803 BOOL status = false;
13804
13805 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
13806 return RETURN_ERR;
13807
13808 output_buf[0] = '\0';
13809
13810 wifi_getApEnable(ap_index,&status);
13811 if (!status)
13812 return RETURN_OK;
13813
13814 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
13815 return RETURN_ERR;
13816 sprintf(cmd, "hostapd_cli -i %s list_sta | tr '\\n' ',' | sed 's/.$//'", interface_name);
13817 _syscmd(cmd, output_buf, output_buf_size);
developer69b61b02023-03-07 17:17:44 +080013818
developer72fb0bb2023-01-11 09:46:29 +080013819 return RETURN_OK;
13820}
13821#endif
13822
13823INT wifi_getProxyArp(INT apIndex, BOOL *enable)
13824{
13825 char output[16]={'\0'};
13826 char config_file[MAX_BUF_SIZE] = {0};
13827
13828 if (!enable)
13829 return RETURN_ERR;
13830
13831 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
13832 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
13833
13834 if (strlen(output) == 0)
13835 *enable = FALSE;
13836 else if (strncmp(output, "1", 1) == 0)
13837 *enable = TRUE;
13838 else
13839 *enable = FALSE;
13840
13841 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
13842 return RETURN_OK;
13843}
13844
13845INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
13846{
13847 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
13848 return RETURN_ERR;
13849 *output_enable=TRUE;
13850 return RETURN_OK;
13851}
13852
13853INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
13854{
13855 char cmd[128] = {0};
13856 char buf[128] = {0};
13857 char line[128] = {0};
13858 size_t len = 0;
13859 FILE *f = NULL;
13860 int index = 0;
13861 int exp = 0;
13862 int mantissa = 0;
13863 int duration = 0;
13864 int radio_index = 0;
13865 int max_radio_num = 0;
13866 uint twt_wake_interval = 0;
13867 int phyId = 0;
13868 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13869
13870 wifi_getMaxRadioNumber(&max_radio_num);
13871
13872 radio_index = ap_index % max_radio_num;
13873
13874 phyId = radio_index_to_phy(radio_index);
13875 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", phyId);
13876 _syscmd(cmd, buf, sizeof(buf));
13877 *numSessionReturned = strtol(buf, NULL, 10) - 1;
13878 if (*numSessionReturned > maxNumberSessions)
13879 *numSessionReturned = maxNumberSessions;
13880 else if (*numSessionReturned < 1) {
13881 *numSessionReturned = 0;
13882 return RETURN_OK;
13883 }
13884
13885 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | tail -n %d | tr '|' ' ' | tr -s ' '", phyId, *numSessionReturned);
13886 if ((f = popen(cmd, "r")) == NULL) {
13887 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
13888 return RETURN_ERR;
13889 }
13890
13891 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
13892 while((fgets(line, sizeof(line), f)) != NULL) {
13893 char *tmp = NULL;
13894 strcpy(buf, line);
13895 tmp = strtok(buf, " ");
13896 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
13897 tmp = strtok(NULL, " ");
13898 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
13899 tmp = strtok(NULL, " ");
13900 if (strstr(tmp, "t")) {
13901 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
13902 }
13903 if (strstr(tmp, "a")) {
13904 twtSessions[index].twtParameters.operation.announced = TRUE;
13905 }
13906 tmp = strtok(NULL, " ");
13907 exp = strtol(tmp, NULL, 10);
13908 tmp = strtok(NULL, " ");
13909 mantissa = strtol(tmp, NULL, 10);
13910 tmp = strtok(NULL, " ");
13911 duration = strtol(tmp, NULL, 10);
13912
13913 // only implicit supported
13914 twtSessions[index].twtParameters.operation.implicit = TRUE;
13915 // only individual agreement supported
13916 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
13917
13918 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
13919 twt_wake_interval = mantissa * (1 << exp);
13920 if (mantissa == 0 || twt_wake_interval/mantissa != (1 << exp)) {
13921 // Overflow handling
13922 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
13923 } else {
13924 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
13925 }
13926 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
13927 index++;
13928 }
13929
13930 pclose(f);
13931 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13932 return RETURN_OK;
13933}