blob: 4689331dcd58925c429c3f1f9fcdde58c046e7f6 [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>
developer8dd72532023-05-17 19:58:35 +080057#include <net/if.h>
58#include <unl.h>
59#include "mtk_vendor_nl80211.h"
developer72fb0bb2023-01-11 09:46:29 +080060#endif
61
62#include <ev.h>
63#include <wpa_ctrl.h>
64#include <errno.h>
65#include <time.h>
66#define MAC_ALEN 6
67
68#define MAX_BUF_SIZE 256
69#define MAX_CMD_SIZE 256
70#define IF_NAME_SIZE 16
71#define CONFIG_PREFIX "/nvram/hostapd"
72#define ACL_PREFIX "/nvram/hostapd-acl"
73#define DENY_PREFIX "/nvram/hostapd-deny"
74//#define ACL_PREFIX "/tmp/wifi_acl_list" //RDKB convention
75#define SOCK_PREFIX "/var/run/hostapd/wifi"
76#define VAP_STATUS_FILE "/nvram/vap-status"
77#define ESSID_FILE "/tmp/essid"
78#define GUARD_INTERVAL_FILE "/nvram/guard-interval"
79#define CHANNEL_STATS_FILE "/tmp/channel_stats"
80#define DFS_ENABLE_FILE "/nvram/dfs_enable.txt"
81#define VLAN_FILE "/nvram/hostapd.vlan"
82#define PSK_FILE "/nvram/hostapd"
83#define MCS_FILE "/tmp/MCS"
developera1255e42023-05-13 17:45:02 +080084#define POWER_PERCENTAGE "/tmp/POWER"
85#define MGMT_POWER_CTRL "/tmp/mgmt_power_ctrl"
86/*LOGAN_DAT_FILE: may be different on customer's platform.*/
87#define LOGAN_DAT_FILE "/etc/wireless/mediatek/mt7990.b"
88
developer72fb0bb2023-01-11 09:46:29 +080089#define NOACK_MAP_FILE "/tmp/NoAckMap"
developerf6a87542023-05-16 15:47:28 +080090
developer72fb0bb2023-01-11 09:46:29 +080091#define BRIDGE_NAME "brlan0"
developerd1824452023-05-18 12:30:04 +080092#define BASE_PHY_INDEX 1
93#define BASE_RADIO_INDEX 0
developer72fb0bb2023-01-11 09:46:29 +080094
95/*
96 MAX_APS - Number of all AP available in system
97 2x Home AP
98 2x Backhaul AP
99 2x Guest AP
100 2x Secure Onboard AP
101 2x Service AP
102
103*/
104
105
106#define MAX_APS MAX_NUM_RADIOS*5
developer7e4a2a62023-04-06 19:56:03 +0800107
108#define PREFIX_WIFI2G "ra"
109#define PREFIX_WIFI5G "rai"
110#define PREFIX_WIFI6G "rax"
developer72fb0bb2023-01-11 09:46:29 +0800111
developer47cc27a2023-05-17 23:09:58 +0800112#define PREFIX_SSID_2G "RDKB_2G"
113#define PREFIX_SSID_5G "RDKB_5G"
114#define PREFIX_SSID_6G "RDKB_6G"
115
developer72fb0bb2023-01-11 09:46:29 +0800116#ifndef RADIO_PREFIX
117#define RADIO_PREFIX "wlan"
118#endif
119
120#define MAX_ASSOCIATED_STA_NUM 2007
121
122//Uncomment to enable debug logs
123//#define WIFI_DEBUG
developer49b17232023-05-19 16:35:19 +0800124enum {
125 DEBUG_OFF = 0,
126 DEBUG_ERROR = 1,
127 DEBUG_WARN = 2,
128 DEBUG_NOTICE = 3,
129 DEBUG_INFO = 4
130};
131int wifi_debug_level = DEBUG_NOTICE;
132#define wifi_debug(level, fmt, args...) \
133{ \
134 if (level <= wifi_debug_level) \
135 { \
136 printf("[%s][%d]"fmt"\n", __func__, __LINE__, ##args); \
137 } \
138}
developer72fb0bb2023-01-11 09:46:29 +0800139
140#ifdef WIFI_DEBUG
141#define wifi_dbg_printf printf
142#define WIFI_ENTRY_EXIT_DEBUG printf
143#else
144#define wifi_dbg_printf(format, args...) printf("")
145#define WIFI_ENTRY_EXIT_DEBUG(format, args...) printf("")
146#endif
147
148#define HOSTAPD_CONF_0 "/nvram/hostapd0.conf" //private-wifi-2g
149#define HOSTAPD_CONF_1 "/nvram/hostapd1.conf" //private-wifi-5g
150#define HOSTAPD_CONF_4 "/nvram/hostapd4.conf" //public-wifi-2g
151#define HOSTAPD_CONF_5 "/nvram/hostapd5.conf" //public-wifi-5g
152#define DEF_HOSTAPD_CONF_0 "/usr/ccsp/wifi/hostapd0.conf"
153#define DEF_HOSTAPD_CONF_1 "/usr/ccsp/wifi/hostapd1.conf"
154#define DEF_HOSTAPD_CONF_4 "/usr/ccsp/wifi/hostapd4.conf"
155#define DEF_HOSTAPD_CONF_5 "/usr/ccsp/wifi/hostapd5.conf"
156#define DEF_RADIO_PARAM_CONF "/usr/ccsp/wifi/radio_param_def.cfg"
157#define LM_DHCP_CLIENT_FORMAT "%63d %17s %63s %63s"
158
159#define HOSTAPD_HT_CAPAB "[LDPC][SHORT-GI-20][SHORT-GI-40][MAX-AMSDU-7935]"
160
161#define BW_FNAME "/nvram/bw_file.txt"
162
163#define PS_MAX_TID 16
164
developer96b38512023-02-22 11:17:45 +0800165#define MAX_CARD_INDEX 3
166
developer72fb0bb2023-01-11 09:46:29 +0800167static wifi_radioQueueType_t _tid_ac_index_get[PS_MAX_TID] = {
168 WIFI_RADIO_QUEUE_TYPE_BE, /* 0 */
169 WIFI_RADIO_QUEUE_TYPE_BK, /* 1 */
170 WIFI_RADIO_QUEUE_TYPE_BK, /* 2 */
171 WIFI_RADIO_QUEUE_TYPE_BE, /* 3 */
172 WIFI_RADIO_QUEUE_TYPE_VI, /* 4 */
173 WIFI_RADIO_QUEUE_TYPE_VI, /* 5 */
174 WIFI_RADIO_QUEUE_TYPE_VO, /* 6 */
175 WIFI_RADIO_QUEUE_TYPE_VO, /* 7 */
176 WIFI_RADIO_QUEUE_TYPE_BE, /* 8 */
177 WIFI_RADIO_QUEUE_TYPE_BK, /* 9 */
178 WIFI_RADIO_QUEUE_TYPE_BK, /* 10 */
179 WIFI_RADIO_QUEUE_TYPE_BE, /* 11 */
180 WIFI_RADIO_QUEUE_TYPE_VI, /* 12 */
181 WIFI_RADIO_QUEUE_TYPE_VI, /* 13 */
182 WIFI_RADIO_QUEUE_TYPE_VO, /* 14 */
183 WIFI_RADIO_QUEUE_TYPE_VO, /* 15 */
184};
185
186typedef unsigned long long u64;
187
188/* Enum to define WiFi Bands */
189typedef enum
190{
191 band_invalid = -1,
192 band_2_4 = 0,
193 band_5 = 1,
194 band_6 = 2,
195} wifi_band;
196
developer17038e62023-03-02 14:43:43 +0800197char* wifi_band_str[] = {
198 "2G",
199 "5G",
200 "6G",
201};
202
developer72fb0bb2023-01-11 09:46:29 +0800203typedef enum {
204 WIFI_MODE_A = 0x01,
205 WIFI_MODE_B = 0x02,
206 WIFI_MODE_G = 0x04,
207 WIFI_MODE_N = 0x08,
208 WIFI_MODE_AC = 0x10,
209 WIFI_MODE_AX = 0x20,
developera1255e42023-05-13 17:45:02 +0800210 WIFI_MODE_BE = 0x40,
developer72fb0bb2023-01-11 09:46:29 +0800211} wifi_ieee80211_Mode;
212
developerd1824452023-05-18 12:30:04 +0800213typedef enum ht_config_bw{
214 HT_BW_20,
215 HT_BW_40,
216};
217
218typedef enum vht_config_bw{
219 VHT_BW_2040,
220 VHT_BW_80,
221 VHT_BW_160,
222 VHT_BW_8080,
223};
224
225typedef enum eht_config_bw{
226 EHT_BW_20,
227 EHT_BW_40,
228 EHT_BW_80,
229 EHT_BW_160,
230 EHT_BW_320,
231};
232
developer72fb0bb2023-01-11 09:46:29 +0800233#ifdef WIFI_HAL_VERSION_3
234
235// Return number of elements in array
236#ifndef ARRAY_SIZE
237#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
238#endif /* ARRAY_SIZE */
239
240#ifndef ARRAY_AND_SIZE
241#define ARRAY_AND_SIZE(x) (x),ARRAY_SIZE(x)
242#endif /* ARRAY_AND_SIZE */
243
244#define WIFI_ITEM_STR(key, str) {0, sizeof(str)-1, (int)key, (intptr_t)str}
245
246typedef struct {
247 int32_t value;
248 int32_t param;
249 intptr_t key;
250 intptr_t data;
251} wifi_secur_list;
252
253static int util_unii_5g_centerfreq(const char *ht_mode, int channel);
254static int util_unii_6g_centerfreq(const char *ht_mode, int channel);
255wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key);
256wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str);
257char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key);
258static int ieee80211_channel_to_frequency(int channel, int *freqMHz);
developer47cc27a2023-05-17 23:09:58 +0800259static void wifi_PrepareDefaultHostapdConfigs(void);
260static void wifi_psk_file_reset();
261
developer49b17232023-05-19 16:35:19 +0800262/*type define the nl80211 call back func*/
263typedef int (*mtk_nl80211_cb) (struct nl_msg *, void *);
264
265/**
266*struct mtk_nl80211_param
267* init mtk nl80211 using parameters
268* @sub_cmd: the cmd define in the mtk_vendor_nl80211.h.
269* @if_type: now only support the NL80211_ATTR_IFINDEX/NL80211_ATTR_WIPHY.
270* @if_idx: the index should match the interface or wiphy.
271* Note: NA
272**/
273struct mtk_nl80211_param {
274 unsigned int sub_cmd;
275 int if_type;
276 int if_idx;
277};
278
279/**
developer121a8e72023-05-22 09:19:39 +0800280*struct mtk_nl80211_cb_data
281* init mtk nl80211 call back parameters
282* @out_buf: store the mtk vendor output msg for wifi hal buffer.
283* @out_len: the output buffer length.
284* Note: NA
285**/
286struct mtk_nl80211_cb_data {
287 char * out_buf;
288 unsigned int out_len;
289};
290
291/**
developer49b17232023-05-19 16:35:19 +0800292*mtk_nl80211_init
293* init mtk nl80211 netlink and init the vendor msg common part.
294* @nl: netlink, just init it.
295* @msg: netlink message will alloc it.
296* the msg send success/fails is not free by app
297* only the nla_put etc api fails should use nlmsg_free.
298* @msg_data: vendor data msg attr pointer.
299* @param: init using interface and sub_cmd parameter.
300*
301*init the netlink context and mtk netlink vendor msg.
302*
303*return:
304* 0: success
305* other: fail
306**/
307
308int mtk_nl80211_init(struct unl *nl, struct nl_msg **msg,
309 struct nlattr **msg_data, struct mtk_nl80211_param *param) {
310 /*sanity check here*/
311 if (!nl || !param) {
312 (void)fprintf(stderr,
313 "[%s][%d]:nl(0x%lx) or param(0x%lx) is null, error!\n",
314 __func__, __LINE__, nl, param);
315 return -1;
316 }
317 /*if_type check*/
318 if ( param->if_type != NL80211_ATTR_IFINDEX && param->if_type != NL80211_ATTR_WIPHY) {
319 (void)fprintf(stderr,
320 "[%s][%d]:if_type(0x%x) is not supported, only 0x%x and 0x%x supported.\n",
321 __func__, __LINE__, param->if_type, NL80211_ATTR_IFINDEX, NL80211_ATTR_WIPHY);
322 return -1;
323 }
324 /*init the nl*/
325 if (unl_genl_init(nl, "nl80211") < 0) {
326 (void)fprintf(stderr, "[%s][%d]::Failed to connect to nl80211\n",
327 __func__, __LINE__);
328 return -1;
329 }
330 /*init the msg*/
331 *msg = unl_genl_msg(nl, NL80211_CMD_VENDOR, false);
332
333 if (nla_put_u32(*msg, param->if_type, param->if_idx) ||
334 nla_put_u32(*msg, NL80211_ATTR_VENDOR_ID, MTK_NL80211_VENDOR_ID) ||
335 nla_put_u32(*msg, NL80211_ATTR_VENDOR_SUBCMD, param->sub_cmd)) {
336 (void)fprintf(stderr,
337 "[%s][%d]:Nla put error: if_type: 0x%x, if_idx: 0x%x, sub_cmd: 0x%x\n",
338 __func__, __LINE__, param->if_type, param->if_idx, param->sub_cmd);
339 goto err;
340 }
341
342 *msg_data = nla_nest_start(*msg, NL80211_ATTR_VENDOR_DATA);
343 if (!*msg_data) {
344 (void)fprintf(stderr, "[%s][%d]:Nla put NL80211_ATTR_VENDOR_DATA start error\n",
345 __func__, __LINE__);
346 goto err;
347 }
348
349 return 0;
350err:
351
352 nlmsg_free(*msg);
353 unl_free(nl);
354 return -1;
355}
356
357/**
358*mtk_nl80211_send
359* set the vendor cmd call back and sent the vendor msg.
360* @nl: netlink.
361* @msg: netlink message.
362* @msg_data: vendor data msg attr pointer.
363* @handler: if the msg have call back shoud add the call back func
364* the event msg will handle by the call back func(exp:get cmd)
365* other set it as NULL(exp:set cmd).
366* @arg:call back func arg parameter.
367*add end of the netlink msg, set the call back and send msg
368*
369*return:
370* 0: success
371* other: fail
372**/
373int mtk_nl80211_send(struct unl *nl, struct nl_msg *msg,
374 struct nlattr *msg_data, mtk_nl80211_cb handler, void *arg) {
375 int ret = 0;
376 /*sanity check*/
377 if (!nl || !msg || !msg_data) {
378 (void)fprintf(stderr,
379 "[%s][%d]:nl(0x%lx),msg(0x%lx) or msg_data(0x%lx) is null, error!\n",
380 __func__, __LINE__, nl, msg, msg_data);
381 return -1;
382 }
383 /*end the msg attr of vendor data*/
384 nla_nest_end(msg, msg_data);
385 /*send the msg and set call back */
386 ret = unl_genl_request(nl, msg, handler, arg);
387 if (ret)
388 (void)fprintf(stderr, "send nl80211 cmd fails\n");
389 return ret;
390}
391
392/**
393*mtk_nl80211_deint
394* deinit the netlink and the nl80211 vendor msg.
395* @nl: netlink.
396*
397*free deinit the netlink and the nl80211 vendor msg.
398*
399*return:
400* 0: success
401**/
402
403int mtk_nl80211_deint(struct unl *nl) {
404 unl_free(nl);
405 return 0;
406}
407
developer72fb0bb2023-01-11 09:46:29 +0800408
409static wifi_secur_list map_security[] =
410{
411 WIFI_ITEM_STR(wifi_security_mode_none, "None"),
412 WIFI_ITEM_STR(wifi_security_mode_wep_64, "WEP-64"),
413 WIFI_ITEM_STR(wifi_security_mode_wep_128, "WEP-128"),
414 WIFI_ITEM_STR(wifi_security_mode_wpa_personal, "WPA-Personal"),
415 WIFI_ITEM_STR(wifi_security_mode_wpa_enterprise, "WPA-Enterprise"),
416 WIFI_ITEM_STR(wifi_security_mode_wpa2_personal, "WPA2-Personal"),
417 WIFI_ITEM_STR(wifi_security_mode_wpa2_enterprise, "WPA2-Enterprise"),
418 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_personal, "WPA-WPA2-Personal"),
419 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_enterprise, "WPA-WPA2-Enterprise"),
420 WIFI_ITEM_STR(wifi_security_mode_wpa3_personal, "WPA3-Personal"),
421 WIFI_ITEM_STR(wifi_security_mode_wpa3_transition, "WPA3-Personal-Transition"),
422 WIFI_ITEM_STR(wifi_security_mode_wpa3_enterprise, "WPA3-Enterprise")
423};
424
425wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key)
426{
427 wifi_secur_list *item;
428 int i;
429
430 for (item = list,i = 0;i < list_sz; item++, i++) {
431 if ((int)(item->key) == key) {
432 return item;
433 }
434 }
435
436 return NULL;
437}
438
439char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key)
440{
441 wifi_secur_list *item = wifi_get_item_by_key(list, list_sz, key);
442
443 if (!item) {
444 return "";
445 }
446
447 return (char *)(item->data);
448}
449
450wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str)
451{
452 wifi_secur_list *item;
453 int i;
454
455 for (item = list,i = 0;i < list_sz; item++, i++) {
456 if (strcmp((char *)(item->data), str) == 0) {
457 return item;
458 }
459 }
460
461 return NULL;
462}
463#endif /* WIFI_HAL_VERSION_3 */
464
developer96b38512023-02-22 11:17:45 +0800465
466static char l1profile[32] = "/etc/wireless/l1profile.dat";
developer17038e62023-03-02 14:43:43 +0800467char main_prefix[MAX_NUM_RADIOS][IFNAMSIZ];
468char ext_prefix[MAX_NUM_RADIOS][IFNAMSIZ];
469#define MAX_SSID_LEN 64
470char default_ssid[MAX_NUM_RADIOS][MAX_SSID_LEN];;
developer745f0bd2023-03-06 14:32:53 +0800471int radio_band[MAX_NUM_RADIOS];
developer17038e62023-03-02 14:43:43 +0800472
473static int array_index_to_vap_index(UINT radioIndex, int arrayIndex);
474static int vap_index_to_array_index(int vapIndex, int *radioIndex, int *arrayIndex);
475
developer96b38512023-02-22 11:17:45 +0800476
477static int
478get_value(const char *conf_file, const char *param, char *value, int len)
479{
480 FILE *fp;
481 int ret = -1;
482 int param_len = strlen(param);
483 int buf_len;
484 char buf[256];
485
486 fp = fopen(conf_file, "r");
487 if (!fp) {
488 return -1;
489 }
490
491 while (fgets(buf, sizeof(buf), fp)) {
492 buf_len = strlen(buf);
493 if (buf[buf_len - 1] == '\n') {
494 buf_len--;
495 buf[buf_len] = '\0';
496 }
497 if ((buf_len > param_len) &&
498 (strncmp(buf, param, param_len) == 0) &&
499 (buf[param_len] == '=')) {
500
501 if (buf_len == (param_len + 1)) {
502 value[0] = '\0';
503 ret = 0;
504 } else {
505 ret = snprintf(value, len, "%s", buf + (param_len + 1));
506 }
507 fclose(fp);
508 return ret;
509 }
510 }
511 fclose(fp);
512 return -1;
513}
514
515static int
516get_value_by_idx(const char *conf_file, const char *param, int idx, char *value, int len)
517{
518 char buf[256];
519 int ret;
520 char *save_ptr = NULL;
521 char *tok = NULL;
522
523 ret = get_value(conf_file, param, buf, sizeof(buf));
524 if (ret < 0)
525 return ret;
526
527 tok = strtok_r(buf, ";", &save_ptr);
528 do {
529 if (idx == 0 || tok == NULL)
530 break;
531 else
532 idx--;
533
534 tok = strtok_r(NULL, ";", &save_ptr);
535 } while (tok != NULL);
536
537 if (tok) {
538 ret = snprintf(value, len, "%s", tok);
539 } else {
540 ret = 0;
541 value[0] = '\0';
542 }
543
544 return ret;
545}
546
547
developer72fb0bb2023-01-11 09:46:29 +0800548#ifdef HAL_NETLINK_IMPL
549typedef struct {
550 int id;
551 struct nl_sock* socket;
552 struct nl_cb* cb;
553} Netlink;
554
555static int mac_addr_aton(unsigned char *mac_addr, char *arg)
556{
557 unsigned int mac_addr_int[6]={};
558 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);
559 mac_addr[0] = mac_addr_int[0];
560 mac_addr[1] = mac_addr_int[1];
561 mac_addr[2] = mac_addr_int[2];
562 mac_addr[3] = mac_addr_int[3];
563 mac_addr[4] = mac_addr_int[4];
564 mac_addr[5] = mac_addr_int[5];
565 return 0;
566}
567
568static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
569{
570 unsigned int mac_addr_int[6]={};
571 mac_addr_int[0] = arg[0];
572 mac_addr_int[1] = arg[1];
573 mac_addr_int[2] = arg[2];
574 mac_addr_int[3] = arg[3];
575 mac_addr_int[4] = arg[4];
576 mac_addr_int[5] = arg[5];
577 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]);
578 return;
579}
580
581static int ieee80211_frequency_to_channel(int freq)
582{
583 /* see 802.11-2007 17.3.8.3.2 and Annex J */
584 if (freq == 2484)
585 return 14;
586 /* see 802.11ax D6.1 27.3.23.2 and Annex E */
587 else if (freq == 5935)
588 return 2;
589 else if (freq < 2484)
590 return (freq - 2407) / 5;
591 else if (freq >= 4910 && freq <= 4980)
592 return (freq - 4000) / 5;
593 else if (freq < 5950)
594 return (freq - 5000) / 5;
595 else if (freq <= 45000) /* DMG band lower limit */
596 /* see 802.11ax D6.1 27.3.23.2 */
597 return (freq - 5950) / 5;
598 else if (freq >= 58320 && freq <= 70200)
599 return (freq - 56160) / 2160;
600 else
601 return 0;
602}
603
604static int initSock80211(Netlink* nl) {
605 nl->socket = nl_socket_alloc();
606 if (!nl->socket) {
607 fprintf(stderr, "Failing to allocate the sock\n");
608 return -ENOMEM;
609 }
610
611 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
612
613 if (genl_connect(nl->socket)) {
614 fprintf(stderr, "Failed to connect\n");
615 nl_close(nl->socket);
616 nl_socket_free(nl->socket);
617 return -ENOLINK;
618 }
619
620 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
621 if (nl->id< 0) {
622 fprintf(stderr, "interface not found.\n");
623 nl_close(nl->socket);
624 nl_socket_free(nl->socket);
625 return -ENOENT;
626 }
627
628 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
629 if ((!nl->cb)) {
630 fprintf(stderr, "Failed to allocate netlink callback.\n");
631 nl_close(nl->socket);
632 nl_socket_free(nl->socket);
633 return ENOMEM;
634 }
635
636 return nl->id;
637}
638
639static int nlfree(Netlink *nl)
640{
641 nl_cb_put(nl->cb);
642 nl_close(nl->socket);
643 nl_socket_free(nl->socket);
644 return 0;
645}
646
647static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
648 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
649 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
650 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
651};
652
653static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
654};
655
656static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
657};
658
659typedef struct _wifi_channelStats_loc {
660 INT array_size;
661 INT ch_number;
662 BOOL ch_in_pool;
663 INT ch_noise;
664 BOOL ch_radar_noise;
665 INT ch_max_80211_rssi;
666 INT ch_non_80211_noise;
667 INT ch_utilization;
668 ULLONG ch_utilization_total;
669 ULLONG ch_utilization_busy;
670 ULLONG ch_utilization_busy_tx;
671 ULLONG ch_utilization_busy_rx;
672 ULLONG ch_utilization_busy_self;
673 ULLONG ch_utilization_busy_ext;
674} wifi_channelStats_t_loc;
675
676typedef struct wifi_device_info {
677 INT wifi_devIndex;
678 UCHAR wifi_devMacAddress[6];
679 CHAR wifi_devIPAddress[64];
680 BOOL wifi_devAssociatedDeviceAuthentiationState;
681 INT wifi_devSignalStrength;
682 INT wifi_devTxRate;
683 INT wifi_devRxRate;
684} wifi_device_info_t;
685
686#endif
687
688//For 5g Alias Interfaces
689static BOOL priv_flag = TRUE;
690static BOOL pub_flag = TRUE;
691static BOOL Radio_flag = TRUE;
692//wifi_setApBeaconRate(1, beaconRate);
693
694BOOL multiple_set = FALSE;
695
696struct params
697{
698 char * name;
699 char * value;
700};
701
702static int _syscmd(char *cmd, char *retBuf, int retBufSize)
703{
704 FILE *f;
705 char *ptr = retBuf;
706 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
707
708 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
709 if((f = popen(cmd, "r")) == NULL) {
710 fprintf(stderr,"\npopen %s error\n", cmd);
711 return RETURN_ERR;
712 }
713
714 while(!feof(f))
715 {
716 *ptr = 0;
717 if(bufSize>=128) {
718 bufbytes=128;
719 } else {
720 bufbytes=bufSize-1;
721 }
722
723 fgets(ptr,bufbytes,f);
724 readbytes=strlen(ptr);
725
726 if(!readbytes)
727 break;
728
729 bufSize-=readbytes;
730 ptr += readbytes;
731 }
732 cmd_ret = pclose(f);
733 retBuf[retBufSize-1]=0;
734 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
735
736 return cmd_ret >> 8;
737}
738
739INT radio_index_to_phy(int radioIndex)
740{
developer17038e62023-03-02 14:43:43 +0800741 /* TODO */
742 return radioIndex;
developer72fb0bb2023-01-11 09:46:29 +0800743}
744
745INT wifi_getMaxRadioNumber(INT *max_radio_num)
746{
747 char cmd[64] = {0};
748 char buf[4] = {0};
749
750 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
751
752 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
753 _syscmd(cmd, buf, sizeof(buf));
754 *max_radio_num = strtoul(buf, NULL, 10) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS:strtoul(buf, NULL, 10);
755
756 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
757
758 return RETURN_OK;
759}
760
developer17038e62023-03-02 14:43:43 +0800761wifi_band radio_index_to_band(int radioIndex)
762{
developer745f0bd2023-03-06 14:32:53 +0800763 return radio_band[radioIndex];
developer17038e62023-03-02 14:43:43 +0800764}
765
developer72fb0bb2023-01-11 09:46:29 +0800766wifi_band wifi_index_to_band(int apIndex)
767{
768 char cmd[128] = {0};
769 char buf[64] = {0};
770 int nl80211_band = 0;
771 int i = 0;
772 int phyIndex = 0;
773 int radioIndex = 0;
774 int max_radio_num = 0;
775 wifi_band band = band_invalid;
776
777 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
778
779 wifi_getMaxRadioNumber(&max_radio_num);
780 radioIndex = apIndex % max_radio_num;
781 phyIndex = radio_index_to_phy(radioIndex);
782 while(i < 10){
783 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Band .:' | tail -n 1 | tr -d ':\\n' | awk '{print $2}'", phyIndex);
784 _syscmd(cmd, buf, sizeof(buf));
785 nl80211_band = strtol(buf, NULL, 10);
786 if (nl80211_band == 1)
787 band = band_2_4;
788 else if (nl80211_band == 2)
789 band = band_5;
790 else if (nl80211_band == 4) // band == 3 is 60GHz
791 band = band_6;
792
793 if(band != band_invalid)
794 break;
developer69b61b02023-03-07 17:17:44 +0800795
developer72fb0bb2023-01-11 09:46:29 +0800796 i++;
797 sleep(1);
798 }
799
800 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
801 return band;
802}
803
804static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
805{
developer7e4a2a62023-04-06 19:56:03 +0800806 char cmd[MAX_CMD_SIZE] = {0};
807 char buf[MAX_BUF_SIZE] = {0};
808 int ret = 0;
developer72fb0bb2023-01-11 09:46:29 +0800809
developer7e4a2a62023-04-06 19:56:03 +0800810 ret = snprintf(cmd, MAX_CMD_SIZE, "cat %s 2> /dev/null | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"",
811 conf_file, param);
developer72fb0bb2023-01-11 09:46:29 +0800812
developer7e4a2a62023-04-06 19:56:03 +0800813 if (ret < 0) {
814 printf("%s: snprintf error!", __func__);
815 return -1;
816 }
817
818 ret = _syscmd(cmd, buf, sizeof(buf));
819 if ((ret != 0) && (strlen(buf) == 0)) {
820 printf("%s: _syscmd error!", __func__);
821 return -1;
822 }
823
824 snprintf(output, output_size, "%s", buf);
825
826 return 0;
developer72fb0bb2023-01-11 09:46:29 +0800827}
828
829static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
830{
developer7e4a2a62023-04-06 19:56:03 +0800831 char cmd[MAX_CMD_SIZE] = {0};
832 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +0800833
developer7e4a2a62023-04-06 19:56:03 +0800834 for (int i = 0; i < item_count; i++) {
developer72fb0bb2023-01-11 09:46:29 +0800835 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
developer7e4a2a62023-04-06 19:56:03 +0800836 if (strlen(buf) == 0) /*no such item, insert it*/
developera1255e42023-05-13 17:45:02 +0800837 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 +0800838 else /*find the item, update it*/
developer72fb0bb2023-01-11 09:46:29 +0800839 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 +0800840
developer72fb0bb2023-01-11 09:46:29 +0800841 if(_syscmd(cmd, buf, sizeof(buf)))
842 return -1;
843 }
844
developera1255e42023-05-13 17:45:02 +0800845 return 0;
846}
847static int wifi_datfileRead(char *conf_file, char *param, char *output, int output_size)
848{
849 char cmd[MAX_CMD_SIZE] = {0};
850 char buf[MAX_BUF_SIZE] = {0};
851 int ret = 0;
852
853 ret = snprintf(cmd, MAX_CMD_SIZE, "cat %s 2> /dev/null | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"",
854 conf_file, param);
855
856 if (ret < 0) {
857 printf("%s: snprintf error!", __func__);
858 return -1;
859 }
860
861 ret = _syscmd(cmd, buf, sizeof(buf));
862 if ((ret != 0) && (strlen(buf) == 0)) {
863 printf("%s: _syscmd error!", __func__);
864 return -1;
865 }
866
867 snprintf(output, output_size, "%s", buf);
868
developer72fb0bb2023-01-11 09:46:29 +0800869 return 0;
870}
871
developera1255e42023-05-13 17:45:02 +0800872static int wifi_datfileWrite(char *conf_file, struct params *list, int item_count)
873{
874 char cmd[MAX_CMD_SIZE] = {0};
875 char buf[MAX_BUF_SIZE] = {0};
876
877 for (int i = 0; i < item_count; i++) {
878 wifi_datfileRead(conf_file, list[i].name, buf, sizeof(buf));
879 if (strlen(buf) == 0) /*no such item, insert it*/
880 snprintf(cmd, sizeof(cmd), "sed -i -e '$a %s=%s' %s", list[i].name, list[i].value, conf_file);
881 else /*find the item, update it*/
882 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=%s/\" %s", list[i].name, list[i].name, list[i].value, conf_file);
883
884 if(_syscmd(cmd, buf, sizeof(buf)))
885 return -1;
886 }
887
888 return 0;
889}
890
developer72fb0bb2023-01-11 09:46:29 +0800891//For Getting Current Interface Name from corresponding hostapd configuration
892static int wifi_GetInterfaceName(int apIndex, char *interface_name)
893{
894 char config_file[128] = {0};
895
896 if (interface_name == NULL)
897 return RETURN_ERR;
898
899 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
900
901 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
902 wifi_hostapdRead(config_file, "interface", interface_name, 16);
903 if (strlen(interface_name) == 0)
904 return RETURN_ERR;
905
906 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
907 return RETURN_OK;
908}
909
developera1255e42023-05-13 17:45:02 +0800910static UCHAR get_bssnum_byindex(INT radio_index, UCHAR *bss_cnt)
911{
912 char interface_name[IF_NAME_SIZE] = {0};
913 char cmd[MAX_BUF_SIZE]={'\0'};
914 char buf[MAX_CMD_SIZE]={'\0'};
915 UCHAR channel = 0;
916
917 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
918 return RETURN_ERR;
919 /*interface name to channel number*/
920 snprintf(cmd, sizeof(cmd), "iw dev %s info | grep -i 'channel' | cut -d ' ' -f2", interface_name);
921 _syscmd(cmd, buf, sizeof(buf));
922 channel = atoi(buf);
923 WIFI_ENTRY_EXIT_DEBUG("%s:channel=%d\n", __func__, channel);
924 /*count dev number with the same channel*/
925 snprintf(cmd, sizeof(cmd), "iw dev | grep -i 'channel %d' | wc -l", channel);
926 _syscmd(cmd, buf, sizeof(buf));
927 *bss_cnt = atoi(buf) - 1;/*1 for apcli interface*/
928 WIFI_ENTRY_EXIT_DEBUG("%s:bss_cnt=%d\n", __func__, *bss_cnt);
929 return RETURN_OK;
930}
developer72fb0bb2023-01-11 09:46:29 +0800931
developerd1824452023-05-18 12:30:04 +0800932/* index: radio index or phy index
933 phy: true-> base phy command
934 false-> base radio command */
935static int wifi_mwctlSet(int index, struct params *mwctl, bool phy)
936{
937 char cmd[MAX_CMD_SIZE]={'\0'};
938 char buf[MAX_BUF_SIZE]={'\0'};
939 char interface_name[16] = {0};
940
941 if (phy == TRUE)
942 snprintf(cmd, sizeof(cmd), "mwctl phy phy%d set %s%s", index, mwctl->name, mwctl->value);
943 else {
944 if (wifi_GetInterfaceName(index, interface_name) != RETURN_OK)
945 return RETURN_ERR;
946 snprintf(cmd, sizeof(cmd), "mwctl %s set %s%s", interface_name, mwctl->name, mwctl->value);
947 }
948 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
949 return RETURN_ERR;
950
951 return RETURN_OK;
952}
953
developer72fb0bb2023-01-11 09:46:29 +0800954static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
955{
956 char interface_name[16] = {0};
957 if (multiple_set == TRUE)
958 return RETURN_OK;
959 char cmd[MAX_CMD_SIZE]="", output[32]="";
960 FILE *fp;
961 int i;
962 //NOTE RELOAD should be done in ApplySSIDSettings
963 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
964 return RETURN_ERR;
965 for(i=0; i<item_count; i++, list++)
966 {
developerf6a87542023-05-16 15:47:28 +0800967 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s SET %s %s", interface_name, list->name, list->value);
developer72fb0bb2023-01-11 09:46:29 +0800968 if((fp = popen(cmd, "r"))==NULL)
969 {
970 perror("popen failed");
971 return -1;
972 }
973 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
974 {
975 pclose(fp);
976 perror("fgets failed");
977 return -1;
978 }
979 pclose(fp);
980 }
981 return 0;
982}
983
developer7e4a2a62023-04-06 19:56:03 +0800984static int wifi_quick_reload_ap(int apIndex)
985{
986 char interface_name[IF_NAME_SIZE] = {0};
987 char cmd[MAX_CMD_SIZE] = {0};
988 char buf[MAX_BUF_SIZE] = {0};
989
990 if (multiple_set == TRUE)
991 return RETURN_OK;
992
993 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
994 return RETURN_ERR;
995
996 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s reload", interface_name);
997 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
998 return RETURN_ERR;
999
1000 return RETURN_OK;
1001}
1002
developer72fb0bb2023-01-11 09:46:29 +08001003static int wifi_reloadAp(int apIndex)
1004{
1005 char interface_name[16] = {0};
1006 if (multiple_set == TRUE)
1007 return RETURN_OK;
1008 char cmd[MAX_CMD_SIZE]="";
1009 char buf[MAX_BUF_SIZE]="";
1010
1011 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
1012 return RETURN_ERR;
1013 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s reload", interface_name);
1014 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
1015 return RETURN_ERR;
1016
1017 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s disable", interface_name);
1018 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
1019 return RETURN_ERR;
1020
1021 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s enable", interface_name);
1022 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
1023 return RETURN_ERR;
1024
1025 return RETURN_OK;
1026}
1027
1028INT File_Reading(CHAR *file, char *Value)
1029{
1030 FILE *fp = NULL;
1031 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
1032 int count = 0;
1033
1034 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1035 fp = popen(file,"r");
1036 if(fp == NULL)
1037 return RETURN_ERR;
1038
1039 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
1040 {
1041 for(count=0;buf[count]!='\n';count++)
1042 copy_buf[count]=buf[count];
1043 copy_buf[count]='\0';
1044 }
1045 strcpy(Value,copy_buf);
1046 pclose(fp);
1047 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1048
1049 return RETURN_OK;
1050}
1051
1052void wifi_RestartHostapd_2G()
1053{
1054 int Public2GApIndex = 4;
1055
1056 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1057 wifi_setApEnable(Public2GApIndex, FALSE);
1058 wifi_setApEnable(Public2GApIndex, TRUE);
1059 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1060}
1061
1062void wifi_RestartHostapd_5G()
1063{
1064 int Public5GApIndex = 5;
1065
1066 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1067 wifi_setApEnable(Public5GApIndex, FALSE);
1068 wifi_setApEnable(Public5GApIndex, TRUE);
1069 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1070}
1071
1072void wifi_RestartPrivateWifi_2G()
1073{
1074 int PrivateApIndex = 0;
1075
1076 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1077 wifi_setApEnable(PrivateApIndex, FALSE);
1078 wifi_setApEnable(PrivateApIndex, TRUE);
1079 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1080}
1081
1082void wifi_RestartPrivateWifi_5G()
1083{
1084 int Private5GApIndex = 1;
1085
1086 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1087 wifi_setApEnable(Private5GApIndex, FALSE);
1088 wifi_setApEnable(Private5GApIndex, TRUE);
1089 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1090}
1091
1092static int writeBandWidth(int radioIndex,char *bw_value)
1093{
1094 char buf[MAX_BUF_SIZE];
1095 char cmd[MAX_CMD_SIZE];
1096
1097 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
1098 if(_syscmd(cmd, buf, sizeof(buf)))
1099 {
1100 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
1101 _syscmd(cmd, buf, sizeof(buf));
1102 return RETURN_OK;
1103 }
1104
1105 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
1106 _syscmd(cmd,buf,sizeof(buf));
1107 return RETURN_OK;
1108}
1109
1110static int readBandWidth(int radioIndex,char *bw_value)
1111{
1112 char buf[MAX_BUF_SIZE] = {0};
1113 char cmd[MAX_CMD_SIZE] = {0};
1114 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
1115 _syscmd(cmd,buf,sizeof(buf));
1116 if(NULL!=strstr(buf,"20MHz"))
developer72fb0bb2023-01-11 09:46:29 +08001117 strcpy(bw_value,"20MHz");
developer72fb0bb2023-01-11 09:46:29 +08001118 else if(NULL!=strstr(buf,"40MHz"))
developer72fb0bb2023-01-11 09:46:29 +08001119 strcpy(bw_value,"40MHz");
developer72fb0bb2023-01-11 09:46:29 +08001120 else if(NULL!=strstr(buf,"80MHz"))
developer72fb0bb2023-01-11 09:46:29 +08001121 strcpy(bw_value,"80MHz");
developerd1824452023-05-18 12:30:04 +08001122 else if(NULL!=strstr(buf,"160MHz"))
1123 strcpy(bw_value,"160MHz");
1124 else if(NULL!=strstr(buf,"320MHz"))
1125 strcpy(bw_value,"320MHz");
developer72fb0bb2023-01-11 09:46:29 +08001126 else
developer72fb0bb2023-01-11 09:46:29 +08001127 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08001128 return RETURN_OK;
1129}
1130
1131// Input could be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
1132INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
1133{
1134 struct params params={'\0'};
1135 char config_file[MAX_BUF_SIZE] = {0};
1136 char buf[MAX_BUF_SIZE] = {'\0'};
1137
1138 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1139 // Copy the numeric value
1140 if (strlen (beaconRate) >= 5) {
1141 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
1142 buf[strlen(beaconRate) - 4] = '\0';
1143 } else if (strlen(beaconRate) > 0)
1144 strcpy(buf, beaconRate);
1145 else
1146 return RETURN_ERR;
1147
1148 params.name = "beacon_rate";
1149 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
1150 if (strncmp(buf, "5.5", 3) == 0) {
1151 snprintf(buf, sizeof(buf), "55");
1152 params.value = buf;
1153 } else {
1154 strcat(buf, "0");
1155 params.value = buf;
1156 }
1157
1158 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1159 wifi_hostapdWrite(config_file, &params, 1);
1160 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1161 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1162
1163 return RETURN_OK;
1164}
1165
1166INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
1167{
1168 char config_file[128] = {'\0'};
1169 char temp_output[128] = {'\0'};
1170 char buf[128] = {'\0'};
1171 char cmd[128] = {'\0'};
1172 int rate = 0;
1173 int phyId = 0;
1174
1175 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1176 if (NULL == beaconRate)
1177 return RETURN_ERR;
1178
1179 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1180 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
1181 phyId = radio_index_to_phy(radioIndex);
1182 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
1183 if(strlen(buf) > 0) {
1184 if (strncmp(buf, "55", 2) == 0)
1185 snprintf(temp_output, sizeof(temp_output), "5.5Mbps");
1186 else {
1187 rate = strtol(buf, NULL, 10)/10;
1188 snprintf(temp_output, sizeof(temp_output), "%dMbps", rate);
1189 }
1190 } else {
1191 // config not set, so we would use lowest rate as default
1192 sprintf(cmd, "iw phy%d info | grep Bitrates -A1 | tail -n 1 | awk '{print $2}' | tr -d '.0\\n'", phyId);
1193 _syscmd(cmd, buf, sizeof(buf));
1194 snprintf(temp_output, sizeof(temp_output), "%sMbps", buf);
1195 }
1196 strncpy(beaconRate, temp_output, sizeof(temp_output));
1197 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1198
1199 return RETURN_OK;
1200}
1201
1202INT wifi_setLED(INT radioIndex, BOOL enable)
1203{
1204 return 0;
1205}
1206INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
1207{
1208 return RETURN_OK;
1209}
1210/**********************************************************************************
1211 *
developer69b61b02023-03-07 17:17:44 +08001212 * Wifi Subsystem level function prototypes
developer72fb0bb2023-01-11 09:46:29 +08001213 *
1214**********************************************************************************/
1215//---------------------------------------------------------------------------------------------------
1216//Wifi system api
1217//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 +08001218INT wifi_getHalVersion(CHAR *output_string) //RDKB
developer72fb0bb2023-01-11 09:46:29 +08001219{
1220 if(!output_string)
1221 return RETURN_ERR;
1222 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
1223
1224 return RETURN_OK;
1225}
1226
1227
1228/* wifi_factoryReset() function */
1229/**
developer69b61b02023-03-07 17:17:44 +08001230* @description Clears internal variables to implement a factory reset of the Wi-Fi
developer72fb0bb2023-01-11 09:46:29 +08001231* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
1232*
1233* @param None
1234*
1235* @return The status of the operation.
1236* @retval RETURN_OK if successful.
1237* @retval RETURN_ERR if any error is detected
1238*
1239* @execution Synchronous
1240* @sideeffect None
1241*
1242* @note This function must not suspend and must not invoke any blocking system
1243* calls. It should probably just send a message to a driver event handler task.
1244*
1245*/
1246INT wifi_factoryReset()
1247{
developer47cc27a2023-05-17 23:09:58 +08001248 char cmd[MAX_CMD_SIZE] = {0};
1249 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08001250
developer47cc27a2023-05-17 23:09:58 +08001251 /*delete running hostapd conf files*/
1252 wifi_dbg_printf("\n[%s]: deleting hostapd conf file.", __func__);
1253 snprintf(cmd, MAX_CMD_SIZE, "rm -rf /nvram/*.conf");
1254 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08001255
developer47cc27a2023-05-17 23:09:58 +08001256 wifi_PrepareDefaultHostapdConfigs();
1257 wifi_psk_file_reset();
1258
1259 memset(cmd, 0, MAX_CMD_SIZE);
1260 memset(buf, 0, MAX_BUF_SIZE);
1261
1262 snprintf(cmd, MAX_CMD_SIZE, "systemctl restart hostapd.service");
1263 _syscmd(cmd, buf, sizeof(buf));
1264
1265 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08001266}
1267
1268/* wifi_factoryResetRadios() function */
1269/**
1270* @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.
1271*
1272* @param None
1273* @return The status of the operation
1274* @retval RETURN_OK if successful
1275* @retval RETURN_ERR if any error is detected
1276*
1277* @execution Synchronous
1278*
1279* @sideeffect None
1280*
1281* @note This function must not suspend and must not invoke any blocking system
1282* calls. It should probably just send a message to a driver event handler task.
1283*
1284*/
1285INT wifi_factoryResetRadios()
1286{
1287 if((RETURN_OK == wifi_factoryResetRadio(0)) && (RETURN_OK == wifi_factoryResetRadio(1)))
1288 return RETURN_OK;
1289
1290 return RETURN_ERR;
1291}
1292
1293
1294/* wifi_factoryResetRadio() function */
1295/**
1296* @description Restore selected radio parameters without touching access point parameters
1297*
1298* @param radioIndex - Index of Wi-Fi Radio channel
1299*
1300* @return The status of the operation.
1301* @retval RETURN_OK if successful.
1302* @retval RETURN_ERR if any error is detected
1303*
1304* @execution Synchronous.
1305* @sideeffect None.
1306*
1307* @note This function must not suspend and must not invoke any blocking system
1308* calls. It should probably just send a message to a driver event handler task.
1309*
1310*/
1311INT wifi_factoryResetRadio(int radioIndex) //RDKB
1312{
developer47cc27a2023-05-17 23:09:58 +08001313 char cmd[MAX_CMD_SIZE] = {0};
1314 char buf[MAX_BUF_SIZE] = {0};
1315 char vap_idx = 0;
developer72fb0bb2023-01-11 09:46:29 +08001316
developer47cc27a2023-05-17 23:09:58 +08001317 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08001318
developer47cc27a2023-05-17 23:09:58 +08001319 snprintf(cmd, MAX_CMD_SIZE, "systemctl stop hostapd.service");
1320 _syscmd(cmd, buf, sizeof(buf));
1321
1322 memset(cmd, 0, MAX_CMD_SIZE);
1323 memset(buf, 0, MAX_BUF_SIZE);
1324
1325 for (vap_idx = radioIndex; vap_idx < MAX_APS; vap_idx += MAX_NUM_RADIOS)
1326 wifi_factoryResetAP(vap_idx);
1327
1328 snprintf(cmd, MAX_CMD_SIZE, "systemctl start hostapd.service");
1329 _syscmd(cmd, buf, sizeof(buf));
1330
1331 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
1332 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08001333}
1334
1335/* wifi_initRadio() function */
1336/**
1337* Description: This function call initializes the specified radio.
developer69b61b02023-03-07 17:17:44 +08001338* Implementation specifics may dictate the functionality since
developer72fb0bb2023-01-11 09:46:29 +08001339* different hardware implementations may have different initilization requirements.
1340* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
1341*
1342* @return The status of the operation.
1343* @retval RETURN_OK if successful.
1344* @retval RETURN_ERR if any error is detected
1345*
1346* @execution Synchronous.
1347* @sideeffect None.
1348*
1349* @note This function must not suspend and must not invoke any blocking system
1350* calls. It should probably just send a message to a driver event handler task.
1351*
1352*/
1353INT wifi_initRadio(INT radioIndex)
1354{
1355 //TODO: Initializes the wifi subsystem (for specified radio)
1356 return RETURN_OK;
1357}
1358void macfilter_init()
1359{
1360 char count[4]={'\0'};
1361 char buf[253]={'\0'};
1362 char tmp[19]={'\0'};
1363 int dev_count,block,mac_entry=0;
1364 char res[4]={'\0'};
1365 char acl_file_path[64] = {'\0'};
1366 FILE *fp = NULL;
1367 int index=0;
1368 char iface[10]={'\0'};
1369 char config_file[MAX_BUF_SIZE] = {0};
1370
1371
1372 sprintf(acl_file_path,"/tmp/mac_filter.sh");
1373
1374 fp=fopen(acl_file_path,"w+");
1375 if (fp == NULL) {
1376 fprintf(stderr, "%s: failed to open file %s.\n", __func__, acl_file_path);
developer17038e62023-03-02 14:43:43 +08001377 return;
developer72fb0bb2023-01-11 09:46:29 +08001378 }
1379 sprintf(buf,"#!/bin/sh \n");
1380 fprintf(fp,"%s\n",buf);
1381
1382 system("chmod 0777 /tmp/mac_filter.sh");
1383
1384 for(index=0;index<=1;index++)
1385 {
1386 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
1387 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
1388 sprintf(buf,"syscfg get %dcountfilter",index);
1389 _syscmd(buf,count,sizeof(count));
1390 mac_entry=atoi(count);
1391
1392 sprintf(buf,"syscfg get %dblockall",index);
1393 _syscmd(buf,res,sizeof(res));
1394 block = atoi(res);
1395
1396 //Allow only those macs mentioned in ACL
1397 if(block==1)
1398 {
1399 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1400 fprintf(fp,"%s\n",buf);
1401 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1402 {
1403 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1404 _syscmd(buf,tmp,sizeof(tmp));
1405 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
1406 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
1407 fprintf(fp,"%s\n",buf);
1408 }
1409 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
1410 fprintf(fp,"%s\n",buf);
1411 }
1412
1413 //Block all the macs mentioned in ACL
1414 else if(block==2)
1415 {
1416 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1417 fprintf(fp,"%s\n",buf);
1418
1419 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1420 {
1421 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1422 _syscmd(buf,tmp,sizeof(tmp));
1423 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
1424 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
1425 fprintf(fp,"%s\n",buf);
1426 }
1427 }
1428 }
1429 fclose(fp);
1430}
1431
developer17038e62023-03-02 14:43:43 +08001432
1433static void
1434wifi_ParseProfile(void)
1435{
1436 int i;
1437 int max_radio_num = 0;
1438 int card_idx;
1439 int band_idx;
1440 int phy_idx = 0;
developer745f0bd2023-03-06 14:32:53 +08001441 int wireless_mode = 0;
developer17038e62023-03-02 14:43:43 +08001442 char buf[MAX_BUF_SIZE] = {0};
1443 char chip_name[12];
1444 char card_profile[MAX_BUF_SIZE] = {0};
1445 char band_profile[MAX_BUF_SIZE] = {0};
1446 FILE* fp;
1447
1448 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1449
1450 memset(main_prefix, 0, sizeof(main_prefix));
1451 memset(ext_prefix, 0, sizeof(ext_prefix));
1452 memset(default_ssid, 0, sizeof(default_ssid));
developer745f0bd2023-03-06 14:32:53 +08001453 for (i = 0; i < MAX_NUM_RADIOS; i++)
1454 radio_band[i] = band_invalid;
developer17038e62023-03-02 14:43:43 +08001455
1456 if (wifi_getMaxRadioNumber(&max_radio_num) != RETURN_OK) {
1457 /* LOG */
1458 return;
1459 }
1460
1461 for (card_idx = 0; card_idx < 3; card_idx++) {
1462 snprintf(buf, sizeof(buf), "INDEX%d", card_idx);
1463 if (get_value(l1profile, buf, chip_name, sizeof(chip_name)) < 0) {
1464 break;
1465 }
1466 snprintf(buf, sizeof(buf), "INDEX%d_profile_path", card_idx);
1467 if (get_value(l1profile, buf, card_profile, sizeof(card_profile)) < 0) {
1468 break;
1469 }
1470 for (band_idx = 0; band_idx < 3; band_idx++) {
1471 snprintf(buf, sizeof(buf), "BN%d_profile_path", band_idx);
1472 if (get_value(card_profile, buf, band_profile, sizeof(band_profile)) < 0) {
1473 /* LOG */
1474 break;
1475 }
1476
1477 snprintf(buf, sizeof(buf), "INDEX%d_main_ifname", card_idx);
1478 if (get_value_by_idx(l1profile, buf, band_idx, main_prefix[phy_idx], IFNAMSIZ) < 0) {
1479 /* LOG */
1480 }
1481
1482 snprintf(buf, sizeof(buf), "INDEX%d_ext_ifname", card_idx);
1483 if (get_value_by_idx(l1profile, buf, band_idx, ext_prefix[phy_idx], IFNAMSIZ) < 0) {
1484 /* LOG */
1485 }
1486
1487 if (get_value(band_profile, "SSID1", default_ssid[phy_idx], sizeof(default_ssid[phy_idx])) < 0) {
1488 /* LOG */
1489 }
developer745f0bd2023-03-06 14:32:53 +08001490 if (get_value(band_profile, "WirelessMode", buf, sizeof(buf)) < 0) {
1491 /* LOG */
1492 }
1493
1494 wireless_mode = atoi(buf);
1495 switch (wireless_mode) {
1496 case 22:
1497 case 16:
1498 case 6:
1499 case 4:
1500 case 1:
1501 radio_band[phy_idx] = band_2_4;
1502 break;
1503 case 23:
1504 case 17:
1505 case 14:
1506 case 11:
1507 case 2:
1508 radio_band[phy_idx] = band_5;
1509 break;
1510 case 24:
1511 case 18:
1512 radio_band[phy_idx] = band_6;
1513 break;
1514 }
developer17038e62023-03-02 14:43:43 +08001515 phy_idx++;
1516 }
1517 }
1518
1519 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1520}
1521
1522static void
1523wifi_PrepareDefaultHostapdConfigs(void)
1524{
developer0132ed92023-03-21 13:48:53 +08001525 int radio_idx;
1526 int bss_idx;
1527 int ap_idx;
developer0132ed92023-03-21 13:48:53 +08001528 char buf[MAX_BUF_SIZE] = {0};
1529 char config_file[MAX_BUF_SIZE] = {0};
1530 char ssid[MAX_BUF_SIZE] = {0};
1531 char interface[32] = {0};
1532 char ret_buf[MAX_BUF_SIZE] = {0};
1533 char psk_file[64] = {0};
1534 struct params params[3];
developer47cc27a2023-05-17 23:09:58 +08001535 char *band_str[3] = {"2G", "5G", "6G"};
developer17038e62023-03-02 14:43:43 +08001536
developer0132ed92023-03-21 13:48:53 +08001537 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1538 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++) {
developer47cc27a2023-05-17 23:09:58 +08001539
developer0132ed92023-03-21 13:48:53 +08001540 for (bss_idx = 0; bss_idx < 5; bss_idx++) {
developer47cc27a2023-05-17 23:09:58 +08001541 ap_idx = array_index_to_vap_index(radio_idx, bss_idx);
developer0132ed92023-03-21 13:48:53 +08001542
developer47cc27a2023-05-17 23:09:58 +08001543 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_idx);
1544 snprintf(buf, sizeof(buf), "cp /etc/hostapd-%s.conf %s", band_str[radio_idx], config_file);
1545 _syscmd(buf, ret_buf, sizeof(ret_buf));
developer17038e62023-03-02 14:43:43 +08001546
developer47cc27a2023-05-17 23:09:58 +08001547 if (radio_idx == band_2_4) {
1548 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_2G, bss_idx);
1549 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI2G, bss_idx);
1550 } else if (radio_idx == band_5) {
1551 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_5G, bss_idx);
1552 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI5G, bss_idx);
1553 } else if (radio_idx == band_6) {
1554 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_6G, bss_idx);
1555 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI6G, bss_idx);
1556 }
developer17038e62023-03-02 14:43:43 +08001557
developer47cc27a2023-05-17 23:09:58 +08001558 /* fix wpa_psk_file path */
1559 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", ap_idx);
developer17038e62023-03-02 14:43:43 +08001560
developer47cc27a2023-05-17 23:09:58 +08001561 params[0].name = "ssid";
1562 params[0].value = ssid;
1563 params[1].name = "interface";
1564 params[1].value = interface;
1565 params[2].name = "wpa_psk_file";
1566 params[2].value = psk_file;
developer17038e62023-03-02 14:43:43 +08001567
developer47cc27a2023-05-17 23:09:58 +08001568 wifi_hostapdWrite(config_file, params, 3);
developer0132ed92023-03-21 13:48:53 +08001569 }
1570 }
1571 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer17038e62023-03-02 14:43:43 +08001572}
1573
1574static void
1575wifiBringUpInterfacesForRadio(int radio_idx)
1576{
developer0132ed92023-03-21 13:48:53 +08001577 int bss_idx;
1578 int ap_idx;
1579 int band_idx;
1580 char cmd[MAX_CMD_SIZE] = {0};
1581 char config_file[MAX_BUF_SIZE] = {0};
1582 char ret_buf[MAX_BUF_SIZE] = {0};
developer8a3bbbf2023-03-15 17:47:23 +08001583 char inf_name[IF_NAME_SIZE] = {0};
developer17038e62023-03-02 14:43:43 +08001584
1585 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer8a3bbbf2023-03-15 17:47:23 +08001586
developered997d32023-04-18 22:45:39 +08001587 bss_idx = 0;
1588 /*TBD: we need refine setup flow and mbss flow*/
1589// for (bss_idx = 0; bss_idx < 5; bss_idx++) {
developer0132ed92023-03-21 13:48:53 +08001590 ap_idx = array_index_to_vap_index(radio_idx, bss_idx);
1591
1592 snprintf(cmd, sizeof(cmd), "touch %s%d.psk", PSK_FILE, ap_idx);
1593 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1594
1595 memset(cmd, 0, MAX_CMD_SIZE);
1596 memset(ret_buf, 0, MAX_BUF_SIZE);
developer17038e62023-03-02 14:43:43 +08001597
developer0132ed92023-03-21 13:48:53 +08001598 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_idx);
1599 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:%s", radio_idx, config_file);
1600 _syscmd(cmd, ret_buf, sizeof(ret_buf));
developer8a3bbbf2023-03-15 17:47:23 +08001601
1602 wifi_GetInterfaceName(ap_idx, inf_name);
1603
1604 memset(cmd, 0, MAX_CMD_SIZE);
1605 memset(ret_buf, 0, MAX_BUF_SIZE);
1606
1607 /* fix vap-status file */
1608 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=1/\" %s", inf_name, inf_name, VAP_STATUS_FILE);
1609 _syscmd(cmd, ret_buf, sizeof(ret_buf));
developered997d32023-04-18 22:45:39 +08001610// }
1611
1612 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer17038e62023-03-02 14:43:43 +08001613}
1614
1615static void
1616wifi_BringUpInterfaces(void)
1617{
1618 int radio_idx;
1619 int bss_idx;
1620 int ap_idx;
1621 int band_idx;
1622 char cmd[MAX_BUF_SIZE] = {0};
1623 char config_file[MAX_BUF_SIZE] = {0};
1624 char ret_buf[MAX_BUF_SIZE]={'\0'};
1625
1626 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1627 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++) {
1628 band_idx = radio_index_to_band(radio_idx);
1629 if (band_idx < 0) {
1630 break;
1631 }
1632 wifiBringUpInterfacesForRadio(radio_idx);
1633 }
1634 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1635}
1636
1637static void
1638wifi_BringDownInterfacesForRadio(int radio_idx)
1639{
1640 int bss_idx;
1641 int ap_idx;
1642 int band_idx;
1643 char cmd[MAX_BUF_SIZE] = {0};
1644 char config_file[MAX_BUF_SIZE] = {0};
1645 char ret_buf[MAX_BUF_SIZE]={'\0'};
1646
1647 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer17038e62023-03-02 14:43:43 +08001648
developer8a3bbbf2023-03-15 17:47:23 +08001649 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s", main_prefix[radio_idx]);
1650 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1651
1652
developer17038e62023-03-02 14:43:43 +08001653 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1654}
1655
1656
1657static void
1658wifi_BringDownInterfaces(void)
1659{
1660 int radio_idx;
1661 int bss_idx;
1662 int ap_idx;
1663 int band_idx;
1664 char cmd[MAX_BUF_SIZE] = {0};
1665 char config_file[MAX_BUF_SIZE] = {0};
1666 char ret_buf[MAX_BUF_SIZE]={'\0'};
1667
1668 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1669 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++) {
1670 band_idx = radio_index_to_band(radio_idx);
1671 if (band_idx < 0) {
1672 break;
1673 }
1674 wifi_BringDownInterfacesForRadio(radio_idx);
1675 }
1676 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1677}
1678
developer47cc27a2023-05-17 23:09:58 +08001679static void wifi_psk_file_reset()
1680{
1681 char cmd[MAX_CMD_SIZE] = {0};
1682 char ret_buf[MAX_BUF_SIZE] = {0};
1683 char psk_file[MAX_CMD_SIZE]= {0};
1684 char vap_idx = 0;
1685
1686 for (vap_idx = 0; vap_idx < MAX_APS; vap_idx++) {
1687 snprintf(psk_file, sizeof(psk_file), "%s%d.psk", PSK_FILE, vap_idx);
1688
1689 if (access(psk_file, F_OK) != 0) {
1690 snprintf(cmd, MAX_CMD_SIZE, "touch %s", psk_file);
1691 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1692 } else {
1693 snprintf(cmd, MAX_CMD_SIZE, "echo '' > %s", psk_file);
1694 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1695 }
1696 }
1697}
1698
developer8a3bbbf2023-03-15 17:47:23 +08001699static void wifi_vap_status_reset()
1700{
1701 char cmd[MAX_CMD_SIZE] = {0};
1702 char ret_buf[MAX_BUF_SIZE] = {0};
1703 char radio_idx = 0;
1704 char bss_idx = 0;
developer8666b312023-03-24 14:05:31 +08001705
developer8a3bbbf2023-03-15 17:47:23 +08001706 if (access(VAP_STATUS_FILE, F_OK) != 0) {
1707 snprintf(cmd, MAX_CMD_SIZE, "touch %s", VAP_STATUS_FILE);
1708 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1709 } else {
1710 snprintf(cmd, MAX_CMD_SIZE, "echo '' > %s", VAP_STATUS_FILE);
1711 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1712 }
1713
1714 memset(cmd, 0, MAX_CMD_SIZE);
1715 memset(ret_buf, 0, MAX_BUF_SIZE);
1716
1717 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++)
1718 for (bss_idx = 0; bss_idx < 5; bss_idx++) {
1719 snprintf(cmd, MAX_CMD_SIZE, "echo %s%d=0 >> %s", ext_prefix[radio_idx], bss_idx, VAP_STATUS_FILE);
1720 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1721 }
1722
1723}
developer17038e62023-03-02 14:43:43 +08001724
developer72fb0bb2023-01-11 09:46:29 +08001725// Initializes the wifi subsystem (all radios)
1726INT wifi_init() //RDKB
1727{
developer96b38512023-02-22 11:17:45 +08001728 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1729 //Not intitializing macfilter for Turris-Omnia Platform for now
1730 //macfilter_init();
developer17038e62023-03-02 14:43:43 +08001731 wifi_ParseProfile();
1732 wifi_PrepareDefaultHostapdConfigs();
developer47cc27a2023-05-17 23:09:58 +08001733 wifi_psk_file_reset();
developer17038e62023-03-02 14:43:43 +08001734 //system("/usr/sbin/iw reg set US");
1735 system("systemctl start hostapd.service");
1736 sleep(2);
developer8a3bbbf2023-03-15 17:47:23 +08001737
1738 wifi_vap_status_reset();
1739
developer17038e62023-03-02 14:43:43 +08001740 wifi_BringUpInterfaces();
developer96b38512023-02-22 11:17:45 +08001741
developer96b38512023-02-22 11:17:45 +08001742
1743 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08001744
1745 return RETURN_OK;
1746}
1747
1748/* wifi_reset() function */
1749/**
1750* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
developer69b61b02023-03-07 17:17:44 +08001751* Implementation specifics may dictate what is actualy reset since
developer72fb0bb2023-01-11 09:46:29 +08001752* different hardware implementations may have different requirements.
1753* Parameters : None
1754*
1755* @return The status of the operation.
1756* @retval RETURN_OK if successful.
1757* @retval RETURN_ERR if any error is detected
1758*
1759* @execution Synchronous.
1760* @sideeffect None.
1761*
1762* @note This function must not suspend and must not invoke any blocking system
1763* calls. It should probably just send a message to a driver event handler task.
1764*
1765*/
1766INT wifi_reset()
1767{
developer17038e62023-03-02 14:43:43 +08001768
1769 wifi_BringDownInterfaces();
1770 sleep(2);
1771
developer96b38512023-02-22 11:17:45 +08001772 //TODO: resets the wifi subsystem, deletes all APs
1773 system("systemctl stop hostapd.service");
1774 sleep(2);
developer17038e62023-03-02 14:43:43 +08001775
developer96b38512023-02-22 11:17:45 +08001776 system("systemctl start hostapd.service");
1777 sleep(5);
developer17038e62023-03-02 14:43:43 +08001778
1779 wifi_PrepareDefaultHostapdConfigs();
developer47cc27a2023-05-17 23:09:58 +08001780 wifi_psk_file_reset();
developer17038e62023-03-02 14:43:43 +08001781 sleep(2);
developer8a3bbbf2023-03-15 17:47:23 +08001782
1783 wifi_vap_status_reset();
1784
developer17038e62023-03-02 14:43:43 +08001785 wifi_BringUpInterfaces();
1786
developer72fb0bb2023-01-11 09:46:29 +08001787 return RETURN_OK;
1788}
1789
1790/* wifi_down() function */
1791/**
1792* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
developer69b61b02023-03-07 17:17:44 +08001793* Implementation specifics may dictate some functionality since
developer72fb0bb2023-01-11 09:46:29 +08001794* different hardware implementations may have different requirements.
1795*
1796* @param None
1797*
1798* @return The status of the operation
1799* @retval RETURN_OK if successful
1800* @retval RETURN_ERR if any error is detected
1801*
1802* @execution Synchronous
1803* @sideeffect None
1804*
1805* @note This function must not suspend and must not invoke any blocking system
1806* calls. It should probably just send a message to a driver event handler task.
1807*
1808*/
1809INT wifi_down()
1810{
developer96b38512023-02-22 11:17:45 +08001811 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developer17038e62023-03-02 14:43:43 +08001812 wifi_BringDownInterfaces();
1813 sleep(2);
1814
developer96b38512023-02-22 11:17:45 +08001815 system("systemctl stop hostapd.service");
1816 sleep(2);
developer72fb0bb2023-01-11 09:46:29 +08001817 return RETURN_OK;
1818}
1819
1820
1821/* wifi_createInitialConfigFiles() function */
1822/**
1823* @description This function creates wifi configuration files. The format
developer69b61b02023-03-07 17:17:44 +08001824* and content of these files are implementation dependent. This function call is
1825* used to trigger this task if necessary. Some implementations may not need this
1826* function. If an implementation does not need to create config files the function call can
developer72fb0bb2023-01-11 09:46:29 +08001827* do nothing and return RETURN_OK.
1828*
1829* @param None
1830*
1831* @return The status of the operation
1832* @retval RETURN_OK if successful
1833* @retval RETURN_ERR if any error is detected
1834*
1835* @execution Synchronous
1836* @sideeffect None
1837*
1838* @note This function must not suspend and must not invoke any blocking system
1839* calls. It should probably just send a message to a driver event handler task.
1840*
1841*/
1842INT wifi_createInitialConfigFiles()
1843{
1844 //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)
1845 return RETURN_OK;
1846}
1847
developer7e4a2a62023-04-06 19:56:03 +08001848/* outputs the country code to a max 64 character string */
developer72fb0bb2023-01-11 09:46:29 +08001849INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1850{
developer7e4a2a62023-04-06 19:56:03 +08001851 char interface_name[IF_NAME_SIZE] = {0};
1852 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer72fb0bb2023-01-11 09:46:29 +08001853
developer7e4a2a62023-04-06 19:56:03 +08001854 if (!output_string || (radioIndex >= MAX_NUM_RADIOS)) {
1855 printf("%s: input para error!!!\n", __func__);
1856 return RETURN_ERR;
1857 }
developer72fb0bb2023-01-11 09:46:29 +08001858
developer7e4a2a62023-04-06 19:56:03 +08001859 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK) {
1860 printf("%s: get inf_name error!!!\n", __func__);
1861 return RETURN_ERR;
1862 }
1863
1864 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i %s status driver | grep country | cut -d '=' -f2 | tr -d '\\n'",
1865 interface_name);
1866 _syscmd(cmd, buf, sizeof(buf));
1867
1868 if(strlen(buf))
1869 snprintf(output_string, 64, "%s", buf);
1870 else
1871 return RETURN_ERR;
1872
1873 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08001874}
1875
1876INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1877{
developer7e4a2a62023-04-06 19:56:03 +08001878 /*Set wifi config. Wait for wifi reset to apply*/
1879 char str[MAX_BUF_SIZE] = {0};
1880 char cmd[MAX_CMD_SIZE] = {0};
1881 struct params params;
1882 char config_file[MAX_BUF_SIZE] = {0};
1883 int ret = 0;
developer72fb0bb2023-01-11 09:46:29 +08001884
developer7e4a2a62023-04-06 19:56:03 +08001885 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08001886
developer7e4a2a62023-04-06 19:56:03 +08001887 if(NULL == CountryCode || strlen(CountryCode) >= 32 ) {
1888 printf("%s: input para error!!!\n", __func__);
1889 return RETURN_ERR;
1890 }
developer72fb0bb2023-01-11 09:46:29 +08001891
developer7e4a2a62023-04-06 19:56:03 +08001892 if (!strlen(CountryCode))
1893 strncpy(CountryCode, "US", sizeof("US")); /*default set the code to US*/
developer72fb0bb2023-01-11 09:46:29 +08001894
developer7e4a2a62023-04-06 19:56:03 +08001895 params.name = "country_code";
1896 params.value = CountryCode;
developer72fb0bb2023-01-11 09:46:29 +08001897
developer7e4a2a62023-04-06 19:56:03 +08001898 snprintf(config_file, MAX_BUF_SIZE, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1899 ret = wifi_hostapdWrite(config_file, &params, 1);
1900
1901 if (ret) {
1902 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n",
1903 __func__, ret);
1904 }
1905
1906 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1907
1908 if (ret) {
1909 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n",
1910 __func__, ret);
1911 }
1912
1913 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
1914
1915 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08001916}
1917
1918INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1919{
1920 char interface_name[16] = {0};
1921 char channel_util_file[64] = {0};
1922 char cmd[128] = {0};
1923 char buf[128] = {0};
1924 char line[128] = {0};
1925 char *param = NULL, *value = NULL;
1926 int read = 0;
1927 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1928 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1929 size_t len = 0;
1930 FILE *f = NULL;
1931
1932 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1933
1934 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
1935 return RETURN_ERR;
1936 snprintf(cmd, sizeof(cmd), "iw %s scan | grep signal | awk '{print $2}' | sort -n | tail -n1", interface_name);
1937 _syscmd(cmd, buf, sizeof(buf));
1938 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1939
1940 memset(cmd, 0, sizeof(cmd));
1941 memset(buf, 0, sizeof(buf));
1942 snprintf(cmd, sizeof(cmd), "iw %s survey dump | grep 'in use' -A6", interface_name);
1943 if ((f = popen(cmd, "r")) == NULL) {
1944 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1945 return RETURN_ERR;
1946 }
1947
1948 read = getline(&line, &len, f);
1949 while (read != -1) {
1950 param = strtok(line, ":\t");
1951 value = strtok(NULL, " ");
1952 if(strstr(param, "frequency") != NULL) {
1953 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1954 }
1955 if(strstr(param, "noise") != NULL) {
1956 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1957 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1958 }
1959 if(strstr(param, "channel active time") != NULL) {
1960 ActiveTime = strtol(value, NULL, 10);
1961 }
1962 if(strstr(param, "channel busy time") != NULL) {
1963 BusyTime = strtol(value, NULL, 10);
1964 }
1965 if(strstr(param, "channel transmit time") != NULL) {
1966 TransmitTime = strtol(value, NULL, 10);
1967 }
1968 read = getline(&line, &len, f);
1969 }
1970 pclose(f);
1971
1972 // The file should store the last active, busy and transmit time
1973 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1974 f = fopen(channel_util_file, "r");
1975 if (f != NULL) {
1976 read = getline(&line, &len, f);
1977 preActiveTime = strtol(line, NULL, 10);
1978 read = getline(&line, &len, f);
1979 preBusyTime = strtol(line, NULL, 10);
1980 read = getline(&line, &len, f);
1981 preTransmitTime = strtol(line, NULL, 10);
1982 fclose(f);
1983 }
1984
1985 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1986 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1987
1988 f = fopen(channel_util_file, "w");
1989 if (f != NULL) {
1990 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1991 fclose(f);
1992 }
1993 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1994 return RETURN_OK;
1995}
1996
1997/**********************************************************************************
1998 *
1999 * Wifi radio level function prototypes
2000 *
2001**********************************************************************************/
2002
2003//Get the total number of radios in this wifi subsystem
2004INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
2005{
2006 if (NULL == output)
2007 return RETURN_ERR;
2008 *output = MAX_NUM_RADIOS;
2009
2010 return RETURN_OK;
2011}
2012
developer69b61b02023-03-07 17:17:44 +08002013//Get the total number of SSID entries in this wifi subsystem
developer72fb0bb2023-01-11 09:46:29 +08002014INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
2015{
2016 if (NULL == output)
2017 return RETURN_ERR;
2018 *output = MAX_APS;
2019
2020 return RETURN_OK;
2021}
2022
2023//Get the Radio enable config parameter
2024INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
2025{
2026 char interface_name[16] = {0};
2027 char buf[128] = {0}, cmd[128] = {0};
2028
2029 if (NULL == output_bool)
2030 return RETURN_ERR;
2031
2032 *output_bool = FALSE;
2033 if (radioIndex >= MAX_NUM_RADIOS)// Target has two wifi radios
2034 return RETURN_ERR;
2035
2036 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
2037 return RETURN_ERR;
2038 sprintf(cmd, "hostapd_cli -i %s status | grep state | cut -d '=' -f2", interface_name);
2039 _syscmd(cmd, buf, sizeof(buf));
2040
2041 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 || strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0)
2042 *output_bool = TRUE;
2043 return RETURN_OK;
2044}
2045
developere82c0ca2023-05-10 16:25:35 +08002046typedef long time_t;
2047static time_t radio_up_time[MAX_NUM_RADIOS];
2048
developer72fb0bb2023-01-11 09:46:29 +08002049INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
2050{
2051 char interface_name[16] = {0};
2052 char cmd[MAX_CMD_SIZE] = {0};
developer8a3bbbf2023-03-15 17:47:23 +08002053 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08002054 int apIndex, ret;
developer69b61b02023-03-07 17:17:44 +08002055 int max_radio_num = 0;
developer72fb0bb2023-01-11 09:46:29 +08002056 int phyId = 0;
2057
2058 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2059
2060 phyId = radio_index_to_phy(radioIndex);
2061
2062 wifi_getMaxRadioNumber(&max_radio_num);
2063
developer8a3bbbf2023-03-15 17:47:23 +08002064 if(enable == FALSE) {
developer47cc27a2023-05-17 23:09:58 +08002065
2066 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
2067 return RETURN_ERR;
2068
2069 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s", interface_name);
developer8a3bbbf2023-03-15 17:47:23 +08002070 _syscmd(cmd, buf, sizeof(buf));
developere82c0ca2023-05-10 16:25:35 +08002071 if(strncmp(buf, "OK", 2))
2072 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
developer8a3bbbf2023-03-15 17:47:23 +08002073 } else {
developere82c0ca2023-05-10 16:25:35 +08002074 for (apIndex = radioIndex; apIndex < MAX_APS; apIndex += max_radio_num) {
developer72fb0bb2023-01-11 09:46:29 +08002075 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
2076 return RETURN_ERR;
2077
developer8a3bbbf2023-03-15 17:47:23 +08002078 memset(cmd, 0, MAX_CMD_SIZE);
2079 memset(buf, 0, MAX_BUF_SIZE);
2080
developer72fb0bb2023-01-11 09:46:29 +08002081 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
2082 _syscmd(cmd, buf, sizeof(buf));
developer8a3bbbf2023-03-15 17:47:23 +08002083
2084 if(*buf == '1') {
2085
2086 memset(cmd, 0, MAX_CMD_SIZE);
2087 memset(buf, 0, MAX_BUF_SIZE);
2088
developer72fb0bb2023-01-11 09:46:29 +08002089 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
2090 phyId, apIndex);
2091 _syscmd(cmd, buf, sizeof(buf));
developer8a3bbbf2023-03-15 17:47:23 +08002092
developer72fb0bb2023-01-11 09:46:29 +08002093 }
2094 }
developere82c0ca2023-05-10 16:25:35 +08002095 time(&radio_up_time[radioIndex]);
developer72fb0bb2023-01-11 09:46:29 +08002096 }
2097
2098 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2099 return RETURN_OK;
2100}
2101
2102//Get the Radio enable status
2103INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
2104{
2105 if (NULL == output_bool)
2106 return RETURN_ERR;
2107
2108 return wifi_getRadioEnable(radioIndex, output_bool);
2109}
2110
2111//Get the Radio Interface name from platform, eg "wlan0"
2112INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
2113{
2114 if (NULL == output_string || radioIndex>=MAX_NUM_RADIOS || radioIndex<0)
2115 return RETURN_ERR;
2116 return wifi_GetInterfaceName(radioIndex, output_string);
2117}
2118
2119//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
2120//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.
2121INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
2122{
2123 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
2124 // For max bit rate, we should always choose the best MCS
2125 char mode[64] = {0};
2126 char channel_bandwidth_str[64] = {0};
2127 char *tmp = NULL;
2128 UINT mode_map = 0;
2129 UINT num_subcarrier = 0;
2130 UINT code_bits = 0;
2131 float code_rate = 0; // use max code rate
2132 int NSS = 0;
2133 UINT Symbol_duration = 0;
developer69b61b02023-03-07 17:17:44 +08002134 UINT GI_duration = 0;
developer72fb0bb2023-01-11 09:46:29 +08002135 wifi_band band = band_invalid;
2136 wifi_guard_interval_t gi = wifi_guard_interval_auto;
2137 BOOL enable = FALSE;
2138 float bit_rate = 0;
developera1255e42023-05-13 17:45:02 +08002139 int ant_bitmap = 0;
developer72fb0bb2023-01-11 09:46:29 +08002140
2141 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2142 if (NULL == output_string)
2143 return RETURN_ERR;
2144
2145 wifi_getRadioEnable(radioIndex, &enable);
2146 if (enable == FALSE) {
2147 snprintf(output_string, 64, "0 Mb/s");
2148 return RETURN_OK;
2149 }
2150
2151 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
2152 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
2153 return RETURN_ERR;
2154 }
2155
2156 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
2157 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
2158 return RETURN_ERR;
2159 }
2160
2161 if (gi == wifi_guard_interval_3200)
2162 GI_duration = 32;
2163 else if (gi == wifi_guard_interval_1600)
2164 GI_duration = 16;
2165 else if (gi == wifi_guard_interval_800)
2166 GI_duration = 8;
2167 else // auto, 400
2168 GI_duration = 4;
2169
2170 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
2171 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
2172 return RETURN_ERR;
2173 }
2174
2175 if (strstr(channel_bandwidth_str, "80+80") != NULL)
2176 strcpy(channel_bandwidth_str, "160");
2177
2178 if (mode_map & WIFI_MODE_AX) {
2179 if (strstr(channel_bandwidth_str, "160") != NULL)
2180 num_subcarrier = 1960;
2181 else if (strstr(channel_bandwidth_str, "80") != NULL)
2182 num_subcarrier = 980;
2183 else if (strstr(channel_bandwidth_str, "40") != NULL)
2184 num_subcarrier = 468;
2185 else if (strstr(channel_bandwidth_str, "20") != NULL)
2186 num_subcarrier = 234;
2187 code_bits = 10;
2188 code_rate = (float)5/6;
2189 Symbol_duration = 128;
developera1255e42023-05-13 17:45:02 +08002190 GI_duration = 8;/*HE no GI 400ns*/
developer72fb0bb2023-01-11 09:46:29 +08002191 } else if (mode_map & WIFI_MODE_AC) {
2192 if (strstr(channel_bandwidth_str, "160") != NULL)
2193 num_subcarrier = 468;
2194 else if (strstr(channel_bandwidth_str, "80") != NULL)
2195 num_subcarrier = 234;
2196 else if (strstr(channel_bandwidth_str, "40") != NULL)
2197 num_subcarrier = 108;
2198 else if (strstr(channel_bandwidth_str, "20") != NULL)
2199 num_subcarrier = 52;
2200 code_bits = 8;
2201 code_rate = (float)5/6;
2202 Symbol_duration = 32;
2203 } else if (mode_map & WIFI_MODE_N) {
2204 if (strstr(channel_bandwidth_str, "160") != NULL)
2205 num_subcarrier = 468;
2206 else if (strstr(channel_bandwidth_str, "80") != NULL)
2207 num_subcarrier = 234;
2208 else if (strstr(channel_bandwidth_str, "40") != NULL)
2209 num_subcarrier = 108;
2210 else if (strstr(channel_bandwidth_str, "20") != NULL)
2211 num_subcarrier = 52;
2212 code_bits = 6;
2213 code_rate = (float)3/4;
2214 Symbol_duration = 32;
2215 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
2216 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
2217 snprintf(output_string, 64, "65 Mb/s");
2218 return RETURN_OK;
2219 } else {
2220 snprintf(output_string, 64, "0 Mb/s");
2221 return RETURN_OK;
2222 }
2223
2224 // Spatial streams
developera1255e42023-05-13 17:45:02 +08002225 if (wifi_getRadioTxChainMask(radioIndex, &ant_bitmap) != RETURN_OK) {
developer72fb0bb2023-01-11 09:46:29 +08002226 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
2227 return RETURN_ERR;
2228 }
developera1255e42023-05-13 17:45:02 +08002229 for (; ant_bitmap > 0; ant_bitmap >>= 1)
2230 NSS += ant_bitmap & 1;
developer72fb0bb2023-01-11 09:46:29 +08002231
2232 // multiple 10 is to align duration unit (0.1 us)
2233 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
2234 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
developera1255e42023-05-13 17:45:02 +08002235 WIFI_ENTRY_EXIT_DEBUG("%s:num_subcarrier=%d, code_bits=%d, code_rate=%.3f, nss=%d, symbol time=%u, %.1f Mb/s\n",
2236 __func__, num_subcarrier, code_bits, code_rate, NSS, Symbol_duration + GI_duration, bit_rate);
developer72fb0bb2023-01-11 09:46:29 +08002237 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2238
2239 return RETURN_OK;
2240}
2241#if 0
2242INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
2243{
2244 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2245 char cmd[64];
2246 char buf[1024];
2247 int apIndex;
2248
developer69b61b02023-03-07 17:17:44 +08002249 if (NULL == output_string)
developer72fb0bb2023-01-11 09:46:29 +08002250 return RETURN_ERR;
2251
2252 apIndex=(radioIndex==0)?0:1;
2253
2254 snprintf(cmd, sizeof(cmd), "iwconfig %s | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", interface_name);
2255 _syscmd(cmd,buf, sizeof(buf));
2256
2257 snprintf(output_string, 64, "%s", buf);
2258 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2259 return RETURN_OK;
2260}
2261#endif
2262
2263
2264//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
2265//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.
2266INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
2267{
2268 wifi_band band = band_invalid;
2269
2270 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2271 if (NULL == output_string)
2272 return RETURN_ERR;
2273
2274 band = wifi_index_to_band(radioIndex);
2275
2276 memset(output_string, 0, 10);
2277 if (band == band_2_4)
2278 strcpy(output_string, "2.4GHz");
2279 else if (band == band_5)
2280 strcpy(output_string, "5GHz");
2281 else if (band == band_6)
2282 strcpy(output_string, "6GHz");
2283 else
2284 return RETURN_ERR;
2285 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2286
2287 return RETURN_OK;
2288#if 0
2289 char buf[MAX_BUF_SIZE]={'\0'};
2290 char str[MAX_BUF_SIZE]={'\0'};
2291 char cmd[MAX_CMD_SIZE]={'\0'};
2292 char *ch=NULL;
2293 char *ch2=NULL;
2294
2295 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2296 if (NULL == output_string)
2297 return RETURN_ERR;
2298
2299
2300 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2301
2302 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
2303 {
2304 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2305 return RETURN_ERR;
2306 }
2307 ch=strchr(buf,'\n');
2308 *ch='\0';
2309 ch=strchr(buf,'=');
2310 if(ch==NULL)
2311 return RETURN_ERR;
2312
2313
2314 ch++;
2315
2316 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
2317 strcpy(buf,"0");
2318 if(strlen(ch) == 1)
2319 ch=strcat(buf,ch);
2320
2321
2322 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2323
2324 if(_syscmd(cmd,str,64) == RETURN_ERR)
2325 {
2326 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2327 return RETURN_ERR;
2328 }
2329
2330
2331 ch2=strchr(str,'\n');
2332 //replace \n with \0
2333 *ch2='\0';
2334 ch2=strchr(str,'=');
2335 if(ch2==NULL)
2336 {
2337 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2338 return RETURN_ERR;
2339 }
2340 else
2341 wifi_dbg_printf("%s",ch2+1);
2342
2343
2344 ch2++;
2345
2346
2347 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
2348
2349 memset(buf,'\0',sizeof(buf));
2350 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
2351 {
2352 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2353 return RETURN_ERR;
2354 }
2355 if (strstr(buf,"2.4") != NULL )
2356 strcpy(output_string,"2.4GHz");
2357 else if(strstr(buf,"5.") != NULL )
2358 strcpy(output_string,"5GHz");
2359 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2360
2361 return RETURN_OK;
2362#endif
2363}
2364
2365//Get the frequency band at which the radio is operating, eg: "2.4GHz"
2366//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.
2367INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
2368{
2369 wifi_band band = band_invalid;
2370 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2371 if (NULL == output_string)
2372 return RETURN_ERR;
2373 band = wifi_index_to_band(radioIndex);
2374
developer69b61b02023-03-07 17:17:44 +08002375 if (band == band_2_4)
developer72fb0bb2023-01-11 09:46:29 +08002376 snprintf(output_string, 64, "2.4GHz");
2377 else if (band == band_5)
developer69b61b02023-03-07 17:17:44 +08002378 snprintf(output_string, 64, "5GHz");
developer72fb0bb2023-01-11 09:46:29 +08002379 else if (band == band_6)
2380 snprintf(output_string, 64, "6GHz");
2381
2382 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2383
2384 return RETURN_OK;
2385#if 0
2386 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2387 char buf[MAX_BUF_SIZE]={'\0'};
2388 char str[MAX_BUF_SIZE]={'\0'};
2389 char cmd[MAX_CMD_SIZE]={'\0'};
2390 char *ch=NULL;
2391 char *ch2=NULL;
2392 char ch1[5]="0";
2393
2394 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2395
2396 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
2397 {
2398 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2399 return RETURN_ERR;
2400 }
2401
2402 ch=strchr(buf,'\n');
2403 *ch='\0';
2404 ch=strchr(buf,'=');
2405 if(ch==NULL)
2406 return RETURN_ERR;
2407 ch++;
2408
2409 if(strlen(ch)==1)
2410 {
2411 strcat(ch1,ch);
2412
2413 }
2414 else
2415 {
2416 strcpy(ch1,ch);
2417 }
2418
2419
2420
2421 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2422 if(_syscmd(cmd,str,64) == RETURN_ERR)
2423 {
2424 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2425 return RETURN_ERR;
2426 }
2427
2428
2429 ch2=strchr(str,'\n');
2430 //replace \n with \0
2431 *ch2='\0';
2432 ch2=strchr(str,'=');
2433 if(ch2==NULL)
2434 {
2435 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2436 return RETURN_ERR;
2437 }
2438 else
2439 wifi_dbg_printf("%s",ch2+1);
2440 ch2++;
2441
2442
2443 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
2444 memset(buf,'\0',sizeof(buf));
2445 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
2446 {
2447 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2448 return RETURN_ERR;
2449 }
2450
2451
2452 if(strstr(buf,"2.4")!=NULL)
2453 {
2454 strcpy(output_string,"2.4GHz");
2455 }
2456 if(strstr(buf,"5.")!=NULL)
2457 {
2458 strcpy(output_string,"5GHz");
2459 }
2460 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2461 return RETURN_OK;
2462#endif
2463}
2464
2465//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
2466//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.
2467INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
2468{
2469 char cmd[128]={0};
2470 char buf[128]={0};
2471 char temp_output[128] = {0};
2472 wifi_band band;
2473 int phyId = 0;
2474
2475 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer69b61b02023-03-07 17:17:44 +08002476 if (NULL == output_string)
developer72fb0bb2023-01-11 09:46:29 +08002477 return RETURN_ERR;
2478
2479 band = wifi_index_to_band(radioIndex);
2480 if (band == band_2_4) {
2481 strcat(temp_output, "b,g,");
2482 } else if (band == band_5) {
2483 strcat(temp_output, "a,");
2484 }
2485 phyId = radio_index_to_phy(radioIndex);
2486 // ht capabilities
2487 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);
2488 _syscmd(cmd, buf, sizeof(buf));
2489 if (strlen(buf) >= 4 && strncmp(buf, "0x00", 4) != 0) {
2490 strcat(temp_output, "n,");
2491 }
2492
2493 // vht capabilities
2494 if (band == band_5) {
2495 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'VHT Capabilities' | cut -d '(' -f2 | cut -c1-10 | tr -d '\\n'", phyId);
2496 _syscmd(cmd, buf, sizeof(buf));
2497 if (strlen(buf) >= 10 && strncmp(buf, "0x00000000", 10) != 0) {
2498 strcat(temp_output, "ac,");
2499 }
2500 }
2501
2502 // he capabilities
2503 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);
2504 _syscmd(cmd, buf, sizeof(buf));
2505 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
2506 strcat(temp_output, "ax,");
2507 }
2508
developere82c0ca2023-05-10 16:25:35 +08002509 // eht capabilities
2510 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);
2511 _syscmd(cmd, buf, sizeof(buf));
2512 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
2513 strcat(temp_output, "be,");
2514 }
2515
developer72fb0bb2023-01-11 09:46:29 +08002516 // Remove the last comma
2517 if (strlen(temp_output) != 0)
2518 temp_output[strlen(temp_output)-1] = '\0';
2519 strncpy(output_string, temp_output, strlen(temp_output));
2520 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2521 return RETURN_OK;
2522}
2523
2524//Get the radio operating mode, and pure mode flag. eg: "ac"
2525//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.
2526INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
2527{
2528 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2529 if (NULL == output_string)
2530 return RETURN_ERR;
2531
2532 if (radioIndex == 0) {
2533 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
2534 *gOnly = FALSE;
2535 *nOnly = TRUE;
2536 *acOnly = FALSE;
2537 } else {
2538 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
2539 *gOnly = FALSE;
2540 *nOnly = FALSE;
2541 *acOnly = FALSE;
2542 }
2543 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2544
2545 return RETURN_OK;
2546#if 0
2547 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2548 char buf[64] = {0};
2549 char config_file[MAX_BUF_SIZE] = {0};
2550
developer69b61b02023-03-07 17:17:44 +08002551 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
developer72fb0bb2023-01-11 09:46:29 +08002552 return RETURN_ERR;
2553
2554 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2555 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
2556
2557 wifi_dbg_printf("\nhw_mode=%s\n",buf);
developer69b61b02023-03-07 17:17:44 +08002558 if (strlen(buf) == 0)
developer72fb0bb2023-01-11 09:46:29 +08002559 {
2560 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
2561 return RETURN_ERR;
2562 }
2563 if(strcmp(buf,"g")==0)
2564 {
2565 wifi_dbg_printf("\nG\n");
2566 *gOnly=TRUE;
2567 *nOnly=FALSE;
2568 *acOnly=FALSE;
2569 }
2570 else if(strcmp(buf,"n")==0)
2571 {
2572 wifi_dbg_printf("\nN\n");
2573 *gOnly=FALSE;
2574 *nOnly=TRUE;
2575 *acOnly=FALSE;
2576 }
2577 else if(strcmp(buf,"ac")==0)
2578 {
2579 wifi_dbg_printf("\nac\n");
2580 *gOnly=FALSE;
2581 *nOnly=FALSE;
2582 *acOnly=TRUE;
2583 }
2584 /* hostapd-5G.conf has "a" as hw_mode */
2585 else if(strcmp(buf,"a")==0)
2586 {
2587 wifi_dbg_printf("\na\n");
2588 *gOnly=FALSE;
2589 *nOnly=FALSE;
2590 *acOnly=FALSE;
2591 }
2592 else
2593 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
2594
2595 //for a,n mode
2596 if(radioIndex == 1)
2597 {
2598 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
2599 if(strcmp(buf,"1")==0)
2600 {
2601 strncpy(output_string, "n", 1);
2602 *nOnly=FALSE;
2603 }
2604 }
2605
2606 wifi_dbg_printf("\nReturning from getRadioStandard\n");
2607 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2608 return RETURN_OK;
2609#endif
2610}
2611
developer0f10c772023-05-16 21:43:39 +08002612enum WIFI_MODE {
2613 WMODE_INVALID = 0,
2614 WMODE_A = 1 << 0,
2615 WMODE_B = 1 << 1,
2616 WMODE_G = 1 << 2,
2617 WMODE_GN = 1 << 3,
2618 WMODE_AN = 1 << 4,
2619 WMODE_AC = 1 << 5,
2620 WMODE_AX_24G = 1 << 6,
2621 WMODE_AX_5G = 1 << 7,
2622 WMODE_AX_6G = 1 << 8,
2623 WMODE_BE_24G = 1 << 9,
2624 WMODE_BE_5G = 1 << 10,
2625 WMODE_BE_6G = 1 << 11,
2626 /*
2627 * total types of supported wireless mode,
2628 * add this value once yow add new type
2629 */
2630 WMODE_COMP = 12,
2631};
2632
2633#define RADIO_MODE_LEN 32
developer72fb0bb2023-01-11 09:46:29 +08002634INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
2635{
developer0f10c772023-05-16 21:43:39 +08002636 char cmd[MAX_CMD_SIZE] = {0};
2637 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08002638 wifi_band band;
developer0f10c772023-05-16 21:43:39 +08002639 unsigned int phymode;
2640 unsigned char radio_mode_tem_len;
2641 char interface_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08002642
2643 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2644 if(NULL == output_string || NULL == pureMode)
2645 return RETURN_ERR;
2646
developer0f10c772023-05-16 21:43:39 +08002647 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
2648 return RETURN_ERR;
2649
2650 snprintf(cmd, sizeof(cmd), "mwctl %s dump radio_info | grep 'phymode' | cut -d ' ' -f2", interface_name);
developer72fb0bb2023-01-11 09:46:29 +08002651 _syscmd(cmd, buf, sizeof(buf));
2652
developer0f10c772023-05-16 21:43:39 +08002653 phymode = strtoul(buf, NULL, 10);
2654 band = wifi_index_to_band(radioIndex);
2655
2656 // puremode is a bit map
developer72fb0bb2023-01-11 09:46:29 +08002657 *pureMode = 0;
developer0f10c772023-05-16 21:43:39 +08002658 memset(output_string, 0, RADIO_MODE_LEN);
2659
2660 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2661
2662 switch (band) {
2663 case band_2_4:
2664 if (phymode & WMODE_B) {
2665 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "b,");
2666 *pureMode |= WIFI_MODE_B;
2667 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2668 }
2669 if (phymode & WMODE_G) {
2670 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "g,");
2671 *pureMode |= WIFI_MODE_G;
2672 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2673 }
2674 if (phymode & WMODE_GN) {
2675 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "n,");
2676 *pureMode |= WIFI_MODE_N;
2677 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2678 }
2679 if (phymode & WMODE_AX_24G) {
2680 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "ax,");
2681 *pureMode |= WIFI_MODE_AX;
2682 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2683 }
2684 if (phymode & WMODE_BE_24G) {
2685 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "be,");
2686 *pureMode |= WIFI_MODE_BE;
2687 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2688 }
2689 break;
2690 case band_5:
2691 if (phymode & WMODE_A) {
2692 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "a,");
2693 *pureMode |= WIFI_MODE_A;
2694 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2695 }
2696 if (phymode & WMODE_AN) {
2697 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "n,");
2698 *pureMode |= WIFI_MODE_N;
2699 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2700 }
2701 if (phymode & WMODE_AC) {
2702 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "ac,");
2703 *pureMode |= WIFI_MODE_AC;
2704 }
2705 if (phymode & WMODE_AX_5G) {
2706 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "ax,");
2707 *pureMode |= WIFI_MODE_AX;
2708 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2709 }
2710 if (phymode & WMODE_BE_5G) {
2711 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "be,");
2712 *pureMode |= WIFI_MODE_BE;
2713 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2714 }
2715 break;
2716 case band_6:
2717 if (phymode & WMODE_AX_6G) {
2718 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "ax,");
2719 *pureMode |= WIFI_MODE_AX;
2720 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2721 }
2722 if (phymode & WMODE_BE_6G) {
2723 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "be,");
2724 *pureMode |= WIFI_MODE_BE;
2725 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2726 }
2727 break;
2728 default:
2729 fprintf(stderr, "%s band_idx invalid\n", __func__);
2730 break;
2731 }
2732
2733 /* Remove the last comma */
2734 if (strlen(output_string) != 0)
2735 output_string[strlen(output_string)-1] = '\0';
developer72fb0bb2023-01-11 09:46:29 +08002736
2737 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2738 return RETURN_OK;
2739}
2740
2741// Set the radio operating mode, and pure mode flag.
2742INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
2743{
developer69b61b02023-03-07 17:17:44 +08002744 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
developer72fb0bb2023-01-11 09:46:29 +08002745 if (strcmp (channelMode,"11A") == 0)
2746 {
2747 writeBandWidth(radioIndex,"20MHz");
2748 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2749 printf("\nChannel Mode is 802.11a (5GHz)\n");
2750 }
2751 else if (strcmp (channelMode,"11NAHT20") == 0)
2752 {
2753 writeBandWidth(radioIndex,"20MHz");
2754 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2755 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
2756 }
2757 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
2758 {
2759 writeBandWidth(radioIndex,"40MHz");
2760 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2761 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
2762 }
2763 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
2764 {
2765 writeBandWidth(radioIndex,"40MHz");
2766 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2767 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
2768 }
2769 else if (strcmp (channelMode,"11ACVHT20") == 0)
2770 {
2771 writeBandWidth(radioIndex,"20MHz");
2772 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2773 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
2774 }
2775 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
2776 {
2777 writeBandWidth(radioIndex,"40MHz");
2778 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2779 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2780 }
2781 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
2782 {
2783 writeBandWidth(radioIndex,"40MHz");
2784 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2785 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2786 }
2787 else if (strcmp (channelMode,"11ACVHT80") == 0)
2788 {
2789 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
2790 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
2791 }
2792 else if (strcmp (channelMode,"11ACVHT160") == 0)
2793 {
2794 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
2795 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
developer69b61b02023-03-07 17:17:44 +08002796 }
developer72fb0bb2023-01-11 09:46:29 +08002797 else if (strcmp (channelMode,"11B") == 0)
2798 {
2799 writeBandWidth(radioIndex,"20MHz");
2800 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2801 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
2802 }
2803 else if (strcmp (channelMode,"11G") == 0)
2804 {
2805 writeBandWidth(radioIndex,"20MHz");
2806 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2807 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
2808 }
2809 else if (strcmp (channelMode,"11NGHT20") == 0)
2810 {
2811 writeBandWidth(radioIndex,"20MHz");
2812 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2813 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
2814 }
2815 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
2816 {
2817 writeBandWidth(radioIndex,"40MHz");
2818 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2819 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2820 }
2821 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
2822 {
2823 writeBandWidth(radioIndex,"40MHz");
2824 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2825 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2826 }
developer69b61b02023-03-07 17:17:44 +08002827 else
developer72fb0bb2023-01-11 09:46:29 +08002828 {
2829 return RETURN_ERR;
2830 }
2831 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2832
2833 return RETURN_OK;
2834}
2835
developer0f10c772023-05-16 21:43:39 +08002836typedef enum _RT_802_11_PHY_MODE {
2837 PHY_11BG_MIXED = 0,
2838 PHY_11B = 1,
2839 PHY_11A = 2,
2840 PHY_11ABG_MIXED = 3,
2841 PHY_11G = 4,
2842 PHY_11ABGN_MIXED = 5, /* both band 5 */
2843 PHY_11N_2_4G = 6, /* 11n-only with 2.4G band 6 */
2844 PHY_11GN_MIXED = 7, /* 2.4G band 7 */
2845 PHY_11AN_MIXED = 8, /* 5G band 8 */
2846 PHY_11BGN_MIXED = 9, /* if check 802.11b. 9 */
2847 PHY_11AGN_MIXED = 10, /* if check 802.11b. 10 */
2848 PHY_11N_5G = 11, /* 11n-only with 5G band 11 */
2849 PHY_11VHT_N_ABG_MIXED = 12, /* 12 -> AC/A/AN/B/G/GN mixed */
2850 PHY_11VHT_N_AG_MIXED = 13, /* 13 -> AC/A/AN/G/GN mixed */
2851 PHY_11VHT_N_A_MIXED = 14, /* 14 -> AC/AN/A mixed in 5G band */
2852 PHY_11VHT_N_MIXED = 15, /* 15 -> AC/AN mixed in 5G band */
2853 PHY_11AX_24G = 16,
2854 PHY_11AX_5G = 17,
2855 PHY_11AX_6G = 18,
2856 PHY_11AX_24G_6G = 19,
2857 PHY_11AX_5G_6G = 20,
2858 PHY_11AX_24G_5G_6G = 21,
2859 PHY_11BE_24G = 22,
2860 PHY_11BE_5G = 23,
2861 PHY_11BE_6G = 24,
2862 PHY_11BE_24G_6G = 25,
2863 PHY_11BE_5G_6G = 26,
2864 PHY_11BE_24G_5G_6G = 27,
2865 PHY_MODE_MAX,
2866} RT_802_11_PHY_MODE;
2867
2868unsigned int puremode_to_wireless_mode(INT radioIndex, UINT pureMode)
2869{
2870 int band_idx = 0;
2871 unsigned int wireless_mode = PHY_MODE_MAX;
2872
2873 band_idx = radio_index_to_band(radioIndex);
2874
2875 switch (band_idx) {
2876 case band_2_4:
2877 if (pureMode == (WIFI_MODE_G | WIFI_MODE_N))
2878 wireless_mode = PHY_11GN_MIXED;
2879 if (pureMode == (WIFI_MODE_B | WIFI_MODE_G | WIFI_MODE_N))
2880 wireless_mode = PHY_11BGN_MIXED;
2881 if (pureMode & WIFI_MODE_AX)
2882 wireless_mode = PHY_11AX_24G;
2883 if (pureMode & WIFI_MODE_BE)
2884 wireless_mode = PHY_11BE_24G;
2885 break;
2886 case band_5:
2887 if (pureMode == WIFI_MODE_N)
2888 wireless_mode = PHY_11N_5G;
2889 if ((pureMode == WIFI_MODE_AC) || (pureMode == (WIFI_MODE_N | WIFI_MODE_AC)))
2890 wireless_mode = PHY_11VHT_N_MIXED;
2891 if (pureMode == (WIFI_MODE_A | WIFI_MODE_N | WIFI_MODE_AC))
2892 wireless_mode = PHY_11VHT_N_A_MIXED;
2893 if (pureMode & WIFI_MODE_AX)
2894 wireless_mode = PHY_11AX_5G;
2895 if (pureMode & WIFI_MODE_BE)
2896 wireless_mode = PHY_11BE_5G;
2897 break;
2898 case band_6:
2899 if (pureMode & WIFI_MODE_AX)
2900 wireless_mode = PHY_11AX_6G;
2901 if (pureMode & WIFI_MODE_BE)
2902 wireless_mode = PHY_11BE_6G;
2903 break;
2904 default:
2905 fprintf(stderr, "%s band_idx invalid\n", __func__);
2906 break;
2907 }
2908
2909 return wireless_mode;
2910}
2911
developer72fb0bb2023-01-11 09:46:29 +08002912// Set the radio operating mode, and pure mode flag.
2913INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
2914{
developer0f10c772023-05-16 21:43:39 +08002915 unsigned int wireless_mode = PHY_MODE_MAX;
developer69b61b02023-03-07 17:17:44 +08002916
developer0f10c772023-05-16 21:43:39 +08002917 char interface_name[IF_NAME_SIZE] = {0};
2918 char cmd[MAX_CMD_SIZE] = {0};
2919 char buf[MAX_BUF_SIZE] = {0};
2920 int i;
developer72fb0bb2023-01-11 09:46:29 +08002921
developer0f10c772023-05-16 21:43:39 +08002922 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08002923
developer0f10c772023-05-16 21:43:39 +08002924 wireless_mode = puremode_to_wireless_mode(radioIndex, pureMode);
developer72fb0bb2023-01-11 09:46:29 +08002925
developer0f10c772023-05-16 21:43:39 +08002926 if (wireless_mode == PHY_MODE_MAX) {
2927 fprintf(stderr, "%s wireless_mode invalid pureMode = %x\n", __func__, pureMode);
2928 return RETURN_ERR;
2929 }
developer72fb0bb2023-01-11 09:46:29 +08002930
developer0f10c772023-05-16 21:43:39 +08002931 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
2932 return RETURN_ERR;
2933 snprintf(cmd, sizeof(cmd), "mwctl %s set phymode %d", interface_name, wireless_mode);
2934 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08002935
developer0f10c772023-05-16 21:43:39 +08002936 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2937
2938 return RETURN_OK;
2939}
2940
2941INT wifi_setRadioMode_by_dat(INT radioIndex, UINT pureMode)
2942{
2943 unsigned int wireless_mode = PHY_MODE_MAX;
2944 char interface_name[IF_NAME_SIZE] = {0};
2945 char cmd[MAX_CMD_SIZE] = {0};
2946 char buf[MAX_BUF_SIZE] = {0};
2947 int i;
2948 char dat_file[MAX_BUF_SIZE] = {0};
2949 struct params params={0};
2950
2951 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, pureMode, __LINE__);
2952
2953 wireless_mode = puremode_to_wireless_mode(radioIndex, pureMode);
2954
2955 if (wireless_mode == PHY_MODE_MAX) {
2956 fprintf(stderr, "%s wireless_mode invalid pureMode = %x\n", __func__, pureMode);
2957 return RETURN_ERR;
2958 }
2959
2960 params.name = "WirelessMode";
2961 snprintf(buf, sizeof(buf), "%d", wireless_mode);
2962 params.value = buf;
2963
2964 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, radioIndex);
2965 wifi_datfileWrite(dat_file, &params, 1);
2966
developer72fb0bb2023-01-11 09:46:29 +08002967 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2968
2969 return RETURN_OK;
2970}
2971
2972INT wifi_setRadioHwMode(INT radioIndex, CHAR *hw_mode) {
2973
2974 char config_file[64] = {0};
2975 char buf[64] = {0};
2976 struct params params = {0};
2977 wifi_band band = band_invalid;
2978
2979 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2980
2981 band = wifi_index_to_band(radioIndex);
2982
2983 if (strncmp(hw_mode, "a", 1) == 0 && (band != band_5 && band != band_6))
2984 return RETURN_ERR;
2985 else if ((strncmp(hw_mode, "b", 1) == 0 || strncmp(hw_mode, "g", 1) == 0) && band != band_2_4)
2986 return RETURN_ERR;
2987 else if ((strncmp(hw_mode, "a", 1) && strncmp(hw_mode, "b", 1) && strncmp(hw_mode, "g", 1)) || band == band_invalid)
2988 return RETURN_ERR;
2989
2990 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2991 params.name = "hw_mode";
2992 params.value = hw_mode;
2993 wifi_hostapdWrite(config_file, &params, 1);
2994 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2995
2996 if (band == band_2_4) {
2997 if (strncmp(hw_mode, "b", 1) == 0) {
2998 wifi_setRadioMode(radioIndex, "20MHz", WIFI_MODE_B);
2999 snprintf(buf, sizeof(buf), "%s", "1,2,5.5,11");
3000 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
3001 snprintf(buf, sizeof(buf), "%s", "1,2");
3002 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
3003 } else {
3004 // We don't set mode here, because we don't know whitch mode should be set (g, n or ax?).
3005
3006 snprintf(buf, sizeof(buf), "%s", "6,9,12,18,24,36,48,54");
3007 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
3008 snprintf(buf, sizeof(buf), "%s", "6,12,24");
3009 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
3010 }
3011 }
3012
3013 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3014 return RETURN_OK;
3015}
3016
3017INT wifi_setNoscan(INT radioIndex, CHAR *noscan)
3018{
3019 char config_file[64] = {0};
3020 struct params params = {0};
3021 wifi_band band = band_invalid;
3022
3023 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3024
3025 band = wifi_index_to_band(radioIndex);
3026 if (band != band_2_4)
3027 return RETURN_OK;
3028
3029 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3030 params.name = "noscan";
3031 params.value = noscan;
3032 wifi_hostapdWrite(config_file, &params, 1);
3033 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3034
3035 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3036 return RETURN_OK;
3037}
3038
3039//Get the list of supported channel. eg: "1-11"
3040//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.
3041INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
3042{
3043 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer69b61b02023-03-07 17:17:44 +08003044 if (NULL == output_string)
developer72fb0bb2023-01-11 09:46:29 +08003045 return RETURN_ERR;
3046 char cmd[256] = {0};
3047 char buf[128] = {0};
3048 BOOL dfs_enable = false;
3049 int phyId = 0;
3050
3051 // Parse possible channel number and separate them with commas.
3052 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
3053 phyId = radio_index_to_phy(radioIndex);
3054 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
3055 if (dfs_enable)
3056 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 +08003057 else
developer72fb0bb2023-01-11 09:46:29 +08003058 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);
3059
3060 _syscmd(cmd,buf,sizeof(buf));
3061 strncpy(output_string, buf, sizeof(buf));
3062
3063 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3064 return RETURN_OK;
3065}
developerd1824452023-05-18 12:30:04 +08003066//Getting current radio extension channel
3067INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
3068{
3069 CHAR buf[150] = {0};
3070 CHAR cmd[150] = {0};
3071
3072 wifi_datfileRead(file, "HT_EXTCHA", buf, sizeof(buf));
3073 if (strncmp(buf, "0", 1) == 0) //bewlow
3074 strcpy(Value,"BelowControlChannel");
3075 if(strncmp(buf, "1", 1) == 0) //above
3076 strcpy(Value,"AboveControlChannel");
3077 return RETURN_OK;
3078}
developerf6a87542023-05-16 15:47:28 +08003079
developer72fb0bb2023-01-11 09:46:29 +08003080//Get the list for used channel. eg: "1,6,9,11"
3081//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.
3082INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
3083{
3084 char interface_name[16] = {0};
3085 char cmd[128] = {0};
3086 char buf[128] = {0};
3087 char config_file[64] = {0};
3088 int channel = 0;
3089 int freq = 0;
3090 int bandwidth = 0;
3091 int center_freq = 0;
3092 int center_channel = 0;
3093 int channel_delta = 0;
3094 wifi_band band = band_invalid;
3095
3096 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3097
3098 if (NULL == output_string)
3099 return RETURN_ERR;
3100
3101 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3102 return RETURN_ERR;
3103 sprintf(cmd, "iw %s info | grep channel | sed -e 's/[^0-9 ]//g'", interface_name);
3104 _syscmd(cmd, buf, sizeof(buf));
3105 if (strlen(buf) == 0) {
3106 fprintf(stderr, "%s: failed to get channel information from iw.\n", __func__);
3107 return RETURN_ERR;
3108 }
3109 sscanf(buf, "%d %d %d %*d %d", &channel, &freq, &bandwidth, &center_freq);
3110
3111 if (bandwidth == 20) {
3112 snprintf(output_string, 256, "%d", channel);
3113 return RETURN_OK;
3114 }
3115
3116 center_channel = ieee80211_frequency_to_channel(center_freq);
3117
3118 band = wifi_index_to_band(radioIndex);
3119 if (band == band_2_4 && bandwidth == 40) {
developerd1824452023-05-18 12:30:04 +08003120 sprintf(config_file, "%s%d.dat", LOGAN_DAT_FILE, band);
developer72fb0bb2023-01-11 09:46:29 +08003121 memset(buf, 0, sizeof(buf));
3122 wifi_halgetRadioExtChannel(config_file, buf); // read ht_capab for HT40+ or -
3123
3124 if (strncmp(buf, "AboveControlChannel", strlen("AboveControlChannel")) == 0 && channel < 10) {
3125 snprintf(output_string, 256, "%d,%d", channel, channel+4);
3126 } else if (strncmp(buf, "BelowControlChannel", strlen("BelowControlChannel")) == 0 && channel > 4) {
3127 snprintf(output_string, 256, "%d,%d", channel-4, channel);
3128 } else {
3129 fprintf(stderr, "%s: invalid channel %d set with %s\n.", __func__, channel, buf);
3130 return RETURN_ERR;
3131 }
3132 } else if (band == band_5 || band == band_6){
3133 // to minus 20 is an offset, because frequence of a channel have a range. We need to use offset to calculate correct channel.
developerd1824452023-05-18 12:30:04 +08003134 // 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 +08003135 channel_delta = (bandwidth-20)/10;
developerd1824452023-05-18 12:30:04 +08003136 memset(output_string, 0, 256);
3137 for (int i = center_channel-channel_delta; i <= center_channel+channel_delta; i+=4) {
3138 // If i is not the last channel, we add a comma.
3139 snprintf(buf, sizeof(buf), "%d%s", i, i==center_channel+channel_delta?"":",");
3140 strncat(output_string, buf, strlen(buf));
3141 }
developer72fb0bb2023-01-11 09:46:29 +08003142 } else
3143 return RETURN_ERR;
3144
3145 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3146 return RETURN_OK;
3147}
3148
developer69b61b02023-03-07 17:17:44 +08003149//Get the running channel number
developerd1824452023-05-18 12:30:04 +08003150INT wifi_getRadioChannel(INT radioIndex, ULONG *output_ulong) //RDKB
developer72fb0bb2023-01-11 09:46:29 +08003151{
3152 char channel_str[16] = {0};
3153 char config_file[128] = {0};
developerd1824452023-05-18 12:30:04 +08003154 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08003155
3156 if (output_ulong == NULL)
3157 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08003158 band = wifi_index_to_band(radioIndex);
3159 snprintf(config_file, sizeof(config_file), "%s%d.dat", LOGAN_DAT_FILE, band);
3160 wifi_datfileRead(config_file, "Channel", channel_str, sizeof(channel_str));
developer72fb0bb2023-01-11 09:46:29 +08003161
3162 *output_ulong = strtoul(channel_str, NULL, 10);
3163
3164 return RETURN_OK;
3165}
3166
3167
3168INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
3169{
3170 char cmd[1024] = {0}, buf[5] = {0};
3171 char interface_name[16] = {0};
3172
3173 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3174 if (NULL == output_ulong)
3175 return RETURN_ERR;
3176
3177 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
3178 if (wifi_getApName(apIndex,interface_name) != RETURN_OK)
3179 return RETURN_ERR;
3180 _syscmd(cmd,buf,sizeof(buf));
3181 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
3182 if (*output_ulong == 0) {
3183 return RETURN_ERR;
3184 }
3185
3186 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3187 return RETURN_OK;
3188}
3189
3190//Storing the previous channel value
3191INT wifi_storeprevchanval(INT radioIndex)
3192{
3193 char buf[256] = {0};
3194 char output[4]={'\0'};
3195 char config_file[MAX_BUF_SIZE] = {0};
developerd1824452023-05-18 12:30:04 +08003196 wifi_band band = band_invalid;
3197
3198 band = wifi_index_to_band(radioIndex);
3199 if (band == band_invalid) {
3200 return RETURN_ERR;
3201 wifi_dbg_printf("[%s]: Invalid radio index", __func__);
3202 }
3203 snprintf(config_file, sizeof(config_file), "%s%d.dat",LOGAN_DAT_FILE, band);
3204 wifi_datfileRead(config_file, "Channel", output, sizeof(output));
3205
3206 if(band == band_2_4)
developer72fb0bb2023-01-11 09:46:29 +08003207 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
developerd1824452023-05-18 12:30:04 +08003208 else if(band == band_5)
developer72fb0bb2023-01-11 09:46:29 +08003209 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
developerd1824452023-05-18 12:30:04 +08003210 else
3211 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval6G_AutoChannelEnable");
developer72fb0bb2023-01-11 09:46:29 +08003212 system(buf);
3213 Radio_flag = FALSE;
3214 return RETURN_OK;
3215}
3216
3217//Set the running channel number
3218INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
3219{
3220 // We only write hostapd config here
3221 char str_channel[8]={0};
3222 char *list_channel;
3223 char config_file[128] = {0};
3224 char possible_channels[256] = {0};
developerd1824452023-05-18 12:30:04 +08003225 char config_file_dat[128] = {0};
developer72fb0bb2023-01-11 09:46:29 +08003226 int max_radio_num = 0;
3227 struct params list = {0};
developerd1824452023-05-18 12:30:04 +08003228 struct params dat = {0};
3229 struct params acs = {0};
3230 wifi_band band = band_invalid;
3231 bool acs_channel = false;
developer72fb0bb2023-01-11 09:46:29 +08003232
3233 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3234
developerd1824452023-05-18 12:30:04 +08003235 if (channel == 0)
3236 acs_channel = true;
developer72fb0bb2023-01-11 09:46:29 +08003237 // Check valid
3238 sprintf(str_channel, "%lu", channel);
3239
developerd1824452023-05-18 12:30:04 +08003240
developer72fb0bb2023-01-11 09:46:29 +08003241 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
3242 list_channel = strtok(possible_channels, ",");
3243 while(true)
3244 {
3245 if(list_channel == NULL) { // input not in the list
3246 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
3247 return RETURN_ERR;
3248 }
3249 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
3250 break;
3251 list_channel = strtok(NULL, ",");
3252 }
developerd1824452023-05-18 12:30:04 +08003253 /*
developer72fb0bb2023-01-11 09:46:29 +08003254 list.name = "channel";
3255 list.value = str_channel;
3256 wifi_getMaxRadioNumber(&max_radio_num);
3257 for(int i=0; i<=MAX_APS/max_radio_num;i++)
3258 {
3259 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
3260 wifi_hostapdWrite(config_file, &list, 1);
3261 }
developerd1824452023-05-18 12:30:04 +08003262 */
3263 dat.name = "Channel";
3264 dat.value = str_channel;
3265 band = wifi_index_to_band(radioIndex);
3266 snprintf(config_file_dat, sizeof(config_file_dat), "%s%d.dat", LOGAN_DAT_FILE, band);
3267 wifi_datfileWrite(config_file_dat, &dat, 1);
3268 if (acs_channel == true) {
3269 acs.name = "AutoChannelSelect";
3270 acs.value = "3";
3271 } else {
3272 acs.name = "AutoChannelSelect";
3273 acs.value = "0";
3274 }
3275 wifi_datfileWrite(config_file_dat, &acs, 1);
developerc0772e62023-05-18 15:10:48 +08003276 wifi_reloadAp(radioIndex);
developer72fb0bb2023-01-11 09:46:29 +08003277 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3278 return RETURN_OK;
3279}
3280
3281INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
3282{
3283 struct params list[2];
3284 char str_idx[16];
3285 char config_file[64];
3286 int max_num_radios = 0;
3287 wifi_band band = band_invalid;
3288
3289 band = wifi_index_to_band(radioIndex);
3290 if (band == band_2_4)
3291 return RETURN_OK;
3292
3293 snprintf(str_idx, sizeof(str_idx), "%lu", channel);
3294 list[0].name = "vht_oper_centr_freq_seg0_idx";
3295 list[0].value = str_idx;
3296 list[1].name = "he_oper_centr_freq_seg0_idx";
3297 list[1].value = str_idx;
3298
3299 wifi_getMaxRadioNumber(&max_num_radios);
3300 for(int i=0; i<=MAX_APS/max_num_radios; i++)
3301 {
3302 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
3303 if (band == band_6)
3304 wifi_hostapdWrite(config_file, &list[1], 1);
3305 else
3306 wifi_hostapdWrite(config_file, list, 2);
3307 }
3308
3309 return RETURN_OK;
3310}
3311
3312//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
3313//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
3314INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
3315{
3316 //Set to wifi config only. Wait for wifi reset to apply.
3317 char buf[256] = {0};
3318 char str_channel[256] = {0};
3319 int count = 0;
3320 ULONG Value = 0;
3321 FILE *fp = NULL;
3322 if(enable == TRUE)
3323 {
3324 wifi_setRadioChannel(radioIndex,Value);
3325 }
3326 return RETURN_OK;
3327}
3328
3329INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
3330{
3331 if (output_bool == NULL)
3332 return RETURN_ERR;
3333
3334 *output_bool = TRUE;
3335
3336 return RETURN_OK;
3337}
3338
3339INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
3340{
developer69b61b02023-03-07 17:17:44 +08003341 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08003342 return RETURN_ERR;
3343 *output_bool=FALSE;
3344 return RETURN_OK;
3345}
3346
3347INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
3348{
developer69b61b02023-03-07 17:17:44 +08003349 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08003350 return RETURN_ERR;
3351 *output_bool=FALSE;
3352 return RETURN_OK;
3353}
3354
3355INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
3356{
3357 //Set to wifi config only. Wait for wifi reset to apply.
3358 return RETURN_OK;
3359}
3360
3361INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
3362{
3363 return RETURN_OK;
3364}
3365
3366INT wifi_factoryResetAP(int apIndex)
3367{
developer47cc27a2023-05-17 23:09:58 +08003368 char ap_config_file[MAX_CMD_SIZE] = {0};
3369 char cmd[MAX_CMD_SIZE] = {0};
3370 char ret_buf[MAX_BUF_SIZE] = {0};
3371 int radio_idx = 0;
3372 int bss_idx = 0;
3373 char ssid[32] = {0};
3374 char interface[IF_NAME_SIZE] = {0};
3375 char psk_file[MAX_CMD_SIZE] = {0};
3376 struct params params[3] = {0};
3377 char *band_str[3] = {"2G", "5G", "6G"};
developer72fb0bb2023-01-11 09:46:29 +08003378
3379 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3380
developer47cc27a2023-05-17 23:09:58 +08003381 /*del old config file*/
3382 snprintf(ap_config_file, MAX_CMD_SIZE, "%s%d.conf", CONFIG_PREFIX, apIndex);
3383 snprintf(cmd, MAX_CMD_SIZE, "rm %s", ap_config_file);
3384 _syscmd(cmd, ret_buf, sizeof(ret_buf));
developer72fb0bb2023-01-11 09:46:29 +08003385
developer47cc27a2023-05-17 23:09:58 +08003386 memset(cmd, 0, sizeof(cmd));
3387 memset(ret_buf, 0, sizeof(ret_buf));
developer72fb0bb2023-01-11 09:46:29 +08003388
developer47cc27a2023-05-17 23:09:58 +08003389 vap_index_to_array_index(apIndex, &radio_idx, &bss_idx);
3390
3391 /*prepare new config file*/
3392 snprintf(cmd, sizeof(cmd), "cp /etc/hostapd-%s.conf %s", band_str[radio_idx], ap_config_file);
3393 _syscmd(cmd, ret_buf, sizeof(ret_buf));
3394
3395 if (radio_idx == band_2_4) {
3396 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_2G, bss_idx);
3397 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI2G, bss_idx);
3398 } else if (radio_idx == band_5) {
3399 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_5G, bss_idx);
3400 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI5G, bss_idx);
3401 } else if (radio_idx == band_6) {
3402 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_6G, bss_idx);
3403 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI6G, bss_idx);
3404 }
3405
3406 /* fix wpa_psk_file path */
3407 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", apIndex);
3408
3409 params[0].name = "ssid";
3410 params[0].value = ssid;
3411 params[1].name = "interface";
3412 params[1].value = interface;
3413 params[2].name = "wpa_psk_file";
3414 params[2].value = psk_file;
3415
3416 wifi_hostapdWrite(ap_config_file, params, 3);
3417
3418 /*clear psk file*/
3419 memset(cmd, 0, sizeof(cmd));
3420 memset(ret_buf, 0, sizeof(ret_buf));
3421
3422 snprintf(psk_file, sizeof(psk_file), "%s%d.psk", PSK_FILE, apIndex);
3423
3424 if (access(psk_file, F_OK) != 0) {
3425 snprintf(cmd, MAX_CMD_SIZE, "touch %s", psk_file);
3426 _syscmd(cmd, ret_buf, sizeof(ret_buf));
3427 } else {
3428 snprintf(cmd, MAX_CMD_SIZE, "echo '' > %s", psk_file);
3429 _syscmd(cmd, ret_buf, sizeof(ret_buf));
3430 }
3431
3432 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3433
3434 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08003435}
3436
3437//To set Band Steering AP group
3438//To-do
3439INT wifi_setBandSteeringApGroup(char *ApGroup)
3440{
3441 return RETURN_OK;
3442}
3443
3444INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
3445{
3446 char config_file[128] = {'\0'};
3447 char buf[128] = {'\0'};
3448
3449 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3450 if (dtimInterval == NULL)
3451 return RETURN_ERR;
3452
3453 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developer885b56c2023-05-22 15:02:46 +08003454 wifi_hostapdRead(config_file, "dtim_period", buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08003455
3456 if (strlen(buf) == 0) {
3457 *dtimInterval = 2;
3458 } else {
3459 *dtimInterval = strtoul(buf, NULL, 10);
3460 }
3461
3462 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3463 return RETURN_OK;
3464}
3465
3466INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
3467{
3468 struct params params={0};
3469 char config_file[MAX_BUF_SIZE] = {'\0'};
3470 char buf[MAX_BUF_SIZE] = {'\0'};
3471
3472 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3473 if (dtimInterval < 1 || dtimInterval > 255) {
3474 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
3475 return RETURN_ERR;
3476 }
developer69b61b02023-03-07 17:17:44 +08003477
developer72fb0bb2023-01-11 09:46:29 +08003478 params.name = "dtim_period";
3479 snprintf(buf, sizeof(buf), "%d", dtimInterval);
3480 params.value = buf;
3481
3482 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
3483 wifi_hostapdWrite(config_file, &params, 1);
3484 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3485
3486 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3487 return RETURN_OK;
3488}
3489
3490//Check if the driver support the Dfs
3491INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
3492{
3493 wifi_band band = band_invalid;
developer69b61b02023-03-07 17:17:44 +08003494 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08003495 return RETURN_ERR;
3496 *output_bool=FALSE;
3497
3498 band = wifi_index_to_band(radioIndex);
3499 if (band == band_5)
3500 *output_bool = TRUE;
3501 return RETURN_OK;
3502}
3503
3504//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.
3505//The value of this parameter is a comma seperated list of channel number
3506INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
3507{
developer69b61b02023-03-07 17:17:44 +08003508 if (NULL == output_pool)
developer72fb0bb2023-01-11 09:46:29 +08003509 return RETURN_ERR;
3510 if (radioIndex==1)
developer69b61b02023-03-07 17:17:44 +08003511 return RETURN_OK;//TODO need to handle for 5GHz band, i think
developer72fb0bb2023-01-11 09:46:29 +08003512 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
3513
3514 return RETURN_OK;
3515}
3516
3517INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
3518{
3519 //Set to wifi config. And apply instantly.
3520 return RETURN_OK;
3521}
3522
3523INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
3524{
developer69b61b02023-03-07 17:17:44 +08003525 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
developer72fb0bb2023-01-11 09:46:29 +08003526 return RETURN_ERR;
3527 *output_interval_seconds=1800;
3528 *output_dwell_milliseconds=40;
3529
3530 return RETURN_OK;
3531}
3532
3533INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
3534{
3535 //Set to wifi config. And apply instantly.
3536 return RETURN_OK;
3537}
3538
3539INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
3540{
3541 if (output_bool == NULL)
3542 return RETURN_ERR;
developer69b61b02023-03-07 17:17:44 +08003543 *output_bool = true;
3544 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08003545}
3546
3547INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
3548{
3549 return RETURN_OK;
3550}
3551
3552//Get the Dfs enable status
3553INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
3554{
3555 char buf[16] = {0};
3556 FILE *f = NULL;
developerd1824452023-05-18 12:30:04 +08003557 char config_file_dat[128] = {0};
3558 char dfs_key[16] = "DfsEnable";
3559 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08003560
3561 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3562
3563 if (output_bool == NULL)
3564 return RETURN_ERR;
developerf6a87542023-05-16 15:47:28 +08003565 *output_bool = TRUE; // default
developerd1824452023-05-18 12:30:04 +08003566 band = wifi_index_to_band(radioIndex);
3567 snprintf(config_file_dat, sizeof(config_file_dat), "%s%d.dat", LOGAN_DAT_FILE, band);
3568
3569 wifi_datfileRead(config_file_dat, dfs_key, buf, sizeof(buf));
3570
3571 if (strncmp(buf, "0", 1) == 0)
3572 *output_bool = FALSE;
developer72fb0bb2023-01-11 09:46:29 +08003573 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3574 return RETURN_OK;
3575}
3576
3577//Set the Dfs enable status
3578INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
3579{
3580 char config_file[128] = {0};
developerd1824452023-05-18 12:30:04 +08003581 char config_dat_file[128] = {0};
developer72fb0bb2023-01-11 09:46:29 +08003582 FILE *f = NULL;
developerd1824452023-05-18 12:30:04 +08003583 struct params dat = {0};
3584 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08003585
3586 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3587
3588 f = fopen(DFS_ENABLE_FILE, "w");
3589 if (f == NULL)
3590 return RETURN_ERR;
3591 fprintf(f, "%d", enable);
3592 fclose(f);
3593
developer72fb0bb2023-01-11 09:46:29 +08003594 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
3595
developerd1824452023-05-18 12:30:04 +08003596 dat.name = "DfsEnable";
3597 dat.value = enable?"0":"1";
3598 band = wifi_index_to_band(radioIndex);
3599 snprintf(config_dat_file, sizeof(config_dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
3600 wifi_datfileWrite(config_dat_file, &dat, 1);
developer72fb0bb2023-01-11 09:46:29 +08003601 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3602 return RETURN_OK;
3603}
3604
3605//Check if the driver support the AutoChannelRefreshPeriod
3606INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
3607{
developer69b61b02023-03-07 17:17:44 +08003608 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08003609 return RETURN_ERR;
3610 *output_bool=FALSE; //not support
3611
3612 return RETURN_OK;
3613}
3614
3615//Get the ACS refresh period in seconds
3616INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
3617{
developer69b61b02023-03-07 17:17:44 +08003618 if (NULL == output_ulong)
developer72fb0bb2023-01-11 09:46:29 +08003619 return RETURN_ERR;
3620 *output_ulong=300;
3621
3622 return RETURN_OK;
3623}
3624
3625//Set the ACS refresh period in seconds
3626INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
3627{
3628 return RETURN_ERR;
3629}
3630
3631//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
3632//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.
3633INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
3634{
developer8666b312023-03-24 14:05:31 +08003635 char cmd[MAX_CMD_SIZE] = {0}, buf[64] = {0};
developer72fb0bb2023-01-11 09:46:29 +08003636 char extchannel[128] = {0};
developer8666b312023-03-24 14:05:31 +08003637 char interface_name[64] = {0};
3638 int ret = 0, len=0;
developer72fb0bb2023-01-11 09:46:29 +08003639 BOOL radio_enable = FALSE;
3640 wifi_band band;
3641
3642 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3643
developerd1824452023-05-18 12:30:04 +08003644 if (NULL == output_string) {
3645 WIFI_ENTRY_EXIT_DEBUG("output_string is nuill %s: %d \n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08003646 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08003647 }
3648 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR) {
3649 WIFI_ENTRY_EXIT_DEBUG("wifi_getRadioEnable failed %s: %d \n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08003650 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08003651 }
3652 if (radio_enable != TRUE) {
3653 WIFI_ENTRY_EXIT_DEBUG("Radio %d is not enable failed %s: %d \n", radioIndex, __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08003654 return RETURN_OK;
developerd1824452023-05-18 12:30:04 +08003655 }
developer8666b312023-03-24 14:05:31 +08003656 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3657 return RETURN_ERR;
3658 /*IW command get BW320 to do*/
developerd1824452023-05-18 12:30:04 +08003659
developer8666b312023-03-24 14:05:31 +08003660 snprintf(cmd, sizeof(cmd),"iw dev %s info | grep 'width' | cut -d ' ' -f6 | tr -d '\\n'", interface_name);
3661 ret = _syscmd(cmd, buf, sizeof(buf));
3662 len = strlen(buf);
3663 if((ret != 0) || (len == 0))
3664 {
3665 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
3666 return RETURN_ERR;
3667 }
3668
developer72fb0bb2023-01-11 09:46:29 +08003669 band = wifi_index_to_band(radioIndex);
developer8666b312023-03-24 14:05:31 +08003670 if (band == band_2_4 && strncmp(buf, "20", 2) == 0) {
developer72fb0bb2023-01-11 09:46:29 +08003671 wifi_getRadioExtChannel(radioIndex, extchannel);
developer8666b312023-03-24 14:05:31 +08003672 if (strncmp(extchannel, "Auto", 4) != 0) // not auto means we have set HT40+/-
3673 snprintf(buf, sizeof(buf), "40");
developer72fb0bb2023-01-11 09:46:29 +08003674 }
developer8666b312023-03-24 14:05:31 +08003675 snprintf(output_string, 64, "%sMHz", buf);
developer72fb0bb2023-01-11 09:46:29 +08003676 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3677
3678 return RETURN_OK;
3679}
developer72fb0bb2023-01-11 09:46:29 +08003680//Set the Operating Channel Bandwidth.
3681INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
3682{
3683 char config_file[128];
developerd1824452023-05-18 12:30:04 +08003684 char ht_value[16];
3685 char vht_value[16];
3686 char eht_value[16];
3687 struct params dat[3];
3688 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08003689
3690 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3691
3692 if(NULL == bandwidth)
3693 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08003694 band = wifi_index_to_band(radioIndex);
developer72fb0bb2023-01-11 09:46:29 +08003695
developerd1824452023-05-18 12:30:04 +08003696 if(strstr(bandwidth,"320") != NULL) {
3697 snprintf(ht_value, sizeof(ht_value), "%d", HT_BW_40);
3698 snprintf(vht_value, sizeof(vht_value), "%d", VHT_BW_160);
3699 snprintf(eht_value, sizeof(eht_value), "%d", EHT_BW_320);
3700 } else if(strstr(bandwidth,"160") != NULL) {
3701 snprintf(ht_value, sizeof(ht_value), "%d", HT_BW_40);
3702 snprintf(vht_value, sizeof(vht_value), "%d", VHT_BW_160);
3703 snprintf(eht_value, sizeof(eht_value), "%d", EHT_BW_160);
3704 } else if(strstr(bandwidth,"80") != NULL) {
3705 snprintf(ht_value, sizeof(ht_value), "%d", HT_BW_40);
3706 snprintf(vht_value, sizeof(vht_value), "%d", VHT_BW_80);
3707 snprintf(eht_value, sizeof(eht_value), "%d", EHT_BW_80);
3708 } else if(strstr(bandwidth,"40") != NULL) {
3709 snprintf(ht_value, sizeof(ht_value), "%d", HT_BW_40);
3710 snprintf(vht_value, sizeof(vht_value), "%d", VHT_BW_2040);
3711 snprintf(eht_value, sizeof(eht_value), "%d", EHT_BW_40);
3712 } else if(strstr(bandwidth,"20") != NULL) {
3713 snprintf(ht_value, sizeof(ht_value), "%d", HT_BW_20);
3714 snprintf(vht_value, sizeof(vht_value), "%d", VHT_BW_2040);
3715 snprintf(eht_value, sizeof(eht_value), "%d", EHT_BW_20);
3716 } else {
developer72fb0bb2023-01-11 09:46:29 +08003717 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
3718 return RETURN_ERR;
3719 }
3720
developerd1824452023-05-18 12:30:04 +08003721 snprintf(config_file, sizeof(config_file), "%s%d.dat", LOGAN_DAT_FILE, band);
3722 dat[0].name = "HT_BW";
3723 dat[0].value = ht_value;
3724 dat[1].name = "VHT_BW";
3725 dat[1].value = vht_value;
3726 dat[2].name = "EHT_ApBw";
3727 dat[2].value = eht_value;
3728 wifi_datfileWrite(config_file, dat, 3);
developer72fb0bb2023-01-11 09:46:29 +08003729
3730 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3731 return RETURN_OK;
3732}
3733
developer72fb0bb2023-01-11 09:46:29 +08003734//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
3735//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.
3736INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
3737{
3738 char config_file[64] = {0};
developerd1824452023-05-18 12:30:04 +08003739 char config_dat_file[64] = {0};
developer72fb0bb2023-01-11 09:46:29 +08003740 char mode_str[16] = {0};
3741 char buf[64] = {0};
developerd1824452023-05-18 12:30:04 +08003742 char cmd[MAX_CMD_SIZE] = {0};
3743 char interface_name[64] = {0};
3744 int ret = 0, len=0;
developer72fb0bb2023-01-11 09:46:29 +08003745 wifi_band band;
developerd1824452023-05-18 12:30:04 +08003746 ULONG channel = 0;
3747 int centr_channel = 0;
developer72fb0bb2023-01-11 09:46:29 +08003748 UINT mode_map = 0;
developerd1824452023-05-18 12:30:04 +08003749 int freq=0;
developer72fb0bb2023-01-11 09:46:29 +08003750
3751 if (output_string == NULL)
3752 return RETURN_ERR;
3753
3754 wifi_getRadioMode(radioIndex, mode_str, &mode_map);
3755
3756 band = wifi_index_to_band(radioIndex);
3757 if (band == band_invalid)
3758 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08003759 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3760 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08003761
3762 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
3763
3764 snprintf(output_string, 64, "Auto");
developer23e71282023-01-18 10:25:19 +08003765 if (band == band_2_4 || (!(mode_map&WIFI_MODE_AC) && !(mode_map&WIFI_MODE_AX))) {
developerd1824452023-05-18 12:30:04 +08003766 // 2G band or ac and ax mode is disable, we will check HT_EXTCHA
3767 snprintf(config_dat_file, sizeof(config_dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
3768 wifi_halgetRadioExtChannel(config_dat_file, output_string);
developer23e71282023-01-18 10:25:19 +08003769 if (!(mode_map&WIFI_MODE_N))
developer72fb0bb2023-01-11 09:46:29 +08003770 snprintf(output_string, 64, "Auto");
3771 } else {
3772 // 5G and 6G band with ac or ax mode.
3773 wifi_getRadioChannel(radioIndex, &channel);
developerd1824452023-05-18 12:30:04 +08003774 snprintf(cmd, sizeof(cmd),"iw dev %s info | grep 'center1' | cut -d ' ' -f9 | tr -d '\\n'", interface_name);
3775
3776 ret = _syscmd(cmd, buf, sizeof(buf));
3777 len = strlen(buf);
3778 if((ret != 0) || (len == 0))
3779 {
3780 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
3781 return RETURN_ERR;
3782 }
3783 sscanf(buf, "%d", &freq);
3784 centr_channel = ieee80211_frequency_to_channel(freq);
3785 if (centr_channel > (int)channel)
developer72fb0bb2023-01-11 09:46:29 +08003786 snprintf(output_string, 64, "AboveControlChannel");
3787 else
3788 snprintf(output_string, 64, "BelowControlChannel");
3789 }
3790
3791 return RETURN_OK;
3792}
3793
3794//Set the extension channel.
3795INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
developer69b61b02023-03-07 17:17:44 +08003796{
developer72fb0bb2023-01-11 09:46:29 +08003797 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3798 struct params params={0};
3799 char config_file[64] = {0};
developerd1824452023-05-18 12:30:04 +08003800 char config_dat_file[64] = {0};
3801 char ext_channel[64] = {0};
developer72fb0bb2023-01-11 09:46:29 +08003802 char buf[128] = {0};
3803 char cmd[128] = {0};
3804 int max_radio_num =0, ret = 0, bandwidth = 0;
3805 unsigned long channel = 0, centr_channel = 0;
3806 bool stbcEnable = FALSE;
3807 params.name = "ht_capab";
3808 wifi_band band;
3809
3810 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3811 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
3812 _syscmd(cmd, buf, sizeof(buf));
3813 if (strlen(buf) != 0)
3814 stbcEnable = TRUE;
3815 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, buf) != RETURN_OK)
3816 return RETURN_ERR;
3817 bandwidth = strtol(buf, NULL, 10);
3818 // TDK expected to get error with 20MHz
3819 if (bandwidth == 20 || strstr(buf, "80+80") != NULL)
3820 return RETURN_ERR;
3821
3822 band = wifi_index_to_band(radioIndex);
3823 if (band == band_invalid)
3824 return RETURN_ERR;
3825
3826 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK)
3827 return RETURN_ERR;
3828
3829 if (band == band_5) {
3830 snprintf(buf, sizeof(buf), "HT%d", bandwidth);
3831 centr_channel = util_unii_5g_centerfreq(buf, channel);
3832 if (centr_channel == 0)
3833 return RETURN_ERR;
3834 }
3835
3836 if(NULL!= strstr(string,"Above")) {
3837 if ((band == band_2_4 && channel > 9) || (band == band_5 && channel > centr_channel))
3838 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08003839 snprintf(ext_channel, sizeof(ext_channel), "Above");
developer72fb0bb2023-01-11 09:46:29 +08003840 } else if(NULL!= strstr(string,"Below")) {
3841 if ((band == band_2_4 && channel < 5) || (band == band_5 && channel < centr_channel))
3842 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08003843 snprintf(ext_channel, sizeof(ext_channel), "Above");
3844 } else
3845 printf("%s: invalid EXT_CHA:%s\n", __func__, string);
developer72fb0bb2023-01-11 09:46:29 +08003846
developerd1824452023-05-18 12:30:04 +08003847 params.name = "HT_EXTCHA";
developer72fb0bb2023-01-11 09:46:29 +08003848 params.value = ext_channel;
3849
developerd1824452023-05-18 12:30:04 +08003850 snprintf (config_dat_file, sizeof(config_dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
3851 wifi_datfileWrite(config_dat_file, &params, 1);
3852
developer72fb0bb2023-01-11 09:46:29 +08003853 wifi_getMaxRadioNumber(&max_radio_num);
3854 for(int i=0; i<=MAX_APS/max_radio_num; i++)
3855 {
3856 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(max_radio_num*i));
developer72fb0bb2023-01-11 09:46:29 +08003857 wifi_setRadioSTBCEnable(radioIndex+(max_radio_num*i), stbcEnable);
3858 }
3859
3860 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
3861 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3862 return RETURN_OK;
3863}
3864
3865//Get the guard interval value. eg "400nsec" or "800nsec"
3866//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.
3867INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
3868{
3869 wifi_guard_interval_t GI;
3870
3871 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3872
3873 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
3874 return RETURN_ERR;
3875
3876 if (GI == wifi_guard_interval_400)
3877 strcpy(output_string, "400nsec");
3878 else if (GI == wifi_guard_interval_800)
3879 strcpy(output_string, "800nsec");
3880 else if (GI == wifi_guard_interval_1600)
3881 strcpy(output_string, "1600nsec");
3882 else if (GI == wifi_guard_interval_3200)
3883 strcpy(output_string, "3200nsec");
3884 else
3885 strcpy(output_string, "Auto");
3886
3887 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3888 return RETURN_OK;
3889}
3890
3891//Set the guard interval value.
3892INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
3893{
3894 wifi_guard_interval_t GI;
3895 int ret = 0;
3896
3897 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3898
3899 if (strcmp(string, "400nsec") == 0)
3900 GI = wifi_guard_interval_400;
3901 else if (strcmp(string , "800nsec") == 0)
3902 GI = wifi_guard_interval_800;
3903 else if (strcmp(string , "1600nsec") == 0)
3904 GI = wifi_guard_interval_1600;
3905 else if (strcmp(string , "3200nsec") == 0)
3906 GI = wifi_guard_interval_3200;
3907 else
3908 GI = wifi_guard_interval_auto;
3909
3910 ret = wifi_setGuardInterval(radioIndex, GI);
3911
3912 if (ret == RETURN_ERR) {
3913 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
3914 return RETURN_ERR;
3915 }
3916
3917 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3918 return RETURN_OK;
3919}
3920
3921//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
3922INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
3923{
3924 char buf[32]={0};
3925 char mcs_file[64] = {0};
3926 char cmd[64] = {0};
3927 int mode_bitmap = 0;
3928
3929 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3930 if(output_int == NULL)
3931 return RETURN_ERR;
3932 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
3933
3934 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
3935 _syscmd(cmd, buf, sizeof(buf));
3936 if (strlen(buf) > 0)
3937 *output_int = strtol(buf, NULL, 10);
3938 else {
3939 // output the max MCS for the current radio mode
3940 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
3941 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
3942 return RETURN_ERR;
3943 }
3944 if (mode_bitmap & WIFI_MODE_AX) {
3945 *output_int = 11;
3946 } else if (mode_bitmap & WIFI_MODE_AC) {
3947 *output_int = 9;
3948 } else if (mode_bitmap & WIFI_MODE_N) {
3949 *output_int = 7;
3950 }
3951 }
3952 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3953
3954 return RETURN_OK;
3955}
3956
3957//Set the Modulation Coding Scheme index
3958INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
3959{
developera1255e42023-05-13 17:45:02 +08003960 /*Only HE mode can specify MCS capability. We don't support MCS in HT mode,
3961 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 +08003962 char config_file[64] = {0};
3963 char set_value[16] = {0};
3964 char mcs_file[32] = {0};
developer72fb0bb2023-01-11 09:46:29 +08003965 struct params set_config = {0};
3966 FILE *f = NULL;
developera1255e42023-05-13 17:45:02 +08003967 INT nss = 0;
3968 int ant_bitmap = 0;
3969 unsigned short cal_value = 0;
3970 UCHAR tval = 0, i = 0;
developer72fb0bb2023-01-11 09:46:29 +08003971
3972 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3973
3974 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
3975
3976 // -1 means auto
3977 if (MCS > 15 || MCS < -1) {
3978 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
3979 return RETURN_ERR;
3980 }
developera1255e42023-05-13 17:45:02 +08003981 wifi_getRadioTxChainMask(radioIndex, &ant_bitmap);/*nss is a bit map value,1111*/
3982 for(; ant_bitmap > 0; ant_bitmap >>= 1)
3983 nss += 1;
3984 //printf("%s:nss = %d\n", __func__, nss);
3985 /*16-bit combination of 2-bit values of Max HE-MCS For 1..8 SS;each 2-bit value have following meaning:
3986 0 = HE-MCS 0-7, 1 = HE-MCS 0-9, 2 = HE-MCS 0-11, 3 = not supported*/
developer72fb0bb2023-01-11 09:46:29 +08003987 if (MCS > 9 || MCS == -1)
developera1255e42023-05-13 17:45:02 +08003988 tval = 2;/*one stream value*/
developer72fb0bb2023-01-11 09:46:29 +08003989 else if (MCS > 7)
developera1255e42023-05-13 17:45:02 +08003990 tval = 1;
developer72fb0bb2023-01-11 09:46:29 +08003991 else
developera1255e42023-05-13 17:45:02 +08003992 tval = 0;
3993 for (i = 0; i < nss; i++)
3994 cal_value |= (tval << (2*i));
3995 snprintf(set_value, sizeof(set_value), "%x", cal_value);
3996 WIFI_ENTRY_EXIT_DEBUG("%s:set=%s, cal=%x\n", __func__, set_value, cal_value);
3997 set_config.name = "he_basic_mcs_nss_set";/*He capability in beacon or response*/
developer72fb0bb2023-01-11 09:46:29 +08003998 set_config.value = set_value;
3999
4000 wifi_hostapdWrite(config_file, &set_config, 1);
4001 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
4002
4003 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
4004 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
4005 f = fopen(mcs_file, "w");
4006 if (f == NULL) {
4007 fprintf(stderr, "%s: fopen failed\n", __func__);
4008 return RETURN_ERR;
4009 }
4010 fprintf(f, "%d", MCS);
4011 fclose(f);
4012
4013 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4014 return RETURN_OK;
4015}
4016
4017//Get supported Transmit Power list, eg : "0,25,50,75,100"
4018//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.
4019INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
4020{
4021 if (NULL == output_list)
4022 return RETURN_ERR;
4023 snprintf(output_list, 64,"0,25,50,75,100");
4024 return RETURN_OK;
4025}
4026
4027//Get current Transmit Power in dBm units.
4028//The transmite power level is in units of full power for this radio.
4029INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
4030{
4031 char interface_name[16] = {0};
4032 char cmd[128]={0};
4033 char buf[16]={0};
developera1255e42023-05-13 17:45:02 +08004034 char pwr_file[128]={0};
4035
developer72fb0bb2023-01-11 09:46:29 +08004036 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4037
4038 if(output_ulong == NULL)
4039 return RETURN_ERR;
4040
4041 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4042 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +08004043/*
developer72fb0bb2023-01-11 09:46:29 +08004044 snprintf(cmd, sizeof(cmd), "iw %s info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", interface_name);
4045 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08004046 *output_ulong = strtol(buf, NULL, 10);
developera1255e42023-05-13 17:45:02 +08004047*/
4048 snprintf(pwr_file, sizeof(pwr_file), "%s%d.txt", POWER_PERCENTAGE, radioIndex);
4049 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", pwr_file);
4050 _syscmd(cmd, buf, sizeof(buf));
4051 if (strlen(buf) > 0)
4052 *output_ulong = strtol(buf, NULL, 10);
4053 else
4054 *output_ulong = 100;
developer72fb0bb2023-01-11 09:46:29 +08004055 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4056 return RETURN_OK;
4057}
4058
4059//Set Transmit Power
4060//The transmite power level is in units of full power for this radio.
4061INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
4062{
4063 char interface_name[16] = {0};
4064 char *support;
4065 char cmd[128]={0};
4066 char buf[128]={0};
4067 char txpower_str[64] = {0};
developera1255e42023-05-13 17:45:02 +08004068 char pwr_file[128]={0};
4069 FILE *f = NULL;
developer72fb0bb2023-01-11 09:46:29 +08004070
4071 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4072
4073 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4074 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +08004075 // Get the Tx power supported list and check that is the input in the list
4076 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
4077 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
4078 support = strtok(buf, ",");
4079 while(true)
4080 {
4081 if(support == NULL) { // input not in the list
4082 wifi_dbg_printf("Input value is invalid.\n");
4083 return RETURN_ERR;
4084 }
4085 if (strncmp(txpower_str, support, strlen(support)) == 0) {
4086 break;
4087 }
4088 support = strtok(NULL, ",");
4089 }
4090 snprintf(cmd, sizeof(cmd), "mwctl dev %s set pwr PercentageCtrl=1\n", interface_name);
4091 _syscmd(cmd, buf, sizeof(buf));
4092 snprintf(cmd, sizeof(cmd), "mwctl dev %s set pwr PowerDropCtrl=%lu\n", interface_name, TransmitPower);
4093 _syscmd(cmd, buf, sizeof(buf));
4094 snprintf(pwr_file, sizeof(pwr_file), "%s%d.txt", POWER_PERCENTAGE, radioIndex);
4095 f = fopen(pwr_file, "w");
4096 if (f == NULL) {
4097 fprintf(stderr, "%s: fopen failed\n", __func__);
4098 return RETURN_ERR;
4099 }
4100 fprintf(f, "%d", TransmitPower);
4101 fclose(f);
4102/* 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 +08004103 _syscmd(cmd, buf, sizeof(buf));
4104 maximum_tx = strtol(buf, NULL, 10);
4105
4106 // Get the Tx power supported list and check that is the input in the list
4107 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
4108 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
4109 support = strtok(buf, ",");
4110 while(true)
4111 {
4112 if(support == NULL) { // input not in the list
4113 wifi_dbg_printf("Input value is invalid.\n");
4114 return RETURN_ERR;
4115 }
4116 if (strncmp(txpower_str, support, strlen(support)) == 0) {
4117 break;
4118 }
4119 support = strtok(NULL, ",");
4120 }
4121 txpower = TransmitPower*maximum_tx/100;
4122 phyId = radio_index_to_phy(radioIndex);
4123 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", phyId, txpower);
4124 _syscmd(cmd, buf, sizeof(buf));
4125 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera1255e42023-05-13 17:45:02 +08004126*/
4127 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08004128}
4129
4130//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
4131INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
4132{
developer69b61b02023-03-07 17:17:44 +08004133 if (NULL == Supported)
developer72fb0bb2023-01-11 09:46:29 +08004134 return RETURN_ERR;
4135 *Supported = TRUE;
4136
4137 return RETURN_OK;
4138}
4139
4140//Get 80211h feature enable
4141INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
4142{
4143 char buf[64]={'\0'};
4144 char config_file[64] = {'\0'};
4145
4146 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4147 if(enable == NULL)
4148 return RETURN_ERR;
4149
4150 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
developerd1824452023-05-18 12:30:04 +08004151 /* wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf)); */
4152 wifi_datfileRead(config_file, "IEEE80211H", buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08004153
4154 if (strncmp(buf, "1", 1) == 0)
4155 *enable = TRUE;
4156 else
4157 *enable = FALSE;
4158
4159 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4160 return RETURN_OK;
4161}
4162
4163//Set 80211h feature enable
4164INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
4165{
4166 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4167 struct params params={'\0'};
developerd1824452023-05-18 12:30:04 +08004168 struct params dat={0};
developer72fb0bb2023-01-11 09:46:29 +08004169 char config_file[MAX_BUF_SIZE] = {0};
developerd1824452023-05-18 12:30:04 +08004170 char config_dat_file[MAX_BUF_SIZE] = {0};
4171 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08004172
4173 params.name = "ieee80211h";
4174
4175 if (enable) {
4176 params.value = "1";
4177 } else {
4178 params.value = "0";
4179 }
4180
developerd1824452023-05-18 12:30:04 +08004181 dat.name = "IEEE80211H";
4182 dat.value = params.value;
4183
4184 band = wifi_index_to_band(radioIndex);
4185 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4186 snprintf(config_dat_file, sizeof(config_dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
developer69b61b02023-03-07 17:17:44 +08004187
developerd1824452023-05-18 12:30:04 +08004188 wifi_hostapdWrite(config_file, &params, 1);
4189 wifi_datfileWrite(config_dat_file, &dat, 1);
developer72fb0bb2023-01-11 09:46:29 +08004190 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
4191 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4192 return RETURN_OK;
4193}
4194
4195//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.
4196INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
4197{
4198 if (NULL == output)
4199 return RETURN_ERR;
4200 *output=100;
4201
4202 return RETURN_OK;
4203}
4204
4205//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.
4206INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
4207{
4208 if (NULL == output)
4209 return RETURN_ERR;
4210 *output = -99;
4211
4212 return RETURN_OK;
4213}
4214
4215INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
4216{
4217 return RETURN_ERR;
4218}
4219
4220
4221//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
4222INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
4223{
4224 char interface_name[16] = {0};
4225 char cmd[MAX_BUF_SIZE]={'\0'};
4226 char buf[MAX_CMD_SIZE]={'\0'};
4227
4228 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4229 if(output == NULL)
4230 return RETURN_ERR;
4231
4232 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4233 return RETURN_ERR;
4234 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", interface_name);
4235 _syscmd(cmd, buf, sizeof(buf));
4236 *output = atoi(buf);
4237
4238 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4239 return RETURN_OK;
4240}
developer69b61b02023-03-07 17:17:44 +08004241
developer72fb0bb2023-01-11 09:46:29 +08004242INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
4243{
4244 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4245 struct params params={'\0'};
4246 char buf[MAX_BUF_SIZE] = {'\0'};
4247 char config_file[MAX_BUF_SIZE] = {'\0'};
4248
4249 if (BeaconPeriod < 15 || BeaconPeriod > 65535)
4250 return RETURN_ERR;
4251
4252 params.name = "beacon_int";
4253 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
4254 params.value = buf;
4255
4256 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
4257 wifi_hostapdWrite(config_file, &params, 1);
developer69b61b02023-03-07 17:17:44 +08004258
developer72fb0bb2023-01-11 09:46:29 +08004259 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
4260 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4261 return RETURN_OK;
4262}
4263
4264//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.
4265INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
4266{
4267 //TODO: need to revisit below implementation
4268 char *temp;
4269 char temp_output[128] = {0};
4270 char temp_TransmitRates[64] = {0};
4271 char config_file[64] = {0};
4272
4273 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4274 if (NULL == output)
4275 return RETURN_ERR;
4276 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
4277 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
developer69b61b02023-03-07 17:17:44 +08004278
developer72fb0bb2023-01-11 09:46:29 +08004279 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
4280 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
4281 } else {
4282 temp = strtok(temp_TransmitRates," ");
4283 while(temp!=NULL)
4284 {
4285 // Convert 100 kbps to Mbps
4286 temp[strlen(temp)-1]=0;
4287 if((temp[0]=='5') && (temp[1]=='\0'))
4288 {
4289 temp="5.5";
4290 }
4291 strcat(temp_output,temp);
4292 temp = strtok(NULL," ");
4293 if(temp!=NULL)
4294 {
4295 strcat(temp_output,",");
4296 }
4297 }
4298 strcpy(output,temp_output);
4299 }
4300 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4301 return RETURN_OK;
4302}
4303
4304INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
4305{
4306 char *temp;
4307 char temp1[128];
4308 char temp_output[128];
4309 char temp_TransmitRates[128];
4310 char set[128];
4311 char sub_set[128];
4312 int set_count=0,subset_count=0;
4313 int set_index=0,subset_index=0;
4314 char *token;
4315 int flag=0, i=0;
4316 struct params params={'\0'};
4317 char config_file[MAX_BUF_SIZE] = {0};
4318 wifi_band band = wifi_index_to_band(radioIndex);
4319
4320 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4321 if(NULL == TransmitRates)
4322 return RETURN_ERR;
4323 strcpy(sub_set,TransmitRates);
4324
4325 //Allow only supported Data transmit rate to be set
4326 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
4327 token = strtok(sub_set,",");
4328 while( token != NULL ) /* split the basic rate to be set, by comma */
4329 {
4330 sub_set[subset_count]=atoi(token);
4331 subset_count++;
4332 token=strtok(NULL,",");
4333 }
4334 token=strtok(set,",");
4335 while(token!=NULL) /* split the supported rate by comma */
4336 {
4337 set[set_count]=atoi(token);
4338 set_count++;
4339 token=strtok(NULL,",");
4340 }
4341 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
4342 {
4343 for(set_index=0;set_index < set_count;set_index++)
4344 {
4345 flag=0;
4346 if(sub_set[subset_index]==set[set_index])
4347 break;
4348 else
4349 flag=1; /* No match found */
4350 }
4351 if(flag==1)
4352 return RETURN_ERR; //If value not found return Error
4353 }
4354 strcpy(temp_TransmitRates,TransmitRates);
4355
4356 for(i=0;i<strlen(temp_TransmitRates);i++)
4357 {
4358 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
4359 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
4360 {
4361 continue;
4362 }
4363 else
4364 {
4365 return RETURN_ERR;
4366 }
4367 }
4368 strcpy(temp_output,"");
4369 temp = strtok(temp_TransmitRates,",");
4370 while(temp!=NULL)
4371 {
4372 strcpy(temp1,temp);
4373 if(band == band_5)
4374 {
4375 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
4376 {
4377 return RETURN_ERR;
4378 }
4379 }
4380
4381 if(strcmp(temp,"5.5")==0)
4382 {
4383 strcpy(temp1,"55");
4384 }
4385 else
4386 {
4387 strcat(temp1,"0");
4388 }
4389 strcat(temp_output,temp1);
4390 temp = strtok(NULL,",");
4391 if(temp!=NULL)
4392 {
4393 strcat(temp_output," ");
4394 }
4395 }
4396 strcpy(TransmitRates,temp_output);
4397
4398 params.name= "basic_rates";
4399 params.value =TransmitRates;
4400
4401 wifi_dbg_printf("\n%s:",__func__);
4402 wifi_dbg_printf("\nparams.value=%s\n",params.value);
4403 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
4404 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
4405 wifi_hostapdWrite(config_file,&params,1);
4406 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4407 return RETURN_OK;
4408}
4409
4410//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
4411INT wifi_GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
4412{
4413 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
4414 FILE *fp = NULL;
4415 char path[256] = {0}, output_string[256] = {0};
4416 int count = 0;
4417 char *interface = NULL;
4418
4419 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
4420 if (fp == NULL)
4421 {
4422 printf("Failed to run command in Function %s\n", __FUNCTION__);
4423 return RETURN_ERR;
4424 }
4425 if (fgets(path, sizeof(path) - 1, fp) != NULL)
4426 {
4427 interface = strchr(path, '=');
4428
4429 if (interface != NULL)
4430 {
4431 strcpy(output_string, interface + 1);
4432 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
4433 interface_name[count] = output_string[count];
4434
4435 interface_name[count] = '\0';
4436 }
4437 }
4438 pclose(fp);
4439 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
4440 return RETURN_OK;
4441}
4442
4443INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
4444{
4445 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
4446 output_struct->radio_BytesSent = 0;
4447 output_struct->radio_BytesReceived = 0;
4448 output_struct->radio_PacketsSent = 0;
4449 output_struct->radio_PacketsReceived = 0;
4450 output_struct->radio_ErrorsSent = 0;
4451 output_struct->radio_ErrorsReceived = 0;
4452 output_struct->radio_DiscardPacketsSent = 0;
4453 output_struct->radio_DiscardPacketsReceived = 0;
4454 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
4455 return RETURN_OK;
4456}
4457
4458
4459INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
4460{
4461 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
4462 CHAR buf[MAX_CMD_SIZE] = {0};
4463 CHAR Value[MAX_BUF_SIZE] = {0};
4464 FILE *fp = NULL;
4465
4466 if (ifname == NULL || strlen(ifname) <= 1)
4467 return RETURN_OK;
4468
4469 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
4470 system(buf);
4471
4472 fp = fopen("/tmp/Radio_Stats.txt", "r");
4473 if(fp == NULL)
4474 {
4475 printf("/tmp/Radio_Stats.txt not exists \n");
4476 return RETURN_ERR;
4477 }
4478 fclose(fp);
4479
4480 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4481 File_Reading(buf, Value);
4482 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
4483
4484 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4485 File_Reading(buf, Value);
4486 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
4487
4488 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4489 File_Reading(buf, Value);
4490 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
4491
4492 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4493 File_Reading(buf, Value);
4494 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
4495
4496 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4497 File_Reading(buf, Value);
4498 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
4499
4500 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4501 File_Reading(buf, Value);
4502 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
4503
4504 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4505 File_Reading(buf, Value);
4506 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
4507
4508 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4509 File_Reading(buf, Value);
4510 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
4511
4512 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
4513 return RETURN_OK;
4514}
4515
4516INT GetIfacestatus(CHAR *interface_name, CHAR *status)
4517{
developer7e4a2a62023-04-06 19:56:03 +08004518 CHAR buf[MAX_CMD_SIZE] = {0};
4519 INT count = 0;
developer72fb0bb2023-01-11 09:46:29 +08004520
developer7e4a2a62023-04-06 19:56:03 +08004521 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
4522
4523 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL) {
4524 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
4525 File_Reading(buf, status);
4526 }
4527
4528 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
4529 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08004530}
4531
4532//Get detail radio traffic static info
4533INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
4534{
4535
developer69b61b02023-03-07 17:17:44 +08004536#if 0
4537 //ifconfig radio_x
developer72fb0bb2023-01-11 09:46:29 +08004538 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
4539 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
4540 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
4541 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
4542
4543 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
4544 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
4545 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.
4546 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.
4547
developer69b61b02023-03-07 17:17:44 +08004548 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 +08004549 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].
4550 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
4551 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.
4552 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
4553 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
4554 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
4555 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
4556 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
4557
4558 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
4559 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
4560 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
4561 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.
4562
4563 return RETURN_OK;
4564#endif
4565
4566 CHAR interface_name[64] = {0};
4567 BOOL iface_status = FALSE;
4568 wifi_radioTrafficStats2_t radioTrafficStats = {0};
4569
4570 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
4571 if (NULL == output_struct)
4572 return RETURN_ERR;
4573
4574 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4575 return RETURN_ERR;
4576
4577 wifi_getApEnable(radioIndex, &iface_status);
4578
4579 if (iface_status == TRUE)
4580 wifi_halGetIfStats(interface_name, &radioTrafficStats);
4581 else
4582 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
4583
4584 output_struct->radio_BytesSent = radioTrafficStats.radio_BytesSent;
4585 output_struct->radio_BytesReceived = radioTrafficStats.radio_BytesReceived;
4586 output_struct->radio_PacketsSent = radioTrafficStats.radio_PacketsSent;
4587 output_struct->radio_PacketsReceived = radioTrafficStats.radio_PacketsReceived;
4588 output_struct->radio_ErrorsSent = radioTrafficStats.radio_ErrorsSent;
4589 output_struct->radio_ErrorsReceived = radioTrafficStats.radio_ErrorsReceived;
4590 output_struct->radio_DiscardPacketsSent = radioTrafficStats.radio_DiscardPacketsSent;
4591 output_struct->radio_DiscardPacketsReceived = radioTrafficStats.radio_DiscardPacketsReceived;
4592
4593 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
4594 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].
4595 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
4596 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.
4597 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
4598 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
4599 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
4600 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
4601 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
4602
4603 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
4604 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
4605 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
4606 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.
4607
4608 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
4609
4610 return RETURN_OK;
4611}
4612
4613//Set radio traffic static Measureing rules
4614INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
4615{
4616 //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
4617 // Else, save the MeasuringRate and MeasuringInterval for future usage
4618
4619 return RETURN_OK;
4620}
4621
4622//To start or stop RadioTrafficStats
4623INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
4624{
4625 //zqiu: If the RadioTrafficStats process running
4626 // if(enable)
4627 // return RETURN_OK.
4628 // else
4629 // Stop RadioTrafficStats process
developer69b61b02023-03-07 17:17:44 +08004630 // Else
developer72fb0bb2023-01-11 09:46:29 +08004631 // if(enable)
4632 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
4633 // else
4634 // return RETURN_OK.
4635
4636 return RETURN_OK;
4637}
4638
4639//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
4640INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
4641{
4642 //zqiu: Please ignor signalIndex.
developer69b61b02023-03-07 17:17:44 +08004643 if (NULL == SignalLevel)
developer72fb0bb2023-01-11 09:46:29 +08004644 return RETURN_ERR;
developer47cc27a2023-05-17 23:09:58 +08004645
developer72fb0bb2023-01-11 09:46:29 +08004646 *SignalLevel=(radioIndex==0)?-19:-19;
4647
4648 return RETURN_OK;
4649}
4650
4651//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
4652INT wifi_applyRadioSettings(INT radioIndex)
4653{
4654 return RETURN_OK;
4655}
4656
4657//Get the radio index assocated with this SSID entry
4658INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
4659{
4660 if(NULL == radioIndex)
4661 return RETURN_ERR;
4662 int max_radio_num = 0;
4663 wifi_getMaxRadioNumber(&max_radio_num);
4664 *radioIndex = ssidIndex%max_radio_num;
4665 return RETURN_OK;
4666}
4667
4668//Device.WiFi.SSID.{i}.Enable
4669//Get SSID enable configuration parameters (not the SSID enable status)
4670INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
4671{
developer69b61b02023-03-07 17:17:44 +08004672 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08004673 return RETURN_ERR;
4674
4675 return wifi_getApEnable(ssidIndex, output_bool);
4676}
4677
4678//Device.WiFi.SSID.{i}.Enable
4679//Set SSID enable configuration parameters
4680INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
4681{
4682 return wifi_setApEnable(ssidIndex, enable);
4683}
4684
4685//Device.WiFi.SSID.{i}.Status
4686//Get the SSID enable status
4687INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
4688{
4689 char cmd[MAX_CMD_SIZE]={0};
4690 char buf[MAX_BUF_SIZE]={0};
4691 BOOL output_bool;
4692
4693 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4694 if (NULL == output_string)
4695 return RETURN_ERR;
developer69b61b02023-03-07 17:17:44 +08004696
developer72fb0bb2023-01-11 09:46:29 +08004697 wifi_getApEnable(ssidIndex,&output_bool);
4698 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
4699
4700 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4701 return RETURN_OK;
4702}
4703
4704// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
4705INT wifi_getSSIDName(INT apIndex, CHAR *output)
4706{
4707 char config_file[MAX_BUF_SIZE] = {0};
4708
developer69b61b02023-03-07 17:17:44 +08004709 if (NULL == output)
developer72fb0bb2023-01-11 09:46:29 +08004710 return RETURN_ERR;
4711
4712 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4713 wifi_hostapdRead(config_file,"ssid",output,32);
4714
4715 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
4716 return RETURN_OK;
4717}
4718
developer69b61b02023-03-07 17:17:44 +08004719// Set a max 32 byte string and sets an internal variable to the SSID name
developer72fb0bb2023-01-11 09:46:29 +08004720INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
4721{
4722 char str[MAX_BUF_SIZE]={'\0'};
4723 char cmd[MAX_CMD_SIZE]={'\0'};
4724 struct params params;
4725 char config_file[MAX_BUF_SIZE] = {0};
4726
4727 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4728 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
4729 return RETURN_ERR;
4730
4731 params.name = "ssid";
4732 params.value = ssid_string;
4733 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4734 wifi_hostapdWrite(config_file, &params, 1);
4735 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4736 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4737
4738 return RETURN_OK;
4739}
4740
4741//Get the BSSID
4742INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
4743{
developer7e4a2a62023-04-06 19:56:03 +08004744 char cmd[MAX_CMD_SIZE] = {0};
4745 char inf_name[IF_NAME_SIZE] = {0};
4746 char conf_file[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08004747
developer7e4a2a62023-04-06 19:56:03 +08004748 if (!output_string)
developer72fb0bb2023-01-11 09:46:29 +08004749 return RETURN_ERR;
4750
developer47cc27a2023-05-17 23:09:58 +08004751 if (wifi_GetInterfaceName(ssidIndex, inf_name) != RETURN_OK)
4752 return RETURN_ERR;
developer7e4a2a62023-04-06 19:56:03 +08004753
4754 if(ssidIndex >= 0 && ssidIndex < MAX_APS) {
4755 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 +08004756 _syscmd(cmd, output_string, 64);
developer7e4a2a62023-04-06 19:56:03 +08004757 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08004758 }
developer7e4a2a62023-04-06 19:56:03 +08004759
developer72fb0bb2023-01-11 09:46:29 +08004760 strncpy(output_string, "\0", 1);
4761
4762 return RETURN_ERR;
4763}
4764
4765//Get the MAC address associated with this Wifi SSID
4766INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
4767{
4768 wifi_getBaseBSSID(ssidIndex,output_string);
4769 return RETURN_OK;
4770}
4771
4772//Get the basic SSID traffic static info
4773//Apply SSID and AP (in the case of Acess Point devices) to the hardware
4774//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
4775INT wifi_applySSIDSettings(INT ssidIndex)
4776{
4777 char interface_name[16] = {0};
4778 BOOL status = false;
4779 char cmd[MAX_CMD_SIZE] = {0};
4780 char buf[MAX_CMD_SIZE] = {0};
4781 int apIndex, ret;
4782 int max_radio_num = 0;
4783 int radioIndex = 0;
4784
4785 wifi_getMaxRadioNumber(&max_radio_num);
4786
4787 radioIndex = ssidIndex % max_radio_num;
4788
4789 wifi_getApEnable(ssidIndex,&status);
4790 // Do not apply when ssid index is disabled
4791 if (status == false)
4792 return RETURN_OK;
4793
4794 /* Doing full remove and add for ssid Index
4795 * Not all hostapd options are supported with reload
4796 * for example macaddr_acl
4797 */
4798 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
4799 return RETURN_ERR;
4800
4801 ret = wifi_setApEnable(ssidIndex,true);
4802
4803 /* Workaround for hostapd issue with multiple bss definitions
4804 * when first created interface will be removed
4805 * then all vaps other vaps on same phy are removed
4806 * after calling setApEnable to false readd all enabled vaps */
4807 for(int i=0; i < MAX_APS/max_radio_num; i++) {
4808 apIndex = max_radio_num*i+radioIndex;
4809 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4810 return RETURN_ERR;
4811 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
4812 _syscmd(cmd, buf, sizeof(buf));
4813 if(*buf == '1')
4814 wifi_setApEnable(apIndex, true);
4815 }
4816
4817 return ret;
4818}
4819
4820struct channels_noise {
4821 int channel;
4822 int noise;
4823};
4824
4825// Return noise array for each channel
4826int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
4827{
4828 char interface_name[16] = {0};
4829 FILE *f = NULL;
4830 char cmd[128] = {0};
4831 char line[256] = {0};
4832 size_t len = 0;
4833 ssize_t read = 0;
4834 int tmp = 0, arr_index = -1;
4835
4836 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4837 return RETURN_ERR;
4838 sprintf(cmd, "iw dev %s survey dump | grep 'frequency\\|noise' | awk '{print $2}'", interface_name);
4839
4840 if ((f = popen(cmd, "r")) == NULL) {
4841 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
4842 return RETURN_ERR;
4843 }
developer69b61b02023-03-07 17:17:44 +08004844
developer72fb0bb2023-01-11 09:46:29 +08004845 while(fgets(line, sizeof(line), f) != NULL) {
4846 if(arr_index < channels_num){
4847 sscanf(line, "%d", &tmp);
4848 if (tmp > 0) { // channel frequency, the first line must be frequency
4849 arr_index++;
4850 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
4851 } else { // noise
4852 channels_noise_arr[arr_index].noise = tmp;
4853 }
4854 }else{
4855 break;
4856 }
4857 }
4858 pclose(f);
4859 return RETURN_OK;
4860}
4861
4862//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
4863//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
developer69b61b02023-03-07 17:17:44 +08004864INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
developer72fb0bb2023-01-11 09:46:29 +08004865{
4866 int index = -1;
4867 wifi_neighbor_ap2_t *scan_array = NULL;
4868 char cmd[256]={0};
4869 char buf[128]={0};
4870 char file_name[32] = {0};
4871 char filter_SSID[32] = {0};
4872 char line[256] = {0};
4873 char interface_name[16] = {0};
4874 char *ret = NULL;
4875 int freq=0;
4876 FILE *f = NULL;
4877 size_t len=0;
4878 int channels_num = 0;
4879 int vht_channel_width = 0;
4880 int get_noise_ret = RETURN_ERR;
4881 bool filter_enable = false;
4882 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
4883 int phyId = 0;
4884
4885 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
4886
4887 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4888 return RETURN_ERR;
4889
4890 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
4891 f = fopen(file_name, "r");
4892 if (f != NULL) {
4893 fgets(filter_SSID, sizeof(file_name), f);
4894 if (strlen(filter_SSID) != 0)
4895 filter_enable = true;
4896 fclose(f);
4897 }
4898
4899 phyId = radio_index_to_phy(radioIndex);
4900 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
4901 _syscmd(cmd, buf, sizeof(buf));
4902 channels_num = strtol(buf, NULL, 10);
4903
4904
4905
4906 sprintf(cmd, "iw dev %s scan | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
4907 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", interface_name, interface_name);
4908 fprintf(stderr, "cmd: %s\n", cmd);
4909 if ((f = popen(cmd, "r")) == NULL) {
4910 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
4911 return RETURN_ERR;
4912 }
developer69b61b02023-03-07 17:17:44 +08004913
developer72fb0bb2023-01-11 09:46:29 +08004914 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
4915 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
developer69b61b02023-03-07 17:17:44 +08004916
developer72fb0bb2023-01-11 09:46:29 +08004917 ret = fgets(line, sizeof(line), f);
4918 while (ret != NULL) {
4919 if(strstr(line, "BSS") != NULL) { // new neighbor info
developer69b61b02023-03-07 17:17:44 +08004920 // 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 +08004921 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
4922 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
4923
4924 if (!filter_BSS) {
4925 index++;
4926 wifi_neighbor_ap2_t *tmp;
4927 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
4928 if (tmp == NULL) { // no more memory to use
4929 index--;
4930 wifi_dbg_printf("%s: realloc failed\n", __func__);
4931 break;
4932 }
4933 scan_array = tmp;
4934 }
4935 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
4936
4937 filter_BSS = false;
4938 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
4939 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
4940 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
4941 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
4942 } else if (strstr(line, "freq") != NULL) {
4943 sscanf(line," freq: %d", &freq);
4944 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
4945
4946 if (freq >= 2412 && freq <= 2484) {
4947 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
4948 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
4949 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
4950 }
4951 else if (freq >= 5160 && freq <= 5805) {
4952 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
4953 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
4954 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
4955 }
4956
4957 scan_array[index].ap_Noise = 0;
4958 if (get_noise_ret == RETURN_OK) {
4959 for (int i = 0; i < channels_num; i++) {
4960 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
4961 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
4962 break;
4963 }
4964 }
4965 }
4966 } else if (strstr(line, "beacon interval") != NULL) {
4967 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
4968 } else if (strstr(line, "signal") != NULL) {
4969 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
4970 } else if (strstr(line,"SSID") != NULL) {
4971 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
4972 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
4973 filter_BSS = true;
4974 }
4975 } else if (strstr(line, "Supported rates") != NULL) {
4976 char SRate[80] = {0}, *tmp = NULL;
4977 memset(buf, 0, sizeof(buf));
4978 strcpy(SRate, line);
4979 tmp = strtok(SRate, ":");
4980 tmp = strtok(NULL, ":");
4981 strcpy(buf, tmp);
4982 memset(SRate, 0, sizeof(SRate));
4983
4984 tmp = strtok(buf, " \n");
4985 while (tmp != NULL) {
4986 strcat(SRate, tmp);
4987 if (SRate[strlen(SRate) - 1] == '*') {
4988 SRate[strlen(SRate) - 1] = '\0';
4989 }
4990 strcat(SRate, ",");
4991
4992 tmp = strtok(NULL, " \n");
4993 }
4994 SRate[strlen(SRate) - 1] = '\0';
4995 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
4996 } else if (strstr(line, "DTIM") != NULL) {
4997 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
4998 } else if (strstr(line, "VHT capabilities") != NULL) {
4999 strcat(scan_array[index].ap_SupportedStandards, ",ac");
5000 strcpy(scan_array[index].ap_OperatingStandards, "ac");
5001 } else if (strstr(line, "HT capabilities") != NULL) {
5002 strcat(scan_array[index].ap_SupportedStandards, ",n");
5003 strcpy(scan_array[index].ap_OperatingStandards, "n");
5004 } else if (strstr(line, "VHT operation") != NULL) {
5005 ret = fgets(line, sizeof(line), f);
5006 sscanf(line," * channel width: %d", &vht_channel_width);
5007 if(vht_channel_width == 1) {
5008 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
5009 } else {
5010 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
5011 }
5012 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
5013 continue;
5014 } else if (strstr(line, "HT operation") != NULL) {
5015 ret = fgets(line, sizeof(line), f);
5016 sscanf(line," * secondary channel offset: %s", &buf);
5017 if (!strcmp(buf, "above")) {
5018 //40Mhz +
5019 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
5020 }
5021 else if (!strcmp(buf, "below")) {
5022 //40Mhz -
5023 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
5024 } else {
5025 //20Mhz
5026 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
5027 }
5028 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
5029 continue;
5030 } else if (strstr(line, "HE capabilities") != NULL) {
5031 strcat(scan_array[index].ap_SupportedStandards, ",ax");
5032 strcpy(scan_array[index].ap_OperatingStandards, "ax");
5033 ret = fgets(line, sizeof(line), f);
5034 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
5035 if (strstr(line, "HE40/2.4GHz") != NULL)
5036 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
5037 else
5038 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
5039 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
5040 if (strstr(line, "HE80/5GHz") != NULL) {
5041 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
5042 ret = fgets(line, sizeof(line), f);
5043 } else
5044 continue;
5045 if (strstr(line, "HE160/5GHz") != NULL)
5046 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
5047 }
5048 continue;
5049 } else if (strstr(line, "WPA") != NULL) {
5050 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
5051 } else if (strstr(line, "RSN") != NULL) {
5052 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
5053 } else if (strstr(line, "Group cipher") != NULL) {
5054 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
5055 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
5056 strcpy(scan_array[index].ap_EncryptionMode, "AES");
5057 }
5058 }
5059 ret = fgets(line, sizeof(line), f);
5060 }
5061
5062 if (!filter_BSS) {
5063 *output_array_size = index + 1;
5064 } else {
5065 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
5066 *output_array_size = index;
5067 }
5068 *neighbor_ap_array = scan_array;
5069 pclose(f);
5070 free(channels_noise_arr);
5071 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5072 return RETURN_OK;
5073}
5074
5075//>> Deprecated: used for old RDKB code.
5076INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
5077{
5078 INT status = RETURN_ERR;
5079
5080 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5081 output_struct->wifi_PLCPErrorCount = 0;
5082 output_struct->wifi_FCSErrorCount = 0;
5083 output_struct->wifi_InvalidMACCount = 0;
5084 output_struct->wifi_PacketsOtherReceived = 0;
5085 output_struct->wifi_Noise = 0;
5086 status = RETURN_OK;
5087 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5088 return status;
5089}
5090
5091INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
5092{
5093 char interface_name[16] = {0};
5094 char cmd[128] = {0};
5095 char buf[1280] = {0};
5096 char *pos = NULL;
5097
5098 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5099 if (NULL == output_struct)
5100 return RETURN_ERR;
5101
5102 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5103 return RETURN_ERR;
5104
5105 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
5106
5107 snprintf(cmd, sizeof(cmd), "ifconfig %s", interface_name);
5108 _syscmd(cmd, buf, sizeof(buf));
5109
5110 pos = buf;
5111 if ((pos = strstr(pos, "RX packets:")) == NULL)
5112 return RETURN_ERR;
5113 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
5114
5115 if ((pos = strstr(pos, "TX packets:")) == NULL)
5116 return RETURN_ERR;
5117 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
5118
5119 if ((pos = strstr(pos, "RX bytes:")) == NULL)
5120 return RETURN_ERR;
5121 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
5122
5123 if ((pos = strstr(pos, "TX bytes:")) == NULL)
5124 return RETURN_ERR;
5125 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
5126
5127 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l | tr -d '\n'", interface_name);
5128 _syscmd(cmd, buf, sizeof(buf));
5129 sscanf(buf, "%lu", &output_struct->wifi_Associations);
5130
5131#if 0
5132 //TODO: need to revisit below implementation
5133 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5134 char interface_name[MAX_BUF_SIZE] = {0};
5135 char interface_status[MAX_BUF_SIZE] = {0};
5136 char Value[MAX_BUF_SIZE] = {0};
5137 char buf[MAX_CMD_SIZE] = {0};
5138 char cmd[MAX_CMD_SIZE] = {0};
5139 FILE *fp = NULL;
5140
5141 if (NULL == output_struct) {
5142 return RETURN_ERR;
5143 }
5144
5145 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
5146
5147 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
5148 {
5149 if(apIndex == 0) //private_wifi for 2.4G
5150 {
5151 wifi_GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
5152 }
5153 else if(apIndex == 1) //private_wifi for 5G
5154 {
5155 wifi_GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
5156 }
5157 else if(apIndex == 4) //public_wifi for 2.4G
5158 {
5159 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
5160 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
5161 {
5162 return RETURN_ERR;
5163 }
5164 if(buf[0] == '#')//tp-link
5165 wifi_GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
5166 else//tenda
5167 wifi_GetInterfaceName_virtualInterfaceName_2G(interface_name);
5168 }
5169 else if(apIndex == 5) //public_wifi for 5G
5170 {
5171 wifi_GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
5172 }
5173
5174 GetIfacestatus(interface_name, interface_status);
5175
5176 if(0 != strcmp(interface_status, "1"))
5177 return RETURN_ERR;
5178
5179 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
5180 system(cmd);
5181
5182 fp = fopen("/tmp/SSID_Stats.txt", "r");
5183 if(fp == NULL)
5184 {
5185 printf("/tmp/SSID_Stats.txt not exists \n");
5186 return RETURN_ERR;
5187 }
5188 fclose(fp);
5189
5190 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
5191 File_Reading(buf, Value);
5192 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
5193
5194 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
5195 File_Reading(buf, Value);
5196 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
5197
5198 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
5199 File_Reading(buf, Value);
5200 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
5201
5202 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
5203 File_Reading(buf, Value);
5204 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
5205
5206 /* There is no specific parameter from caller to associate the value wifi_Associations */
5207 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
5208 //_syscmd(cmd, buf, sizeof(buf));
5209 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
5210 }
5211#endif
5212 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5213 return RETURN_OK;
5214}
5215
5216INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
5217{
5218 char interface_name[MAX_BUF_SIZE] = {0};
5219 char interface_status[MAX_BUF_SIZE] = {0};
5220 char Value[MAX_BUF_SIZE] = {0};
5221 char buf[MAX_CMD_SIZE] = {0};
5222 char cmd[MAX_CMD_SIZE] = {0};
5223 FILE *fp = NULL;
5224
5225 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5226 if (NULL == output_struct)
5227 return RETURN_ERR;
5228
5229 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
5230
5231 if (wifi_GetInterfaceName(apIndex,interface_name) != RETURN_OK)
5232 return RETURN_ERR;
5233 GetIfacestatus(interface_name, interface_status);
5234
5235 if(0 != strcmp(interface_status, "1"))
5236 return RETURN_ERR;
5237
5238 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
5239 system(cmd);
5240
5241 fp = fopen("/tmp/SSID_Stats.txt", "r");
5242 if(fp == NULL)
5243 {
5244 printf("/tmp/SSID_Stats.txt not exists \n");
5245 return RETURN_ERR;
5246 }
5247 fclose(fp);
5248
5249 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
5250 File_Reading(buf, Value);
5251 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
5252
5253 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
5254 File_Reading(buf, Value);
5255 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
5256
5257 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
5258 File_Reading(buf, Value);
5259 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
5260
5261 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
5262 File_Reading(buf, Value);
5263 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
5264
5265 output_struct->wifi_UnicastPacketsSent = 0;
5266 output_struct->wifi_UnicastPacketsReceived = 0;
5267 output_struct->wifi_MulticastPacketsSent = 0;
5268 output_struct->wifi_MulticastPacketsReceived = 0;
5269 output_struct->wifi_BroadcastPacketsSent = 0;
5270 output_struct->wifi_BroadcastPacketsRecevied = 0;
5271 output_struct->wifi_UnknownPacketsReceived = 0;
5272
5273 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5274 return RETURN_OK;
5275}
5276
5277INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
5278{
5279 INT status = RETURN_ERR;
5280
5281 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5282 //Below values should get updated from hal
5283 output_struct->wifi_RetransCount=0;
5284 output_struct->wifi_FailedRetransCount=0;
5285 output_struct->wifi_RetryCount=0;
5286 output_struct->wifi_MultipleRetryCount=0;
5287 output_struct->wifi_ACKFailureCount=0;
5288 output_struct->wifi_AggregatedPacketCount=0;
5289
5290 status = RETURN_OK;
5291 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5292
5293 return status;
5294}
5295
5296INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
5297{
5298 INT status = RETURN_ERR;
5299 UINT index;
5300 wifi_neighbor_ap_t *pt=NULL;
5301
5302 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5303 *output_array_size=2;
5304 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
5305 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
5306 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
5307 strcpy(pt->ap_Radio,"");
5308 strcpy(pt->ap_SSID,"");
5309 strcpy(pt->ap_BSSID,"");
5310 strcpy(pt->ap_Mode,"");
5311 pt->ap_Channel=1;
5312 pt->ap_SignalStrength=0;
5313 strcpy(pt->ap_SecurityModeEnabled,"");
5314 strcpy(pt->ap_EncryptionMode,"");
5315 strcpy(pt->ap_OperatingFrequencyBand,"");
5316 strcpy(pt->ap_SupportedStandards,"");
5317 strcpy(pt->ap_OperatingStandards,"");
5318 strcpy(pt->ap_OperatingChannelBandwidth,"");
5319 pt->ap_BeaconPeriod=1;
5320 pt->ap_Noise=0;
5321 strcpy(pt->ap_BasicDataTransferRates,"");
5322 strcpy(pt->ap_SupportedDataTransferRates,"");
5323 pt->ap_DTIMPeriod=1;
5324 pt->ap_ChannelUtilization = 1;
5325 }
5326
5327 status = RETURN_OK;
5328 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5329
5330 return status;
5331}
5332
5333//----------------- AP HAL -------------------------------
5334
5335//>> Deprecated: used for old RDKB code.
5336INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
5337{
5338 if (NULL == output_ulong || NULL == output_struct)
5339 return RETURN_ERR;
5340 *output_ulong = 0;
5341 *output_struct = NULL;
5342 return RETURN_OK;
5343}
5344
5345#ifdef HAL_NETLINK_IMPL
5346static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
5347 struct nlattr *tb[NL80211_ATTR_MAX + 1];
5348 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
5349 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
5350 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
5351 char mac_addr[20];
5352 static int count=0;
5353 int rate=0;
5354
5355 wifi_device_info_t *out = (wifi_device_info_t*)arg;
5356
5357 nla_parse(tb,
5358 NL80211_ATTR_MAX,
5359 genlmsg_attrdata(gnlh, 0),
5360 genlmsg_attrlen(gnlh, 0),
5361 NULL);
5362
5363 if(!tb[NL80211_ATTR_STA_INFO]) {
5364 fprintf(stderr, "sta stats missing!\n");
5365 return NL_SKIP;
5366 }
5367
5368
5369 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
5370 fprintf(stderr, "failed to parse nested attributes!\n");
5371 return NL_SKIP;
5372 }
5373
5374 //devIndex starts from 1
5375 if( ++count == out->wifi_devIndex )
5376 {
5377 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
5378 //Getting the mac addrress
5379 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
5380
5381 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
5382 fprintf(stderr, "failed to parse nested rate attributes!");
5383 return NL_SKIP;
5384 }
5385
5386 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
5387 if(rinfo[NL80211_RATE_INFO_BITRATE])
5388 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
5389 out->wifi_devTxRate = rate/10;
5390 }
5391
5392 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
5393 fprintf(stderr, "failed to parse nested rate attributes!");
5394 return NL_SKIP;
5395 }
5396
5397 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
5398 if(rinfo[NL80211_RATE_INFO_BITRATE])
5399 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
5400 out->wifi_devRxRate = rate/10;
5401 }
5402 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
5403 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
5404
5405 out->wifi_devAssociatedDeviceAuthentiationState = 1;
5406 count = 0; //starts the count for next cycle
5407 return NL_STOP;
5408 }
5409
5410 return NL_SKIP;
5411
5412}
5413#endif
5414
5415INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
5416{
5417#ifdef HAL_NETLINK_IMPL
5418 Netlink nl = {0};
5419 char if_name[10] = {0};
5420 char interface_name[16] = {0};
5421
5422 wifi_device_info_t info = {0};
5423 info.wifi_devIndex = devIndex;
5424
5425 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5426 return RETURN_ERR;
5427
5428 snprintf(if_name,sizeof(if_name),"%s", interface_name);
5429
5430 nl.id = initSock80211(&nl);
5431
5432 if (nl.id < 0) {
5433 fprintf(stderr, "Error initializing netlink \n");
5434 return -1;
5435 }
5436
5437 struct nl_msg* msg = nlmsg_alloc();
5438
5439 if (!msg) {
5440 fprintf(stderr, "Failed to allocate netlink message.\n");
5441 nlfree(&nl);
5442 return -2;
5443 }
5444
5445 genlmsg_put(msg,
developer8dd72532023-05-17 19:58:35 +08005446 NL_AUTO_PID,
developer72fb0bb2023-01-11 09:46:29 +08005447 NL_AUTO_SEQ,
5448 nl.id,
5449 0,
5450 NLM_F_DUMP,
5451 NL80211_CMD_GET_STATION,
5452 0);
5453
5454 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
developer8dd72532023-05-17 19:58:35 +08005455 nl_send_auto_complete(nl.socket, msg);
developer72fb0bb2023-01-11 09:46:29 +08005456 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
5457 nl_recvmsgs(nl.socket, nl.cb);
5458 nlmsg_free(msg);
5459 nlfree(&nl);
5460
5461 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
5462 output_struct->wifi_devRxRate = info.wifi_devRxRate;
5463 output_struct->wifi_devTxRate = info.wifi_devTxRate;
5464 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
5465 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
5466 return RETURN_OK;
5467#else
5468 //iw utility to retrieve station information
5469#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
5470#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
5471#define MACFILE "/tmp/wifi_AssoMac.txt"
5472#define TXRATEFILE "/tmp/wifi_txrate.txt"
5473#define RXRATEFILE "/tmp/wifi_rxrate.txt"
5474 FILE *file = NULL;
5475 char if_name[10] = {'\0'};
5476 char pipeCmd[256] = {'\0'};
5477 char line[256] = {0};
5478 char interface_name[16] = {0};
5479 int count = 0, device = 0;
5480
5481 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5482 return RETURN_ERR;
5483
5484 snprintf(if_name,sizeof(if_name),"%s", interface_name);
5485
5486 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
5487 file = popen(pipeCmd, "r");
5488
5489 if(file == NULL)
5490 return RETURN_ERR; //popen failed
5491
5492 fgets(line, sizeof line, file);
5493 device = atoi(line);
5494 pclose(file);
5495
5496 if(device == 0)
5497 return RETURN_ERR; //No devices are connected
5498
5499 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
5500 system(pipeCmd);
5501
5502 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
5503
5504 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
5505
5506 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
5507
5508 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
5509
5510 //devIndex starts from 1, ++count
5511 if((file = fopen(SIGNALFILE, "r")) != NULL )
5512 {
5513 for(count =0;fgets(line, sizeof line, file) != NULL;)
5514 {
5515 if (++count == devIndex)
5516 {
5517 output_struct->wifi_devSignalStrength = atoi(line);
5518 break;
5519 }
5520 }
5521 fclose(file);
5522 }
5523 else
5524 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
5525
5526 if((file = fopen(MACFILE, "r")) != NULL )
5527 {
5528 for(count =0;fgets(line, sizeof line, file) != NULL;)
5529 {
5530 if (++count == devIndex)
5531 {
5532 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]);
5533 break;
5534 }
5535 }
5536 fclose(file);
5537 }
5538 else
5539 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
5540
5541 if((file = fopen(TXRATEFILE, "r")) != NULL )
5542 {
5543 for(count =0;fgets(line, sizeof line, file) != NULL;)
5544 {
5545 if (++count == devIndex)
5546 {
5547 output_struct->wifi_devTxRate = atoi(line);
5548 break;
5549 }
5550 }
5551 fclose(file);
5552 }
5553 else
5554 fprintf(stderr,"fopen wifi_txrate.txt failed");
5555
5556 if((file = fopen(RXRATEFILE, "r")) != NULL)
5557 {
5558 for(count =0;fgets(line, sizeof line, file) != NULL;)
5559 {
5560 if (++count == devIndex)
5561 {
5562 output_struct->wifi_devRxRate = atoi(line);
5563 break;
5564 }
5565 }
5566 fclose(file);
5567 }
5568 else
5569 fprintf(stderr,"fopen wifi_rxrate.txt failed");
5570
5571 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
5572
5573 return RETURN_OK;
5574#endif
5575}
5576
5577INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
5578{
5579 if (NULL == device)
5580 return RETURN_ERR;
5581 return RETURN_OK;
5582}
5583//<<
5584
5585
5586//--------------wifi_ap_hal-----------------------------
5587//enables CTS protection for the radio used by this AP
5588INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
5589{
5590 //save config and Apply instantly
5591 return RETURN_ERR;
5592}
5593
5594// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
5595INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
5596{
5597 char config_file[64] = {'\0'};
developerd1824452023-05-18 12:30:04 +08005598 char config_dat_file[64] = {'\0'};
developer72fb0bb2023-01-11 09:46:29 +08005599 char buf[64] = {'\0'};
developerd1824452023-05-18 12:30:04 +08005600 struct params list = {0};
5601 struct params dat = {0};
5602 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08005603
5604 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5605 list.name = "ht_coex";
5606 snprintf(buf, sizeof(buf), "%d", enable);
5607 list.value = buf;
5608
developerd1824452023-05-18 12:30:04 +08005609 dat.name = "HT_BSSCoexistence";
5610 dat.value = buf;
5611
5612 band = wifi_index_to_band(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08005613 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developerd1824452023-05-18 12:30:04 +08005614 snprintf(config_dat_file, sizeof(config_dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
developer72fb0bb2023-01-11 09:46:29 +08005615 wifi_hostapdWrite(config_file, &list, 1);
developerd1824452023-05-18 12:30:04 +08005616 wifi_datfileWrite(config_dat_file, &list, 1);
developer72fb0bb2023-01-11 09:46:29 +08005617 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5618
5619 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5620
5621 return RETURN_OK;
5622}
5623
5624//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
5625INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
5626{
5627 char config_file[MAX_BUF_SIZE] = {'\0'};
5628 char buf[MAX_BUF_SIZE] = {'\0'};
5629 struct params list;
5630
5631 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5632 if (threshold < 256 || threshold > 2346 )
5633 return RETURN_ERR;
5634 list.name = "fragm_threshold";
5635 snprintf(buf, sizeof(buf), "%d", threshold);
5636 list.value = buf;
5637
5638 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
5639 wifi_hostapdWrite(config_file, &list, 1);
5640 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5641
5642 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5643
5644 return RETURN_OK;
5645}
5646
5647// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
5648INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
5649{
5650 char config_file[64] = {'\0'};
5651 char cmd[512] = {'\0'};
5652 char buf[512] = {'\0'};
5653 char stbc_config[16] = {'\0'};
5654 wifi_band band;
5655 int iterator = 0;
5656 BOOL current_stbc = FALSE;
5657 int ant_count = 0;
5658 int ant_bitmap = 0;
5659 struct params list;
developera1255e42023-05-13 17:45:02 +08005660 char dat_file[64] = {'\0'};
developer72fb0bb2023-01-11 09:46:29 +08005661
5662 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5663
5664 band = wifi_index_to_band(radioIndex);
5665 if (band == band_invalid)
5666 return RETURN_ERR;
5667
5668 if (band == band_2_4)
5669 iterator = 1;
developera1255e42023-05-13 17:45:02 +08005670 else if ((band == band_5) || (band == band_6))
developer72fb0bb2023-01-11 09:46:29 +08005671 iterator = 2;
5672 else
5673 return RETURN_OK;
5674
5675 wifi_getRadioTxChainMask(radioIndex, &ant_bitmap);
5676 for (; ant_bitmap > 0; ant_bitmap >>= 1)
5677 ant_count += ant_bitmap & 1;
5678
5679 if (ant_count == 1 && STBC_Enable == TRUE) {
5680 fprintf(stderr, "%s: can not enable STBC when using only one antenna\n", __func__);
5681 return RETURN_OK;
5682 }
5683
5684 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
5685
5686 // set ht and vht config
5687 for (int i = 0; i < iterator; i++) {
5688 memset(stbc_config, 0, sizeof(stbc_config));
5689 memset(cmd, 0, sizeof(cmd));
5690 memset(buf, 0, sizeof(buf));
5691 list.name = (i == 0)?"ht_capab":"vht_capab";
5692 snprintf(stbc_config, sizeof(stbc_config), "%s", list.name);
5693 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
5694 _syscmd(cmd, buf, sizeof(buf));
5695 if (strlen(buf) != 0)
5696 current_stbc = TRUE;
5697 if (current_stbc == STBC_Enable)
5698 continue;
5699
5700 if (STBC_Enable == TRUE) {
5701 // Append the STBC flags in capab config
5702 memset(cmd, 0, sizeof(cmd));
5703 if (i == 0)
5704 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
5705 else
5706 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1][RX-STBC-1]/' %s", config_file);
5707 _syscmd(cmd, buf, sizeof(buf));
5708 } else if (STBC_Enable == FALSE) {
5709 // Remove the STBC flags and remain other flags in capab
5710 memset(cmd, 0, sizeof(cmd));
5711 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
5712 _syscmd(cmd, buf, sizeof(buf));
5713 memset(cmd, 0, sizeof(cmd));
5714 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
5715 _syscmd(cmd, buf, sizeof(buf));
5716 }
5717 wifi_hostapdRead(config_file, list.name, buf, sizeof(buf));
5718 list.value = buf;
5719 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
5720 }
developera1255e42023-05-13 17:45:02 +08005721 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
5722 snprintf(cmd, sizeof(cmd), "sed -r -i 's/^HT_STBC=.*/HT_STBC=%d/g' %s", STBC_Enable, dat_file);
5723 _syscmd(cmd, buf, sizeof(buf));
5724 if ((band == band_5) || (band == band_6)) {
5725 snprintf(cmd, sizeof(cmd), "sed -r -i 's/^VHT_STBC=.*/VHT_STBC=%d/g' %s", STBC_Enable, dat_file);
5726 _syscmd(cmd, buf, sizeof(buf));
5727 }
5728 /*wifi_reloadAp(radioIndex);
5729 the caller do this.*/
developer72fb0bb2023-01-11 09:46:29 +08005730
5731 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5732 return RETURN_OK;
5733}
5734
5735// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
5736INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
5737{
developer2c22d832023-05-18 17:46:26 +08005738 char dat_file[128] = {0};
5739 BOOL enable;
5740 wifi_band band;
5741 char amdus_buff[8] = {'\0'};
developer72fb0bb2023-01-11 09:46:29 +08005742
developer2c22d832023-05-18 17:46:26 +08005743 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08005744
developer2c22d832023-05-18 17:46:26 +08005745 band = wifi_index_to_band(radioIndex);
5746 if (band == band_invalid) {
5747 printf("%s:Band Error\n", __func__);
5748 return RETURN_ERR;
5749 }
5750 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
5751 wifi_datfileRead(dat_file, "HT_AMSDU", amdus_buff, sizeof(amdus_buff));
5752 if (strncmp(amdus_buff, "1", 1) == 0)
developer72fb0bb2023-01-11 09:46:29 +08005753 *output_bool = TRUE;
developer2c22d832023-05-18 17:46:26 +08005754 else
5755 *output_bool = FALSE;
developer72fb0bb2023-01-11 09:46:29 +08005756
developer2c22d832023-05-18 17:46:26 +08005757 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5758
5759 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08005760}
5761
5762// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
5763INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
5764{
developer2c22d832023-05-18 17:46:26 +08005765 char dat_file[128] = {0};
5766 BOOL enable;
5767 wifi_band band;
5768 char amdus_buff[8] = {'\0'};
5769 struct params params = {0};
developer72fb0bb2023-01-11 09:46:29 +08005770
developer2c22d832023-05-18 17:46:26 +08005771 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08005772
developer2c22d832023-05-18 17:46:26 +08005773 band = wifi_index_to_band(radioIndex);
5774 if (band == band_invalid) {
5775 printf("%s:Band Error\n", __func__);
5776 return RETURN_ERR;
5777 }
5778 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
5779 wifi_datfileRead(dat_file, "HT_AMSDU", amdus_buff, sizeof(amdus_buff));
5780 if (strncmp(amdus_buff, "1", 1) == 0)
5781 enable = TRUE;
5782 else
5783 enable = FALSE;
5784 if (amsduEnable == enable)
5785 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08005786
developer2c22d832023-05-18 17:46:26 +08005787 params.name = "HT_AMSDU";
5788 if (amsduEnable)
5789 params.value = "1";
5790 else
5791 params.value = "0";
5792 wifi_datfileWrite(dat_file, &params, 1);
5793 wifi_reloadAp(radioIndex);
developer72fb0bb2023-01-11 09:46:29 +08005794
developer2c22d832023-05-18 17:46:26 +08005795 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08005796
developer72fb0bb2023-01-11 09:46:29 +08005797 return RETURN_OK;
5798}
5799
5800//P2 // outputs the number of Tx streams
5801INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
5802{
5803 char buf[8] = {0};
5804 char cmd[128] = {0};
5805 int phyId = 0;
5806
5807 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5808
5809 phyId = radio_index_to_phy(radioIndex);
5810 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Configured Antennas' | awk '{print $4}'", phyId);
5811 _syscmd(cmd, buf, sizeof(buf));
5812
5813 *output_int = (INT)strtol(buf, NULL, 16);
5814
5815 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5816
5817 return RETURN_OK;
5818}
5819
5820INT fitChainMask(INT radioIndex, int antcount)
5821{
5822 char buf[128] = {0};
5823 char cmd[128] = {0};
5824 char config_file[64] = {0};
5825 wifi_band band;
5826 struct params list[2] = {0};
5827
5828 band = wifi_index_to_band(radioIndex);
5829 if (band == band_invalid)
5830 return RETURN_ERR;
5831
5832 list[0].name = "he_mu_beamformer";
5833 list[1].name = "he_su_beamformer";
5834
5835 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
5836 if (antcount == 1) {
5837 // remove config about multiple antennas
5838 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
5839 _syscmd(cmd, buf, sizeof(buf));
5840
5841 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SOUNDING-DIMENSION-.\\]//' %s", config_file);
5842 _syscmd(cmd, buf, sizeof(buf));
5843
5844 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SU-BEAMFORMER\\]//' %s", config_file);
5845 _syscmd(cmd, buf, sizeof(buf));
5846
5847 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[MU-BEAMFORMER\\]//' %s", config_file);
5848 _syscmd(cmd, buf, sizeof(buf));
5849
5850 list[0].value = "0";
5851 list[1].value = "0";
5852 } else {
5853 // 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.
5854 if (band == band_2_4 || band == band_5) {
5855 snprintf(cmd, sizeof(cmd), "cat %s | grep '^ht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
5856 _syscmd(cmd, buf, sizeof(buf));
5857 if (strlen(buf) > 0) {
5858 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC]/' %s", config_file);
5859 _syscmd(cmd, buf, sizeof(buf));
5860 }
5861 }
5862 if (band == band_5) {
5863 snprintf(cmd, sizeof(cmd), "cat %s | grep '^vht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
5864 _syscmd(cmd, buf, sizeof(buf));
5865 if (strlen(buf) > 0) {
5866 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1]/' %s", config_file);
5867 _syscmd(cmd, buf, sizeof(buf));
5868 }
5869 }
5870
5871 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SU-BEAMFORMER\\]'", config_file);
5872 _syscmd(cmd, buf, sizeof(buf));
5873 if (strlen(buf) == 0) {
5874 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SU-BEAMFORMER]/' %s", config_file);
5875 _syscmd(cmd, buf, sizeof(buf));
5876 }
5877
5878 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[MU-BEAMFORMER\\]'", config_file);
5879 _syscmd(cmd, buf, sizeof(buf));
5880 if (strlen(buf) == 0) {
5881 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[MU-BEAMFORMER]/' %s", config_file);
5882 _syscmd(cmd, buf, sizeof(buf));
5883 }
5884
5885 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SOUNDING-DIMENSION-.\\]'", config_file);
5886 _syscmd(cmd, buf, sizeof(buf));
5887 if (strlen(buf) == 0) {
5888 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SOUNDING-DIMENSION-%d]/' %s", antcount, config_file);
5889 } else {
5890 snprintf(cmd, sizeof(cmd), "sed -r -i 's/(SOUNDING-DIMENSION-)./\\1%d/' %s", antcount, config_file);
5891 }
5892 _syscmd(cmd, buf, sizeof(buf));
5893
5894 list[0].value = "1";
5895 list[1].value = "1";
5896 }
5897 wifi_hostapdWrite(config_file, list, 2);
5898}
5899
5900//P2 // sets the number of Tx streams to an enviornment variable
5901INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
5902{
5903 char cmd[128] = {0};
5904 char buf[128] = {0};
5905 int phyId = 0;
5906 int cur_mask = 0;
developera1255e42023-05-13 17:45:02 +08005907 int antcountmsk = 0;
5908 INT cur_nss = 0;
5909 UCHAR dat_file[64] = {0};
5910 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08005911
5912 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5913
5914 if (numStreams <= 0) {
5915 fprintf(stderr, "%s: chainmask is not supported %d.\n", __func__, numStreams);
5916 return RETURN_ERR;
5917 }
5918
developera1255e42023-05-13 17:45:02 +08005919 wifi_getRadioTxChainMask(radioIndex, &cur_mask);//this is mask value
5920 for(; cur_mask > 0; cur_mask >>= 1)//convert to number of streams.
5921 cur_nss += 1;
5922 WIFI_ENTRY_EXIT_DEBUG("%s:cur_nss=%d, new_nss=%d\n", __func__, cur_nss, numStreams);
5923 if (cur_nss == numStreams)
developer72fb0bb2023-01-11 09:46:29 +08005924 return RETURN_OK;
5925
5926 wifi_setRadioEnable(radioIndex, FALSE);
5927
5928 phyId = radio_index_to_phy(radioIndex);
developera1255e42023-05-13 17:45:02 +08005929 //iw need mask value.
5930 for (;numStreams > 0; numStreams--)
5931 antcountmsk |= 0x1 << (numStreams - 1);
5932 snprintf(cmd, sizeof(cmd), "iw phy%d set antenna 0x%x 2>&1", phyId, antcountmsk);
developer72fb0bb2023-01-11 09:46:29 +08005933 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08005934 if (strlen(buf) > 0) {
5935 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
5936 return RETURN_ERR;
5937 }
developera1255e42023-05-13 17:45:02 +08005938 band = wifi_index_to_band(radioIndex);
5939 if (band == band_invalid) {
5940 printf("%s:Band Error\n", __func__);
5941 return RETURN_ERR;
5942 }
5943 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
5944 snprintf(cmd, sizeof(cmd), "sed -r -i 's/^HT_TxStream=.*/HT_TxStream=%d/g' %s", numStreams, dat_file);
5945 _syscmd(cmd, buf, sizeof(buf));
5946 if (strlen(buf) > 0) {
5947 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
5948 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08005949 }
developera1255e42023-05-13 17:45:02 +08005950 snprintf(cmd, sizeof(cmd), "sed -r -i 's/^HT_RxStream=.*/HT_RxStream=%d/g' %s", numStreams, dat_file);
5951 _syscmd(cmd, buf, sizeof(buf));
5952 if (strlen(buf) > 0) {
5953 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
5954 return RETURN_ERR;
5955 }
5956 fitChainMask(radioIndex, numStreams);
developer72fb0bb2023-01-11 09:46:29 +08005957 wifi_setRadioEnable(radioIndex, TRUE);
5958
5959 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5960 return RETURN_OK;
5961}
5962
5963//P2 // outputs the number of Rx streams
5964INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
5965{
5966 char buf[8] = {0};
5967 char cmd[128] = {0};
5968 int phyId = 0;
5969
5970 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5971
5972 phyId = radio_index_to_phy(radioIndex);
5973 sprintf(cmd, "iw phy%d info | grep 'Configured Antennas' | awk '{print $6}'", phyId);
5974 _syscmd(cmd, buf, sizeof(buf));
5975
5976 *output_int = (INT)strtol(buf, NULL, 16);
5977
5978 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5979
5980 return RETURN_OK;
5981}
5982
5983//P2 // sets the number of Rx streams to an enviornment variable
5984INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
5985{
5986 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5987 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
5988 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
5989 return RETURN_ERR;
5990 }
5991 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5992 return RETURN_ERR;
5993}
5994
5995//Get radio RDG enable setting
5996INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
5997{
developer47cc27a2023-05-17 23:09:58 +08005998 if (NULL == output_bool)
5999 return RETURN_ERR;
6000
6001 *output_bool = TRUE;
6002 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006003}
6004
6005//Get radio RDG enable setting
6006INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
6007{
developer47cc27a2023-05-17 23:09:58 +08006008 char cmd[MAX_CMD_SIZE] = {0};
6009 char buf[MAX_BUF_SIZE] = {0};
6010 char rdg_status[2] = {0};
6011 char dat_file[MAX_CMD_SIZE] = {0};
6012 struct params params = {0};
6013
6014 if (NULL == output_bool)
6015 return RETURN_ERR;
6016
6017 /*prepare dat file path*/
6018 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, radioIndex);
6019
6020 wifi_datfileRead(dat_file, "HT_RDG", rdg_status, sizeof(rdg_status));
6021 if (!strncmp(rdg_status, "1", sizeof(rdg_status)))
6022 *output_bool = TRUE;
6023 else
6024 *output_bool = FALSE;
6025
6026 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006027}
6028
6029//Set radio RDG enable setting
6030INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
6031{
developer47cc27a2023-05-17 23:09:58 +08006032 char cmd[MAX_CMD_SIZE] = {0};
6033 char buf[MAX_BUF_SIZE] = {0};
6034 char dat_file[MAX_CMD_SIZE] = {0};
6035 struct params params = {0};
6036
6037 /*prepare dat file path*/
6038 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, radioIndex);
6039
6040 params.name = "HT_RDG";
6041
6042 if (enable) {
6043 params.value = "1";
6044 } else {
6045 params.value = "0";
6046 }
6047
6048 wifi_datfileWrite(dat_file, &params, 1);
6049
6050 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006051}
6052
6053//Get radio ADDBA enable setting
6054INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
6055{
developer8e6583c2023-05-23 13:36:06 +08006056 char interface_name[16] = {0};
6057 char cmd[128]={0};
6058 char buf[10]={0};
6059 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6060
6061 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developer72fb0bb2023-01-11 09:46:29 +08006062 return RETURN_ERR;
developer8e6583c2023-05-23 13:36:06 +08006063
6064 snprintf(cmd, sizeof(cmd), "mwctl %s set ba_decline s", interface_name);
6065 _syscmd(cmd, buf, sizeof(buf));
6066
6067 if (strncmp(buf, "enabled", 7) == 0)
6068 *output_bool = TRUE;
6069 else
6070 *output_bool = FALSE;
6071
6072 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6073
developer72fb0bb2023-01-11 09:46:29 +08006074 return RETURN_OK;
6075}
6076
6077//Set radio ADDBA enable setting
6078INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
6079{
6080 return RETURN_ERR;
6081}
6082
6083//Get radio auto block ack enable setting
6084INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
6085{
developer8e6583c2023-05-23 13:36:06 +08006086 char interface_name[16] = {0};
6087 char cmd[128]={0};
6088 char buf[10]={0};
6089 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6090
6091 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developer72fb0bb2023-01-11 09:46:29 +08006092 return RETURN_ERR;
developer8e6583c2023-05-23 13:36:06 +08006093
6094 snprintf(cmd, sizeof(cmd), "mwctl %s set ba_auto s", interface_name);
6095 _syscmd(cmd, buf, sizeof(buf));
6096 if (strncmp(buf, "enabled", 7) == 0)
6097 *output_bool = TRUE;
6098 else
6099 *output_bool = FALSE;
6100
6101 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6102
developer72fb0bb2023-01-11 09:46:29 +08006103 return RETURN_OK;
6104}
6105
6106//Set radio auto block ack enable setting
6107INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
6108{
6109 return RETURN_ERR;
6110}
6111
6112//Get radio 11n pure mode enable support
6113INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
6114{
6115 if (NULL == output_bool)
6116 return RETURN_ERR;
6117 *output_bool = TRUE;
6118 return RETURN_OK;
6119}
6120
6121//Get radio 11n pure mode enable setting
6122INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
6123{
6124 if (NULL == output_bool)
6125 return RETURN_ERR;
6126 *output_bool = TRUE;
6127 return RETURN_OK;
6128}
6129
6130//Set radio 11n pure mode enable setting
6131INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
6132{
6133 return RETURN_ERR;
6134}
6135
6136//Get radio IGMP snooping enable setting
6137INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
6138{
6139 char interface_name[16] = {0};
6140 char cmd[128]={0};
developer8e6583c2023-05-23 13:36:06 +08006141 char buf[10]={0};
developer72fb0bb2023-01-11 09:46:29 +08006142 bool bridge = FALSE, mac80211 = FALSE;
6143 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6144
developer72fb0bb2023-01-11 09:46:29 +08006145 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
6146 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006147
developer8e6583c2023-05-23 13:36:06 +08006148 snprintf(cmd, sizeof(cmd), "mwctl %s set multicast_snooping enable=s", interface_name);
6149 _syscmd(cmd, buf, sizeof(buf));
6150 if (strncmp(buf, "enabled", 7) == 0)
developer72fb0bb2023-01-11 09:46:29 +08006151 *output_bool = TRUE;
developer8e6583c2023-05-23 13:36:06 +08006152 else
6153 *output_bool = FALSE;
developer72fb0bb2023-01-11 09:46:29 +08006154
6155 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6156 return RETURN_OK;
6157}
6158
6159//Set radio IGMP snooping enable setting
6160INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
6161{
6162 char interface_name[16] = {0};
6163 char cmd[128]={0};
6164 char buf[4]={0};
developer72fb0bb2023-01-11 09:46:29 +08006165
developer8e6583c2023-05-23 13:36:06 +08006166 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6167 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
6168 return RETURN_ERR;
6169 snprintf(cmd, sizeof(cmd), "mwctl %s set multicast_snooping enable=1", interface_name);
developer72fb0bb2023-01-11 09:46:29 +08006170 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006171 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6172 return RETURN_OK;
6173}
6174
6175//Get the Reset count of radio
developer69b61b02023-03-07 17:17:44 +08006176INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
developer72fb0bb2023-01-11 09:46:29 +08006177{
developer69b61b02023-03-07 17:17:44 +08006178 if (NULL == output_int)
developer72fb0bb2023-01-11 09:46:29 +08006179 return RETURN_ERR;
6180 *output_int = (radioIndex==0)? 1: 3;
6181
6182 return RETURN_OK;
6183}
6184
6185
6186//---------------------------------------------------------------------------------------------------
6187//
6188// Additional Wifi AP level APIs used for Access Point devices
6189//
6190//---------------------------------------------------------------------------------------------------
6191
6192// creates a new ap and pushes these parameters to the hardware
6193INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
6194{
6195 // Deprecated when use hal version 3, use wifi_createVap() instead.
6196 return RETURN_OK;
6197}
6198
6199// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
6200INT wifi_deleteAp(INT apIndex)
6201{
developer7e4a2a62023-04-06 19:56:03 +08006202 char interface_name[16] = {0};
6203 char buf[MAX_BUF_SIZE];
6204 char cmd[MAX_CMD_SIZE];
developer72fb0bb2023-01-11 09:46:29 +08006205
developer7e4a2a62023-04-06 19:56:03 +08006206 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6207 return RETURN_ERR;
developer8a3bbbf2023-03-15 17:47:23 +08006208
developer7e4a2a62023-04-06 19:56:03 +08006209 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw REMOVE %s", interface_name);
6210 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006211
developer7e4a2a62023-04-06 19:56:03 +08006212 wifi_removeApSecVaribles(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08006213
developer7e4a2a62023-04-06 19:56:03 +08006214 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006215}
6216
6217// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
6218INT wifi_getApName(INT apIndex, CHAR *output_string)
6219{
developer7e4a2a62023-04-06 19:56:03 +08006220 char interface_name[IF_NAME_SIZE] = {0};
developer47cc27a2023-05-17 23:09:58 +08006221 int radio_idx = 0;
6222 int bss_idx = 0;
developer72fb0bb2023-01-11 09:46:29 +08006223
developer7e4a2a62023-04-06 19:56:03 +08006224 if(!output_string)
6225 return RETURN_ERR;
6226
6227 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
6228 vap_index_to_array_index(apIndex, &radio_idx, &bss_idx);
6229
6230 snprintf(output_string, IF_NAME_SIZE, "%s%d", ext_prefix[radio_idx], bss_idx); // For wifiagent generating data model.
6231 } else
6232 snprintf(output_string, IF_NAME_SIZE, "%s", interface_name);
6233
6234 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006235}
6236
6237// Outputs the index number in that corresponds to the SSID string
6238INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
6239{
developer7e4a2a62023-04-06 19:56:03 +08006240 char cmd [128] = {0};
6241 char buf[32] = {0};
6242 char ap_idx = 0;
6243 char *apIndex_str = NULL;
6244 char radio_idx = 0;
6245 char bss_idx = 0;
developer72fb0bb2023-01-11 09:46:29 +08006246
developer7e4a2a62023-04-06 19:56:03 +08006247 snprintf(cmd, sizeof(cmd), "grep -rn ^interface=%s$ /nvram/hostapd*.conf | cut -d '.' -f1 | cut -d 'd' -f2 | tr -d '\\n'",
6248 inputSsidString);
6249 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006250
developer7e4a2a62023-04-06 19:56:03 +08006251 if (strlen(buf)) {
6252 apIndex_str = strtok(buf, "\n");
6253 *output_int = strtoul(apIndex_str, NULL, 10);
6254 return RETURN_OK;
6255 }
developer72fb0bb2023-01-11 09:46:29 +08006256
developer7e4a2a62023-04-06 19:56:03 +08006257 /* If interface name is not in hostapd config, the caller maybe wifi agent to generate data model.*/
6258 if (strstr(inputSsidString, PREFIX_WIFI6G)) {
6259 bss_idx = atoi(inputSsidString + strlen(PREFIX_WIFI6G));
6260 radio_idx = 2;
6261 } else if (strstr(inputSsidString, PREFIX_WIFI5G)) {
6262 bss_idx = atoi(inputSsidString + strlen(PREFIX_WIFI5G));
6263 radio_idx = 1;
6264 } else if (strstr(inputSsidString, PREFIX_WIFI2G)) {
6265 bss_idx = atoi(inputSsidString + strlen(PREFIX_WIFI2G));
6266 radio_idx = 0;
6267 } else {
6268 printf("%s: hostapd conf not find, unknow inf(%s), return ERROR!!!(%d).\n",
6269 __func__, inputSsidString, ap_idx);
6270 *output_int = -1;
6271 return RETURN_ERR;
6272 }
6273
6274 ap_idx = array_index_to_vap_index(radio_idx, bss_idx);
6275
6276 if (ap_idx >= 0 && ap_idx < MAX_VAP) {
6277 printf("%s: hostapd conf not find, inf(%s), use inf idx(%d).\n",
6278 __func__, inputSsidString, ap_idx);
6279 *output_int = ap_idx;
6280 return RETURN_OK;
6281 }
6282
6283 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006284}
6285
6286INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
6287{
6288 return wifi_getIndexFromName(inputSsidString, output_int);
6289}
6290
6291// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
6292INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
6293{
6294 char buf[MAX_BUF_SIZE] = {0};
6295 char cmd[MAX_CMD_SIZE] = {0};
6296 char config_file[MAX_BUF_SIZE] = {0};
6297
6298 if(NULL == output_string)
6299 return RETURN_ERR;
6300
6301 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6302 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
6303 if((strcmp(buf,"3")==0))
6304 snprintf(output_string, 32, "WPAand11i");
6305 else if((strcmp(buf,"2")==0))
6306 snprintf(output_string, 32, "11i");
6307 else if((strcmp(buf,"1")==0))
6308 snprintf(output_string, 32, "WPA");
6309 else
6310 snprintf(output_string, 32, "None");
6311
6312 return RETURN_OK;
6313}
6314
6315// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
6316INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
6317{
6318 char config_file[MAX_BUF_SIZE] = {0};
6319 struct params list;
6320
6321 if (NULL == beaconTypeString)
6322 return RETURN_ERR;
6323 list.name = "wpa";
6324 list.value = "0";
6325
6326 if((strcmp(beaconTypeString,"WPAand11i")==0))
6327 list.value="3";
6328 else if((strcmp(beaconTypeString,"11i")==0))
6329 list.value="2";
6330 else if((strcmp(beaconTypeString,"WPA")==0))
6331 list.value="1";
6332
6333 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6334 wifi_hostapdWrite(config_file, &list, 1);
6335 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6336 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6337 return RETURN_OK;
6338}
6339
6340// sets the beacon interval on the hardware for this AP
6341INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
6342{
6343 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6344 struct params params={'\0'};
6345 char buf[MAX_BUF_SIZE] = {'\0'};
6346 char config_file[MAX_BUF_SIZE] = {'\0'};
6347
6348 params.name = "beacon_int";
6349 snprintf(buf, sizeof(buf), "%u", beaconInterval);
6350 params.value = buf;
6351
6352 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6353 wifi_hostapdWrite(config_file, &params, 1);
developer69b61b02023-03-07 17:17:44 +08006354
developer72fb0bb2023-01-11 09:46:29 +08006355 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6356 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6357 return RETURN_OK;
6358}
6359
6360INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
6361{
6362 if (wifi_setApDTIMInterval(apIndex, dtimInterval) != RETURN_OK)
6363 return RETURN_ERR;
6364 return RETURN_OK;
6365}
6366
6367// Get the packet size threshold supported.
6368INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
6369{
6370 //save config and apply instantly
6371 if (NULL == output_bool)
6372 return RETURN_ERR;
6373 *output_bool = TRUE;
6374 return RETURN_OK;
6375}
6376
6377// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
6378INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
6379{
developer72fb0bb2023-01-11 09:46:29 +08006380 char buf[16] = {0};
6381 char config_file[128] = {0};
6382 struct params param = {0};
6383
6384 if (threshold > 65535) {
6385 fprintf(stderr, "%s: rts threshold %u is too big.\n", __func__, threshold);
6386 return RETURN_ERR;
6387 }
6388
developer23e71282023-01-18 10:25:19 +08006389 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developer72fb0bb2023-01-11 09:46:29 +08006390 snprintf(buf, sizeof(buf), "%u", threshold);
6391 param.name = "rts_threshold";
6392 param.value = buf;
6393 wifi_hostapdWrite(config_file, &param, 1);
6394 wifi_hostapdProcessUpdate(apIndex, &param, 1);
6395 wifi_reloadAp(apIndex);
6396
6397 return RETURN_OK;
6398}
6399
6400// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
6401INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
6402{
6403 if (NULL == output_string)
6404 return RETURN_ERR;
6405 snprintf(output_string, 32, "TKIPandAESEncryption");
6406 return RETURN_OK;
6407
6408}
6409
6410// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
6411INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
6412{
6413 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6414 char *param_name = NULL;
6415 char buf[32] = {0}, config_file[MAX_BUF_SIZE] = {0};
6416
6417 if(NULL == output_string)
6418 return RETURN_ERR;
6419
6420 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6421 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6422
6423 if(strcmp(buf,"0")==0)
6424 {
6425 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
6426 snprintf(output_string, 32, "None");
6427 return RETURN_OK;
6428 }
6429 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
6430 param_name = "rsn_pairwise";
6431 else if((strcmp(buf,"1")==0))
6432 param_name = "wpa_pairwise";
6433 else
6434 return RETURN_ERR;
6435 memset(output_string,'\0',32);
6436 wifi_hostapdRead(config_file,param_name,output_string,32);
6437 if (strlen(output_string) == 0) { // rsn_pairwise is optional. When it is empty use wpa_pairwise instead.
6438 param_name = "wpa_pairwise";
6439 memset(output_string, '\0', 32);
6440 wifi_hostapdRead(config_file, param_name, output_string, 32);
6441 }
6442 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
6443
developere5750452023-05-15 16:46:42 +08006444 if(strcmp(output_string,"TKIP CCMP") == 0)
6445 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
6446 else if(strcmp(output_string,"TKIP") == 0)
developer72fb0bb2023-01-11 09:46:29 +08006447 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
6448 else if(strcmp(output_string,"CCMP") == 0)
6449 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
developer72fb0bb2023-01-11 09:46:29 +08006450
6451 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6452 return RETURN_OK;
6453}
6454
6455// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
6456INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
6457{
6458 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6459 struct params params={'\0'};
6460 char output_string[32];
6461 char config_file[MAX_BUF_SIZE] = {0};
6462
6463 memset(output_string,'\0',32);
developere5750452023-05-15 16:46:42 +08006464 wifi_getApBeaconType(apIndex,output_string);
developer72fb0bb2023-01-11 09:46:29 +08006465
6466 if(strcmp(encMode, "TKIPEncryption") == 0)
6467 params.value = "TKIP";
6468 else if(strcmp(encMode,"AESEncryption") == 0)
6469 params.value = "CCMP";
6470 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
6471 params.value = "TKIP CCMP";
6472
6473 if((strcmp(output_string,"WPAand11i")==0))
6474 {
6475 params.name = "wpa_pairwise";
6476 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6477 wifi_hostapdWrite(config_file, &params, 1);
6478 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6479
6480 params.name = "rsn_pairwise";
6481 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6482 wifi_hostapdWrite(config_file, &params, 1);
6483 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6484
6485 return RETURN_OK;
6486 }
6487 else if((strcmp(output_string,"11i")==0))
6488 {
6489 params.name = "rsn_pairwise";
6490 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6491 wifi_hostapdWrite(config_file, &params, 1);
6492 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6493 return RETURN_OK;
6494 }
6495 else if((strcmp(output_string,"WPA")==0))
6496 {
6497 params.name = "wpa_pairwise";
6498 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6499 wifi_hostapdWrite(config_file, &params, 1);
6500 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6501 return RETURN_OK;
6502 }
6503
6504 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6505 return RETURN_OK;
6506}
6507
6508// deletes internal security varable settings for this ap
6509INT wifi_removeApSecVaribles(INT apIndex)
6510{
6511 //TODO: remove the entry in hostapd config file
6512 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s.conf//g' /tmp/conf_filename", interface_name);
6513 //_syscmd(cmd, buf, sizeof(buf));
6514
6515 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s//g' /tmp/conf_filename", interface_name);
6516 //_syscmd(cmd, buf, sizeof(buf));
6517 return RETURN_ERR;
6518}
6519
6520// changes the hardware settings to disable encryption on this ap
6521INT wifi_disableApEncryption(INT apIndex)
6522{
6523 //Apply instantly
6524 return RETURN_ERR;
6525}
6526
6527// set the authorization mode on this ap
6528// mode mapping as: 1: open, 2: shared, 4:auto
6529INT wifi_setApAuthMode(INT apIndex, INT mode)
6530{
6531 struct params params={0};
6532 char config_file[64] = {0};
6533 int ret;
6534
6535 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
6536
6537 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
6538 params.name = "auth_algs";
6539
developere5750452023-05-15 16:46:42 +08006540 if ((mode & 1 && mode & 2) || mode & 4)
developer72fb0bb2023-01-11 09:46:29 +08006541 params.value = "3";
6542 else if (mode & 2)
6543 params.value = "2";
6544 else if (mode & 1)
6545 params.value = "1";
6546 else
6547 params.value = "0";
6548
6549 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6550 wifi_hostapdWrite(config_file, &params, 1);
6551 wifi_hostapdProcessUpdate(apIndex, &params, 1);
developere5750452023-05-15 16:46:42 +08006552 wifi_reloadAp(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08006553 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
6554
6555 return RETURN_OK;
6556}
6557
6558// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
6559INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
6560{
6561 //save to wifi config, and wait for wifi restart to apply
6562 struct params params={'\0'};
6563 char config_file[MAX_BUF_SIZE] = {0};
6564 int ret;
6565
6566 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6567 if(authMode == NULL)
6568 return RETURN_ERR;
6569
6570 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
6571 params.name = "wpa_key_mgmt";
6572
6573 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
6574 params.value = "WPA-PSK";
6575 else if(strcmp(authMode,"EAPAuthentication") == 0)
6576 params.value = "WPA-EAP";
6577 else if (strcmp(authMode, "SAEAuthentication") == 0)
6578 params.value = "SAE";
6579 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
6580 params.value = "WPA-EAP-SUITE-B-192";
6581 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
6582 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer3086e2f2023-01-17 09:40:01 +08006583 else if (strcmp(authMode, "Enhanced_Open") == 0)
6584 params.value = "OWE";
developer72fb0bb2023-01-11 09:46:29 +08006585 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
6586 return RETURN_OK; //This is taken careof in beaconType
6587
6588 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6589 ret=wifi_hostapdWrite(config_file,&params,1);
6590 if(!ret)
6591 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
6592 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6593
6594 return ret;
6595}
6596
6597// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
6598INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
6599{
6600 //save to wifi config, and wait for wifi restart to apply
6601 char BeaconType[50] = {0};
6602 char config_file[MAX_BUF_SIZE] = {0};
6603
6604 *authMode = 0;
6605 wifi_getApBeaconType(apIndex,BeaconType);
6606 printf("%s____%s \n",__FUNCTION__,BeaconType);
6607
6608 if(strcmp(BeaconType,"None") == 0)
6609 strcpy(authMode,"None");
6610 else
6611 {
6612 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6613 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
6614 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
6615 if(strcmp(authMode,"WPA-PSK") == 0)
6616 strcpy(authMode,"SharedAuthentication");
6617 else if(strcmp(authMode,"WPA-EAP") == 0)
6618 strcpy(authMode,"EAPAuthentication");
6619 }
6620
6621 return RETURN_OK;
6622}
6623
6624// Outputs the number of stations associated per AP
6625INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
6626{
6627 char interface_name[16] = {0};
6628 char cmd[128]={0};
6629 char buf[128]={0};
6630 BOOL status = false;
6631
6632 if(apIndex > MAX_APS)
6633 return RETURN_ERR;
6634
6635 wifi_getApEnable(apIndex,&status);
6636 if (!status)
6637 return RETURN_OK;
6638
6639 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);//alternate method
6640 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6641 return RETURN_ERR;
6642 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l", interface_name);
6643 _syscmd(cmd, buf, sizeof(buf));
6644 sscanf(buf,"%lu", output_ulong);
6645
6646 return RETURN_OK;
6647}
6648
6649// manually removes any active wi-fi association with the device specified on this ap
6650INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
6651{
developer7e4a2a62023-04-06 19:56:03 +08006652 char inf_name[16] = {0};
6653 char cmd[MAX_CMD_SIZE] = {0};
6654 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08006655
developer7e4a2a62023-04-06 19:56:03 +08006656 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
developer72fb0bb2023-01-11 09:46:29 +08006657 return RETURN_ERR;
developer7e4a2a62023-04-06 19:56:03 +08006658
6659 snprintf(cmd, sizeof(cmd),"hostapd_cli -i %s disassociate %s", inf_name, client_mac);
6660 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006661
6662 return RETURN_OK;
6663}
6664
6665// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
6666INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
6667{
developer7e4a2a62023-04-06 19:56:03 +08006668 int max_radio_num = 0;
6669
6670 if(NULL == output_int)
6671 return RETURN_ERR;
6672
6673 wifi_getMaxRadioNumber(&max_radio_num);
6674 *output_int = apIndex % max_radio_num;
6675
6676 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006677}
6678
6679// sets the radio index for the specific ap
6680INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
6681{
6682 //set to config only and wait for wifi reset to apply settings
6683 return RETURN_ERR;
6684}
6685
developer121a8e72023-05-22 09:19:39 +08006686
6687#define MAX_ACL_DUMP_LEN 4096
6688int mtk_acl_list_dump_callback(struct nl_msg *msg, void *cb)
6689{
6690 struct nlattr *tb[NL80211_ATTR_MAX + 1];
6691 struct nlattr *vndr_tb[MTK_NL80211_VENDOR_AP_ACL_ATTR_MAX + 1];
6692 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
6693 char *show_str = NULL;
6694 int err = 0, skip_len = 0;
6695 unsigned short acl_result_len = 0;
6696 struct mtk_nl80211_cb_data *cb_data = cb;
6697
6698 if (!msg || !cb_data) {
6699 wifi_debug(DEBUG_ERROR, "msg(0x%lx) or cb_data(0x%lx) is null,error.", msg, cb_data);
6700 return NL_SKIP;
6701 }
6702
6703 err = nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
6704 genlmsg_attrlen(gnlh, 0), NULL);
6705 if (err < 0) {
6706 wifi_debug(DEBUG_ERROR, "nla_parse acl list nl80211 msg fails,error.");
6707 return NL_SKIP;
6708 }
6709
6710 if (tb[NL80211_ATTR_VENDOR_DATA]) {
6711 err = nla_parse_nested(vndr_tb, MTK_NL80211_VENDOR_AP_ACL_ATTR_MAX,
6712 tb[NL80211_ATTR_VENDOR_DATA], NULL);
6713 if (err < 0)
6714 return NL_SKIP;
6715 if (vndr_tb[MTK_NL80211_VENDOR_ATTR_ACL_LIST_INFO]) {
6716 acl_result_len = nla_len(vndr_tb[MTK_NL80211_VENDOR_ATTR_ACL_LIST_INFO]);
6717 show_str = nla_data(vndr_tb[MTK_NL80211_VENDOR_ATTR_ACL_LIST_INFO]);
6718 if (acl_result_len > MAX_ACL_DUMP_LEN) {
6719 wifi_debug(DEBUG_ERROR,"the scan result len is invalid !!!\n");
6720 return NL_SKIP;
6721 } else if (*(show_str + acl_result_len - 1) != '\0') {
6722 wifi_debug(DEBUG_INFO, "the result string is not ended with right terminator, handle it!!!\n");
6723 *(show_str + acl_result_len - 1) = '\0';
6724 }
6725 wifi_debug(DEBUG_INFO, "driver msg:%s\n", show_str);
6726 /*skip the first line: 'policy=1\n' len check*/
6727 skip_len = (strchr(show_str, '\n')+1 - show_str);
6728 if (cb_data->out_len < acl_result_len-skip_len) {
6729 wifi_debug(DEBUG_ERROR, "output buffer is not enough! error.\n");
6730 return NL_SKIP;
6731 }
6732 memset(cb_data->out_buf, 0, cb_data->out_len);
6733 /*skip the first line: 'policy=1\n' to find the acl mac addrs*/
6734 memmove(cb_data->out_buf, strchr(show_str, '\n')+1, acl_result_len-skip_len);
6735 wifi_debug(DEBUG_INFO, "out buff:%s", cb_data->out_buf);
6736 } else
6737 wifi_debug(DEBUG_ERROR, "no acl result attr\n");
6738 } else
6739 wifi_debug(DEBUG_ERROR, "no any acl result from driver\n");
6740 return NL_OK;
6741}
developer72fb0bb2023-01-11 09:46:29 +08006742// Get the ACL MAC list per AP
6743INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
6744{
developer7e4a2a62023-04-06 19:56:03 +08006745 char inf_name[IF_NAME_SIZE] = {0};
developer121a8e72023-05-22 09:19:39 +08006746 struct mtk_nl80211_param params;
6747 unsigned int if_idx = 0;
6748 int ret = -1;
6749 struct unl unl_ins;
6750 struct nl_msg *msg = NULL;
6751 struct nlattr * msg_data = NULL;
6752 struct mtk_nl80211_param param;
6753 struct mtk_nl80211_cb_data cb_data;
developer72fb0bb2023-01-11 09:46:29 +08006754
developer7e4a2a62023-04-06 19:56:03 +08006755 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
6756 return RETURN_ERR;
6757
developer121a8e72023-05-22 09:19:39 +08006758 if_idx = if_nametoindex(inf_name);
6759 if (!if_idx) {
6760 wifi_debug(DEBUG_ERROR,"can't finde ifname(%s) index,ERROR", inf_name);
6761 return RETURN_ERR;
6762 }
6763 /*init mtk nl80211 vendor cmd*/
6764 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_ACL;
6765 param.if_type = NL80211_ATTR_IFINDEX;
6766 param.if_idx = if_idx;
6767
6768 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
6769 if (ret) {
6770 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
6771 return RETURN_ERR;
6772 }
developer7e4a2a62023-04-06 19:56:03 +08006773
developer121a8e72023-05-22 09:19:39 +08006774 /*add mtk vendor cmd data*/
6775 if (nla_put_flag(msg, MTK_NL80211_VENDOR_ATTR_ACL_SHOW_ALL)) {
6776 printf("Nla put ACL_SHOW_ALL attribute error\n");
6777 nlmsg_free(msg);
6778 goto err;
6779 }
developer72fb0bb2023-01-11 09:46:29 +08006780
developer121a8e72023-05-22 09:19:39 +08006781 /*send mtk nl80211 vendor msg*/
6782 cb_data.out_buf = macArray;
6783 cb_data.out_len = buf_size;
6784
6785 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, mtk_acl_list_dump_callback, &cb_data);
6786 if (ret) {
6787 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
6788 goto err;
6789 }
6790 /*deinit mtk nl80211 vendor msg*/
6791 mtk_nl80211_deint(&unl_ins);
6792 wifi_debug(DEBUG_NOTICE,"send cmd success, get macArray:%s", macArray);
developer72fb0bb2023-01-11 09:46:29 +08006793 return RETURN_OK;
developer121a8e72023-05-22 09:19:39 +08006794err:
6795 mtk_nl80211_deint(&unl_ins);
6796 wifi_debug(DEBUG_ERROR,"send cmd fails");
6797 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006798}
6799
6800INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
6801{
developer72fb0bb2023-01-11 09:46:29 +08006802
developer7e4a2a62023-04-06 19:56:03 +08006803 wifi_getApAclDevices(apIndex, macArray, buf_size);
developer72fb0bb2023-01-11 09:46:29 +08006804
6805 return RETURN_OK;
6806}
6807
6808
6809// Get the list of stations associated per AP
6810INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
6811{
developer7e4a2a62023-04-06 19:56:03 +08006812 char interface_name[IF_NAME_SIZE] = {0};
6813 char cmd[MAX_CMD_SIZE];
developer72fb0bb2023-01-11 09:46:29 +08006814
developer7e4a2a62023-04-06 19:56:03 +08006815 if(apIndex > 3) //Currently supporting apIndex upto 3
6816 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006817
developer7e4a2a62023-04-06 19:56:03 +08006818 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6819 return RETURN_ERR;
6820
6821 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s list_sta", interface_name);
6822 _syscmd(cmd, macArray, buf_size);
6823 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006824}
6825
developer8dd72532023-05-17 19:58:35 +08006826int hex2num(char c)
6827{
6828 if (c >= '0' && c <= '9')
6829 return c - '0';
6830 if (c >= 'a' && c <= 'f')
6831 return c - 'a' + 10;
6832 if (c >= 'A' && c <= 'F')
6833 return c - 'A' + 10;
6834 return -1;
6835}
6836
6837/**
6838 * hwaddr_aton2 - Convert ASCII string to MAC address (in any known format)
6839 * @txt: MAC address as a string (e.g., 00:11:22:33:44:55 or 0011.2233.4455)
6840 * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
6841 * Returns: Characters used (> 0) on success, -1 on failure
6842 */
6843int hwaddr_aton2(const char *txt, unsigned char *addr)
6844{
6845 int i;
6846 const char *pos = txt;
6847
6848 for (i = 0; i < 6; i++) {
6849 int a, b;
6850
6851 while (*pos == ':' || *pos == '.' || *pos == '-')
6852 pos++;
6853
6854 a = hex2num(*pos++);
6855 if (a < 0)
6856 return -1;
6857 b = hex2num(*pos++);
6858 if (b < 0)
6859 return -1;
6860 *addr++ = (a << 4) | b;
6861 }
6862
6863 return pos - txt;
6864}
6865
developer72fb0bb2023-01-11 09:46:29 +08006866// adds the mac address to the filter list
6867//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
6868INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
6869{
developer7e4a2a62023-04-06 19:56:03 +08006870 char cmd[MAX_CMD_SIZE] = {0};
6871 char buf[MAX_BUF_SIZE] = {0};
6872 char inf_name[IF_NAME_SIZE] = {0};
developer8dd72532023-05-17 19:58:35 +08006873 int if_idx, ret = 0;
developer49b17232023-05-19 16:35:19 +08006874 struct nl_msg *msg = NULL;
6875 struct nlattr * msg_data = NULL;
6876 struct mtk_nl80211_param param;
developer8dd72532023-05-17 19:58:35 +08006877 unsigned char mac[ETH_ALEN] = {0x00, 0x0c, 0x43, 0x11, 0x22, 0x33};
6878 struct unl unl_ins;
developer7e4a2a62023-04-06 19:56:03 +08006879 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
6880 return RETURN_ERR;
developer7e4a2a62023-04-06 19:56:03 +08006881 if (!DeviceMacAddress)
6882 return RETURN_ERR;
developer8dd72532023-05-17 19:58:35 +08006883 if (hwaddr_aton2(DeviceMacAddress, mac) < 0) {
6884 printf("error device mac address=%s\n", DeviceMacAddress);
6885 return RETURN_ERR;
6886 }
developer72fb0bb2023-01-11 09:46:29 +08006887
developer8dd72532023-05-17 19:58:35 +08006888 if_idx = if_nametoindex(inf_name);
developer49b17232023-05-19 16:35:19 +08006889 /*init mtk nl80211 vendor cmd*/
6890 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_ACL;
6891 param.if_type = NL80211_ATTR_IFINDEX;
6892 param.if_idx = if_idx;
6893 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
6894 if (ret) {
6895 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
developer8dd72532023-05-17 19:58:35 +08006896 return RETURN_ERR;
6897 }
developer49b17232023-05-19 16:35:19 +08006898 /*add mtk vendor cmd data*/
6899 if (nla_put(msg, MTK_NL80211_VENDOR_ATTR_ACL_ADD_MAC, ETH_ALEN, mac)) {
6900 printf("Nla put attribute error\n");
developer8dd72532023-05-17 19:58:35 +08006901 nlmsg_free(msg);
6902 goto err;
6903 }
6904
developer49b17232023-05-19 16:35:19 +08006905 /*send mtk nl80211 vendor msg*/
6906 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
6907 if (ret) {
6908 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
developer8dd72532023-05-17 19:58:35 +08006909 goto err;
6910 }
developer49b17232023-05-19 16:35:19 +08006911 /*deinit mtk nl80211 vendor msg*/
6912 mtk_nl80211_deint(&unl_ins);
6913 wifi_debug(DEBUG_NOTICE, "set cmd success.\n");
developer8dd72532023-05-17 19:58:35 +08006914 return RETURN_OK;
6915err:
developer49b17232023-05-19 16:35:19 +08006916 mtk_nl80211_deint(&unl_ins);
6917 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
developer8dd72532023-05-17 19:58:35 +08006918 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006919}
6920
6921// deletes the mac address from the filter list
6922//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
6923INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
6924{
developer7e4a2a62023-04-06 19:56:03 +08006925 char cmd[MAX_CMD_SIZE] = {0};
6926 char buf[MAX_BUF_SIZE] = {0};
6927 char inf_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08006928
developer7e4a2a62023-04-06 19:56:03 +08006929 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
6930 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006931
developer7e4a2a62023-04-06 19:56:03 +08006932 if (!DeviceMacAddress)
6933 return RETURN_ERR;
6934
6935 /* mwctl acl del sta */
6936 snprintf(cmd, sizeof(cmd), "mwctl %s acl del=%s", inf_name, DeviceMacAddress);
6937 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006938
6939 return RETURN_OK;
6940}
6941
6942// outputs the number of devices in the filter list
6943INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
6944{
developer7e4a2a62023-04-06 19:56:03 +08006945 char cmd[MAX_CMD_SIZE] = {0};
6946 char buf[MAX_BUF_SIZE] = {0};
6947 char inf_name[IF_NAME_SIZE] = {0};
6948 char sta_num = 0;
developer72fb0bb2023-01-11 09:46:29 +08006949
developer72fb0bb2023-01-11 09:46:29 +08006950 if(output_uint == NULL)
6951 return RETURN_ERR;
6952
developer7e4a2a62023-04-06 19:56:03 +08006953 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
6954 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006955
developer7e4a2a62023-04-06 19:56:03 +08006956 /* mwctl acl get sta num */
6957 snprintf(cmd, sizeof(cmd), "mwctl %s acl show_all | wc -l | tr -d '\\n'", inf_name);
6958 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006959
developer7e4a2a62023-04-06 19:56:03 +08006960 if (atoi(buf) > 1)
6961 *output_uint = atoi(buf) - 1; /*except the line of acl_policy*/
6962 else {
6963 *output_uint = 0;
6964 printf("%s: acl get wrong return content!!!\n", __func__);
6965 }
6966
6967 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006968}
6969
6970INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
6971{
6972 char cmd[128]={'\0'};
6973 char buf[128]={'\0'};
6974
6975 if(strcmp(action,"DENY")==0)
6976 {
6977 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
6978 system(buf);
6979 return RETURN_OK;
6980 }
6981
6982 if(strcmp(action,"ALLOW")==0)
6983 {
6984 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
6985 system(buf);
6986 return RETURN_OK;
6987 }
6988
6989 return RETURN_ERR;
6990
6991}
6992
6993// enable kick for devices on acl black list
6994INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
6995{
developer47cc27a2023-05-17 23:09:58 +08006996 char aclArray[MAX_BUF_SIZE] = {0}, *acl = NULL;
6997 char assocArray[MAX_BUF_SIZE] = {0}, *asso = NULL;
developer72fb0bb2023-01-11 09:46:29 +08006998
6999 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
7000 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
7001
developer7e4a2a62023-04-06 19:56:03 +08007002 /* if there are no devices connected there is nothing to do */
developer72fb0bb2023-01-11 09:46:29 +08007003 if (strlen(assocArray) < 17)
7004 return RETURN_OK;
7005
developer7e4a2a62023-04-06 19:56:03 +08007006 if (enable == TRUE) {
7007 /* kick off the MAC which is in ACL array (deny list) */
7008 acl = strtok(aclArray, "\n");
developer72fb0bb2023-01-11 09:46:29 +08007009 while (acl != NULL) {
7010 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
7011 wifi_kickApAssociatedDevice(apIndex, acl);
7012
developer7e4a2a62023-04-06 19:56:03 +08007013 acl = strtok(NULL, "\n");
developer72fb0bb2023-01-11 09:46:29 +08007014 }
7015 wifi_setApMacAddressControlMode(apIndex, 2);
developer7e4a2a62023-04-06 19:56:03 +08007016 } else
developer72fb0bb2023-01-11 09:46:29 +08007017 wifi_setApMacAddressControlMode(apIndex, 0);
developer72fb0bb2023-01-11 09:46:29 +08007018
developer72fb0bb2023-01-11 09:46:29 +08007019 return RETURN_OK;
7020}
7021
7022INT wifi_setPreferPrivateConnection(BOOL enable)
7023{
7024 return RETURN_OK;
7025}
7026
7027// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
7028INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
7029{
developer7e4a2a62023-04-06 19:56:03 +08007030 char inf_name[IF_NAME_SIZE] = {0};
7031 char cmd[MAX_CMD_SIZE] = {0};
7032 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08007033
developer7e4a2a62023-04-06 19:56:03 +08007034 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
7035 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007036
developer7e4a2a62023-04-06 19:56:03 +08007037 /*mwctl set acl policy*/
7038 snprintf(cmd, sizeof(cmd), "mwctl %s acl policy=%d", inf_name, filterMode);
7039 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08007040
developer7e4a2a62023-04-06 19:56:03 +08007041 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08007042}
7043
7044// 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.
7045INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
7046{
7047 return RETURN_ERR;
7048}
7049
7050// gets the vlan ID for this ap from an internal enviornment variable
7051INT wifi_getApVlanID(INT apIndex, INT *output_int)
7052{
7053 if(apIndex==0)
7054 {
7055 *output_int=100;
7056 return RETURN_OK;
7057 }
7058
7059 return RETURN_ERR;
7060}
7061
7062// sets the vlan ID for this ap to an internal enviornment variable
7063INT wifi_setApVlanID(INT apIndex, INT vlanId)
7064{
7065 //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)
7066 return RETURN_ERR;
7067}
7068
7069// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
7070INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
7071{
7072 snprintf(bridgeName, 32, "brlan0");
7073 snprintf(IP, 32, "10.0.0.1");
7074 snprintf(subnet, 32, "255.255.255.0");
7075
7076 return RETURN_OK;
7077}
7078
7079//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
7080INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
7081{
7082 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
7083 return RETURN_ERR;
7084}
7085
7086// reset the vlan configuration for this ap
7087INT wifi_resetApVlanCfg(INT apIndex)
7088{
7089 char original_config_file[64] = {0};
7090 char current_config_file[64] = {0};
7091 char buf[64] = {0};
7092 char cmd[64] = {0};
7093 char vlan_file[64] = {0};
7094 char vlan_tagged_interface[16] = {0};
7095 char vlan_bridge[16] = {0};
7096 char vlan_naming[16] = {0};
7097 struct params list[4] = {0};
7098 wifi_band band;
developera1255e42023-05-13 17:45:02 +08007099 char interface_name[16] = {0};
developer72fb0bb2023-01-11 09:46:29 +08007100
7101 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08007102 band = wifi_index_to_band(apIndex);
7103 if (band == band_2_4)
developera1255e42023-05-13 17:45:02 +08007104 snprintf(original_config_file, sizeof(original_config_file), "/etc/hostapd-2G.conf");
developer72fb0bb2023-01-11 09:46:29 +08007105 else if (band == band_5)
developera1255e42023-05-13 17:45:02 +08007106 snprintf(original_config_file, sizeof(original_config_file), "/etc/hostapd-5G.conf");
developer72fb0bb2023-01-11 09:46:29 +08007107 else if (band == band_6)
developera1255e42023-05-13 17:45:02 +08007108 snprintf(original_config_file, sizeof(original_config_file), "/etc/hostapd-6G.conf");
developer72fb0bb2023-01-11 09:46:29 +08007109
7110 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
7111
7112 if (strlen(vlan_file) == 0)
7113 strcpy(vlan_file, VLAN_FILE);
7114
7115 // The file should exist or this vap would not work.
7116 if (access(vlan_file, F_OK) != 0) {
developera1255e42023-05-13 17:45:02 +08007117 snprintf(cmd, sizeof(cmd), "touch %s", vlan_file);
developer72fb0bb2023-01-11 09:46:29 +08007118 _syscmd(cmd, buf, sizeof(buf));
7119 }
7120 list[0].name = "vlan_file";
7121 list[0].value = vlan_file;
7122
7123 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
7124 list[1].name = "vlan_tagged_interface";
7125 list[1].value = vlan_tagged_interface;
7126
7127 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
7128 list[2].name = "vlan_bridge";
7129 list[2].value = vlan_bridge;
7130
7131 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
7132 list[3].name = "vlan_naming";
7133 list[3].value = vlan_naming;
7134
developera1255e42023-05-13 17:45:02 +08007135 snprintf(current_config_file, sizeof(current_config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developer72fb0bb2023-01-11 09:46:29 +08007136 wifi_hostapdWrite(current_config_file, list, 4);
7137 //Reapply vlan settings
7138 // wifi_pushBridgeInfo(apIndex);
7139
7140 // restart this ap
7141 wifi_setApEnable(apIndex, FALSE);
7142 wifi_setApEnable(apIndex, TRUE);
developera1255e42023-05-13 17:45:02 +08007143 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7144 return RETURN_ERR;
7145 snprintf(cmd, sizeof(cmd), "mwctl dev %s set vlan_tag 0\n", interface_name);
7146 _syscmd(cmd, buf, sizeof(buf));
7147 snprintf(cmd, sizeof(cmd), "mwctl dev %s set vlan_priority 0\n", interface_name);
7148 _syscmd(cmd, buf, sizeof(buf));
7149 snprintf(cmd, sizeof(cmd), "mwctl dev %s set vlan_id 0\n", interface_name);
7150 _syscmd(cmd, buf, sizeof(buf));
7151 snprintf(cmd, sizeof(cmd), "mwctl dev %s set vlan_en 0\n", interface_name);
7152 _syscmd(cmd, buf, sizeof(buf));
7153 snprintf(cmd, sizeof(cmd), "mwctl dev %s set vlan_policy 0:4\n", interface_name);
7154 _syscmd(cmd, buf, sizeof(buf));
7155 snprintf(cmd, sizeof(cmd), "mwctl dev %s set vlan_policy 1:0\n", interface_name);
7156 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08007157 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7158
7159 return RETURN_OK;
7160}
7161
7162// 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.
7163INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
7164{
7165 return RETURN_ERR;
7166}
7167
7168// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
7169INT wifi_startHostApd()
7170{
7171 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7172 system("systemctl start hostapd.service");
7173 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7174 return RETURN_OK;
7175 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
7176}
7177
7178// stops hostapd
developer69b61b02023-03-07 17:17:44 +08007179INT wifi_stopHostApd()
developer72fb0bb2023-01-11 09:46:29 +08007180{
7181 char cmd[128] = {0};
7182 char buf[128] = {0};
7183
7184 sprintf(cmd,"systemctl stop hostapd");
7185 _syscmd(cmd, buf, sizeof(buf));
7186
7187 return RETURN_OK;
7188}
7189
7190// restart hostapd dummy function
7191INT wifi_restartHostApd()
7192{
7193 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7194 system("systemctl restart hostapd-global");
7195 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7196
7197 return RETURN_OK;
7198}
7199
7200static int align_hostapd_config(int index)
7201{
7202 ULONG lval;
7203 wifi_getRadioChannel(index%2, &lval);
7204 wifi_setRadioChannel(index%2, lval);
7205 return RETURN_OK;
7206}
7207
7208// sets the AP enable status variable for the specified ap.
7209INT wifi_setApEnable(INT apIndex, BOOL enable)
7210{
developer7e4a2a62023-04-06 19:56:03 +08007211 char interface_name[16] = {0};
7212 char config_file[MAX_BUF_SIZE] = {0};
7213 char cmd[MAX_CMD_SIZE] = {0};
7214 char buf[MAX_BUF_SIZE] = {0};
developer47cc27a2023-05-17 23:09:58 +08007215 BOOL status = FALSE;
developer7e4a2a62023-04-06 19:56:03 +08007216 int max_radio_num = 0;
7217 int phyId = 0;
developer72fb0bb2023-01-11 09:46:29 +08007218
developer7e4a2a62023-04-06 19:56:03 +08007219 wifi_getApEnable(apIndex, &status);
developer72fb0bb2023-01-11 09:46:29 +08007220
developer7e4a2a62023-04-06 19:56:03 +08007221 wifi_getMaxRadioNumber(&max_radio_num);
7222 if (enable == status)
7223 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08007224
developer7e4a2a62023-04-06 19:56:03 +08007225 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7226 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007227
developer7e4a2a62023-04-06 19:56:03 +08007228 if (enable == TRUE) {
7229 int radioIndex = apIndex % max_radio_num;
7230 phyId = radio_index_to_phy(radioIndex);
developer8a3bbbf2023-03-15 17:47:23 +08007231
developer7e4a2a62023-04-06 19:56:03 +08007232 snprintf(config_file, MAX_BUF_SIZE, "%s%d.conf", CONFIG_PREFIX, apIndex);
7233 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyId, config_file);
7234 _syscmd(cmd, buf, sizeof(buf));
7235 } else {
7236 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw REMOVE %s", interface_name);
7237 _syscmd(cmd, buf, sizeof(buf));
7238 }
7239 snprintf(cmd, MAX_CMD_SIZE, "sed -i -n -e '/^%s=/!p' -e '$a%s=%d' %s",
7240 interface_name, interface_name, enable, VAP_STATUS_FILE);
7241 _syscmd(cmd, buf, sizeof(buf));
7242 //Wait for wifi up/down to apply
7243 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08007244}
7245
7246// Outputs the setting of the internal variable that is set by wifi_setApEnable().
7247INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
7248{
developer7e4a2a62023-04-06 19:56:03 +08007249 char interface_name[IF_NAME_SIZE] = {0};
7250 char cmd[MAX_CMD_SIZE] = {0};
7251 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08007252
developer7e4a2a62023-04-06 19:56:03 +08007253 if ((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
7254 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007255
developer7e4a2a62023-04-06 19:56:03 +08007256 *output_bool = 0;
developer72fb0bb2023-01-11 09:46:29 +08007257
developer7e4a2a62023-04-06 19:56:03 +08007258 if ((apIndex >= 0) && (apIndex < MAX_APS)) {
7259 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
7260 *output_bool = FALSE;
7261 return RETURN_OK;
7262 }
7263 snprintf(cmd, MAX_CMD_SIZE, "ifconfig %s 2> /dev/null | grep UP", interface_name);
7264 *output_bool = _syscmd(cmd, buf, sizeof(buf)) ? 0 : 1;
7265 }
developer72fb0bb2023-01-11 09:46:29 +08007266
developer7e4a2a62023-04-06 19:56:03 +08007267 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08007268}
7269
developer69b61b02023-03-07 17:17:44 +08007270// Outputs the AP "Enabled" "Disabled" status from driver
7271INT wifi_getApStatus(INT apIndex, CHAR *output_string)
developer72fb0bb2023-01-11 09:46:29 +08007272{
developer7e4a2a62023-04-06 19:56:03 +08007273 char cmd[128] = {0};
7274 char buf[128] = {0};
7275 BOOL output_bool;
developer72fb0bb2023-01-11 09:46:29 +08007276
developer7e4a2a62023-04-06 19:56:03 +08007277 if (!output_string) {
7278 printf("%s: null pointer!", __func__);
7279 return RETURN_ERR;
7280 }
developer72fb0bb2023-01-11 09:46:29 +08007281
developer7e4a2a62023-04-06 19:56:03 +08007282 wifi_getApEnable(apIndex, &output_bool);
developer72fb0bb2023-01-11 09:46:29 +08007283
developer7e4a2a62023-04-06 19:56:03 +08007284 if(output_bool == 1)
7285 snprintf(output_string, 32, "Up");
7286 else
7287 snprintf(output_string, 32, "Disable");
7288
7289 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08007290}
7291
7292//Indicates whether or not beacons include the SSID name.
7293// outputs a 1 if SSID on the AP is enabled, else outputs 0
7294INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
7295{
7296 //get the running status
7297 char config_file[MAX_BUF_SIZE] = {0};
7298 char buf[16] = {0};
7299
7300 if (!output)
7301 return RETURN_ERR;
7302
7303 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7304 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
7305 // default is enable
7306 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
7307 *output = TRUE;
7308
7309 return RETURN_OK;
7310}
7311
7312// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
7313INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
7314{
7315 //store the config, apply instantly
7316 char config_file[MAX_BUF_SIZE] = {0};
7317 struct params list;
7318
7319 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7320 list.name = "ignore_broadcast_ssid";
7321 list.value = enable?"0":"1";
7322
7323 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7324 wifi_hostapdWrite(config_file, &list, 1);
7325 wifi_hostapdProcessUpdate(apIndex, &list, 1);
7326 //TODO: call hostapd_cli for dynamic_config_control
7327 wifi_reloadAp(apIndex);
7328 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7329
7330 return RETURN_OK;
7331}
7332
7333//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
7334INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
7335{
developer47cc27a2023-05-17 23:09:58 +08007336 /* get the running status */
7337 if(!output_uint)
7338 return RETURN_ERR;
7339
7340 *output_uint = 15;
7341 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08007342}
7343
developer47cc27a2023-05-17 23:09:58 +08007344/*Do not support AP retry limit fix*/
developer72fb0bb2023-01-11 09:46:29 +08007345INT wifi_setApRetryLimit(INT apIndex, UINT number)
7346{
developer47cc27a2023-05-17 23:09:58 +08007347 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007348}
7349
7350//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
7351INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
7352{
developer8e6583c2023-05-23 13:36:06 +08007353 char interface_name[16] = {0};
7354 char cmd[128]={0};
7355 char buf[10]={0};
7356
7357 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08007358 if(!output)
7359 return RETURN_ERR;
developer8e6583c2023-05-23 13:36:06 +08007360
7361 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7362 return RETURN_ERR;
7363 snprintf(cmd, sizeof(cmd), "mwctl %s set wmm_cap s", interface_name);
7364 _syscmd(cmd, buf, sizeof(buf));
7365 if (strncmp(buf, "enabled", 7) == 0)
7366 *output = TRUE;
7367 else
7368 *output = FALSE;
7369
7370 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08007371 return RETURN_OK;
7372}
7373
7374//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
7375INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
7376{
7377 //get the running status from driver
7378 char cmd[128] = {0};
7379 char buf[128] = {0};
7380 int max_radio_num = 0, radioIndex = 0;
7381 int phyId = 0;
7382
7383 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7384
7385 wifi_getMaxRadioNumber(&max_radio_num);
7386 radioIndex = apIndex % max_radio_num;
7387 phyId = radio_index_to_phy(radioIndex);
7388 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", phyId);
7389 _syscmd(cmd,buf, sizeof(buf));
7390
7391 if (strlen(buf) > 0)
7392 *output = true;
7393
7394 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7395
7396 return RETURN_OK;
7397}
7398
7399//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
7400INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
7401{
7402 //get the running status from driver
developer8e6583c2023-05-23 13:36:06 +08007403 char interface_name[16] = {0};
7404 char cmd[128]={0};
7405 char buf[10]={0};
7406
7407 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08007408 if(!output)
7409 return RETURN_ERR;
developer8e6583c2023-05-23 13:36:06 +08007410 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7411 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007412
developer8e6583c2023-05-23 13:36:06 +08007413 snprintf(cmd, sizeof(cmd), "mwctl %s set wmm_cap s", interface_name);
7414 _syscmd(cmd, buf, sizeof(buf));
7415 if (strncmp(buf, "enabled", 7) == 0)
developer72fb0bb2023-01-11 09:46:29 +08007416 *output = TRUE;
7417 else
7418 *output = FALSE;
7419
developer8e6583c2023-05-23 13:36:06 +08007420 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08007421 return RETURN_OK;
7422}
7423
7424// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
7425INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
7426{
7427 //Save config and apply instantly.
developer8e6583c2023-05-23 13:36:06 +08007428 char interface_name[16] = {0};
7429 char cmd[128]={0};
7430 char buf[4]={0};
developer72fb0bb2023-01-11 09:46:29 +08007431
7432 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08007433
developer8e6583c2023-05-23 13:36:06 +08007434 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7435 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007436
developer8e6583c2023-05-23 13:36:06 +08007437 snprintf(cmd, sizeof(cmd), "mwctl %s set WmmCapable=%d", interface_name, enable);
7438 _syscmd(cmd, buf, sizeof(buf));
7439
7440 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08007441 return RETURN_OK;
7442}
7443
7444//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.
7445INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
7446{
7447 //get the running status from driver
7448 if(!output)
7449 return RETURN_ERR;
7450
7451 char config_file[128] = {0};
7452 char buf[16] = {0};
7453
7454 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7455 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
7456 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
7457 *output = TRUE;
7458 else
7459 *output = FALSE;
7460
7461 return RETURN_OK;
7462}
7463
7464// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
7465INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
7466{
7467 //save config and apply instantly.
7468 char config_file[MAX_BUF_SIZE] = {0};
7469 struct params list;
7470
7471 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7472 list.name = "uapsd_advertisement_enabled";
7473 list.value = enable?"1":"0";
7474
7475 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7476 wifi_hostapdWrite(config_file, &list, 1);
7477 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developere82c0ca2023-05-10 16:25:35 +08007478 wifi_quick_reload_ap(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08007479 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7480
7481 return RETURN_OK;
7482}
7483
7484// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
7485INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
7486{
7487 char interface_name[16] = {0};
7488 // assume class 0->BE, 1->BK, 2->VI, 3->VO
7489 char cmd[128] = {0};
7490 char buf[128] = {0};
7491 char ack_filepath[128] = {0};
7492 uint16_t bitmap = 0;
7493 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
7494 FILE *f = NULL;
7495
7496 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
7497
7498 // Get current setting
7499 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
7500 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
7501 _syscmd(cmd, buf, sizeof(buf));
7502 if (strlen(buf) > 0)
7503 bitmap = strtoul(buf, NULL, 10);
7504
7505 bitmap = strtoul(buf, NULL, 10);
7506
7507 if (ackPolicy == TRUE) { // True, unset this class
7508 bitmap &= ~class_map[class];
7509 } else { // False, set this class
7510 bitmap |= class_map[class];
7511 }
7512
7513 f = fopen(ack_filepath, "w");
7514 if (f == NULL) {
7515 fprintf(stderr, "%s: fopen failed\n", __func__);
7516 return RETURN_ERR;
7517 }
7518 fprintf(f, "%hu", bitmap);
7519 fclose(f);
7520
7521 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7522 return RETURN_ERR;
7523 snprintf(cmd, sizeof(cmd), "iw dev %s set noack_map 0x%04x\n", interface_name, bitmap);
7524 _syscmd(cmd, buf, sizeof(buf));
7525
7526 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
7527 return RETURN_OK;
7528}
7529
7530//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.
7531INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
7532{
7533 //get the running status from driver
7534 if(!output_uint)
7535 return RETURN_ERR;
7536
7537 char output[16]={'\0'};
7538 char config_file[MAX_BUF_SIZE] = {0};
7539
7540 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7541 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
7542 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
7543 else {
7544 int device_num = atoi(output);
7545 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
7546 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
7547 return RETURN_ERR;
7548 }
7549 else {
7550 *output_uint = device_num;
7551 }
7552 }
7553
7554 return RETURN_OK;
7555}
7556
7557INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
7558{
7559 //store to wifi config, apply instantly
7560 char str[MAX_BUF_SIZE]={'\0'};
7561 char cmd[MAX_CMD_SIZE]={'\0'};
7562 struct params params;
7563 char config_file[MAX_BUF_SIZE] = {0};
7564
7565 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7566 if (number > MAX_ASSOCIATED_STA_NUM) {
7567 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
7568 return RETURN_ERR;
7569 }
7570 sprintf(str, "%d", number);
7571 params.name = "max_num_sta";
7572 params.value = str;
7573
7574 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
7575 int ret = wifi_hostapdWrite(config_file, &params, 1);
7576 if (ret) {
7577 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
7578 ,__func__, ret);
7579 }
7580
7581 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
7582 if (ret) {
7583 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
7584 ,__func__, ret);
7585 }
7586 wifi_reloadAp(apIndex);
7587 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7588
7589 return RETURN_OK;
7590}
7591
7592//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.
7593INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
7594{
7595 //get the current threshold
7596 if(!output_uint)
7597 return RETURN_ERR;
7598 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
7599 if (*output_uint == 0)
7600 *output_uint = 50;
7601 return RETURN_OK;
7602}
7603
7604INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
7605{
7606 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
7607 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
7608 return RETURN_OK;
7609 return RETURN_ERR;
7610}
7611
7612//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.
7613INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
7614{
7615 if(!output_uint)
7616 return RETURN_ERR;
7617 *output_uint = 3;
7618 return RETURN_OK;
7619}
7620
7621//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
7622INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
7623{
7624 if(!output_uint)
7625 return RETURN_ERR;
7626 *output_uint = 3;
7627 return RETURN_OK;
7628}
7629
7630//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.
7631INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
7632{
7633 if(!output_in_seconds)
7634 return RETURN_ERR;
7635 *output_in_seconds = 0;
7636 return RETURN_OK;
7637}
7638
7639//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
7640INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
7641{
7642 if(!output || apIndex>=MAX_APS)
7643 return RETURN_ERR;
7644 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
7645 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
7646 return RETURN_OK;
developer69b61b02023-03-07 17:17:44 +08007647}
developer72fb0bb2023-01-11 09:46:29 +08007648
7649//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
7650INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
7651{
7652 char config_file[128] = {0};
7653 char wpa[16] = {0};
7654 char key_mgmt[64] = {0};
7655 char buf[16] = {0};
7656 if (!output)
7657 return RETURN_ERR;
7658
7659 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7660 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
7661
7662 strcpy(output, "None");//Copying "None" to output string for default case
7663 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
7664 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
7665 if (!strcmp(wpa, "1"))
7666 snprintf(output, 32, "WPA-Personal");
7667 else if (!strcmp(wpa, "2"))
7668 snprintf(output, 32, "WPA2-Personal");
7669 else if (!strcmp(wpa, "3"))
7670 snprintf(output, 32, "WPA-WPA2-Personal");
7671
developere5750452023-05-15 16:46:42 +08007672 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
7673 snprintf(output, 32, "WPA3-Enterprise");
developer72fb0bb2023-01-11 09:46:29 +08007674 } else if (strstr(key_mgmt, "WPA-EAP")) {
7675 if (!strcmp(wpa, "1"))
7676 snprintf(output, 32, "WPA-Enterprise");
7677 else if (!strcmp(wpa, "2"))
7678 snprintf(output, 32, "WPA2-Enterprise");
7679 else if (!strcmp(wpa, "3"))
7680 snprintf(output, 32, "WPA-WPA2-Enterprise");
7681 } else if (strstr(key_mgmt, "SAE")) {
7682 if (strstr(key_mgmt, "WPA-PSK") == NULL)
7683 snprintf(output, 32, "WPA3-Personal");
7684 else
7685 snprintf(output, 32, "WPA3-Personal-Transition");
developer72fb0bb2023-01-11 09:46:29 +08007686 }
7687
7688 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
7689 return RETURN_OK;
7690#if 0
7691 //TODO: need to revisit below implementation
7692 char securityType[32], authMode[32];
7693 int enterpriseMode=0;
7694
7695 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7696 if(!output)
7697 return RETURN_ERR;
7698
7699 wifi_getApBeaconType(apIndex, securityType);
7700 strcpy(output,"None");//By default, copying "None" to output string
7701 if (strncmp(securityType,"None", strlen("None")) == 0)
7702 return RETURN_OK;
7703
7704 wifi_getApBasicAuthenticationMode(apIndex, authMode);
7705 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
7706
7707 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
7708 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
7709 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
7710 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
7711 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
7712 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
7713 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7714
7715 return RETURN_OK;
7716#endif
7717}
developer69b61b02023-03-07 17:17:44 +08007718
developer72fb0bb2023-01-11 09:46:29 +08007719INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
7720{
7721 char securityType[32];
7722 char authMode[32];
7723
7724 //store settings and wait for wifi up to apply
7725 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7726 if(!encMode)
7727 return RETURN_ERR;
7728
7729 if (strcmp(encMode, "None")==0)
7730 {
7731 strcpy(securityType,"None");
7732 strcpy(authMode,"None");
7733 }
7734 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
7735 {
7736 strcpy(securityType,"WPAand11i");
7737 strcpy(authMode,"PSKAuthentication");
7738 }
7739 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
7740 {
7741 strcpy(securityType,"WPAand11i");
7742 strcpy(authMode,"EAPAuthentication");
7743 }
7744 else if (strcmp(encMode, "WPA-Personal")==0)
7745 {
7746 strcpy(securityType,"WPA");
7747 strcpy(authMode,"PSKAuthentication");
7748 }
7749 else if (strcmp(encMode, "WPA-Enterprise")==0)
7750 {
7751 strcpy(securityType,"WPA");
7752 strcpy(authMode,"EAPAuthentication");
7753 }
7754 else if (strcmp(encMode, "WPA2-Personal")==0)
7755 {
7756 strcpy(securityType,"11i");
7757 strcpy(authMode,"PSKAuthentication");
7758 }
7759 else if (strcmp(encMode, "WPA2-Enterprise")==0)
7760 {
7761 strcpy(securityType,"11i");
7762 strcpy(authMode,"EAPAuthentication");
7763 }
7764 else if (strcmp(encMode, "WPA3-Personal") == 0)
7765 {
7766 strcpy(securityType,"11i");
7767 strcpy(authMode,"SAEAuthentication");
7768 }
7769 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
7770 {
7771 strcpy(securityType, "11i");
7772 strcpy(authMode, "PSK-SAEAuthentication");
7773 }
7774 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
7775 {
7776 strcpy(securityType,"11i");
7777 strcpy(authMode,"EAP_192-bit_Authentication");
7778 }
developer3086e2f2023-01-17 09:40:01 +08007779 else if (strcmp(encMode, "OWE") == 0)
7780 {
7781 strcpy(securityType,"11i");
7782 strcpy(authMode,"Enhanced_Open");
7783 }
developer72fb0bb2023-01-11 09:46:29 +08007784 else
7785 {
7786 strcpy(securityType,"None");
7787 strcpy(authMode,"None");
7788 }
7789 wifi_setApBeaconType(apIndex, securityType);
7790 wifi_setApBasicAuthenticationMode(apIndex, authMode);
7791 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7792
7793 return RETURN_OK;
developer69b61b02023-03-07 17:17:44 +08007794}
developer72fb0bb2023-01-11 09:46:29 +08007795
7796
7797//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
7798// output_string must be pre-allocated as 64 character string by caller
7799// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
7800INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
7801{
7802 char buf[16] = {0};
7803 char config_file[MAX_BUF_SIZE] = {0};
7804
7805 if(output_string==NULL)
7806 return RETURN_ERR;
7807
7808 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7809 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
7810
7811 if(strcmp(buf,"0")==0)
7812 {
7813 printf("wpa_mode is %s ......... \n",buf);
7814 return RETURN_ERR;
7815 }
7816
7817 wifi_dbg_printf("\nFunc=%s\n",__func__);
7818 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developere5750452023-05-15 16:46:42 +08007819 wifi_hostapdRead(config_file,"wpa_psk",output_string,65);
developer72fb0bb2023-01-11 09:46:29 +08007820 wifi_dbg_printf("\noutput_string=%s\n",output_string);
7821
7822 return RETURN_OK;
7823}
7824
7825// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
7826// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
7827INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
7828{
7829 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
7830 struct params params={'\0'};
7831 int ret;
7832 char config_file[MAX_BUF_SIZE] = {0};
7833
7834 if(NULL == preSharedKey)
7835 return RETURN_ERR;
7836
developere5750452023-05-15 16:46:42 +08007837 params.name = "wpa_psk";
developer72fb0bb2023-01-11 09:46:29 +08007838
developere5750452023-05-15 16:46:42 +08007839 if(strlen(preSharedKey) != 64)
developer72fb0bb2023-01-11 09:46:29 +08007840 {
developere5750452023-05-15 16:46:42 +08007841 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 64 chars\n");
developer72fb0bb2023-01-11 09:46:29 +08007842 return RETURN_ERR;
7843 }
7844 params.value = preSharedKey;
7845 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7846 ret = wifi_hostapdWrite(config_file, &params, 1);
developere5750452023-05-15 16:46:42 +08007847 if(!ret) {
developer72fb0bb2023-01-11 09:46:29 +08007848 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
developere5750452023-05-15 16:46:42 +08007849 wifi_reloadAp(apIndex);
7850 }
developer72fb0bb2023-01-11 09:46:29 +08007851 return ret;
7852 //TODO: call hostapd_cli for dynamic_config_control
7853}
7854
7855//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
7856// outputs the passphrase, maximum 63 characters
7857INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
7858{
7859 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
7860
7861 wifi_dbg_printf("\nFunc=%s\n",__func__);
7862 if (NULL == output_string)
7863 return RETURN_ERR;
7864
7865 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7866 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
7867 if(strcmp(buf,"0")==0)
7868 {
7869 printf("wpa_mode is %s ......... \n",buf);
7870 return RETURN_ERR;
7871 }
7872
7873 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
7874 wifi_dbg_printf("\noutput_string=%s\n",output_string);
7875
7876 return RETURN_OK;
7877}
7878
7879// sets the passphrase enviornment variable, max 63 characters
7880INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
7881{
7882 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
7883 struct params params={'\0'};
7884 char config_file[MAX_BUF_SIZE] = {0};
7885 int ret;
7886
7887 if(NULL == passPhrase)
7888 return RETURN_ERR;
7889
7890 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
7891 {
7892 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
7893 return RETURN_ERR;
7894 }
7895 params.name = "wpa_passphrase";
7896 params.value = passPhrase;
7897 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7898 ret=wifi_hostapdWrite(config_file,&params,1);
developere5750452023-05-15 16:46:42 +08007899 if(!ret) {
developer72fb0bb2023-01-11 09:46:29 +08007900 wifi_hostapdProcessUpdate(apIndex, &params, 1);
developere5750452023-05-15 16:46:42 +08007901 wifi_reloadAp(apIndex);
7902 }
developer72fb0bb2023-01-11 09:46:29 +08007903
7904 return ret;
7905}
7906
7907//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.
7908INT wifi_setApSecurityReset(INT apIndex)
7909{
7910 char original_config_file[64] = {0};
7911 char current_config_file[64] = {0};
7912 char buf[64] = {0};
7913 char cmd[64] = {0};
7914 char wpa[4] = {0};
7915 char wpa_psk[64] = {0};
7916 char wpa_passphrase[64] = {0};
7917 char wpa_psk_file[128] = {0};
7918 char wpa_key_mgmt[64] = {0};
7919 char wpa_pairwise[32] = {0};
7920 wifi_band band;
7921 struct params list[6];
7922
7923 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7924
7925 band = wifi_index_to_band(apIndex);
7926 if (band == band_2_4)
7927 sprintf(original_config_file, "/etc/hostapd-2G.conf");
7928 else if (band == band_5)
7929 sprintf(original_config_file, "/etc/hostapd-5G.conf");
7930 else if (band == band_6)
7931 sprintf(original_config_file, "/etc/hostapd-6G.conf");
7932 else
7933 return RETURN_ERR;
7934
7935 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
7936 list[0].name = "wpa";
7937 list[0].value = wpa;
developer69b61b02023-03-07 17:17:44 +08007938
developer72fb0bb2023-01-11 09:46:29 +08007939 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
7940 list[1].name = "wpa_psk";
7941 list[1].value = wpa_psk;
7942
7943 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
7944 list[2].name = "wpa_passphrase";
7945 list[2].value = wpa_passphrase;
7946
7947 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
7948
7949 if (strlen(wpa_psk_file) == 0)
7950 strcpy(wpa_psk_file, PSK_FILE);
7951
7952 if (access(wpa_psk_file, F_OK) != 0) {
7953 sprintf(cmd, "touch %s", wpa_psk_file);
7954 _syscmd(cmd, buf, sizeof(buf));
7955 }
7956 list[3].name = "wpa_psk_file";
7957 list[3].value = wpa_psk_file;
7958
7959 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
7960 list[4].name = "wpa_key_mgmt";
7961 list[4].value = wpa_key_mgmt;
7962
7963 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
7964 list[5].name = "wpa_pairwise";
7965 list[5].value = wpa_pairwise;
7966
7967 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7968 wifi_hostapdWrite(current_config_file, list, 6);
7969
7970 wifi_setApEnable(apIndex, FALSE);
7971 wifi_setApEnable(apIndex, TRUE);
7972
7973 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7974 return RETURN_OK;
7975}
7976
7977//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).
7978INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
7979{
7980 char config_file[64] = {0};
7981 char buf[64] = {0};
7982 char cmd[256] = {0};
7983
7984 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7985
7986 if(!IP_output || !Port_output || !RadiusSecret_output)
7987 return RETURN_ERR;
7988
7989 // Read the first matched config
7990 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7991 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7992 _syscmd(cmd, buf, sizeof(buf));
7993 strncpy(IP_output, buf, 64);
7994
7995 memset(buf, 0, sizeof(buf));
7996 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7997 _syscmd(cmd, buf, sizeof(buf));
7998 *Port_output = atoi(buf);
7999
8000 memset(buf, 0, sizeof(buf));
8001 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
8002 _syscmd(cmd, buf, sizeof(buf));
8003 strncpy(RadiusSecret_output, buf, 64);
8004
8005 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8006 return RETURN_OK;
8007}
8008
8009INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
8010{
8011 char config_file[64] = {0};
8012 char port_str[8] = {0};
8013 char cmd[256] = {0};
8014 char buf[128] = {0};
8015
8016 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8017
developere5750452023-05-15 16:46:42 +08008018 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
8019 return RETURN_ERR;
8020
8021 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
8022 return RETURN_ERR;
8023
developer72fb0bb2023-01-11 09:46:29 +08008024 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
8025
8026 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
8027 _syscmd(cmd, buf, sizeof(buf));
8028 memset(cmd, 0, sizeof(cmd));
8029
8030 snprintf(port_str, sizeof(port_str), "%d", port);
8031 if (strlen(buf) == 0)
8032 // Append
8033 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
8034 "auth_server_addr=%s\\n"
8035 "auth_server_port=%s\\n"
8036 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
8037 else {
8038 // Delete the three lines setting after the "# radius 1" comment
8039 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
8040 _syscmd(cmd, buf, sizeof(buf));
8041 memset(cmd, 0, sizeof(cmd));
8042 // Use "# radius 1" comment to find the location to insert the radius setting
8043 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
8044 "# radius 1\\n"
8045 "auth_server_addr=%s\\n"
8046 "auth_server_port=%s\\n"
8047 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
8048 }
8049 if(_syscmd(cmd, buf, sizeof(buf))) {
8050 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
8051 return RETURN_ERR;
8052 }
8053
8054 wifi_reloadAp(apIndex);
8055 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8056 return RETURN_OK;
8057}
8058
8059INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
8060{
8061 char config_file[64] = {0};
8062 char buf[64] = {0};
8063 char cmd[256] = {0};
8064
8065 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8066
8067 if(!IP_output || !Port_output || !RadiusSecret_output)
8068 return RETURN_ERR;
8069
8070 // Read the second matched config
8071 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
8072 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
8073 _syscmd(cmd, buf, sizeof(buf));
8074 strncpy(IP_output, buf, 64);
8075
8076 memset(buf, 0, sizeof(buf));
8077 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
8078 _syscmd(cmd, buf, sizeof(buf));
8079 *Port_output = atoi(buf);
8080
8081 memset(buf, 0, sizeof(buf));
8082 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
8083 _syscmd(cmd, buf, sizeof(buf));
8084 strncpy(RadiusSecret_output, buf, 64);
8085
8086 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8087 return RETURN_OK;
8088}
8089
8090INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
8091{
8092 char config_file[64] = {0};
8093 char port_str[8] = {0};
8094 char cmd[256] = {0};
8095 char buf[128] = {0};
8096
8097 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8098
developere5750452023-05-15 16:46:42 +08008099 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
8100 return RETURN_ERR;
8101
8102 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
8103 return RETURN_ERR;
8104
developer72fb0bb2023-01-11 09:46:29 +08008105 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
8106
8107 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
8108 _syscmd(cmd, buf, sizeof(buf));
8109 memset(cmd, 0, sizeof(cmd));
8110
8111 snprintf(port_str, sizeof(port_str), "%d", port);
8112 if (strlen(buf) == 0)
8113 // Append
8114 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
8115 "auth_server_addr=%s\\n"
8116 "auth_server_port=%s\\n"
8117 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
8118 else {
8119 // Delete the three lines setting after the "# radius 2" comment
8120 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
8121 _syscmd(cmd, buf, sizeof(buf));
8122 memset(cmd, 0, sizeof(cmd));
8123 // Use "# radius 2" comment to find the location to insert the radius setting
8124 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
8125 "# radius 2\\n"
8126 "auth_server_addr=%s\\n"
8127 "auth_server_port=%s\\n"
8128 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
8129 }
8130 if(_syscmd(cmd, buf, sizeof(buf))) {
8131 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
8132 return RETURN_ERR;
8133 }
8134
8135 wifi_reloadAp(apIndex);
8136 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8137 return RETURN_OK;
8138}
8139
8140//RadiusSettings
8141INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
8142{
8143 if(!output)
8144 return RETURN_ERR;
8145
8146 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
developer69b61b02023-03-07 17:17:44 +08008147 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
8148 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
8149 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
8150 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 +08008151 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 +08008152 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
8153 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
8154 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 +08008155 //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.
8156
8157 return RETURN_OK;
8158}
8159
8160INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
8161{
8162 //store the paramters, and apply instantly
8163 return RETURN_ERR;
8164}
8165
8166//Device.WiFi.AccessPoint.{i}.WPS.Enable
8167//Enables or disables WPS functionality for this access point.
8168// outputs the WPS enable state of this ap in output_bool
8169INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
8170{
8171 char interface_name[16] = {0};
8172 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
8173 if(!output_bool)
8174 return RETURN_ERR;
8175 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8176 return RETURN_ERR;
8177 sprintf(cmd,"hostapd_cli -i %s get_config | grep wps_state | cut -d '=' -f2", interface_name);
8178 _syscmd(cmd, buf, sizeof(buf));
8179 if(strstr(buf, "configured"))
8180 *output_bool=TRUE;
8181 else
8182 *output_bool=FALSE;
8183
8184 return RETURN_OK;
developer69b61b02023-03-07 17:17:44 +08008185}
developer72fb0bb2023-01-11 09:46:29 +08008186
8187//Device.WiFi.AccessPoint.{i}.WPS.Enable
8188// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
8189INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
8190{
8191 char config_file[MAX_BUF_SIZE] = {0};
developere5750452023-05-15 16:46:42 +08008192 char buf[128] = {0};
developer72fb0bb2023-01-11 09:46:29 +08008193 struct params params;
8194
8195 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8196 //store the paramters, and wait for wifi up to apply
8197 params.name = "wps_state";
developere5750452023-05-15 16:46:42 +08008198 if (enable == TRUE) {
8199 wifi_getApBeaconType(apIndex, buf);
8200 if (strncmp(buf, "None", 4) == 0) // If ap didn't set encryption
8201 params.value = "1";
8202 else // If ap set encryption
8203 params.value = "2";
8204 } else {
8205 params.value = "0";
8206 }
developer72fb0bb2023-01-11 09:46:29 +08008207
8208 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
8209 wifi_hostapdWrite(config_file, &params, 1);
8210 wifi_hostapdProcessUpdate(apIndex, &params, 1);
8211 wifi_reloadAp(apIndex);
8212
8213 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8214 return RETURN_OK;
8215}
8216
8217//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
8218INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
8219{
8220 if(!output)
8221 return RETURN_ERR;
8222 snprintf(output, 128, "PushButton,PIN");
8223 return RETURN_OK;
8224}
8225
8226//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
8227//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.
8228// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
8229INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
8230{
8231 if(!output)
8232 return RETURN_ERR;
8233 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
8234
8235 return RETURN_OK;
8236}
8237
8238//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
8239// 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
8240INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
8241{
8242 //apply instantly. No setting need to be stored.
8243 char methods[MAX_BUF_SIZE], *token, *next_token;
8244 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
8245 struct params params;
8246
8247 if(!methodString)
8248 return RETURN_ERR;
8249 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8250 //store the paramters, and wait for wifi up to apply
8251
8252 snprintf(methods, sizeof(methods), "%s", methodString);
8253 for(token=methods; *token; token=next_token)
8254 {
8255 strtok_r(token, ",", &next_token);
8256 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
8257 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
8258 else if(*token=='E')
8259 {
8260 if(!strcmp(methods, "Ethernet"))
8261 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
8262 else if(!strcmp(methods, "ExternalNFCToken"))
8263 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
8264 else
8265 printf("%s: Unknown WpsConfigMethod\n", __func__);
8266 }
8267 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
8268 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
8269 else if(*token=='N' && !strcmp(token, "NFCInterface"))
8270 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
8271 else if(*token=='P' )
8272 {
8273 if(!strcmp(token, "PushButton"))
developere5750452023-05-15 16:46:42 +08008274 snprintf(config_methods, sizeof(config_methods), "%s ", "push_button");
developer72fb0bb2023-01-11 09:46:29 +08008275 else if(!strcmp(token, "PIN"))
8276 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
8277 else
8278 printf("%s: Unknown WpsConfigMethod\n", __func__);
8279 }
8280 else
8281 printf("%s: Unknown WpsConfigMethod\n", __func__);
8282 }
8283 params.name = "config_methods";
8284 params.value = config_methods;
8285 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
8286 wifi_hostapdWrite(config_file, &params, 1);
8287 wifi_hostapdProcessUpdate(apIndex, &params, 1);
8288 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8289
8290 return RETURN_OK;
8291}
8292
8293// outputs the pin value, ulong_pin must be allocated by the caller
8294INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
8295{
8296 char buf[MAX_BUF_SIZE] = {0};
8297 char cmd[MAX_CMD_SIZE] = {0};
8298
8299 if(!output_ulong)
8300 return RETURN_ERR;
8301 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
8302 _syscmd(cmd, buf, sizeof(buf));
8303 if(strlen(buf) > 0)
8304 *output_ulong=strtoul(buf, NULL, 10);
8305
8306 return RETURN_OK;
8307}
8308
8309// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
8310INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
8311{
8312 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
8313 char ap_pin[16] = {0};
8314 char buf[MAX_BUF_SIZE] = {0};
8315 char config_file[MAX_BUF_SIZE] = {0};
8316 ULONG prev_pin = 0;
8317 struct params params;
8318
8319 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8320 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
8321 params.name = "ap_pin";
8322 params.value = ap_pin;
8323 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
8324 wifi_hostapdWrite(config_file, &params, 1);
8325 wifi_hostapdProcessUpdate(apIndex, &params, 1);
8326 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8327
8328 return RETURN_OK;
8329}
8330
8331// Output string is either Not configured or Configured, max 32 characters
8332INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
8333{
8334 char interface_name[16] = {0};
8335 char cmd[MAX_CMD_SIZE];
8336 char buf[MAX_BUF_SIZE]={0};
8337
8338 if(!output_string)
8339 return RETURN_ERR;
8340 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8341 snprintf(output_string, 32, "Not configured");
8342 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8343 return RETURN_ERR;
8344 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep wps_state | cut -d'=' -f2", interface_name);
8345 _syscmd(cmd, buf, sizeof(buf));
8346
8347 if(!strncmp(buf, "configured", 10))
8348 snprintf(output_string, 32, "Configured");
8349 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8350
8351 return RETURN_OK;
8352}
8353
8354// sets the WPS pin for this AP
8355INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
8356{
8357 char interface_name[16] = {0};
8358 char cmd[MAX_CMD_SIZE];
8359 char buf[MAX_BUF_SIZE]={0};
8360 BOOL enable;
8361
8362 wifi_getApEnable(apIndex, &enable);
8363 if (!enable)
8364 return RETURN_ERR;
8365 wifi_getApWpsEnable(apIndex, &enable);
8366 if (!enable)
8367 return RETURN_ERR;
8368
8369 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8370 return RETURN_ERR;
8371 snprintf(cmd, 64, "hostapd_cli -i%s wps_pin any %s", interface_name, pin);
8372 _syscmd(cmd, buf, sizeof(buf));
8373 if((strstr(buf, "OK"))!=NULL)
8374 return RETURN_OK;
8375
8376 return RETURN_ERR;
8377}
8378
8379// This function is called when the WPS push button has been pressed for this AP
8380INT wifi_setApWpsButtonPush(INT apIndex)
8381{
8382 char cmd[MAX_CMD_SIZE];
8383 char buf[MAX_BUF_SIZE]={0};
8384 char interface_name[16] = {0};
8385 BOOL enable=FALSE;
8386
8387 wifi_getApEnable(apIndex, &enable);
8388 if (!enable)
8389 return RETURN_ERR;
8390
8391 wifi_getApWpsEnable(apIndex, &enable);
8392 if (!enable)
8393 return RETURN_ERR;
8394
8395 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8396 return RETURN_ERR;
8397
8398 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel; hostapd_cli -i%s wps_pbc", interface_name, interface_name);
8399 _syscmd(cmd, buf, sizeof(buf));
8400
8401 if((strstr(buf, "OK"))!=NULL)
8402 return RETURN_OK;
8403 return RETURN_ERR;
8404}
8405
8406// cancels WPS mode for this AP
8407INT wifi_cancelApWPS(INT apIndex)
8408{
8409 char interface_name[16] = {0};
8410 char cmd[MAX_CMD_SIZE];
8411 char buf[MAX_BUF_SIZE]={0};
8412
8413 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8414 return RETURN_ERR;
8415 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel", interface_name);
8416 _syscmd(cmd,buf, sizeof(buf));
8417
8418 if((strstr(buf, "OK"))!=NULL)
8419 return RETURN_OK;
8420 return RETURN_ERR;
8421}
8422
8423//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
8424//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
8425INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
8426{
8427 char interface_name[16] = {0};
8428 FILE *f = NULL;
8429 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
8430 char cmd[256] = {0}, buf[2048] = {0};
8431 char *param = NULL, *value = NULL, *line=NULL;
8432 size_t len = 0;
8433 ssize_t nread = 0;
8434 wifi_associated_dev_t *dev=NULL;
8435
8436 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8437 *associated_dev_array = NULL;
8438 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8439 return RETURN_ERR;
8440 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
8441 _syscmd(cmd,buf,sizeof(buf));
8442 *output_array_size = atoi(buf);
8443
8444 if (*output_array_size <= 0)
8445 return RETURN_OK;
8446
8447 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
8448 *associated_dev_array = dev;
8449 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt" , interface_name);
8450 _syscmd(cmd,buf,sizeof(buf));
8451 f = fopen("/tmp/connected_devices.txt", "r");
8452 if (f==NULL)
8453 {
8454 *output_array_size=0;
8455 return RETURN_ERR;
8456 }
8457 while ((getline(&line, &len, f)) != -1)
8458 {
8459 param = strtok(line,"=");
8460 value = strtok(NULL,"=");
8461
8462 if( strcmp("flags",param) == 0 )
8463 {
8464 value[strlen(value)-1]='\0';
8465 if(strstr (value,"AUTHORIZED") != NULL )
8466 {
8467 dev[auth_temp].cli_AuthenticationState = 1;
8468 dev[auth_temp].cli_Active = 1;
8469 auth_temp++;
8470 read_flag=1;
8471 }
8472 }
8473 if(read_flag==1)
8474 {
8475 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
8476 {
8477 value[strlen(value)-1]='\0';
8478 sscanf(value, "%x:%x:%x:%x:%x:%x",
8479 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
8480 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
8481 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
8482 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
8483 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
8484 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
8485 mac_temp++;
8486 read_flag=0;
8487 }
8488 }
8489 }
8490 *output_array_size = auth_temp;
8491 auth_temp=0;
8492 mac_temp=0;
8493 free(line);
8494 fclose(f);
8495 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8496 return RETURN_OK;
8497}
8498
8499#define MACADDRESS_SIZE 6
8500
8501INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8502{
8503 FILE *fp = NULL;
8504 char str[MAX_BUF_SIZE] = {0};
8505 int wificlientindex = 0 ;
8506 int count = 0;
8507 int signalstrength = 0;
8508 int arr[MACADDRESS_SIZE] = {0};
8509 unsigned char mac[MACADDRESS_SIZE] = {0};
8510 UINT wifi_count = 0;
8511 char virtual_interface_name[MAX_BUF_SIZE] = {0};
8512 char pipeCmd[MAX_CMD_SIZE] = {0};
8513
8514 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8515 *output_array_size = 0;
8516 *associated_dev_array = NULL;
8517
8518 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
8519 fp = popen(pipeCmd, "r");
developer69b61b02023-03-07 17:17:44 +08008520 if (fp == NULL)
developer72fb0bb2023-01-11 09:46:29 +08008521 {
8522 printf("Failed to run command inside function %s\n",__FUNCTION__ );
8523 return RETURN_ERR;
8524 }
8525
8526 /* Read the output a line at a time - output it. */
8527 fgets(str, sizeof(str)-1, fp);
8528 wifi_count = (unsigned int) atoi ( str );
8529 *output_array_size = wifi_count;
8530 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
8531 pclose(fp);
8532
8533 if(wifi_count == 0)
8534 {
8535 return RETURN_OK;
8536 }
8537 else
8538 {
8539 wifi_associated_dev3_t* temp = NULL;
8540 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
8541 if(temp == NULL)
8542 {
8543 printf("Error Statement. Insufficient memory \n");
8544 return RETURN_ERR;
8545 }
8546
8547 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
8548 system(pipeCmd);
8549 memset(pipeCmd,0,sizeof(pipeCmd));
8550 if(apIndex == 0)
8551 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
8552 else if(apIndex == 1)
8553 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
8554 system(pipeCmd);
8555
8556 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
8557 if(fp == NULL)
8558 {
8559 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
8560 free(temp);
8561 return RETURN_ERR;
8562 }
8563 fclose(fp);
8564
8565 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
8566 fp = popen(pipeCmd, "r");
8567 if(fp)
8568 {
8569 for(count =0 ; count < wifi_count; count++)
8570 {
8571 fgets(str, MAX_BUF_SIZE, fp);
8572 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8573 {
8574 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8575 {
8576 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8577
8578 }
8579 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8580 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]);
8581 }
8582 temp[count].cli_AuthenticationState = 1; //TODO
8583 temp[count].cli_Active = 1; //TODO
8584 }
8585 pclose(fp);
8586 }
8587
8588 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt");
8589 fp = popen(pipeCmd, "r");
8590 if(fp)
developer69b61b02023-03-07 17:17:44 +08008591 {
developer72fb0bb2023-01-11 09:46:29 +08008592 pclose(fp);
8593 }
8594 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
8595 if(fp)
8596 {
8597 for(count =0 ; count < wifi_count ;count++)
8598 {
8599 fgets(str, MAX_BUF_SIZE, fp);
8600 signalstrength = atoi(str);
8601 temp[count].cli_SignalStrength = signalstrength;
8602 temp[count].cli_RSSI = signalstrength;
8603 temp[count].cli_SNR = signalstrength + 95;
8604 }
8605 pclose(fp);
8606 }
8607
8608
8609 if((apIndex == 0) || (apIndex == 4))
8610 {
8611 for(count =0 ; count < wifi_count ;count++)
developer69b61b02023-03-07 17:17:44 +08008612 {
developer72fb0bb2023-01-11 09:46:29 +08008613 strcpy(temp[count].cli_OperatingStandard,"g");
8614 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
8615 }
8616
8617 //BytesSent
8618 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt");
8619 fp = popen(pipeCmd, "r");
8620 if(fp)
developer69b61b02023-03-07 17:17:44 +08008621 {
developer72fb0bb2023-01-11 09:46:29 +08008622 pclose(fp);
8623 }
8624 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
8625 if(fp)
8626 {
8627 for (count = 0; count < wifi_count; count++)
8628 {
8629 fgets(str, MAX_BUF_SIZE, fp);
8630 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
8631 }
8632 pclose(fp);
8633 }
8634
8635 //BytesReceived
8636 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt");
8637 fp = popen(pipeCmd, "r");
8638 if (fp)
8639 {
8640 pclose(fp);
8641 }
8642 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
8643 if (fp)
8644 {
8645 for (count = 0; count < wifi_count; count++)
8646 {
8647 fgets(str, MAX_BUF_SIZE, fp);
8648 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
8649 }
8650 pclose(fp);
8651 }
8652
8653 //PacketsSent
8654 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt");
8655 fp = popen(pipeCmd, "r");
8656 if (fp)
8657 {
8658 pclose(fp);
8659 }
8660
8661 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
8662 if (fp)
8663 {
8664 for (count = 0; count < wifi_count; count++)
8665 {
8666 fgets(str, MAX_BUF_SIZE, fp);
8667 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
8668 }
8669 pclose(fp);
8670 }
8671
8672 //PacketsReceived
8673 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt");
8674 fp = popen(pipeCmd, "r");
8675 if (fp)
8676 {
8677 pclose(fp);
8678 }
8679 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
8680 if (fp)
8681 {
8682 for (count = 0; count < wifi_count; count++)
8683 {
8684 fgets(str, MAX_BUF_SIZE, fp);
8685 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
8686 }
8687 pclose(fp);
8688 }
8689
8690 //ErrorsSent
8691 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt");
8692 fp = popen(pipeCmd, "r");
8693 if (fp)
8694 {
8695 pclose(fp);
8696 }
8697 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
8698 if (fp)
8699 {
8700 for (count = 0; count < wifi_count; count++)
8701 {
8702 fgets(str, MAX_BUF_SIZE, fp);
8703 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
8704 }
8705 pclose(fp);
8706 }
8707
8708 //ErrorsSent
8709 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt");
8710 fp = popen(pipeCmd, "r");
8711 if (fp)
8712 {
8713 pclose(fp);
8714 }
8715 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
8716 if (fp)
8717 {
8718 for (count = 0; count < wifi_count; count++)
8719 {
8720 fgets(str, MAX_BUF_SIZE, fp);
8721 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
8722 }
8723 pclose(fp);
8724 }
8725
8726 //LastDataDownlinkRate
8727 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt");
8728 fp = popen(pipeCmd, "r");
8729 if (fp)
8730 {
8731 pclose(fp);
8732 }
8733 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
8734 if (fp)
8735 {
8736 for (count = 0; count < wifi_count; count++)
8737 {
8738 fgets(str, MAX_BUF_SIZE, fp);
8739 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
8740 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
8741 }
8742 pclose(fp);
8743 }
8744
8745 //LastDataUplinkRate
8746 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt");
8747 fp = popen(pipeCmd, "r");
8748 if (fp)
8749 {
8750 pclose(fp);
8751 }
8752 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
8753 if (fp)
8754 {
8755 for (count = 0; count < wifi_count; count++)
8756 {
8757 fgets(str, MAX_BUF_SIZE, fp);
8758 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
8759 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
8760 }
8761 pclose(fp);
8762 }
8763
8764 }
8765 else if ((apIndex == 1) || (apIndex == 5))
8766 {
8767 for (count = 0; count < wifi_count; count++)
8768 {
8769 strcpy(temp[count].cli_OperatingStandard, "a");
8770 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
8771 temp[count].cli_BytesSent = 0;
8772 temp[count].cli_BytesReceived = 0;
8773 temp[count].cli_LastDataUplinkRate = 0;
8774 temp[count].cli_LastDataDownlinkRate = 0;
8775 temp[count].cli_PacketsSent = 0;
8776 temp[count].cli_PacketsReceived = 0;
8777 temp[count].cli_ErrorsSent = 0;
8778 }
8779 }
8780
8781 for (count = 0; count < wifi_count; count++)
8782 {
8783 temp[count].cli_Retransmissions = 0;
8784 temp[count].cli_DataFramesSentAck = 0;
8785 temp[count].cli_DataFramesSentNoAck = 0;
8786 temp[count].cli_MinRSSI = 0;
8787 temp[count].cli_MaxRSSI = 0;
8788 strncpy(temp[count].cli_InterferenceSources, "", 64);
8789 memset(temp[count].cli_IPAddress, 0, 64);
8790 temp[count].cli_RetransCount = 0;
8791 temp[count].cli_FailedRetransCount = 0;
8792 temp[count].cli_RetryCount = 0;
8793 temp[count].cli_MultipleRetryCount = 0;
8794 }
8795 *associated_dev_array = temp;
8796 }
8797 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8798 return RETURN_OK;
8799}
8800
developer7e4a2a62023-04-06 19:56:03 +08008801int wifihal_interfacestatus(CHAR *wifi_status, CHAR *interface_name)
developer72fb0bb2023-01-11 09:46:29 +08008802{
developer7e4a2a62023-04-06 19:56:03 +08008803 char cmd[MAX_CMD_SIZE] = {0};
8804 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08008805
developer7e4a2a62023-04-06 19:56:03 +08008806 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
8807
8808 snprintf(cmd, MAX_CMD_SIZE, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4 | tr -d '\\n'",
8809 interface_name);
8810 _syscmd(cmd, buf, MAX_BUF_SIZE);
8811
8812 strcpy(wifi_status, buf); /* TBD: check wifi_status mem lenth and replace with strcpy later */
8813
8814 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08008815 return RETURN_OK;
8816}
8817
8818/* #define HOSTAPD_STA_PARAM_ENTRIES 29
8819struct hostapd_sta_param {
8820 char key[50];
8821 char value[100];
8822}
8823
8824static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
8825 int i = 0;
8826
8827 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
8828 if (strncmp(params[i].key,key,50) == 0){
8829 return &params[i].value;
8830 }
8831 i++;
8832 }
8833 return NULL;
8834
8835} */
8836
8837static unsigned int count_occurences(const char *buf, const char *word)
8838{
8839 unsigned int n = 0;
8840 char *ptr = strstr(buf, word);
8841
8842 while (ptr++) {
8843 n++;
8844 ptr = strstr(ptr, word);
8845 }
8846
8847 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
8848 return n;
8849}
8850
8851static const char *get_line_from_str_buf(const char *buf, char *line)
8852{
8853 int i;
8854 int n = strlen(buf);
8855
8856 for (i = 0; i < n; i++) {
8857 line[i] = buf[i];
8858 if (buf[i] == '\n') {
8859 line[i] = '\0';
8860 return &buf[i + 1];
8861 }
8862 }
8863
8864 return NULL;
8865}
8866
8867INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8868{
8869 unsigned int assoc_cnt = 0;
8870 char interface_name[50] = {0};
8871 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
8872 char cmd[MAX_CMD_SIZE] = {'\0'};
8873 char line[256] = {'\0'};
8874 int i = 0;
8875 int ret = 0;
8876 const char *ptr = NULL;
8877 char *key = NULL;
8878 char *val = NULL;
8879 wifi_associated_dev3_t *temp = NULL;
8880 int rssi;
8881
8882 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8883
8884 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8885 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8886 return RETURN_ERR;
8887 }
8888
8889 // Example filtered output of 'iw dev' command:
8890 // Station 0a:69:72:10:d2:fa (on wifi0)
8891 // signal avg:-67 [-71, -71] dBm
8892 // Station 28:c2:1f:25:5f:99 (on wifi0)
8893 // signal avg:-67 [-71, -70] dBm
8894 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
8895 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
8896 return RETURN_ERR;
8897 }
8898
8899 ret = _syscmd(cmd, buf, sizeof(buf));
8900 if (ret == RETURN_ERR) {
8901 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
8902 return RETURN_ERR;
8903 }
8904
8905 *output_array_size = count_occurences(buf, "Station");
8906 if (*output_array_size == 0) return RETURN_OK;
8907
8908 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
8909 if (temp == NULL) {
8910 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
8911 return RETURN_ERR;
8912 }
8913 *associated_dev_array = temp;
8914
8915 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
8916 ptr = get_line_from_str_buf(buf, line);
8917 i = -1;
8918 while (ptr) {
8919 if (strstr(line, "Station")) {
8920 i++;
8921 key = strtok(line, " ");
8922 val = strtok(NULL, " ");
8923 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
8924 &temp[i].cli_MACAddress[0],
8925 &temp[i].cli_MACAddress[1],
8926 &temp[i].cli_MACAddress[2],
8927 &temp[i].cli_MACAddress[3],
8928 &temp[i].cli_MACAddress[4],
8929 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
8930 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
8931 free(*associated_dev_array);
8932 return RETURN_ERR;
8933 }
8934 }
8935 else if (i < 0) {
8936 ptr = get_line_from_str_buf(ptr, line);
8937 continue; // We didn't detect 'station' entry yet
8938 }
8939 else if (strstr(line, "signal avg")) {
8940 key = strtok(line, ":");
8941 val = strtok(NULL, " ");
8942 if (sscanf(val, "%d", &rssi) <= 0 ) {
8943 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
8944 free(*associated_dev_array);
8945 return RETURN_ERR;
8946 }
8947 temp[i].cli_RSSI = rssi;
8948 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
8949 }
8950 // Here other fields can be parsed if added to filter of 'iw dev' command
8951
8952 ptr = get_line_from_str_buf(ptr, line);
8953 };
8954
8955 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8956
8957 return RETURN_OK;
8958}
8959
8960#if 0
8961//To-do
8962INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8963{
8964 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8965
8966 //Using different approach to get required WiFi Parameters from system available commands
developer69b61b02023-03-07 17:17:44 +08008967#if 0
developer72fb0bb2023-01-11 09:46:29 +08008968 FILE *f;
8969 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
8970 char cmd[256], buf[2048];
8971 char *param , *value, *line=NULL;
8972 size_t len = 0;
8973 ssize_t nread;
8974 wifi_associated_dev3_t *dev=NULL;
8975 *associated_dev_array = NULL;
8976 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
8977 _syscmd(cmd,buf,sizeof(buf));
8978 *output_array_size = atoi(buf);
8979
8980 if (*output_array_size <= 0)
8981 return RETURN_OK;
8982
8983 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
8984 *associated_dev_array = dev;
8985 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt", interface_name);
8986 _syscmd(cmd,buf,sizeof(buf));
8987 f = fopen("/tmp/connected_devices.txt", "r");
8988 if (f==NULL)
8989 {
8990 *output_array_size=0;
8991 return RETURN_ERR;
8992 }
8993 while ((nread = getline(&line, &len, f)) != -1)
8994 {
8995 param = strtok(line,"=");
8996 value = strtok(NULL,"=");
8997
8998 if( strcmp("flags",param) == 0 )
8999 {
9000 value[strlen(value)-1]='\0';
9001 if(strstr (value,"AUTHORIZED") != NULL )
9002 {
9003 dev[auth_temp].cli_AuthenticationState = 1;
9004 dev[auth_temp].cli_Active = 1;
9005 auth_temp++;
9006 read_flag=1;
9007 }
9008 }
9009 if(read_flag==1)
9010 {
9011 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
9012 {
9013 value[strlen(value)-1]='\0';
9014 sscanf(value, "%x:%x:%x:%x:%x:%x",
9015 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
9016 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
9017 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
9018 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
9019 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
9020 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
9021
9022 }
9023 else if( strcmp("rx_packets",param) == 0 )
9024 {
9025 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
9026 }
9027
9028 else if( strcmp("tx_packets",param) == 0 )
9029 {
developer69b61b02023-03-07 17:17:44 +08009030 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
developer72fb0bb2023-01-11 09:46:29 +08009031 }
9032
9033 else if( strcmp("rx_bytes",param) == 0 )
9034 {
9035 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
9036 }
9037
9038 else if( strcmp("tx_bytes",param) == 0 )
9039 {
developer69b61b02023-03-07 17:17:44 +08009040 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
developer72fb0bb2023-01-11 09:46:29 +08009041 mac_temp++;
9042 read_flag=0;
developer69b61b02023-03-07 17:17:44 +08009043 }
developer72fb0bb2023-01-11 09:46:29 +08009044 }
9045 }
9046
9047 *output_array_size = auth_temp;
9048 auth_temp=0;
9049 mac_temp=0;
9050 free(line);
9051 fclose(f);
9052#endif
9053 char interface_name[MAX_BUF_SIZE] = {0};
9054 char wifi_status[MAX_BUF_SIZE] = {0};
9055 char hostapdconf[MAX_BUF_SIZE] = {0};
9056
9057 wifi_associated_dev3_t *dev_array = NULL;
9058 ULONG wifi_count = 0;
9059
9060 *associated_dev_array = NULL;
9061 *output_array_size = 0;
9062
9063 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
9064 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
9065 {
9066 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
9067
9068 wifi_GetInterfaceName(interface_name, hostapdconf);
9069
9070 if(strlen(interface_name) > 1)
9071 {
9072 wifihal_interfacestatus(wifi_status,interface_name);
9073 if(strcmp(wifi_status,"RUNNING") == 0)
9074 {
9075 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
9076
9077 *associated_dev_array = dev_array;
developer69b61b02023-03-07 17:17:44 +08009078 *output_array_size = wifi_count;
developer72fb0bb2023-01-11 09:46:29 +08009079 }
9080 else
9081 {
9082 *associated_dev_array = NULL;
9083 }
9084 }
9085 }
9086
9087 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9088 return RETURN_OK;
9089}
9090#endif
9091
9092/* getIPAddress function */
9093/**
9094* @description Returning IpAddress of the Matched String
9095*
developer69b61b02023-03-07 17:17:44 +08009096* @param
developer72fb0bb2023-01-11 09:46:29 +08009097* @str Having MacAddress
developer69b61b02023-03-07 17:17:44 +08009098* @ipaddr Having ipaddr
developer72fb0bb2023-01-11 09:46:29 +08009099* @return The status of the operation
9100* @retval RETURN_OK if successful
9101* @retval RETURN_ERR if any error is detected
9102*
9103*/
9104
9105INT getIPAddress(char *str,char *ipaddr)
9106{
9107 FILE *fp = NULL;
9108 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
9109 int LeaseTime = 0,ret = 0;
9110 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
9111 {
9112 return RETURN_ERR;
9113 }
9114
9115 while ( fgets(buf, sizeof(buf), fp)!= NULL )
9116 {
9117 /*
9118 Sample:sss
9119 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
9120 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
9121 */
9122 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
9123 &(LeaseTime),
9124 phyAddr,
9125 ipAddr,
9126 hostName
9127 );
9128 if(ret != 4)
9129 continue;
9130 if(strcmp(str,phyAddr) == 0)
9131 strcpy(ipaddr,ipAddr);
9132 }
9133 fclose(fp);
9134 return RETURN_OK;
9135}
9136
9137/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
9138/**
9139* @description Returning Inactive wireless connected clients informations
9140*
developer69b61b02023-03-07 17:17:44 +08009141* @param
developer72fb0bb2023-01-11 09:46:29 +08009142* @filename Holding private_wifi 2g/5g content files
9143* @associated_dev_array Having inactiv wireless clients informations
9144* @output_array_size Returning Inactive wireless counts
9145* @return The status of the operation
9146* @retval RETURN_OK if successful
9147* @retval RETURN_ERR if any error is detected
9148*
9149*/
9150
9151INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
9152{
9153 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9154 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
9155 FILE *fp = NULL;
9156 int arr[MACADDRESS_SIZE] = {0};
9157 unsigned char mac[MACADDRESS_SIZE] = {0};
9158 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
9159 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
9160 fp = popen(buf,"r");
9161 if(fp == NULL)
9162 return RETURN_ERR;
9163 else
9164 {
9165 fgets(path,sizeof(path),fp);
9166 maccount = atoi(path);
9167 }
9168 pclose(fp);
9169 *output_array_size = maccount;
9170 wifi_associated_dev3_t* temp = NULL;
9171 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
9172 *associated_dev_array = temp;
9173 if(temp == NULL)
9174 {
9175 printf("Error Statement. Insufficient memory \n");
9176 return RETURN_ERR;
9177 }
9178 memset(buf,0,sizeof(buf));
9179 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
9180 fp = popen(buf,"r");
9181 if (fp == NULL) {
9182 fprintf(stderr, "%s: failed pipe command %s.\n", __func__, buf);
9183 return RETURN_ERR;
9184 }
9185 for(count = 0; count < maccount ; count++)
9186 {
9187 fgets(path,sizeof(path),fp);
9188 for(i = 0; path[i]!='\n';i++)
9189 str[i]=path[i];
9190 str[i]='\0';
9191 getIPAddress(str,ipaddr);
9192 memset(buf,0,sizeof(buf));
9193 if(strlen(ipaddr) > 0)
9194 {
9195 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
9196 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
9197 {
9198 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
9199 {
9200 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
9201 {
9202 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
9203
9204 }
9205 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
9206 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]);
9207 }
9208 temp[count].cli_AuthenticationState = 0; //TODO
developer69b61b02023-03-07 17:17:44 +08009209 temp[count].cli_Active = 0; //TODO
developer72fb0bb2023-01-11 09:46:29 +08009210 temp[count].cli_SignalStrength = 0;
9211 }
9212 else //Active wireless clients info
9213 {
9214 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
9215 {
9216 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
9217 {
9218 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
9219
9220 }
9221 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
9222 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]);
9223 }
9224 temp[count].cli_Active = 1;
9225 }
9226 }
9227 memset(ipaddr,0,sizeof(ipaddr));
9228 }
9229 pclose(fp);
9230 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9231 return RETURN_OK;
9232}
9233//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
9234//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
9235//To get Band Steering Capability
9236INT wifi_getBandSteeringCapability(BOOL *support)
9237{
9238 *support = FALSE;
9239 return RETURN_OK;
9240}
9241
9242
9243//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
9244//To get Band Steering enable status
9245INT wifi_getBandSteeringEnable(BOOL *enable)
9246{
9247 *enable = FALSE;
9248 return RETURN_OK;
9249}
9250
9251//To turn on/off Band steering
9252INT wifi_setBandSteeringEnable(BOOL enable)
9253{
9254 return RETURN_OK;
9255}
9256
9257//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
9258//To get Band Steering AP group
9259INT wifi_getBandSteeringApGroup(char *output_ApGroup)
9260{
9261 if (NULL == output_ApGroup)
9262 return RETURN_ERR;
9263
9264 strcpy(output_ApGroup, "1,2");
9265 return RETURN_OK;
9266}
9267
9268//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
9269//to set and read the band steering BandUtilizationThreshold parameters
9270INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
9271{
9272 return RETURN_ERR;
9273}
9274
9275INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
9276{
9277 return RETURN_ERR;
9278}
9279
9280//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
9281//to set and read the band steering RSSIThreshold parameters
9282INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
9283{
9284 return RETURN_ERR;
9285}
9286
9287INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
9288{
9289 return RETURN_ERR;
9290}
9291
9292
9293//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
9294//to set and read the band steering physical modulation rate threshold parameters
9295INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
9296{
9297 //If chip is not support, return -1
9298 return RETURN_ERR;
9299}
9300
9301INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
9302{
9303 //If chip is not support, return -1
9304 return RETURN_ERR;
9305}
9306
9307//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
9308//to set and read the inactivity time (in seconds) for steering under overload condition
9309INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
9310{
9311 return RETURN_ERR;
9312}
9313
9314INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
9315{
9316 return RETURN_ERR;
9317}
9318
9319//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
9320//to set and read the inactivity time (in seconds) for steering under Idle condition
9321INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
9322{
9323 return RETURN_ERR;
9324}
9325
9326INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
9327{
9328 return RETURN_ERR;
9329}
9330
9331//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
9332//pClientMAC[64]
9333//pSourceSSIDIndex[64]
9334//pDestSSIDIndex[64]
9335//pSteeringReason[256]
9336INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
9337{
9338 //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
9339 *pSteeringTime=time(NULL);
9340 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
9341 return RETURN_OK;
9342}
9343
9344INT wifi_ifConfigDown(INT apIndex)
9345{
9346 INT status = RETURN_OK;
9347 char cmd[64];
9348
9349 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
9350 printf("%s: %s\n", __func__, cmd);
9351 system(cmd);
9352
9353 return status;
9354}
9355
9356INT wifi_ifConfigUp(INT apIndex)
9357{
9358 char interface_name[16] = {0};
9359 char cmd[128];
9360 char buf[1024];
9361
9362 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9363 return RETURN_ERR;
9364 snprintf(cmd, sizeof(cmd), "ifconfig %s up 2>/dev/null", interface_name);
9365 _syscmd(cmd, buf, sizeof(buf));
9366 return 0;
9367}
9368
9369//>> Deprecated. Replace with wifi_applyRadioSettings
9370INT wifi_pushBridgeInfo(INT apIndex)
9371{
9372 char interface_name[16] = {0};
9373 char ip[32] = {0};
9374 char subnet[32] = {0};
9375 char bridge[32] = {0};
9376 int vlanId = 0;
9377 char cmd[128] = {0};
9378 char buf[1024] = {0};
9379
9380 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
9381 wifi_getApVlanID(apIndex,&vlanId);
9382
9383 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9384 return RETURN_ERR;
9385 snprintf(cmd, sizeof(cmd), "cfgVlan %s %s %d %s ", interface_name, bridge, vlanId, ip);
9386 _syscmd(cmd,buf, sizeof(buf));
9387
9388 return 0;
9389}
9390
9391INT wifi_pushChannel(INT radioIndex, UINT channel)
9392{
9393 char interface_name[16] = {0};
9394 char cmd[128];
9395 char buf[1024];
9396 int apIndex;
9397
developer69b61b02023-03-07 17:17:44 +08009398 apIndex=(radioIndex==0)?0:1;
developer72fb0bb2023-01-11 09:46:29 +08009399 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
9400 return RETURN_ERR;
9401 snprintf(cmd, sizeof(cmd), "iwconfig %s freq %d",interface_name,channel);
9402 _syscmd(cmd,buf, sizeof(buf));
9403
9404 return 0;
9405}
9406
9407INT wifi_pushChannelMode(INT radioIndex)
9408{
9409 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
9410 return RETURN_ERR;
9411}
9412
9413INT wifi_pushDefaultValues(INT radioIndex)
9414{
9415 //Apply Comcast specified default radio settings instantly
9416 //AMPDU=1
9417 //AMPDUFrames=32
9418 //AMPDULim=50000
9419 //txqueuelen=1000
9420
9421 return RETURN_ERR;
9422}
9423
9424INT wifi_pushTxChainMask(INT radioIndex)
9425{
9426 //Apply default TxChainMask instantly
9427 return RETURN_ERR;
9428}
9429
9430INT wifi_pushRxChainMask(INT radioIndex)
9431{
9432 //Apply default RxChainMask instantly
9433 return RETURN_ERR;
9434}
9435
9436INT wifi_pushSSID(INT apIndex, CHAR *ssid)
9437{
developer7e4a2a62023-04-06 19:56:03 +08009438 INT status;
developer72fb0bb2023-01-11 09:46:29 +08009439
developer7e4a2a62023-04-06 19:56:03 +08009440 status = wifi_setSSIDName(apIndex, ssid);
9441 wifi_quick_reload_ap(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08009442
developer7e4a2a62023-04-06 19:56:03 +08009443 return status;
developer72fb0bb2023-01-11 09:46:29 +08009444}
9445
9446INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
9447{
9448 //Apply default Ssid Advertisement instantly
9449 return RETURN_ERR;
9450}
9451
9452INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
9453{
developere82c0ca2023-05-10 16:25:35 +08009454 time_t now;
9455
9456 time(&now);
9457 if (now > radio_up_time[radioIndex])
9458 *output = now - radio_up_time[radioIndex];
9459 else {
9460 *output = 0;
9461 return RETURN_ERR;
9462 }
9463
9464 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08009465}
9466
9467INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
9468{
9469 return RETURN_OK;
9470}
9471
9472INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
9473{
9474 return RETURN_OK;
9475}
9476
9477//To-do
9478INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
9479{
9480 char output[16]={'\0'};
9481 char config_file[MAX_BUF_SIZE] = {0};
9482
9483 if (!output_string)
9484 return RETURN_ERR;
9485
9486 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
9487 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
9488
9489 if (strlen(output) == 0)
9490 snprintf(output_string, 64, "Disabled");
9491 else if (strncmp(output, "0", 1) == 0)
9492 snprintf(output_string, 64, "Disabled");
9493 else if (strncmp(output, "1", 1) == 0)
9494 snprintf(output_string, 64, "Optional");
9495 else if (strncmp(output, "2", 1) == 0)
9496 snprintf(output_string, 64, "Required");
9497 else {
9498 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
9499 return RETURN_ERR;
9500 }
9501
9502 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
9503 return RETURN_OK;
9504}
9505INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
9506{
9507 char str[MAX_BUF_SIZE]={'\0'};
9508 char cmd[MAX_CMD_SIZE]={'\0'};
9509 struct params params;
9510 char config_file[MAX_BUF_SIZE] = {0};
9511
9512 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9513 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
9514 return RETURN_ERR;
9515
9516 params.name = "ieee80211w";
9517 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
9518 params.value = "0";
9519 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
9520 params.value = "1";
9521 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
9522 params.value = "2";
9523 else{
9524 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
9525 return RETURN_ERR;
9526 }
9527 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
9528 wifi_hostapdWrite(config_file, &params, 1);
9529 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
9530 return RETURN_OK;
9531}
9532INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
9533{
9534 char output[16]={'\0'};
9535 char config_file[MAX_BUF_SIZE] = {0};
9536
9537 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developerc0772e62023-05-18 15:10:48 +08009538 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developerd1824452023-05-18 12:30:04 +08009539 wifi_datfileRead(config_file, "Channel" , output, sizeof(output));
developer72fb0bb2023-01-11 09:46:29 +08009540
9541 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
9542 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
9543
9544 return RETURN_OK;
9545}
9546
9547INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
9548{
9549 return RETURN_OK;
9550}
9551
9552INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
9553{
9554 return RETURN_OK;
9555}
9556
9557INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
9558{
9559 return RETURN_OK;
9560}
9561
9562INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
9563{
9564 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9565 char config_file[MAX_BUF_SIZE] = {0};
9566
9567 if (NULL == output)
9568 return RETURN_ERR;
9569 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
9570 wifi_hostapdRead(config_file,"hw_mode",output,64);
9571
9572 if(strcmp(output,"b")==0)
9573 sprintf(output, "%s", "1,2,5.5,11");
9574 else if (strcmp(output,"a")==0)
9575 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
9576 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
9577 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
9578
9579 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9580 return RETURN_OK;
9581}
9582
9583INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
9584{
9585 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9586 char *temp;
9587 char temp_output[128];
9588 char temp_TransmitRates[128];
9589 char config_file[MAX_BUF_SIZE] = {0};
9590
9591 if (NULL == output)
9592 return RETURN_ERR;
9593
9594 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
9595 wifi_hostapdRead(config_file,"supported_rates",output,64);
9596
9597 if (strlen(output) == 0) {
9598 wifi_getRadioSupportedDataTransmitRates(wlanIndex, output);
9599 return RETURN_OK;
9600 }
9601 strcpy(temp_TransmitRates,output);
9602 strcpy(temp_output,"");
9603 temp = strtok(temp_TransmitRates," ");
9604 while(temp!=NULL)
9605 {
9606 temp[strlen(temp)-1]=0;
9607 if((temp[0]=='5') && (temp[1]=='\0'))
9608 {
9609 temp="5.5";
9610 }
9611 strcat(temp_output,temp);
9612 temp = strtok(NULL," ");
9613 if(temp!=NULL)
9614 {
9615 strcat(temp_output,",");
9616 }
9617 }
9618 strcpy(output,temp_output);
9619 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9620
9621 return RETURN_OK;
9622}
9623
9624INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
9625{
9626 return RETURN_OK;
9627}
9628
9629
9630INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
9631{
9632 int i=0;
9633 char *temp;
9634 char temp1[128] = {0};
9635 char temp_output[128] = {0};
9636 char temp_TransmitRates[128] = {0};
9637 struct params params={'\0'};
9638 char config_file[MAX_BUF_SIZE] = {0};
9639 wifi_band band = wifi_index_to_band(wlanIndex);
9640
9641 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9642 if(NULL == output)
9643 return RETURN_ERR;
9644 strcpy(temp_TransmitRates,output);
9645
9646 for(i=0;i<strlen(temp_TransmitRates);i++)
9647 {
9648 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
9649 {
9650 continue;
9651 }
9652 else
9653 {
9654 return RETURN_ERR;
9655 }
9656 }
9657 strcpy(temp_output,"");
9658 temp = strtok(temp_TransmitRates,",");
9659 while(temp!=NULL)
9660 {
9661 strcpy(temp1,temp);
9662 if(band == band_5)
9663 {
9664 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
9665 {
9666 return RETURN_ERR;
9667 }
9668 }
9669
9670 if(strcmp(temp,"5.5")==0)
9671 {
9672 strcpy(temp1,"55");
9673 }
9674 else
9675 {
9676 strcat(temp1,"0");
9677 }
9678 strcat(temp_output,temp1);
9679 temp = strtok(NULL,",");
9680 if(temp!=NULL)
9681 {
9682 strcat(temp_output," ");
9683 }
9684 }
9685 strcpy(output,temp_output);
9686
9687 params.name = "supported_rates";
9688 params.value = output;
9689
9690 wifi_dbg_printf("\n%s:",__func__);
9691 wifi_dbg_printf("params.value=%s\n",params.value);
9692 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
9693 wifi_hostapdWrite(config_file,&params,1);
9694 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9695
9696 return RETURN_OK;
9697}
9698
9699
9700static char *sncopy(char *dst, int dst_sz, const char *src)
9701{
9702 if (src && dst && dst_sz > 0) {
9703 strncpy(dst, src, dst_sz);
9704 dst[dst_sz - 1] = '\0';
9705 }
9706 return dst;
9707}
9708
9709static int util_get_sec_chan_offset(int channel, const char* ht_mode)
9710{
9711 if (0 == strcmp(ht_mode, "HT40") ||
9712 0 == strcmp(ht_mode, "HT80") ||
9713 0 == strcmp(ht_mode, "HT160")) {
9714 switch (channel) {
9715 case 1 ... 7:
9716 case 36:
9717 case 44:
9718 case 52:
9719 case 60:
9720 case 100:
9721 case 108:
9722 case 116:
9723 case 124:
9724 case 132:
9725 case 140:
9726 case 149:
9727 case 157:
9728 return 1;
9729 case 8 ... 13:
9730 case 40:
9731 case 48:
9732 case 56:
9733 case 64:
9734 case 104:
9735 case 112:
9736 case 120:
9737 case 128:
9738 case 136:
9739 case 144:
9740 case 153:
9741 case 161:
9742 return -1;
9743 default:
9744 return -EINVAL;
9745 }
9746 }
9747
9748 return -EINVAL;
9749}
9750
9751static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
9752{
9753 int idx = channel%8;
9754 if (0 == strcmp(ht_mode, "HT40") ||
9755 0 == strcmp(ht_mode, "HT80") ||
9756 0 == strcmp(ht_mode, "HT160")) {
9757 switch (idx) {
9758 case 1:
9759 return 1;
9760 case 5:
9761 return -1;
9762 default:
9763 return -EINVAL;
9764 }
9765 }
9766
9767 return -EINVAL;
9768}
9769static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
9770{
9771 if (NULL == hw_mode) return;
9772
9773 if (0 == strcmp(hw_mode, "ac"))
9774 sncopy(bw_mode, bw_mode_len, "ht vht");
9775
9776 if (0 == strcmp(hw_mode, "n"))
9777 sncopy(bw_mode, bw_mode_len, "ht");
9778
9779 return;
9780}
9781
9782static int util_chan_to_freq(int chan)
9783{
9784 if (chan == 14)
9785 return 2484;
9786 else if (chan < 14)
9787 return 2407 + chan * 5;
9788 else if (chan >= 182 && chan <= 196)
9789 return 4000 + chan * 5;
9790 else
9791 return 5000 + chan * 5;
9792 return 0;
9793}
9794
9795static int util_6G_chan_to_freq(int chan)
9796{
9797 if (chan)
9798 return 5950 + chan * 5;
9799 else
9800 return 0;
developer69b61b02023-03-07 17:17:44 +08009801
developer72fb0bb2023-01-11 09:46:29 +08009802}
9803const int *util_unii_5g_chan2list(int chan, int width)
9804{
9805 static const int lists[] = {
9806 // <width>, <chan1>, <chan2>..., 0,
9807 20, 36, 0,
9808 20, 40, 0,
9809 20, 44, 0,
9810 20, 48, 0,
9811 20, 52, 0,
9812 20, 56, 0,
9813 20, 60, 0,
9814 20, 64, 0,
9815 20, 100, 0,
9816 20, 104, 0,
9817 20, 108, 0,
9818 20, 112, 0,
9819 20, 116, 0,
9820 20, 120, 0,
9821 20, 124, 0,
9822 20, 128, 0,
9823 20, 132, 0,
9824 20, 136, 0,
9825 20, 140, 0,
9826 20, 144, 0,
9827 20, 149, 0,
9828 20, 153, 0,
9829 20, 157, 0,
9830 20, 161, 0,
9831 20, 165, 0,
9832 40, 36, 40, 0,
9833 40, 44, 48, 0,
9834 40, 52, 56, 0,
9835 40, 60, 64, 0,
9836 40, 100, 104, 0,
9837 40, 108, 112, 0,
9838 40, 116, 120, 0,
9839 40, 124, 128, 0,
9840 40, 132, 136, 0,
9841 40, 140, 144, 0,
9842 40, 149, 153, 0,
9843 40, 157, 161, 0,
9844 80, 36, 40, 44, 48, 0,
9845 80, 52, 56, 60, 64, 0,
9846 80, 100, 104, 108, 112, 0,
9847 80, 116, 120, 124, 128, 0,
9848 80, 132, 136, 140, 144, 0,
9849 80, 149, 153, 157, 161, 0,
9850 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
9851 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
9852 -1 // final delimiter
9853 };
9854 const int *start;
9855 const int *p;
9856
9857 for (p = lists; *p != -1; p++) {
9858 if (*p == width) {
9859 for (start = ++p; *p != 0; p++) {
9860 if (*p == chan)
9861 return start;
9862 }
9863 }
9864 // move to the end of channel list of given width
9865 while (*p != 0) {
9866 p++;
9867 }
9868 }
9869
9870 return NULL;
9871}
9872
9873static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
9874{
9875 if (NULL == ht_mode)
9876 return 0;
9877
9878 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
9879 const int *chans = util_unii_5g_chan2list(channel, width);
9880 int sum = 0;
9881 int cnt = 0;
9882
9883 if (NULL == chans)
9884 return 0;
9885
9886 while (*chans) {
9887 sum += *chans;
9888 cnt++;
9889 chans++;
9890 }
9891 if (cnt == 0)
9892 return 0;
9893 return sum / cnt;
9894}
9895
9896static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
9897{
9898 if (NULL == ht_mode)
9899 return 0;
9900
9901 int width = strtol((ht_mode + 2), NULL, 10);
9902
9903 int idx = 0 ;
9904 int centerchan = 0;
9905 int chan_ofs = 1;
9906
9907 if (width == 40){
9908 idx = ((channel/4) + chan_ofs)%2;
9909 switch (idx) {
9910 case 0:
9911 centerchan = (channel - 2);
9912 break;
9913 case 1:
9914 centerchan = (channel + 2);
developer69b61b02023-03-07 17:17:44 +08009915 break;
developer72fb0bb2023-01-11 09:46:29 +08009916 default:
9917 return -EINVAL;
9918 }
9919 }else if (width == 80){
developer69b61b02023-03-07 17:17:44 +08009920 idx = ((channel/4) + chan_ofs)%4;
developer72fb0bb2023-01-11 09:46:29 +08009921 switch (idx) {
9922 case 0:
9923 centerchan = (channel - 6);
9924 break;
9925 case 1:
9926 centerchan = (channel + 6);
9927 break;
9928 case 2:
9929 centerchan = (channel + 2);
9930 break;
9931 case 3:
9932 centerchan = (channel - 2);
9933 break;
9934 default:
9935 return -EINVAL;
developer69b61b02023-03-07 17:17:44 +08009936 }
developer72fb0bb2023-01-11 09:46:29 +08009937 }else if (width == 160){
9938 switch (channel) {
9939 case 1 ... 29:
9940 centerchan = 15;
9941 break;
9942 case 33 ... 61:
9943 centerchan = 47;
9944 break;
9945 case 65 ... 93:
9946 centerchan = 79;
9947 break;
9948 case 97 ... 125:
9949 centerchan = 111;
9950 break;
9951 case 129 ... 157:
9952 centerchan = 143;
9953 break;
9954 case 161 ... 189:
9955 centerchan = 175;
9956 break;
9957 case 193 ... 221:
9958 centerchan = 207;
9959 break;
9960 default:
9961 return -EINVAL;
developer69b61b02023-03-07 17:17:44 +08009962 }
developer72fb0bb2023-01-11 09:46:29 +08009963 }
9964 return centerchan;
9965}
9966static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
9967{
9968 BOOL onlyG, onlyN, onlyA;
9969 CHAR tmp[64];
9970 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
9971 if (ret == RETURN_OK) {
9972 sncopy(hw_mode, hw_mode_size, tmp);
9973 }
9974 return ret;
9975}
9976
9977INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
9978{
9979 // Sample commands:
9980 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
9981 // hostapd_cli -i wifi0 chan_switch 30 2437
9982 char cmd[MAX_CMD_SIZE] = {0};
9983 char buf[MAX_BUF_SIZE] = {0};
9984 int freq = 0, ret = 0;
9985 char center_freq1_str[32] = ""; // center_freq1=%d
9986 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
9987 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
9988 char hw_mode[16] = ""; // n|ac
9989 char bw_mode[16] = ""; // ht|ht vht
9990 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
9991 char interface_name[16] = {0};
9992 int sec_chan_offset;
9993 int width;
9994 char config_file[64] = {0};
9995 BOOL stbcEnable = FALSE;
9996 char *ext_str = "None";
9997 wifi_band band = band_invalid;
9998 int center_chan = 0;
9999 int center_freq1 = 0;
developerd1824452023-05-18 12:30:04 +080010000 struct params mwctl = {0};
10001 char str_channel[8]={0};
developer72fb0bb2023-01-11 09:46:29 +080010002
10003 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
10004
10005 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
10006 return RETURN_ERR;
10007
10008 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10009
10010 band = wifi_index_to_band(radioIndex);
10011
10012 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
10013
10014 // Get radio mode HT20|HT40|HT80 etc.
10015 if (channel){
10016 if (band == band_6){
10017 freq = util_6G_chan_to_freq(channel);
10018 }else{
10019 freq = util_chan_to_freq(channel);
10020 }
10021 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
10022
10023 // Provide bandwith if specified
10024 if (channel_width_MHz > 20) {
10025 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
10026 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
10027 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
10028
10029 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
10030 }else if (channel_width_MHz == 20){
10031 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
10032 }
10033
10034
10035 if (channel_width_MHz > 20) {
10036 if (band == band_6){
10037 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
10038 if(center_chan){
10039 center_freq1 = util_6G_chan_to_freq(center_chan);
10040 }
10041 }else{
10042 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
10043 if(center_chan){
10044 center_freq1 = util_chan_to_freq(center_chan);
10045 }
10046 }
developer69b61b02023-03-07 17:17:44 +080010047
developer72fb0bb2023-01-11 09:46:29 +080010048 if (center_freq1)
10049 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
developer69b61b02023-03-07 17:17:44 +080010050
developer72fb0bb2023-01-11 09:46:29 +080010051 }
10052
10053 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
10054 if (band == band_6){
10055 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
10056 }else{
10057 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
10058 }
10059 if (sec_chan_offset != -EINVAL)
10060 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
10061
10062 // Only the first AP, other are hanging on the same radio
10063 int apIndex = radioIndex;
developerd1824452023-05-18 12:30:04 +080010064 /* snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s chan_switch %d %d %s %s %s",
developer72fb0bb2023-01-11 09:46:29 +080010065 interface_name, csa_beacon_count, freq,
developerd1824452023-05-18 12:30:04 +080010066 sec_chan_offset_str, center_freq1_str, opt_chan_info_str); */
10067 snprintf(str_channel, sizeof(str_channel), "%d", channel);
10068 mwctl.name = "channel num=";
10069 mwctl.value = str_channel;
10070 ret = wifi_mwctlSet(radioIndex, &mwctl, BASE_PHY_INDEX);
10071 if (ret != RETURN_OK) {
10072 fprintf(stderr, "%s: wifi_mwctlSet return error.\n", __func__);
10073 return RETURN_ERR;
10074 }
10075 /* wifi_dbg_printf("execute: '%s'\n", cmd);
developerf6a87542023-05-16 15:47:28 +080010076 ret = _syscmd(cmd, buf, sizeof(buf));
developerd1824452023-05-18 12:30:04 +080010077 wifi_reloadAp(radioIndex); */
developer72fb0bb2023-01-11 09:46:29 +080010078
10079 ret = wifi_setRadioChannel(radioIndex, channel);
10080 if (ret != RETURN_OK) {
10081 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
10082 return RETURN_ERR;
10083 }
10084
10085 if (sec_chan_offset == 1) ext_str = "Above";
10086 else if (sec_chan_offset == -1) ext_str = "Below";
10087
developerd1824452023-05-18 12:30:04 +080010088 /*wifi_setRadioCenterChannel(radioIndex, center_chan); */
developer72fb0bb2023-01-11 09:46:29 +080010089
10090 } else {
10091 if (channel_width_MHz > 20)
10092 ext_str = "Above";
10093 }
10094
10095 wifi_setRadioExtChannel(radioIndex, ext_str);
10096
10097 char mhz_str[16];
10098 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
10099 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
10100
10101 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10102
10103 return RETURN_OK;
10104}
10105
10106INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
10107{
10108 int index = -1;
10109 wifi_neighbor_ap2_t *scan_array = NULL;
10110 char cmd[256]={0};
10111 char buf[128]={0};
10112 char file_name[32] = {0};
10113 char filter_SSID[32] = {0};
10114 char line[256] = {0};
10115 char interface_name[16] = {0};
10116 char *ret = NULL;
10117 int freq=0;
10118 FILE *f = NULL;
10119 size_t len=0;
10120 int channels_num = 0;
10121 int vht_channel_width = 0;
10122 int get_noise_ret = RETURN_ERR;
10123 bool filter_enable = false;
10124 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
10125 int phyId = 0;
10126
10127 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
10128
10129 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
10130 f = fopen(file_name, "r");
10131 if (f != NULL) {
10132 fgets(filter_SSID, sizeof(file_name), f);
10133 if (strlen(filter_SSID) != 0)
10134 filter_enable = true;
10135 fclose(f);
10136 }
10137
10138 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
10139 return RETURN_ERR;
10140
10141 phyId = radio_index_to_phy(radio_index);
10142
10143 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
10144 _syscmd(cmd, buf, sizeof(buf));
10145 channels_num = strtol(buf, NULL, 10);
10146
10147 sprintf(cmd, "iw dev %s scan dump | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
10148 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", interface_name, interface_name);
10149 fprintf(stderr, "cmd: %s\n", cmd);
10150 if ((f = popen(cmd, "r")) == NULL) {
10151 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
10152 return RETURN_ERR;
10153 }
developer69b61b02023-03-07 17:17:44 +080010154
developer72fb0bb2023-01-11 09:46:29 +080010155 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
10156 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
developer69b61b02023-03-07 17:17:44 +080010157
developer72fb0bb2023-01-11 09:46:29 +080010158 ret = fgets(line, sizeof(line), f);
10159 while (ret != NULL) {
10160 if(strstr(line, "BSS") != NULL) { // new neighbor info
developer69b61b02023-03-07 17:17:44 +080010161 // 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 +080010162 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
10163 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
10164
10165 if (!filter_BSS) {
10166 index++;
10167 wifi_neighbor_ap2_t *tmp;
10168 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
10169 if (tmp == NULL) { // no more memory to use
10170 index--;
10171 wifi_dbg_printf("%s: realloc failed\n", __func__);
10172 break;
10173 }
10174 scan_array = tmp;
10175 }
10176 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
10177
10178 filter_BSS = false;
10179 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
10180 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
10181 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
10182 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
10183 } else if (strstr(line, "freq") != NULL) {
10184 sscanf(line," freq: %d", &freq);
10185 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
10186
10187 if (freq >= 2412 && freq <= 2484) {
10188 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
10189 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
10190 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
10191 }
10192 else if (freq >= 5160 && freq <= 5805) {
10193 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
10194 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
10195 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
10196 }
10197
10198 scan_array[index].ap_Noise = 0;
10199 if (get_noise_ret == RETURN_OK) {
10200 for (int i = 0; i < channels_num; i++) {
10201 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
10202 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
10203 break;
10204 }
10205 }
10206 }
10207 } else if (strstr(line, "beacon interval") != NULL) {
10208 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
10209 } else if (strstr(line, "signal") != NULL) {
10210 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
10211 } else if (strstr(line,"SSID") != NULL) {
10212 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
10213 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
10214 filter_BSS = true;
10215 }
10216 } else if (strstr(line, "Supported rates") != NULL) {
10217 char SRate[80] = {0}, *tmp = NULL;
10218 memset(buf, 0, sizeof(buf));
10219 strcpy(SRate, line);
10220 tmp = strtok(SRate, ":");
10221 tmp = strtok(NULL, ":");
10222 strcpy(buf, tmp);
10223 memset(SRate, 0, sizeof(SRate));
10224
10225 tmp = strtok(buf, " \n");
10226 while (tmp != NULL) {
10227 strcat(SRate, tmp);
10228 if (SRate[strlen(SRate) - 1] == '*') {
10229 SRate[strlen(SRate) - 1] = '\0';
10230 }
10231 strcat(SRate, ",");
10232
10233 tmp = strtok(NULL, " \n");
10234 }
10235 SRate[strlen(SRate) - 1] = '\0';
10236 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
10237 } else if (strstr(line, "DTIM") != NULL) {
10238 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
10239 } else if (strstr(line, "VHT capabilities") != NULL) {
10240 strcat(scan_array[index].ap_SupportedStandards, ",ac");
10241 strcpy(scan_array[index].ap_OperatingStandards, "ac");
10242 } else if (strstr(line, "HT capabilities") != NULL) {
10243 strcat(scan_array[index].ap_SupportedStandards, ",n");
10244 strcpy(scan_array[index].ap_OperatingStandards, "n");
10245 } else if (strstr(line, "VHT operation") != NULL) {
10246 ret = fgets(line, sizeof(line), f);
10247 sscanf(line," * channel width: %d", &vht_channel_width);
10248 if(vht_channel_width == 1) {
10249 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
10250 } else {
10251 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
10252 }
10253 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
10254 continue;
10255 } else if (strstr(line, "HT operation") != NULL) {
10256 ret = fgets(line, sizeof(line), f);
10257 sscanf(line," * secondary channel offset: %s", &buf);
10258 if (!strcmp(buf, "above")) {
10259 //40Mhz +
10260 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radio_index%1 ? "A": "G");
10261 }
10262 else if (!strcmp(buf, "below")) {
10263 //40Mhz -
10264 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
10265 } else {
10266 //20Mhz
10267 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radio_index%1 ? "A": "G");
10268 }
10269 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
10270 continue;
10271 } else if (strstr(line, "HE capabilities") != NULL) {
10272 strcat(scan_array[index].ap_SupportedStandards, ",ax");
10273 strcpy(scan_array[index].ap_OperatingStandards, "ax");
10274 ret = fgets(line, sizeof(line), f);
10275 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
10276 if (strstr(line, "HE40/2.4GHz") != NULL)
10277 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
10278 else
10279 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
10280 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
10281 if (strstr(line, "HE80/5GHz") != NULL) {
10282 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
10283 ret = fgets(line, sizeof(line), f);
10284 } else
10285 continue;
10286 if (strstr(line, "HE160/5GHz") != NULL)
10287 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
10288 }
10289 continue;
10290 } else if (strstr(line, "WPA") != NULL) {
10291 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
10292 } else if (strstr(line, "RSN") != NULL) {
10293 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
10294 } else if (strstr(line, "Group cipher") != NULL) {
10295 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
10296 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
10297 strcpy(scan_array[index].ap_EncryptionMode, "AES");
10298 }
10299 }
10300 ret = fgets(line, sizeof(line), f);
10301 }
10302
10303 if (!filter_BSS) {
10304 *output_array_size = index + 1;
10305 } else {
10306 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
10307 *output_array_size = index;
10308 }
10309 *neighbor_ap_array = scan_array;
10310 pclose(f);
10311 free(channels_noise_arr);
10312 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10313 return RETURN_OK;
10314}
10315
10316INT wifi_getApAssociatedDeviceStats(
10317 INT apIndex,
10318 mac_address_t *clientMacAddress,
10319 wifi_associated_dev_stats_t *associated_dev_stats,
10320 u64 *handle)
10321{
10322 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
10323 char interface_name[50] = {0};
10324 char cmd[1024] = {0};
10325 char mac_str[18] = {0};
10326 char *key = NULL;
10327 char *val = NULL;
10328 FILE *f = NULL;
10329 char *line = NULL;
10330 size_t len = 0;
10331
10332 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
10333 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
10334 return RETURN_ERR;
10335 }
10336
10337 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
10338 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
10339 if((f = popen(cmd, "r")) == NULL) {
10340 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
10341 return RETURN_ERR;
10342 }
10343
10344 while ((getline(&line, &len, f)) != -1) {
10345 key = strtok(line,":");
10346 val = strtok(NULL,":");
10347
10348 if(!strncmp(key,"rx bytes",8))
10349 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
10350 if(!strncmp(key,"tx bytes",8))
10351 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
10352 if(!strncmp(key,"rx packets",10))
10353 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
10354 if(!strncmp(key,"tx packets",10))
10355 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
10356 if(!strncmp(key,"tx retries",10))
10357 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
10358 if(!strncmp(key,"tx failed",9))
10359 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
10360 if(!strncmp(key,"rx drop misc",13))
10361 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
10362 if(!strncmp(key,"rx bitrate",10)) {
10363 val = strtok(val, " ");
10364 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
10365 }
10366 if(!strncmp(key,"tx bitrate",10)) {
10367 val = strtok(val, " ");
10368 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
10369 }
10370 }
10371 free(line);
10372 pclose(f);
10373 return RETURN_OK;
10374}
10375
10376INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
10377{
developer7e4a2a62023-04-06 19:56:03 +080010378 char interface_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +080010379 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
10380
developer7e4a2a62023-04-06 19:56:03 +080010381 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
10382
developer72fb0bb2023-01-11 09:46:29 +080010383 if (NULL == output_string)
10384 return RETURN_ERR;
10385
10386 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
10387 return RETURN_ERR;
developer7e4a2a62023-04-06 19:56:03 +080010388
10389 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 +080010390 _syscmd(cmd, buf, sizeof(buf));
10391
10392 //size of SSID name restricted to value less than 32 bytes
10393 snprintf(output_string, 32, "%s", buf);
developer7e4a2a62023-04-06 19:56:03 +080010394 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +080010395
10396 return RETURN_OK;
10397}
10398
10399INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
10400{
developer7e4a2a62023-04-06 19:56:03 +080010401 char cmd[MAX_CMD_SIZE] = {0};
10402 char buf[MAX_BUF_SIZE] = {0};
10403 char inf_name[IF_NAME_SIZE] = {0};
10404 char policy = 0;
developer72fb0bb2023-01-11 09:46:29 +080010405
10406 if (!output_filterMode)
10407 return RETURN_ERR;
10408
developer7e4a2a62023-04-06 19:56:03 +080010409 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
10410 return RETURN_ERR;
10411
10412 /* mwctl get acl policy */
10413 snprintf(cmd, sizeof(cmd), "mwctl %s acl show_all | grep policy | cut -d '=' -f2 | tr -d '\\n'", inf_name);
10414 _syscmd(cmd, buf, sizeof(buf));
10415
10416
10417 policy = atoi(buf);
10418
10419 if (policy < 0 || policy > 2) {
10420 printf("%s:get wrong acl policy!!!\n", __func__);
10421 *output_filterMode = 0;
10422 return RETURN_ERR;
10423 } else
10424 *output_filterMode = policy;
10425
developer72fb0bb2023-01-11 09:46:29 +080010426
10427 return RETURN_OK;
10428}
10429
10430INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
10431{
10432 FILE *fp = NULL;
10433 char str[MAX_BUF_SIZE] = {0};
10434 int wificlientindex = 0 ;
10435 int count = 0;
10436 int signalstrength = 0;
10437 int arr[MACADDRESS_SIZE] = {0};
10438 unsigned char mac[MACADDRESS_SIZE] = {0};
10439 UINT wifi_count = 0;
10440 char virtual_interface_name[MAX_BUF_SIZE] = {0};
10441 char pipeCmd[MAX_CMD_SIZE] = {0};
10442
10443 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10444 *output_array_size = 0;
10445 *associated_dev_array = NULL;
10446 char interface_name[50] = {0};
10447
10448 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
10449 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
10450 return RETURN_ERR;
10451 }
10452
10453 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
10454 fp = popen(pipeCmd, "r");
10455 if (fp == NULL)
10456 {
10457 printf("Failed to run command inside function %s\n",__FUNCTION__ );
10458 return RETURN_ERR;
10459 }
10460
10461 /* Read the output a line at a time - output it. */
10462 fgets(str, sizeof(str)-1, fp);
10463 wifi_count = (unsigned int) atoi ( str );
10464 *output_array_size = wifi_count;
10465 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
10466 pclose(fp);
10467
10468 if(wifi_count == 0)
10469 {
10470 return RETURN_OK;
10471 }
10472 else
10473 {
10474 wifi_associated_dev2_t* temp = NULL;
10475 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
10476 *associated_dev_array = temp;
10477 if(temp == NULL)
10478 {
10479 printf("Error Statement. Insufficient memory \n");
10480 return RETURN_ERR;
10481 }
10482
10483 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
10484 system(pipeCmd);
10485
10486 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
10487 if(fp == NULL)
10488 {
10489 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
10490 return RETURN_ERR;
10491 }
10492 fclose(fp);
10493
10494 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
10495 fp = popen(pipeCmd, "r");
10496 if(fp)
10497 {
10498 for(count =0 ; count < wifi_count; count++)
10499 {
10500 fgets(str, MAX_BUF_SIZE, fp);
10501 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
10502 {
10503 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
10504 {
10505 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
10506
10507 }
10508 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
10509 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]);
10510 }
10511 temp[count].cli_AuthenticationState = 1; //TODO
10512 temp[count].cli_Active = 1; //TODO
10513 }
10514 pclose(fp);
10515 }
10516
10517 //Updating RSSI per client
10518 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt");
10519 fp = popen(pipeCmd, "r");
10520 if(fp)
10521 {
10522 pclose(fp);
10523 }
10524 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
10525 if(fp)
10526 {
10527 for(count =0 ; count < wifi_count ;count++)
10528 {
10529 fgets(str, MAX_BUF_SIZE, fp);
10530 signalstrength = atoi(str);
10531 temp[count].cli_RSSI = signalstrength;
10532 }
10533 pclose(fp);
10534 }
10535
10536
10537 //LastDataDownlinkRate
10538 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt");
10539 fp = popen(pipeCmd, "r");
10540 if (fp)
10541 {
10542 pclose(fp);
10543 }
10544 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
10545 if (fp)
10546 {
10547 for (count = 0; count < wifi_count; count++)
10548 {
10549 fgets(str, MAX_BUF_SIZE, fp);
10550 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
10551 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
10552 }
10553 pclose(fp);
10554 }
10555
10556 //LastDataUplinkRate
10557 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt");
10558 fp = popen(pipeCmd, "r");
10559 if (fp)
10560 {
10561 pclose(fp);
10562 }
10563 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
10564 if (fp)
10565 {
10566 for (count = 0; count < wifi_count; count++)
10567 {
10568 fgets(str, MAX_BUF_SIZE, fp);
10569 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
10570 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
10571 }
10572 pclose(fp);
10573 }
10574 }
10575 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10576 return RETURN_OK;
10577
10578}
10579
10580INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
10581{
10582#if 0
10583 /*char buf[1024] = {0};
10584 sprintf(cmd, "ifconfig %s ", interface_name);
10585 _syscmd(cmd, buf, sizeof(buf));*/
10586
10587 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
10588 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
10589 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
10590 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
10591
10592 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.
10593 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].
10594 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].
10595 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].
10596 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
10597 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
10598
10599 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
10600 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
10601 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
10602 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.
10603 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.
10604 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.
10605 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.
10606 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.
10607 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.
10608 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.
10609 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
10610#endif
10611
10612 FILE *fp = NULL;
10613 char interface_name[50] = {0};
10614 char pipeCmd[128] = {0};
10615 char str[256] = {0};
10616 wifi_ssidTrafficStats2_t *out = output_struct;
10617
10618 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
10619 if (!output_struct)
10620 return RETURN_ERR;
10621
10622 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
10623 if (wifi_GetInterfaceName(ssidIndex, interface_name) != RETURN_OK)
10624 return RETURN_ERR;
10625 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
10626
10627 fp = popen(pipeCmd, "r");
10628 if (fp == NULL) {
10629 fprintf(stderr, "%s: popen failed\n", __func__);
10630 return RETURN_ERR;
10631 }
10632 fgets(str, sizeof(str), fp);
10633 pclose(fp);
10634
10635 if (strlen(str) == 0) // interface not exist
10636 return RETURN_OK;
10637
10638 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
10639 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
10640
10641 memset(str, 0, sizeof(str));
10642 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
10643 fp = popen(pipeCmd, "r");
10644 if (fp == NULL) {
10645 fprintf(stderr, "%s: popen failed\n", __func__);
10646 return RETURN_ERR;
10647 }
10648 fgets(str, sizeof(str), fp);
10649
10650 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
10651 &out->ssid_BroadcastPacketsSent);
10652 pclose(fp);
10653
10654 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
10655 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
10656
10657 // Not supported
10658 output_struct->ssid_RetransCount = 0;
10659 output_struct->ssid_FailedRetransCount = 0;
10660 output_struct->ssid_RetryCount = 0;
10661 output_struct->ssid_MultipleRetryCount = 0;
10662 output_struct->ssid_ACKFailureCount = 0;
10663 output_struct->ssid_AggregatedPacketCount = 0;
10664
10665 return RETURN_OK;
10666}
10667
10668//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).
10669INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
10670{
10671 char output_val[16]={'\0'};
10672 char config_file[MAX_BUF_SIZE] = {0};
10673
10674 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10675 if (!output)
10676 return RETURN_ERR;
10677 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10678 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
10679
10680 if( strcmp(output_val,"1") == 0 )
10681 *output = TRUE;
10682 else
10683 *output = FALSE;
10684 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10685
10686 return RETURN_OK;
10687}
10688
10689INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
10690{
10691 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10692 char str[MAX_BUF_SIZE]={'\0'};
10693 char string[MAX_BUF_SIZE]={'\0'};
10694 char cmd[MAX_CMD_SIZE]={'\0'};
10695 char *ch;
10696 char config_file[MAX_BUF_SIZE] = {0};
10697 struct params params;
10698
10699 if(enable == TRUE)
10700 strcpy(string,"1");
10701 else
10702 strcpy(string,"0");
10703
10704 params.name = "ap_isolate";
10705 params.value = string;
10706
10707 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10708 wifi_hostapdWrite(config_file,&params,1);
10709 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10710
10711 return RETURN_OK;
10712}
10713
10714INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
10715{
developera1255e42023-05-13 17:45:02 +080010716 char mgmtpwr_file[32] = {0};
10717 char cmd[64] = {0};
10718 char buf[32]={0};
10719
developer72fb0bb2023-01-11 09:46:29 +080010720 if (NULL == output_dBm)
10721 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +080010722 snprintf(mgmtpwr_file, sizeof(mgmtpwr_file), "%s%d.txt", MGMT_POWER_CTRL, apIndex);
10723 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mgmtpwr_file);
10724 _syscmd(cmd, buf, sizeof(buf));
10725 if (strlen(buf) > 0)
10726 *output_dBm = strtol(buf, NULL, 10);
10727 else
10728 *output_dBm = 23;
developer72fb0bb2023-01-11 09:46:29 +080010729 return RETURN_OK;
10730}
10731
10732INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
10733{
developera1255e42023-05-13 17:45:02 +080010734 char interface_name[16] = {0};
10735 char cmd[128]={0};
10736 char buf[128]={0};
10737 char mgmt_pwr_file[128]={0};
10738 FILE *f = NULL;
10739
10740 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10741
10742 if (wifi_GetInterfaceName(wlanIndex, interface_name) != RETURN_OK)
10743 return RETURN_ERR;
10744 snprintf(cmd, sizeof(cmd), "mwctl dev %s set pwr mgmt_frame_pwr=%d", interface_name, dBm);
10745 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR) {
10746 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10747 return RETURN_ERR;
10748 }
10749 snprintf(mgmt_pwr_file, sizeof(mgmt_pwr_file), "%s%d.txt", MGMT_POWER_CTRL, wlanIndex);
10750 f = fopen(mgmt_pwr_file, "w");
10751 if (f == NULL) {
10752 fprintf(stderr, "%s: fopen failed\n", __func__);
10753 return RETURN_ERR;
10754 }
10755 fprintf(f, "%d", dBm);
10756 fclose(f);
developer72fb0bb2023-01-11 09:46:29 +080010757 return RETURN_OK;
10758}
10759INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
10760{
10761 return RETURN_OK;
10762}
10763INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
10764{
10765 return RETURN_OK;
10766}
10767INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
10768{
10769 return RETURN_OK;
10770}
10771INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
10772{
10773 return RETURN_OK;
10774}
10775INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
10776{
10777 char config_file[MAX_BUF_SIZE] = {0};
10778 struct params list;
10779
10780 list.name = "bss_transition";
10781 list.value = activate?"1":"0";
10782 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
10783 wifi_hostapdWrite(config_file, &list, 1);
10784
10785 return RETURN_OK;
10786}
10787wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
10788
10789void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
10790{
10791 return;
10792}
10793
10794INT wifi_setApCsaDeauth(INT apIndex, INT mode)
10795{
10796 // TODO Implement me!
10797 return RETURN_OK;
10798}
10799
10800INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
10801{
10802 char file_name[128] = {0};
10803 char buf[128] = {0};
10804 FILE *f = NULL;
10805 int max_num_radios = 0;
10806
10807 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10808
10809 wifi_getMaxRadioNumber(&max_num_radios);
10810 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
10811 for (int index = 0; index < max_num_radios; index++) {
10812 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
10813 f = fopen(file_name, "w");
10814 if (f == NULL)
10815 return RETURN_ERR;
10816 // For mode == 0 is to disable filter, just don't write to the file.
10817 if (mode)
10818 fprintf(f, "%s", essid);
10819
10820 fclose(f);
10821 }
10822 } else { // special case, need to set AP's SSID as filter for each radio.
10823 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
10824 f = fopen(file_name, "w");
10825 if (f == NULL)
10826 return RETURN_ERR;
10827
10828 // For mode == 0 is to disable filter, just don't write to the file.
10829 if (mode)
10830 fprintf(f, "%s", essid);
10831
10832 fclose(f);
10833 }
10834
10835 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10836 return RETURN_OK;
10837}
10838
10839INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
10840{
10841 // TODO Implement me!
10842 //Apply wifi_pushRadioChannel() instantly
10843 return RETURN_ERR;
10844}
10845
10846INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
10847{
10848 // TODO Implement me!
10849 return RETURN_OK;
10850}
10851
10852#ifdef HAL_NETLINK_IMPL
10853static int tidStats_callback(struct nl_msg *msg, void *arg) {
10854 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10855 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10856 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10857 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
10858 int rem , tid_index = 0;
10859
10860 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
10861 wifi_associated_dev_tid_entry_t *stats_entry;
10862
10863 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
10864 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
10865 };
10866 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
10867 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
10868 };
10869
10870 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
10871 genlmsg_attrlen(gnlh, 0), NULL);
10872
10873
10874 if (!tb[NL80211_ATTR_STA_INFO]) {
10875 fprintf(stderr, "station stats missing!\n");
10876 return NL_SKIP;
10877 }
10878
10879 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
10880 tb[NL80211_ATTR_STA_INFO],
10881 stats_policy)) {
10882 fprintf(stderr, "failed to parse nested attributes!\n");
10883 return NL_SKIP;
10884 }
10885
developer386281b2023-05-20 15:43:13 +080010886 if (sinfo[NL80211_STA_INFO_TID_STATS]) {
10887 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
10888 {
10889 stats_entry = &out->tid_array[tid_index];
developer72fb0bb2023-01-11 09:46:29 +080010890
developer386281b2023-05-20 15:43:13 +080010891 stats_entry->tid = tid_index;
10892 stats_entry->ac = _tid_ac_index_get[tid_index];
developer72fb0bb2023-01-11 09:46:29 +080010893
developer386281b2023-05-20 15:43:13 +080010894 if(sinfo[NL80211_STA_INFO_TID_STATS])
10895 {
10896 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
10897 printf("failed to parse nested stats attributes!");
10898 return NL_SKIP;
10899 }
developer72fb0bb2023-01-11 09:46:29 +080010900 }
developer386281b2023-05-20 15:43:13 +080010901 if(stats_info[NL80211_TID_STATS_TX_MSDU])
10902 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
developer72fb0bb2023-01-11 09:46:29 +080010903
developer386281b2023-05-20 15:43:13 +080010904 if(tid_index < (PS_MAX_TID - 1))
10905 tid_index++;
10906 }
developer72fb0bb2023-01-11 09:46:29 +080010907 }
10908 //ToDo: sum_time_ms, ewma_time_ms
10909 return NL_SKIP;
10910}
10911#endif
10912
10913INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
10914{
10915#ifdef HAL_NETLINK_IMPL
10916 Netlink nl;
10917 char if_name[10];
10918 char interface_name[16] = {0};
10919
10920 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
10921 return RETURN_ERR;
10922
10923 snprintf(if_name, sizeof(if_name), "%s", interface_name);
10924
10925 nl.id = initSock80211(&nl);
10926
10927 if (nl.id < 0) {
10928 fprintf(stderr, "Error initializing netlink \n");
10929 return -1;
10930 }
10931
10932 struct nl_msg* msg = nlmsg_alloc();
10933
10934 if (!msg) {
10935 fprintf(stderr, "Failed to allocate netlink message.\n");
10936 nlfree(&nl);
10937 return -2;
10938 }
10939
10940 genlmsg_put(msg,
developer8dd72532023-05-17 19:58:35 +080010941 NL_AUTO_PID,
developer72fb0bb2023-01-11 09:46:29 +080010942 NL_AUTO_SEQ,
10943 nl.id,
10944 0,
10945 0,
10946 NL80211_CMD_GET_STATION,
10947 0);
10948
10949 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
10950 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10951 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
developer8dd72532023-05-17 19:58:35 +080010952 nl_send_auto_complete(nl.socket, msg);
developer72fb0bb2023-01-11 09:46:29 +080010953 nl_recvmsgs(nl.socket, nl.cb);
10954 nlmsg_free(msg);
10955 nlfree(&nl);
10956 return RETURN_OK;
10957#else
10958//iw implementation
10959#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
10960#define TOTAL_MAX_LINES 50
10961
10962 char buf[256] = {'\0'}; /* or other suitable maximum line size */
10963 char if_name[32] = {0};
10964 FILE *fp=NULL;
10965 char pipeCmd[1024]= {'\0'};
10966 int lines,tid_index=0;
10967 char mac_addr[20] = {'\0'};
10968
10969 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
10970 return RETURN_ERR;
10971
10972 wifi_associated_dev_tid_entry_t *stats_entry;
10973
10974 strcpy(mac_addr,clientMacAddress);
10975
10976 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
10977 fp= popen(pipeCmd,"r");
10978 if(fp == NULL)
10979 {
10980 perror("popen for station dump failed\n");
10981 return RETURN_ERR;
10982 }
10983 pclose(fp);
10984
10985 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
10986 fp=popen(pipeCmd,"r");
10987 if(fp == NULL)
10988 {
10989 perror("popen for grep station failed\n");
10990 return RETURN_ERR;
10991 }
10992 else if(fgets(buf,sizeof(buf),fp) != NULL)
10993 lines=atoi(buf);
10994 else
10995 {
10996 pclose(fp);
10997 fprintf(stderr,"No devices are connected \n");
10998 return RETURN_ERR;
10999 }
11000 pclose(fp);
11001
11002 if(lines == 1)
11003 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
11004
11005 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
11006 {
11007 stats_entry = &tid_stats->tid_array[tid_index];
11008 stats_entry->tid = tid_index;
11009
11010 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);
11011
11012 fp=popen(pipeCmd,"r");
11013 if(fp ==NULL)
11014 {
11015 perror("Failed to read from tid file \n");
11016 return RETURN_ERR;
11017 }
11018 else if(fgets(buf,sizeof(buf),fp) != NULL)
11019 stats_entry->num_msdus = atol(buf);
11020
11021 pclose(fp);
11022 stats_entry->ac = _tid_ac_index_get[tid_index];
11023// TODO:
11024// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
11025// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
11026 }
11027 return RETURN_OK;
11028#endif
11029}
11030
11031
11032INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
11033{
11034 char interface_name[16] = {0};
11035 char cmd[128]={0};
11036 char buf[128]={0};
11037 int freq = 0;
11038
11039 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11040
11041 // full mode is used to scan all channels.
11042 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
11043 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
11044 ieee80211_channel_to_frequency(chan_list[0], &freq);
11045
11046 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
11047 return RETURN_ERR;
11048
11049 if (freq)
11050 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d freq %d", interface_name, dwell_time, freq);
11051 else
11052 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d", interface_name, dwell_time);
11053
11054 _syscmd(cmd, buf, sizeof(buf));
11055 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11056
11057 return RETURN_OK;
11058}
11059
11060
11061INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
11062{
11063 // TODO Implement me!
11064 return RETURN_ERR;
11065}
11066
11067INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
11068{
11069 // TODO Implement me!
11070 return RETURN_ERR;
11071}
11072
11073INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
11074{
11075 // TODO Implement me!
11076 return RETURN_ERR;
11077}
11078
11079INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
11080{
11081 // TODO Implement me!
11082 return RETURN_ERR;
11083}
11084
11085INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
11086{
11087 // TODO Implement me!
11088 return RETURN_ERR;
11089}
11090
11091INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
11092{
11093 // TODO Implement me!
11094 return RETURN_ERR;
11095}
11096
11097INT wifi_steering_eventUnregister(void)
11098{
11099 // TODO Implement me!
11100 return RETURN_ERR;
11101}
11102
11103INT wifi_delApAclDevices(INT apIndex)
11104{
developer7e4a2a62023-04-06 19:56:03 +080011105 char cmd[MAX_CMD_SIZE] = {0};
11106 char buf[MAX_BUF_SIZE] = {0};
11107 char inf_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +080011108
developer7e4a2a62023-04-06 19:56:03 +080011109 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
11110 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +080011111
developer7e4a2a62023-04-06 19:56:03 +080011112 /* mwctl acl clear all stas */
11113 snprintf(cmd, sizeof(cmd), "mwctl %s acl clear_all", inf_name);
11114 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +080011115
11116 return RETURN_OK;
11117}
11118
11119#ifdef HAL_NETLINK_IMPL
11120static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
11121 struct nlattr *tb[NL80211_ATTR_MAX + 1];
11122 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
11123 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
11124 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
11125 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
11126 char mac_addr[20],dev[20];
11127
11128 nla_parse(tb,
11129 NL80211_ATTR_MAX,
11130 genlmsg_attrdata(gnlh, 0),
11131 genlmsg_attrlen(gnlh, 0),
11132 NULL);
11133
11134 if(!tb[NL80211_ATTR_STA_INFO]) {
11135 fprintf(stderr, "sta stats missing!\n");
11136 return NL_SKIP;
11137 }
11138
11139 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
11140 fprintf(stderr, "failed to parse nested attributes!\n");
11141 return NL_SKIP;
11142 }
11143 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
11144
11145 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
11146
developer386281b2023-05-20 15:43:13 +080011147 if (sinfo[NL80211_STA_INFO_RX_BITRATE]) {
11148 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
11149 fprintf(stderr, "failed to parse nested rate attributes!");
11150 return NL_SKIP;
11151 }
developer72fb0bb2023-01-11 09:46:29 +080011152 }
11153
11154 if(sinfo[NL80211_STA_INFO_TID_STATS])
11155 {
11156 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
11157 printf("failed to parse nested stats attributes!");
11158 return NL_SKIP;
11159 }
11160 }
11161
11162 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
11163 {
11164 printf("Type is VHT\n");
11165 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
11166 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
11167
11168 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
11169 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
11170 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
11171 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
11172 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
11173 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
11174 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
11175 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
11176 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
11177 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
11178 }
11179 else
11180 {
11181 printf(" OFDM or CCK \n");
11182 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
11183 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
11184 }
11185
11186 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
11187 if(rinfo[NL80211_RATE_INFO_MCS])
11188 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
11189 }
11190 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
11191 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
11192 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
11193 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
11194
11195 if(stats_info[NL80211_TID_STATS_RX_MSDU])
11196 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
11197
11198 if (sinfo[NL80211_STA_INFO_SIGNAL])
11199 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
11200 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
11201 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
11202 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
11203 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
11204 //rssi_array need to be filled
11205 return NL_SKIP;
11206}
11207#endif
11208
11209INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
11210{
11211#ifdef HAL_NETLINK_IMPL
11212 Netlink nl;
11213 char if_name[32];
11214 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
11215 return RETURN_ERR;
11216
11217 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
11218
11219 if (*output_array_size <= 0)
11220 return RETURN_OK;
11221
11222 nl.id = initSock80211(&nl);
11223
11224 if (nl.id < 0) {
11225 fprintf(stderr, "Error initializing netlink \n");
11226 return 0;
11227 }
11228
11229 struct nl_msg* msg = nlmsg_alloc();
11230
11231 if (!msg) {
11232 fprintf(stderr, "Failed to allocate netlink message.\n");
11233 nlfree(&nl);
11234 return 0;
11235 }
11236
11237 genlmsg_put(msg,
developer8dd72532023-05-17 19:58:35 +080011238 NL_AUTO_PID,
developer72fb0bb2023-01-11 09:46:29 +080011239 NL_AUTO_SEQ,
11240 nl.id,
11241 0,
11242 0,
11243 NL80211_CMD_GET_STATION,
11244 0);
11245
11246 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
11247 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
11248 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
developer8dd72532023-05-17 19:58:35 +080011249 nl_send_auto_complete(nl.socket, msg);
developer72fb0bb2023-01-11 09:46:29 +080011250 nl_recvmsgs(nl.socket, nl.cb);
11251 nlmsg_free(msg);
11252 nlfree(&nl);
11253 return RETURN_OK;
11254#else
11255 //TODO Implement me
11256 return RETURN_OK;
11257#endif
11258}
11259
11260#ifdef HAL_NETLINK_IMPL
11261static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
11262 struct nlattr *tb[NL80211_ATTR_MAX + 1];
11263 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
11264 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
11265 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
11266 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
11267 char mac_addr[20],dev[20];
11268
11269 nla_parse(tb,
11270 NL80211_ATTR_MAX,
11271 genlmsg_attrdata(gnlh, 0),
11272 genlmsg_attrlen(gnlh, 0),
11273 NULL);
11274
11275 if(!tb[NL80211_ATTR_STA_INFO]) {
11276 fprintf(stderr, "sta stats missing!\n");
11277 return NL_SKIP;
11278 }
11279
11280 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
11281 fprintf(stderr, "failed to parse nested attributes!\n");
11282 return NL_SKIP;
11283 }
11284
11285 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
11286
11287 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
11288
developer386281b2023-05-20 15:43:13 +080011289 if (sinfo[NL80211_STA_INFO_TX_BITRATE]) {
11290 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
11291 fprintf(stderr, "failed to parse nested rate attributes!");
11292 return NL_SKIP;
11293 }
developer72fb0bb2023-01-11 09:46:29 +080011294 }
11295
11296 if(sinfo[NL80211_STA_INFO_TID_STATS])
11297 {
11298 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
11299 printf("failed to parse nested stats attributes!");
11300 return NL_SKIP;
11301 }
11302 }
11303 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
11304 {
11305 printf("Type is VHT\n");
11306 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
11307 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
11308
11309 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
11310 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
11311 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
11312 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
11313 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
11314 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
11315 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
11316 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
11317 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
11318 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
11319 }
11320 else
11321 {
11322 printf(" OFDM or CCK \n");
11323 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
11324 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
11325 }
11326
11327 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
11328 if(rinfo[NL80211_RATE_INFO_MCS])
11329 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
11330 }
11331
11332 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
11333 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
11334 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
11335 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
11336
11337 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
11338 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
11339 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
11340
11341 if(stats_info[NL80211_TID_STATS_TX_MSDU])
11342 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
11343
11344 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
11345 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
11346
11347 if(sinfo[NL80211_STA_INFO_TX_FAILED])
11348 ((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]);
11349
11350 return NL_SKIP;
11351}
11352#endif
11353
11354INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
11355{
11356#ifdef HAL_NETLINK_IMPL
11357 Netlink nl;
11358 char if_name[10];
11359 char interface_name[16] = {0};
11360 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
11361 return RETURN_ERR;
11362
11363 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
11364
11365 if (*output_array_size <= 0)
11366 return RETURN_OK;
11367
11368 snprintf(if_name, sizeof(if_name), "%s", interface_name);
11369
11370 nl.id = initSock80211(&nl);
11371
11372 if(nl.id < 0) {
11373 fprintf(stderr, "Error initializing netlink \n");
11374 return 0;
11375 }
11376
11377 struct nl_msg* msg = nlmsg_alloc();
11378
11379 if(!msg) {
11380 fprintf(stderr, "Failed to allocate netlink message.\n");
11381 nlfree(&nl);
11382 return 0;
11383 }
11384
11385 genlmsg_put(msg,
developer8dd72532023-05-17 19:58:35 +080011386 NL_AUTO_PID,
developer72fb0bb2023-01-11 09:46:29 +080011387 NL_AUTO_SEQ,
11388 nl.id,
11389 0,
11390 0,
11391 NL80211_CMD_GET_STATION,
11392 0);
11393
11394 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
11395 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
11396 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
developer8dd72532023-05-17 19:58:35 +080011397 nl_send_auto_complete(nl.socket, msg);
developer72fb0bb2023-01-11 09:46:29 +080011398 nl_recvmsgs(nl.socket, nl.cb);
11399 nlmsg_free(msg);
11400 nlfree(&nl);
11401 return RETURN_OK;
11402#else
11403 //TODO Implement me
11404 return RETURN_OK;
11405#endif
11406}
11407
11408INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
11409{
11410 // TODO Implement me!
11411 char buf[MAX_BUF_SIZE] = {0};
11412 char config_file[MAX_BUF_SIZE] = {0};
11413
11414 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
11415 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
11416 *activate = (strncmp("1",buf,1) == 0);
11417
11418 return RETURN_OK;
11419}
11420
11421INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
11422{
11423 char config_file[MAX_BUF_SIZE] = {0};
11424 struct params list;
11425
11426 list.name = "rrm_neighbor_report";
11427 list.value = activate?"1":"0";
11428 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
11429 wifi_hostapdWrite(config_file, &list, 1);
11430
11431 return RETURN_OK;
11432}
11433
11434INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
11435{
11436 char buf[32] = {0};
11437 char config_file[MAX_BUF_SIZE] = {0};
11438
11439 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
11440 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
11441 *activate = (strncmp("1",buf,1) == 0);
11442
11443 return RETURN_OK;
11444}
11445#undef HAL_NETLINK_IMPL
11446#ifdef HAL_NETLINK_IMPL
11447static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
11448 struct nlattr *tb[NL80211_ATTR_MAX + 1];
11449 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
11450 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
11451 char dev[20];
11452 int freq =0 ;
11453 static int i=0;
11454
11455 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
11456
11457 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
11458 };
11459
11460 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
11461
11462 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
11463
11464 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
11465 fprintf(stderr, "survey data missing!\n");
11466 return NL_SKIP;
11467 }
11468
11469 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
11470 {
11471 fprintf(stderr, "failed to parse nested attributes!\n");
11472 return NL_SKIP;
11473 }
11474
11475
11476 if(out[0].array_size == 1 )
11477 {
11478 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
11479 {
11480 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
11481 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
11482 out[0].ch_number = ieee80211_frequency_to_channel(freq);
11483
11484 if (sinfo[NL80211_SURVEY_INFO_NOISE])
11485 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
11486 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
11487 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
11488 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
11489 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
11490 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
11491 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
11492 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
11493 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
11494 if (sinfo[NL80211_SURVEY_INFO_TIME])
11495 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
11496 return NL_STOP;
11497 }
11498 }
11499 else
11500 {
11501 if ( i <= out[0].array_size )
11502 {
11503 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
11504 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
11505 out[i].ch_number = ieee80211_frequency_to_channel(freq);
11506
11507 if (sinfo[NL80211_SURVEY_INFO_NOISE])
11508 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
11509 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
11510 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
11511 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
11512 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
11513 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
11514 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
11515 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
11516 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
11517 if (sinfo[NL80211_SURVEY_INFO_TIME])
11518 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
11519 }
11520 }
11521
11522 i++;
11523 return NL_SKIP;
11524}
11525#endif
11526
11527static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
11528{
11529 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
11530 FILE *fp;
11531
11532 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
11533 {
11534 printf("Creating Frequency-Channel Map\n");
11535 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
11536 }
11537 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
11538 if((fp = popen(command, "r")))
11539 {
11540 fgets(output, sizeof(output), fp);
11541 *freqMHz = atoi(output);
11542 pclose(fp);
11543 }
11544
11545 return 0;
11546}
11547
11548static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
11549{
11550 int freqMHz = -1;
11551 char cmd[MAX_CMD_SIZE] = {'\0'};
11552 char interface_name[16] = {0};
11553
11554 ieee80211_channel_to_frequency(channel, &freqMHz);
11555 if (freqMHz == -1) {
11556 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
11557 return -1;
11558 }
11559
11560 wifi_GetInterfaceName(radioIndex, interface_name);
11561 if (sprintf(cmd,"iw dev %s survey dump | grep -A5 %d | tr -d '\\t'", interface_name, freqMHz) < 0) {
11562 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
11563 radioIndex, freqMHz);
11564 return -1;
11565 }
11566
11567 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
11568 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
11569 return -1;
11570 }
11571
11572 return 0;
11573}
11574
11575static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
11576{
11577 const char *ptr = buf;
11578 char *key = NULL;
11579 char *val = NULL;
11580 char line[256] = { '\0' };
11581
11582 while (ptr = get_line_from_str_buf(ptr, line)) {
11583 if (strstr(line, "Frequency")) continue;
11584
11585 key = strtok(line, ":");
11586 val = strtok(NULL, " ");
11587 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
11588
11589 if (!strcmp(key, "noise")) {
11590 sscanf(val, "%d", &stats->ch_noise);
11591 if (stats->ch_noise == 0) {
11592 // Workaround for missing noise information.
11593 // Assume -95 for 2.4G and -103 for 5G
11594 if (radioIndex == 0) stats->ch_noise = -95;
11595 if (radioIndex == 1) stats->ch_noise = -103;
11596 }
11597 }
11598 else if (!strcmp(key, "channel active time")) {
11599 sscanf(val, "%llu", &stats->ch_utilization_total);
11600 }
11601 else if (!strcmp(key, "channel busy time")) {
11602 sscanf(val, "%llu", &stats->ch_utilization_busy);
11603 }
11604 else if (!strcmp(key, "channel receive time")) {
11605 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
11606 }
11607 else if (!strcmp(key, "channel transmit time")) {
11608 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
11609 }
11610 };
11611
11612 return 0;
11613}
11614
11615INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
11616{
11617 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11618#ifdef HAL_NETLINK_IMPL
11619 Netlink nl;
11620 wifi_channelStats_t_loc local[array_size];
11621 char if_name[32];
11622
11623 local[0].array_size = array_size;
11624
11625 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
11626 return RETURN_ERR;
11627
11628 nl.id = initSock80211(&nl);
11629
11630 if (nl.id < 0) {
11631 fprintf(stderr, "Error initializing netlink \n");
11632 return -1;
11633 }
11634
11635 struct nl_msg* msg = nlmsg_alloc();
11636
11637 if (!msg) {
11638 fprintf(stderr, "Failed to allocate netlink message.\n");
11639 nlfree(&nl);
11640 return -2;
11641 }
11642
11643 genlmsg_put(msg,
developer8dd72532023-05-17 19:58:35 +080011644 NL_AUTO_PID,
developer72fb0bb2023-01-11 09:46:29 +080011645 NL_AUTO_SEQ,
11646 nl.id,
11647 0,
11648 NLM_F_DUMP,
11649 NL80211_CMD_GET_SURVEY,
11650 0);
11651
11652 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
developer8dd72532023-05-17 19:58:35 +080011653 nl_send_auto_complete(nl.socket, msg);
developer72fb0bb2023-01-11 09:46:29 +080011654 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
11655 nl_recvmsgs(nl.socket, nl.cb);
11656 nlmsg_free(msg);
11657 nlfree(&nl);
11658 //Copying the Values
11659 for(int i=0;i<array_size;i++)
11660 {
11661 input_output_channelStats_array[i].ch_number = local[i].ch_number;
11662 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
11663 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
11664 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
11665 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
11666 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
11667 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
11668 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
11669 }
11670#else
11671 ULONG channel = 0;
11672 int i;
11673 int number_of_channels = array_size;
11674 char buf[512];
11675 INT ret;
11676 wifi_channelStats_t tmp_stats;
11677
11678 if (number_of_channels == 0) {
11679 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
11680 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
11681 return RETURN_ERR;
11682 }
11683 number_of_channels = 1;
11684 input_output_channelStats_array[0].ch_number = channel;
11685 }
11686
11687 for (i = 0; i < number_of_channels; i++) {
11688
11689 input_output_channelStats_array[i].ch_noise = 0;
11690 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
11691 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
11692 input_output_channelStats_array[i].ch_utilization_busy = 0;
11693 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
11694 input_output_channelStats_array[i].ch_utilization_total = 0;
11695
11696 memset(buf, 0, sizeof(buf));
11697 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
11698 return RETURN_ERR;
11699 }
11700 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
11701 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
11702 return RETURN_ERR;
11703 }
11704
11705 // XXX: fake missing 'self' counter which is not available in iw survey output
11706 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
11707 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
11708
11709 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
11710 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
11711 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
11712 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
11713 input_output_channelStats_array[i].ch_utilization_total *= 1000;
11714
11715 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",
11716 __func__,
11717 input_output_channelStats_array[i].ch_number,
11718 input_output_channelStats_array[i].ch_noise,
11719 input_output_channelStats_array[i].ch_utilization_total,
11720 input_output_channelStats_array[i].ch_utilization_busy,
11721 input_output_channelStats_array[i].ch_utilization_busy_rx,
11722 input_output_channelStats_array[i].ch_utilization_busy_tx,
11723 input_output_channelStats_array[i].ch_utilization_busy_self,
11724 input_output_channelStats_array[i].ch_utilization_busy_ext);
11725 }
11726#endif
11727 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11728 return RETURN_OK;
11729}
11730#define HAL_NETLINK_IMPL
11731
11732/* Hostapd events */
11733
11734#ifndef container_of
11735#define offset_of(st, m) ((size_t)&(((st *)0)->m))
11736#define container_of(ptr, type, member) \
11737 ((type *)((char *)ptr - offset_of(type, member)))
11738#endif /* container_of */
11739
11740struct ctrl {
11741 char sockpath[128];
11742 char sockdir[128];
11743 char bss[IFNAMSIZ];
11744 char reply[4096];
11745 int ssid_index;
11746 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
11747 void (*overrun)(struct ctrl *ctrl);
11748 struct wpa_ctrl *wpa;
11749 unsigned int ovfl;
11750 size_t reply_len;
11751 int initialized;
11752 ev_timer retry;
11753 ev_timer watchdog;
11754 ev_stat stat;
11755 ev_io io;
11756};
11757static wifi_newApAssociatedDevice_callback clients_connect_cb;
11758static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
11759static struct ctrl wpa_ctrl[MAX_APS];
11760static int initialized;
11761
11762static unsigned int ctrl_get_drops(struct ctrl *ctrl)
11763{
11764 char cbuf[256] = {};
11765 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
11766 struct cmsghdr *cmsg;
11767 unsigned int ovfl = ctrl->ovfl;
11768 unsigned int drop;
11769
11770 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
11771 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
11772 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
11773 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
11774
11775 drop = ovfl - ctrl->ovfl;
11776 ctrl->ovfl = ovfl;
11777
11778 return drop;
11779}
11780
11781static void ctrl_close(struct ctrl *ctrl)
11782{
11783 if (ctrl->io.cb)
11784 ev_io_stop(EV_DEFAULT_ &ctrl->io);
11785 if (ctrl->retry.cb)
11786 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
11787 if (!ctrl->wpa)
11788 return;
11789
11790 wpa_ctrl_detach(ctrl->wpa);
11791 wpa_ctrl_close(ctrl->wpa);
11792 ctrl->wpa = NULL;
11793 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
11794}
11795
11796static void ctrl_process(struct ctrl *ctrl)
11797{
11798 const char *str;
11799 int drops;
11800 int level;
11801 int err;
11802
11803 /* Example events:
11804 *
11805 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
11806 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
11807 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
11808 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
11809 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
11810 */
11811 if (!(str = index(ctrl->reply, '>')))
11812 return;
11813 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
11814 return;
11815
11816 str++;
11817
11818 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
11819 if (!(str = index(ctrl->reply, ' ')))
11820 return;
11821 wifi_associated_dev_t sta;
11822 memset(&sta, 0, sizeof(sta));
11823
11824 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
11825 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
11826 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
11827
11828 sta.cli_Active=true;
11829
11830 (clients_connect_cb)(ctrl->ssid_index, &sta);
11831 goto handled;
11832 }
11833
11834 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
11835 if (!(str = index(ctrl->reply, ' ')))
11836 return;
11837
11838 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
11839 goto handled;
11840 }
11841
11842 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
11843 printf("CTRL_WPA: handle TERMINATING event\n");
11844 goto retry;
11845 }
11846
11847 if (strncmp("AP-DISABLED", str, 11) == 0) {
11848 printf("CTRL_WPA: handle AP-DISABLED\n");
11849 goto retry;
11850 }
11851
11852 printf("Event not supported!!\n");
11853
11854handled:
11855
11856 if ((drops = ctrl_get_drops(ctrl))) {
11857 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
11858 if (ctrl->overrun)
11859 ctrl->overrun(ctrl);
11860 }
11861
11862 return;
11863
11864retry:
11865 printf("WPA_CTRL: closing\n");
11866 ctrl_close(ctrl);
11867 printf("WPA_CTRL: retrying from ctrl prcoess\n");
11868 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
11869}
11870
11871static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
11872{
11873 struct ctrl *ctrl = container_of(io, struct ctrl, io);
11874 int err;
11875
11876 memset(ctrl->reply, 0, sizeof(ctrl->reply));
11877 ctrl->reply_len = sizeof(ctrl->reply) - 1;
11878 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
11879 ctrl->reply[ctrl->reply_len] = 0;
11880 if (err < 0) {
11881 if (errno == EAGAIN || errno == EWOULDBLOCK)
11882 return;
11883 ctrl_close(ctrl);
11884 ev_timer_again(EV_A_ &ctrl->retry);
11885 return;
11886 }
11887
11888 ctrl_process(ctrl);
11889}
11890
11891static int ctrl_open(struct ctrl *ctrl)
11892{
11893 int fd;
11894
11895 if (ctrl->wpa)
11896 return 0;
11897
11898 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
11899 if (!ctrl->wpa)
11900 goto err;
11901
11902 if (wpa_ctrl_attach(ctrl->wpa) < 0)
11903 goto err_close;
11904
11905 fd = wpa_ctrl_get_fd(ctrl->wpa);
11906 if (fd < 0)
11907 goto err_detach;
11908
11909 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
11910 goto err_detach;
11911
11912 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
11913 ev_io_start(EV_DEFAULT_ &ctrl->io);
11914
11915 return 0;
11916
11917err_detach:
11918 wpa_ctrl_detach(ctrl->wpa);
11919err_close:
11920 wpa_ctrl_close(ctrl->wpa);
11921err:
11922 ctrl->wpa = NULL;
11923 return -1;
11924}
11925
11926static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
11927{
11928 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
11929
11930 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
11931 ctrl_open(ctrl);
11932}
11933
11934static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
11935{
11936 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
11937
11938 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
11939 if (ctrl_open(ctrl) == 0) {
11940 printf("WPA_CTRL: retry successful\n");
11941 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
11942 }
11943}
11944
11945int ctrl_enable(struct ctrl *ctrl)
11946{
11947 if (ctrl->wpa)
11948 return 0;
11949
11950 if (!ctrl->stat.cb) {
11951 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
11952 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
11953 }
11954
11955 if (!ctrl->retry.cb) {
11956 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
11957 }
11958
11959 return ctrl_open(ctrl);
11960}
11961
11962static void
11963ctrl_msg_cb(char *buf, size_t len)
11964{
11965 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
11966
11967 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
11968 ctrl_process(ctrl);
11969}
11970
11971static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
11972{
11973 int err;
11974
11975 if (!ctrl->wpa)
11976 return -1;
11977 if (*reply_len < 2)
11978 return -1;
11979
11980 (*reply_len)--;
11981 ctrl->reply_len = sizeof(ctrl->reply);
11982 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
11983 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
11984 if (err < 0)
11985 return err;
11986
11987 if (ctrl->reply_len > *reply_len)
11988 ctrl->reply_len = *reply_len;
11989
11990 *reply_len = ctrl->reply_len;
11991 memcpy(reply, ctrl->reply, *reply_len);
11992 reply[*reply_len - 1] = 0;
11993 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
11994 return 0;
11995}
11996
11997static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
11998{
11999 const char *pong = "PONG";
12000 const char *ping = "PING";
12001 char reply[1024];
12002 size_t len = sizeof(reply);
12003 int err;
12004 ULONG s, snum;
12005 INT ret;
12006 BOOL status;
12007
12008 printf("WPA_CTRL: watchdog cb\n");
12009
12010 ret = wifi_getSSIDNumberOfEntries(&snum);
12011 if (ret != RETURN_OK) {
12012 printf("%s: failed to get SSID count", __func__);
12013 return;
12014 }
12015
12016 if (snum > MAX_APS) {
12017 printf("more ssid than supported! %lu\n", snum);
12018 return;
12019 }
12020
12021 for (s = 0; s < snum; s++) {
12022 if (wifi_getApEnable(s, &status) != RETURN_OK) {
12023 printf("%s: failed to get AP Enable for index: %lu\n", __func__, s);
12024 continue;
12025 }
12026 if (status == false) continue;
12027
12028 memset(reply, 0, sizeof(reply));
12029 len = sizeof(reply);
12030 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
12031 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
12032 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
12033 continue;
12034
12035 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
12036 ctrl_close(&wpa_ctrl[s]);
12037 printf("WPA_CTRL: ev_timer_again %lu\n", s);
12038 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
12039 }
12040}
12041
12042static int init_wpa()
12043{
12044 int ret = 0, i = 0;
12045 ULONG s, snum;
12046
12047 ret = wifi_getSSIDNumberOfEntries(&snum);
12048 if (ret != RETURN_OK) {
12049 printf("%s: failed to get SSID count", __func__);
12050 return RETURN_ERR;
12051 }
12052
12053 if (snum > MAX_APS) {
12054 printf("more ssid than supported! %lu\n", snum);
12055 return RETURN_ERR;
12056 }
12057
12058 for (s = 0; s < snum; s++) {
12059 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
12060 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
12061 wpa_ctrl[s].ssid_index = s;
12062 ctrl_enable(&wpa_ctrl[s]);
12063 }
12064
12065 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
12066 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
12067
12068 initialized = 1;
12069 printf("WPA_CTRL: initialized\n");
12070
12071 return RETURN_OK;
12072}
12073
12074void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
12075{
12076 clients_connect_cb = callback_proc;
12077 if (!initialized)
12078 init_wpa();
12079}
12080
12081void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
12082{
12083 clients_disconnect_cb = callback_proc;
12084 if (!initialized)
12085 init_wpa();
12086}
12087
12088INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
12089{
12090 // TODO Implement me!
12091 return RETURN_ERR;
12092}
12093
12094INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
12095{
12096 // TODO Implement me!
12097 return RETURN_ERR;
12098}
12099
12100INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
12101{
12102 int i;
developerd1824452023-05-18 12:30:04 +080012103 int phyId = -1;
12104 char cmd[256] = {0};
12105 char channel_numbers_buf[256] = {0};
12106 char dfs_state_buf[256] = {0};
12107 char line[256] = {0};
developer72fb0bb2023-01-11 09:46:29 +080012108 const char *ptr;
developerd1824452023-05-18 12:30:04 +080012109 BOOL dfs_enable = false;
developer72fb0bb2023-01-11 09:46:29 +080012110
developerd1824452023-05-18 12:30:04 +080012111 memset(outputMap, 0, outputMapSize*sizeof(wifi_channelMap_t)); // all unused entries should be zero
developer72fb0bb2023-01-11 09:46:29 +080012112
developerd1824452023-05-18 12:30:04 +080012113 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
12114 phyId = radio_index_to_phy(radioIndex);
developer72fb0bb2023-01-11 09:46:29 +080012115
developerd1824452023-05-18 12:30:04 +080012116 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 +080012117
developerd1824452023-05-18 12:30:04 +080012118 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
12119 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
12120 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +080012121 }
12122
developerd1824452023-05-18 12:30:04 +080012123 ptr = channel_numbers_buf;
12124 i = 0;
12125 while (ptr = get_line_from_str_buf(ptr, line)) {
12126 if (i >= outputMapSize) {
12127 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
12128 return RETURN_ERR;
12129 }
12130 sscanf(line, "%d", &outputMap[i].ch_number);
12131
12132 memset(cmd, 0, sizeof(cmd));
12133 // Below command should fetch string for DFS state (usable, available or unavailable)
12134 // Example line: "DFS state: usable (for 78930 sec)"
12135 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) {
12136 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
developer72fb0bb2023-01-11 09:46:29 +080012137 return RETURN_ERR;
12138 }
12139
developerd1824452023-05-18 12:30:04 +080012140 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
12141 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
developer72fb0bb2023-01-11 09:46:29 +080012142 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
12143 return RETURN_ERR;
12144 }
12145
developerd1824452023-05-18 12:30:04 +080012146 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
developer59fda4f2023-05-16 15:47:38 +080012147
developerd1824452023-05-18 12:30:04 +080012148 if (!strcmp(dfs_state_buf, "usable")) {
12149 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
12150 } else if (!strcmp(dfs_state_buf, "available")) {
12151 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
12152 } else if (!strcmp(dfs_state_buf, "unavailable")) {
12153 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
12154 } else {
12155 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
developer72fb0bb2023-01-11 09:46:29 +080012156 }
developerd1824452023-05-18 12:30:04 +080012157 i++;
developer59fda4f2023-05-16 15:47:38 +080012158 }
developer40ba1762023-05-13 11:03:49 +080012159
developerd1824452023-05-18 12:30:04 +080012160 return RETURN_OK;
12161
developer72fb0bb2023-01-11 09:46:29 +080012162 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
12163 return RETURN_ERR;
12164}
12165
12166INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
12167{
12168 // TODO Implement me!
12169 return RETURN_ERR;
12170}
12171
12172INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
12173{
12174 return RETURN_OK;
12175}
12176
12177INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
12178{
12179 // TODO Implement me!
12180 return RETURN_ERR;
12181}
12182
12183INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
12184{
12185 // TODO API refrence Implementaion is present on RPI hal
12186 return RETURN_ERR;
12187}
12188
12189INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
12190{
developera1255e42023-05-13 17:45:02 +080012191/*
developer72fb0bb2023-01-11 09:46:29 +080012192 char interface_name[16] = {0};
12193 char cmd[128]={'\0'};
12194 char buf[128]={'\0'};
12195 char *support;
12196 int maximum_tx = 0, current_tx = 0;
developera1255e42023-05-13 17:45:02 +080012197*/ ULONG pwr_percentage = 0;
developer72fb0bb2023-01-11 09:46:29 +080012198
12199 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12200 if(txpwr_pcntg == NULL)
12201 return RETURN_ERR;
12202
developera1255e42023-05-13 17:45:02 +080012203 wifi_getRadioTransmitPower(apIndex, &pwr_percentage);
12204 *txpwr_pcntg = pwr_percentage;
12205/* if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72fb0bb2023-01-11 09:46:29 +080012206 return RETURN_ERR;
12207
12208 // Get the maximum tx power of the device
12209 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", interface_name);
12210 _syscmd(cmd, buf, sizeof(buf));
12211 maximum_tx = strtol(buf, NULL, 10);
12212
12213 // Get the current tx power
12214 memset(cmd, 0, sizeof(cmd));
12215 memset(buf, 0, sizeof(buf));
12216 snprintf(cmd, sizeof(cmd), "iw %s info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", interface_name);
12217 _syscmd(cmd, buf, sizeof(buf));
12218 current_tx = strtol(buf, NULL, 10);
12219
12220 // Get the power supported list and find the current power percentage in supported list
12221 memset(buf, 0, sizeof(buf));
12222 wifi_getRadioTransmitPowerSupported(apIndex, buf);
12223 support = strtok(buf, ",");
12224 while(true)
12225 {
12226 if(support == NULL) { // current power is not in supported list, this should not happen if the power is set by hal.
12227 *txpwr_pcntg = 100;
12228 wifi_dbg_printf("current power is not in supported list\n");
12229 return RETURN_OK;
12230 }
12231 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
12232 if (tmp == current_tx) {
12233 *txpwr_pcntg = strtol(support, NULL, 10);
12234 break;
12235 }
12236 support = strtok(NULL, ",");
12237 }
developera1255e42023-05-13 17:45:02 +080012238*/
developer72fb0bb2023-01-11 09:46:29 +080012239 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12240 return RETURN_OK;
12241}
12242
12243INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
12244{
12245 // TODO precac feature.
developerd1824452023-05-18 12:30:04 +080012246 struct params params[2] = {0};
developer72fb0bb2023-01-11 09:46:29 +080012247 char config_file[128] = {0};
developerd1824452023-05-18 12:30:04 +080012248 BOOL dfs_enable = false;
12249 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +080012250
12251 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developerd1824452023-05-18 12:30:04 +080012252 band = wifi_index_to_band(radioIndex);
12253 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
developer72fb0bb2023-01-11 09:46:29 +080012254
developerd1824452023-05-18 12:30:04 +080012255 if (dfs_enable == false) {
12256 WIFI_ENTRY_EXIT_DEBUG("Please enable DFS firstly!: %s\n", __func__);
12257 return RETURN_ERR;
12258 }
12259 params[0].name = "DfsZeroWaitDefault";
12260 params[0].value = enable?"1":"0";
12261 params[1].name = "DfsDedicatedZeroWait";
12262 params[1].value = enable?"1":"0";
12263 snprintf(config_file, sizeof(config_file), "%s%d.dat", LOGAN_DAT_FILE, band);
12264 wifi_datfileWrite(config_file, params, 2);
developerc0772e62023-05-18 15:10:48 +080012265 wifi_reloadAp(radioIndex);
developer72fb0bb2023-01-11 09:46:29 +080012266 /* TODO precac feature */
12267
12268 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12269 return RETURN_OK;
12270}
12271
12272INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
12273{
12274 char config_file[128] = {0};
developerd1824452023-05-18 12:30:04 +080012275 char buf1[32] = {0};
12276 char buf2[32] = {0};
12277 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +080012278
12279 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12280 if (NULL == enable || NULL == precac)
12281 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +080012282 band = wifi_index_to_band(radioIndex);
12283 snprintf(config_file, sizeof(config_file), "%s%d.dat", LOGAN_DAT_FILE, band);
12284 wifi_datfileRead(config_file, "DfsZeroWaitDefault", buf1, sizeof(buf1));
12285 wifi_datfileRead(config_file, "DfsDedicatedZeroWait", buf2, sizeof(buf2));
12286 if ((strncmp(buf1, "1", 1) == 0) && (strncmp(buf2, "1", 1) == 0))
developer72fb0bb2023-01-11 09:46:29 +080012287 *enable = true;
12288 else
12289 *enable = false;
12290
12291 /* TODO precac feature */
12292
12293 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12294 return RETURN_OK;
12295}
12296
12297INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
12298{
12299 *supported = TRUE;
12300 return RETURN_OK;
12301}
12302
12303INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
12304{
developera1255e42023-05-13 17:45:02 +080012305 UCHAR dat_file[64] = {0};
12306 wifi_band band = band_invalid;
12307 char cmd[128] = {0};
12308 char buf[256] = {0};
12309 char ofdmabuf[32] = {'\0'};
12310 char mimobuf[32] = {'\0'};
12311 char new_ofdmabuf[32] = {'\0'};
12312 char new_mimobuf[32] = {'\0'};
12313 struct params params[2];
12314 char *str_zero = "0;0;0;0;0;0;0;0;0;0;0;0;0;0;0";/*default 15bss per band.*/
12315 char *str_one = "1;1;1;1;1;1;1;1;1;1;1;1;1;1;1";
12316 UCHAR bss_cnt = 0;
12317 UCHAR val_cnt = 0;
12318 char *token = NULL;
developer72fb0bb2023-01-11 09:46:29 +080012319
developera1255e42023-05-13 17:45:02 +080012320 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12321 if ((mu_type < WIFI_DL_MU_TYPE_NONE)
12322 || (mu_type > WIFI_DL_MU_TYPE_OFDMA_MIMO)) {
12323 printf("%s:mu_type input Error", __func__);
12324 return RETURN_ERR;
12325 }
12326 band = wifi_index_to_band(radio_index);
12327 if (band == band_invalid) {
12328 printf("%s:Band Error\n", __func__);
12329 return RETURN_ERR;
12330 }
12331 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
12332 /*get current value in dat file*/
12333 wifi_datfileRead(dat_file, "MuOfdmaDlEnable", ofdmabuf, sizeof(ofdmabuf));
12334 wifi_datfileRead(dat_file, "MuMimoDlEnable", mimobuf, sizeof(mimobuf));
12335 WIFI_ENTRY_EXIT_DEBUG("%s:ofdma-%s, mimo-%s\n", __func__, ofdmabuf, mimobuf);
12336 get_bssnum_byindex(radio_index, &bss_cnt);
12337 val_cnt = 2*bss_cnt - 1;
12338 WIFI_ENTRY_EXIT_DEBUG("bss number: %d\n", bss_cnt);
12339 if ((val_cnt >= sizeof(new_ofdmabuf))
12340 || (val_cnt >= sizeof(new_mimobuf))) {
12341 printf("%s:bss cnt Error", __func__, bss_cnt);
12342 return RETURN_ERR;
12343 }
12344 /*translate set value*/
12345 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
12346 strncpy(new_ofdmabuf, str_zero, val_cnt);
12347 strncpy(new_mimobuf, str_zero, val_cnt);
developer72fb0bb2023-01-11 09:46:29 +080012348 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
developera1255e42023-05-13 17:45:02 +080012349 strncpy(new_ofdmabuf, str_one, val_cnt);
12350 strncpy(new_mimobuf, str_zero, val_cnt);
developer72fb0bb2023-01-11 09:46:29 +080012351 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
developera1255e42023-05-13 17:45:02 +080012352 strncpy(new_ofdmabuf, str_zero, val_cnt);
12353 strncpy(new_mimobuf, str_one, val_cnt);
12354 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO) {
12355 strncpy(new_ofdmabuf, str_one, val_cnt);
12356 strncpy(new_mimobuf, str_one, val_cnt);
developer72fb0bb2023-01-11 09:46:29 +080012357 }
developera1255e42023-05-13 17:45:02 +080012358 WIFI_ENTRY_EXIT_DEBUG("%s:new_ofdmabuf-%s, new_mimobuf-%s\n", __func__, new_ofdmabuf, new_mimobuf);
12359 /*same value, not operation*/
12360 if ((strncmp(new_mimobuf, mimobuf, 1) ==0)
12361 && (strncmp(new_ofdmabuf, ofdmabuf, 1) ==0)) {
12362 printf("%s:Reduntant value\n", __func__);
12363 return RETURN_OK;
12364 }
12365 /*modify dat file to new file*/
12366 params[0].name="MuOfdmaDlEnable";
12367 params[0].value=new_ofdmabuf;
12368 params[1].name="MuMimoDlEnable";
12369 params[1].value=new_mimobuf;
12370 wifi_datfileWrite(dat_file, params, 2);
12371 /*hostapd control restarp ap to take effect on these new value*/
12372 wifi_reloadAp(radio_index);
developer72fb0bb2023-01-11 09:46:29 +080012373 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12374 return RETURN_OK;
12375}
12376
12377INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
12378{
12379 struct params params={0};
12380 char config_file[64] = {0};
12381 char buf[64] = {0};
12382 unsigned int get_mu_type = 0;
developera1255e42023-05-13 17:45:02 +080012383 UCHAR dat_file[64] = {0};
12384 wifi_band band = band_invalid;
12385 char ofdmabuf[32] = {'\0'};
12386 char mimobuf[32] = {'\0'};
12387 char *token = NULL;
12388 UCHAR ofdma = 0;
12389 UCHAR mimo = 0;
developer72fb0bb2023-01-11 09:46:29 +080012390
12391 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12392
12393 if (mu_type == NULL)
12394 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +080012395 band = wifi_index_to_band(radio_index);
12396 if (band == band_invalid) {
12397 printf("%s:Band Error\n", __func__);
12398 return RETURN_ERR;
12399 }
12400 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
12401 /*get current value in dat file*/
12402 wifi_datfileRead(dat_file, "MuOfdmaDlEnable", ofdmabuf, sizeof(ofdmabuf));
12403 wifi_datfileRead(dat_file, "MuMimoDlEnable", mimobuf, sizeof(mimobuf));
developer72fb0bb2023-01-11 09:46:29 +080012404
developera1255e42023-05-13 17:45:02 +080012405 token = strtok(ofdmabuf, ";");
12406 ofdma = strtol(token, NULL, 10);
12407 token = strtok(mimobuf, ";");
12408 mimo = strtol(token, NULL, 10);
12409 WIFI_ENTRY_EXIT_DEBUG("%s:ofdma=%d,mimo=%d\n", __func__, ofdma, mimo);
12410 if ((ofdma == 1) && (mimo == 1))
12411 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
12412 else if ((ofdma == 0) && (mimo == 1))
12413 *mu_type = WIFI_DL_MU_TYPE_MIMO;
12414 else if ((ofdma == 1) && (mimo == 0))
12415 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
12416 else
12417 *mu_type = WIFI_DL_MU_TYPE_NONE;
developer72fb0bb2023-01-11 09:46:29 +080012418 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12419 return RETURN_OK;
12420}
12421
12422INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
12423{
12424 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
developera1255e42023-05-13 17:45:02 +080012425 UCHAR dat_file[64] = {0};
12426 wifi_band band = band_invalid;
12427 char cmd[128] = {0};
12428 char buf[256] = {0};
12429 char ofdmabuf[32] = {'\0'};
12430 char mimobuf[32] = {'\0'};
12431 char new_ofdmabuf[32] = {'\0'};
12432 char new_mimobuf[32] = {'\0'};
12433 struct params params[2];
12434 char *str_zero = "0;0;0;0;0;0;0;0;0;0;0;0;0;0;0";/*default 15bss per band.*/
12435 char *str_one = "1;1;1;1;1;1;1;1;1;1;1;1;1;1;1";
12436 UCHAR bss_cnt = 0;
12437 UCHAR val_cnt = 0;
developer72fb0bb2023-01-11 09:46:29 +080012438
developera1255e42023-05-13 17:45:02 +080012439 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12440 band = wifi_index_to_band(radio_index);
12441 if (band == band_invalid) {
12442 printf("%s:Band Error\n", __func__);
12443 return RETURN_ERR;
12444 }
12445 if ((mu_type < WIFI_UL_MU_TYPE_NONE)
12446 || (mu_type > WIFI_UL_MU_TYPE_OFDMA)) {
12447 printf("%s:mu_type input Error\n", __func__);
12448 return RETURN_ERR;
12449 }
12450 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
12451 /*get current value in dat file*/
12452 wifi_datfileRead(dat_file, "MuOfdmaUlEnable", ofdmabuf, sizeof(ofdmabuf));
12453 wifi_datfileRead(dat_file, "MuMimoUlEnable", mimobuf, sizeof(mimobuf));
12454 WIFI_ENTRY_EXIT_DEBUG("%s:ofdma-%s, mimo-%s\n", __func__, ofdmabuf, mimobuf);
12455 get_bssnum_byindex(radio_index, &bss_cnt);
12456 val_cnt = 2*bss_cnt - 1;
12457 printf("bssNumber:%d,ValCnt:%d\n", bss_cnt, val_cnt);
12458 if ((val_cnt >= sizeof(new_ofdmabuf))
12459 || (val_cnt >= sizeof(new_mimobuf))) {
12460 printf("%s:bss cnt Error\n", __func__, val_cnt);
12461 return RETURN_ERR;
12462 }
12463 /*translate set value*/
12464 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
12465 strncpy(new_ofdmabuf, str_zero, val_cnt);
12466 strncpy(new_mimobuf, str_zero, val_cnt);
developer72fb0bb2023-01-11 09:46:29 +080012467 }
developera1255e42023-05-13 17:45:02 +080012468 if (mu_type == WIFI_UL_MU_TYPE_OFDMA) {
12469 strncpy(new_ofdmabuf, str_one, val_cnt);
12470 strncpy(new_mimobuf, str_zero, val_cnt);
12471 }
12472 printf("%s:new_ofdmabuf-%s, new_mimobuf-%s\n", __func__, new_ofdmabuf, new_mimobuf);
12473 /*same value, not operation*/
12474 if ((strncmp(new_mimobuf, mimobuf, 1) ==0)
12475 && (strncmp(new_ofdmabuf, ofdmabuf, 1) ==0)) {
12476 printf("%s:Reduntant value\n", __func__);
12477 return RETURN_OK;
12478 }
12479 /*modify dat file to new file*/
12480 params[0].name="MuOfdmaUlEnable";
12481 params[0].value=new_ofdmabuf;
12482 params[1].name="MuMimoUlEnable";
12483 params[1].value=new_mimobuf;
12484 wifi_datfileWrite(dat_file, params, 2);
12485 wifi_reloadAp(radio_index);
developer72fb0bb2023-01-11 09:46:29 +080012486 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12487 return RETURN_OK;
12488}
12489
12490INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
12491{
12492 struct params params={0};
12493 char config_file[64] = {0};
12494 char buf[64] = {0};
12495 unsigned int get_mu_type = 0;
developera1255e42023-05-13 17:45:02 +080012496 UCHAR dat_file[64] = {0};
12497 wifi_band band = band_invalid;
12498 char ofdmabuf[32] = {'\0'};
12499 char mimobuf[32] = {'\0'};
12500 char *token = NULL;
12501 UCHAR ofdma = 0;
12502 UCHAR mimo = 0;
developer72fb0bb2023-01-11 09:46:29 +080012503
12504 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12505
12506 if (mu_type == NULL)
12507 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +080012508 band = wifi_index_to_band(radio_index);
12509 if (band == band_invalid) {
12510 printf("%s:Band Error", __func__);
12511 return RETURN_ERR;
12512 }
12513 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
12514 /*get current value in dat file*/
12515 wifi_datfileRead(dat_file, "MuOfdmaUlEnable", ofdmabuf, sizeof(ofdmabuf));
12516 wifi_datfileRead(dat_file, "MuMimoUlEnable", mimobuf, sizeof(mimobuf));
developer72fb0bb2023-01-11 09:46:29 +080012517
developera1255e42023-05-13 17:45:02 +080012518 token = strtok(ofdmabuf, ";");
12519 ofdma = strtol(token, NULL, 10);
12520 token = strtok(mimobuf, ";");
12521 mimo = strtol(token, NULL, 10);
12522 WIFI_ENTRY_EXIT_DEBUG("%s:ofdma=%d, mimo=%d\n", __func__, ofdma, mimo);
12523 if ((ofdma == 1) && (mimo == 0))
12524 *mu_type = WIFI_UL_MU_TYPE_OFDMA;
12525 else
12526 *mu_type = WIFI_UL_MU_TYPE_NONE;
developer72fb0bb2023-01-11 09:46:29 +080012527 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12528 return RETURN_OK;
12529}
12530
12531
12532INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
12533{
12534 char cmd[128] = {0};
12535 char buf[256] = {0};
12536 char config_file[64] = {0};
12537 char GI[8] = {0};
12538 int mode_map = 0;
12539 FILE *f = NULL;
12540 wifi_band band = band_invalid;
developera1255e42023-05-13 17:45:02 +080012541 char dat_file[64] = {'\0'};
12542 struct params params[3];
developer72fb0bb2023-01-11 09:46:29 +080012543
12544 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12545
12546 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
12547 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
12548 return RETURN_ERR;
12549 }
developera1255e42023-05-13 17:45:02 +080012550 /*sanity check*/
12551 if (((guard_interval == wifi_guard_interval_1600)
12552 || (guard_interval == wifi_guard_interval_3200))
12553 && (mode_map & (WIFI_MODE_BE | WIFI_MODE_AX) == 0)) {
12554 wifi_dbg_printf("%s: N/AC Mode not support 1600/3200ns GI\n", __func__);
12555 return RETURN_ERR;
12556 }
developer72fb0bb2023-01-11 09:46:29 +080012557 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
12558 band = wifi_index_to_band(radio_index);
12559
12560 // Hostapd are not supported HE mode GI 1600, 3200 ns.
12561 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
12562 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
12563 _syscmd(cmd, buf, sizeof(buf));
12564 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
12565 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
12566 if (strstr(buf, "[SHORT-GI-") == NULL) {
12567 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[SHORT-GI-20][SHORT-GI-40]/' %s", config_file);
12568 _syscmd(cmd, buf, sizeof(buf));
12569 }
12570 if (band == band_5) {
12571 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
12572 if (strstr(buf, "[SHORT-GI-") == NULL) {
12573 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SHORT-GI-80][SHORT-GI-160]/' %s", config_file);
12574 _syscmd(cmd, buf, sizeof(buf));
12575 }
12576 }
12577 }
developera1255e42023-05-13 17:45:02 +080012578 /*wifi_reloadAp(radio_index);
12579 caller "wifi_setRadioOperatingParameters" have done this step.
12580 */
12581 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
12582 if (guard_interval == wifi_guard_interval_400) {
12583 params[0].name = "HT_GI";
12584 params[0].value = "1";
12585 params[1].name = "VHT_SGI";
12586 params[1].value = "1";
12587 wifi_datfileWrite(dat_file, params, 2);
developer72fb0bb2023-01-11 09:46:29 +080012588 strcpy(GI, "0.4");
developera1255e42023-05-13 17:45:02 +080012589 } else {
12590 params[0].name = "HT_GI";
12591 params[0].value = "0";
12592 params[1].name = "VHT_SGI";
12593 params[1].value = "0";
12594 /*should enable FIXED_HE_GI_SUPPORT in driver*/
12595 params[2].name = "FgiFltf";
12596 if (guard_interval == wifi_guard_interval_800) {
12597 params[2].value = "800";
12598 strcpy(GI, "0.8");
12599 } else if (guard_interval == wifi_guard_interval_1600) {
12600 params[2].value = "1600";
12601 strcpy(GI, "1.6");
12602 } else if (guard_interval == wifi_guard_interval_3200) {
12603 params[2].value = "3200";
12604 strcpy(GI, "3.2");
12605 } else if (guard_interval == wifi_guard_interval_auto) {
12606 params[2].value = "0";
12607 strcpy(GI, "auto");
12608 }
12609 wifi_datfileWrite(dat_file, params, 3);
12610 }
developer72fb0bb2023-01-11 09:46:29 +080012611 // Record GI for get GI function
12612 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
12613 f = fopen(buf, "w");
12614 if (f == NULL)
12615 return RETURN_ERR;
12616 fprintf(f, "%s", GI);
12617 fclose(f);
12618 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12619 return RETURN_OK;
12620}
12621
12622INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
12623{
12624 char buf[32] = {0};
12625 char cmd[64] = {0};
12626
12627 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12628
12629 if (guard_interval == NULL)
12630 return RETURN_ERR;
12631
developera1255e42023-05-13 17:45:02 +080012632 snprintf(cmd, sizeof(cmd), "cat %s%d.txt 2> /dev/null", GUARD_INTERVAL_FILE, radio_index);
developer72fb0bb2023-01-11 09:46:29 +080012633 _syscmd(cmd, buf, sizeof(buf));
12634
12635 if (strncmp(buf, "0.4", 3) == 0)
12636 *guard_interval = wifi_guard_interval_400;
12637 else if (strncmp(buf, "0.8", 3) == 0)
12638 *guard_interval = wifi_guard_interval_800;
12639 else if (strncmp(buf, "1.6", 3) == 0)
12640 *guard_interval = wifi_guard_interval_1600;
12641 else if (strncmp(buf, "3.2", 3) == 0)
12642 *guard_interval = wifi_guard_interval_3200;
12643 else
12644 *guard_interval = wifi_guard_interval_auto;
12645
12646 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12647 return RETURN_OK;
12648}
12649
12650INT wifi_setBSSColor(INT radio_index, UCHAR color)
12651{
12652 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12653 struct params params = {0};
12654 char config_file[128] = {0};
12655 char bss_color[4] ={0};
12656
developera1255e42023-05-13 17:45:02 +080012657 if (color < 1 || color > 63) {
12658 wifi_dbg_printf("color value is err:%d.\n", color);
12659 return RETURN_ERR;
12660 }
developer72fb0bb2023-01-11 09:46:29 +080012661 params.name = "he_bss_color";
12662 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
12663 params.value = bss_color;
12664 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
12665 wifi_hostapdWrite(config_file, &params, 1);
developera1255e42023-05-13 17:45:02 +080012666 //wifi_hostapdProcessUpdate(radio_index, &params, 1);
12667 wifi_reloadAp(radio_index);
developer69b61b02023-03-07 17:17:44 +080012668
developer72fb0bb2023-01-11 09:46:29 +080012669 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12670 return RETURN_OK;
12671}
12672
12673INT wifi_getBSSColor(INT radio_index, UCHAR *color)
12674{
12675 char config_file[128] = {0};
12676 char buf[64] = {0};
12677 char temp_output[128] = {'\0'};
12678
12679 wifi_dbg_printf("\nFunc=%s\n", __func__);
12680 if (NULL == color)
12681 return RETURN_ERR;
12682
12683 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
12684 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
12685
12686 if(strlen(buf) > 0) {
12687 snprintf(temp_output, sizeof(temp_output), "%s", buf);
12688 } else {
12689 snprintf(temp_output, sizeof(temp_output), "1"); // default value
12690 }
12691
12692 *color = (UCHAR)strtoul(temp_output, NULL, 10);
12693 wifi_dbg_printf("\noutput_string=%s\n", color);
12694
12695 return RETURN_OK;
12696}
12697
12698/* multi-psk support */
12699INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
12700{
12701 char cmd[256];
12702 char interface_name[16] = {0};
12703
12704 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
12705 return RETURN_ERR;
12706
12707 sprintf(cmd, "hostapd_cli -i %s sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
12708 interface_name,
12709 mac[0],
12710 mac[1],
12711 mac[2],
12712 mac[3],
12713 mac[4],
12714 mac[5]
12715 );
12716 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
12717 _syscmd(cmd, key->wifi_keyId, 64);
12718
12719
12720 return RETURN_OK;
12721}
12722
12723INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
12724{
12725 char interface_name[16] = {0};
12726 FILE *fd = NULL;
12727 char fname[100];
12728 char cmd[128] = {0};
12729 char out[64] = {0};
12730 wifi_key_multi_psk_t * key = NULL;
12731 if(keysNumber < 0)
12732 return RETURN_ERR;
12733
12734 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
12735 fd = fopen(fname, "w");
12736 if (!fd) {
12737 return RETURN_ERR;
12738 }
12739 key= (wifi_key_multi_psk_t *) keys;
12740 for(int i=0; i<keysNumber; ++i, key++) {
12741 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
12742 }
12743 fclose(fd);
12744
12745 //reload file
12746 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
12747 return RETURN_ERR;
12748 sprintf(cmd, "hostapd_cli -i%s raw RELOAD_WPA_PSK", interface_name);
12749 _syscmd(cmd, out, 64);
12750 return RETURN_OK;
12751}
12752
12753INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
12754{
12755 FILE *fd = NULL;
12756 char fname[100];
12757 char * line = NULL;
12758 char * pos = NULL;
12759 size_t len = 0;
12760 ssize_t read = 0;
12761 INT ret = RETURN_OK;
12762 wifi_key_multi_psk_t *keys_it = NULL;
12763
12764 if (keysNumber < 1) {
12765 return RETURN_ERR;
12766 }
12767
12768 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
12769 fd = fopen(fname, "r");
12770 if (!fd) {
12771 return RETURN_ERR;
12772 }
12773
12774 if (keys == NULL) {
12775 ret = RETURN_ERR;
12776 goto close;
12777 }
12778
12779 keys_it = keys;
12780 while ((read = getline(&line, &len, fd)) != -1) {
12781 //Strip trailing new line if present
12782 if (read > 0 && line[read-1] == '\n') {
12783 line[read-1] = '\0';
12784 }
12785
12786 if(strcmp(line,"keyid=")) {
12787 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
12788 if (!(pos = index(line, ' '))) {
12789 ret = RETURN_ERR;
12790 goto close;
12791 }
12792 pos++;
12793 //Here should be 00:00:00:00:00:00
12794 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
12795 printf("Not supported MAC: %s\n", pos);
12796 }
12797 if (!(pos = index(pos, ' '))) {
12798 ret = RETURN_ERR;
12799 goto close;
12800 }
12801 pos++;
12802
12803 //The rest is PSK
12804 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
12805 keys_it++;
12806
12807 if(--keysNumber <= 0)
12808 break;
12809 }
12810 }
12811
12812close:
12813 free(line);
12814 fclose(fd);
12815 return ret;
12816}
12817/* end of multi-psk support */
12818
12819INT wifi_setNeighborReports(UINT apIndex,
12820 UINT numNeighborReports,
12821 wifi_NeighborReport_t *neighborReports)
12822{
12823 char cmd[256] = { 0 };
12824 char hex_bssid[13] = { 0 };
12825 char bssid[18] = { 0 };
12826 char nr[256] = { 0 };
12827 char ssid[256];
12828 char hex_ssid[256];
12829 char interface_name[16] = {0};
12830 INT ret;
12831
12832 /*rmeove all neighbors*/
12833 wifi_dbg_printf("\n[%s]: removing all neighbors from %s\n", __func__, interface_name);
12834 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
12835 return RETURN_ERR;
12836 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);
12837 system(cmd);
12838
12839 for(unsigned int i = 0; i < numNeighborReports; i++)
12840 {
12841 memset(ssid, 0, sizeof(ssid));
12842 ret = wifi_getSSIDName(apIndex, ssid);
12843 if (ret != RETURN_OK)
12844 return RETURN_ERR;
12845
12846 memset(hex_ssid, 0, sizeof(hex_ssid));
12847 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
12848 sprintf(hex_ssid + k,"%02x", ssid[j]);
12849
12850 snprintf(hex_bssid, sizeof(hex_bssid),
12851 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
12852 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
12853 snprintf(bssid, sizeof(bssid),
12854 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
12855 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
12856
12857 snprintf(nr, sizeof(nr),
12858 "%s" // bssid
12859 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
12860 "%02hhx" // operclass
12861 "%02hhx" // channel
12862 "%02hhx", // phy_mode
12863 hex_bssid,
12864 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
12865 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
12866 neighborReports[i].opClass,
12867 neighborReports[i].channel,
12868 neighborReports[i].phyTable);
12869
12870 snprintf(cmd, sizeof(cmd),
12871 "hostapd_cli set_neighbor "
12872 "%s " // bssid
12873 "ssid=%s " // ssid
12874 "nr=%s " // nr
12875 "-i %s",
12876 bssid,hex_ssid,nr, interface_name);
12877
12878 if (WEXITSTATUS(system(cmd)) != 0)
12879 {
12880 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
12881 }
12882 }
12883
12884 return RETURN_OK;
12885}
12886
12887INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
12888{
12889 return RETURN_OK;
12890}
12891
12892#ifdef _WIFI_HAL_TEST_
12893int main(int argc,char **argv)
12894{
12895 int index;
12896 INT ret=0;
12897 char buf[1024]="";
12898
12899 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12900 if(argc<3)
12901 {
12902 if(argc==2)
12903 {
12904 if(!strcmp(argv[1], "init"))
12905 return wifi_init();
12906 if(!strcmp(argv[1], "reset"))
12907 return wifi_reset();
12908 if(!strcmp(argv[1], "wifi_getHalVersion"))
12909 {
12910 char buffer[64];
12911 if(wifi_getHalVersion(buffer)==RETURN_OK)
12912 printf("Version: %s\n", buffer);
12913 else
12914 printf("Error in wifi_getHalVersion\n");
12915 return RETURN_OK;
12916 }
12917 }
12918 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
12919 exit(-1);
12920 }
12921
12922 index = atoi(argv[2]);
12923 if(strstr(argv[1], "wifi_getApName")!=NULL)
12924 {
12925 wifi_getApName(index,buf);
12926 printf("Ap name is %s \n",buf);
12927 return 0;
12928 }
developer121a8e72023-05-22 09:19:39 +080012929 if (strstr(argv[1], "wifi_setApAclDevice")!=NULL) {
developer49b17232023-05-19 16:35:19 +080012930 if(argc <= 3 )
12931 {
12932 printf("Insufficient arguments \n");
12933 exit(-1);
12934 }
12935 wifi_addApAclDevice(index, argv[3]);
12936 return 0;
12937 }
developer121a8e72023-05-22 09:19:39 +080012938 if (strstr(argv[1], "wifi_getApAclDevices")!=NULL) {
12939 wifi_getApAclDevices(index, buf, MAX_BUF_SIZE);
12940 return 0;
12941 }
12942
developer0f10c772023-05-16 21:43:39 +080012943 if(strstr(argv[1], "wifi_getRadioMode")!=NULL)
12944 {
12945 int mode = 0;
12946
12947 wifi_getRadioMode(index, buf, &mode);
12948 printf("Ap Radio mode is %s , mode = 0x%x\n", buf, mode);
12949 return 0;
12950 }
developer72fb0bb2023-01-11 09:46:29 +080012951 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
12952 {
12953 BOOL b = FALSE;
12954 BOOL *output_bool = &b;
12955 wifi_getRadioAutoChannelEnable(index,output_bool);
12956 printf("Channel enabled = %d \n",b);
12957 return 0;
12958 }
12959 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
12960 {
12961 wifi_getApWpaEncryptionMode(index,buf);
12962 printf("encryption enabled = %s\n",buf);
12963 return 0;
12964 }
12965 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
12966 {
12967 BOOL b = FALSE;
12968 BOOL *output_bool = &b;
12969 wifi_getApSsidAdvertisementEnable(index,output_bool);
12970 printf("advertisment enabled = %d\n",b);
12971 return 0;
12972 }
12973 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
12974 {
12975 if(argc <= 3 )
12976 {
12977 printf("Insufficient arguments \n");
12978 exit(-1);
12979 }
12980
12981 char sta[20] = {'\0'};
12982 ULLONG handle= 0;
12983 strcpy(sta,argv[3]);
12984 mac_address_t st;
12985 mac_addr_aton(st,sta);
12986
12987 wifi_associated_dev_tid_stats_t tid_stats;
12988 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
12989 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
12990 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);
12991 }
12992
12993 if(strstr(argv[1], "getApEnable")!=NULL) {
12994 BOOL enable;
12995 ret=wifi_getApEnable(index, &enable);
12996 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
12997 }
12998 else if(strstr(argv[1], "setApEnable")!=NULL) {
12999 BOOL enable = atoi(argv[3]);
13000 ret=wifi_setApEnable(index, enable);
13001 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
13002 }
13003 else if(strstr(argv[1], "getApStatus")!=NULL) {
developer69b61b02023-03-07 17:17:44 +080013004 char status[64];
developer72fb0bb2023-01-11 09:46:29 +080013005 ret=wifi_getApStatus(index, status);
13006 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
13007 }
13008 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
13009 {
13010 wifi_getSSIDNameStatus(index,buf);
13011 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
13012 return 0;
13013 }
13014 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
13015 wifi_ssidTrafficStats2_t stats={0};
13016 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
13017 printf("%s %d: returns %d\n", argv[1], index, ret);
13018 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
13019 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
13020 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
13021 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
13022 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
13023 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
13024 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
13025 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
13026 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
13027 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
13028 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
13029 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
13030 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
13031 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
13032 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
13033 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
13034 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
13035 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
13036 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
13037 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
13038 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
13039 }
13040 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
13041 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
13042 UINT array_size=0;
13043 UINT i=0;
13044 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
13045 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
developer69b61b02023-03-07 17:17:44 +080013046 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
developer72fb0bb2023-01-11 09:46:29 +080013047 printf(" neighbor %d:\n", i);
13048 printf(" ap_SSID =%s\n", pt->ap_SSID);
13049 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
13050 printf(" ap_Mode =%s\n", pt->ap_Mode);
13051 printf(" ap_Channel =%d\n", pt->ap_Channel);
13052 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
13053 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
13054 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
13055 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
13056 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
13057 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
13058 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
13059 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
13060 printf(" ap_Noise =%d\n", pt->ap_Noise);
13061 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
13062 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
13063 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
developer69b61b02023-03-07 17:17:44 +080013064 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
developer72fb0bb2023-01-11 09:46:29 +080013065 }
13066 if(neighbor_ap_array)
13067 free(neighbor_ap_array); //make sure to free the list
13068 }
13069 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
13070 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
13071 UINT array_size=0;
13072 UINT i=0;
13073 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
13074 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
developer69b61b02023-03-07 17:17:44 +080013075 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
developer72fb0bb2023-01-11 09:46:29 +080013076 printf(" associated_dev %d:\n", i);
13077 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
13078 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
13079 printf(" cli_SNR =%d\n", pt->cli_SNR);
13080 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
13081 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
13082 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
13083 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
13084 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
13085 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
13086 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
13087 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
13088 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
13089 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
13090 }
13091 if(associated_dev_array)
13092 free(associated_dev_array); //make sure to free the list
13093 }
13094
13095 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
13096 {
13097#define MAX_ARRAY_SIZE 64
13098 int i, array_size;
13099 char *p, *ch_str;
13100 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
13101
13102 if(argc != 5)
13103 {
13104 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
13105 exit(-1);
13106 }
13107 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
13108
13109 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
13110 {
13111 strtok_r(ch_str, ",", &p);
13112 input_output_channelStats_array[i].ch_number = atoi(ch_str);
13113 }
13114 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
13115 if(!array_size)
13116 array_size=1;//Need to print current channel statistics
13117 for(i=0; i<array_size; i++)
13118 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
13119 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
13120 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
13121 input_output_channelStats_array[i].ch_number,\
13122 input_output_channelStats_array[i].ch_noise,\
13123 input_output_channelStats_array[i].ch_utilization_busy_rx,\
13124 input_output_channelStats_array[i].ch_utilization_busy_tx,\
13125 input_output_channelStats_array[i].ch_utilization_busy,\
13126 input_output_channelStats_array[i].ch_utilization_busy_ext,\
13127 input_output_channelStats_array[i].ch_utilization_total);
13128 }
13129
13130 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
13131 {
13132 if(argc <= 3 )
13133 {
13134 printf("Insufficient arguments \n");
13135 exit(-1);
13136 }
13137 char mac_addr[20] = {'\0'};
13138 wifi_device_t output_struct;
13139 int dev_index = atoi(argv[3]);
13140
13141 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
13142 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
13143 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);
13144 }
13145
13146 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
13147 {
13148 if (argc <= 3)
13149 {
13150 printf("Insufficient arguments\n");
13151 exit(-1);
13152 }
13153 char args[256];
13154 wifi_NeighborReport_t *neighborReports;
13155
13156 neighborReports = calloc(argc - 2, sizeof(neighborReports));
13157 if (!neighborReports)
13158 {
13159 printf("Failed to allocate memory");
13160 exit(-1);
13161 }
13162
13163 for (int i = 3; i < argc; ++i)
13164 {
13165 char *val;
13166 int j = 0;
13167 memset(args, 0, sizeof(args));
13168 strncpy(args, argv[i], sizeof(args));
13169 val = strtok(args, ";");
13170 while (val != NULL)
13171 {
13172 if (j == 0)
13173 {
13174 mac_addr_aton(neighborReports[i - 3].bssid, val);
13175 } else if (j == 1)
13176 {
13177 neighborReports[i - 3].info = strtol(val, NULL, 16);
13178 } else if (j == 2)
13179 {
13180 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
13181 } else if (j == 3)
13182 {
13183 neighborReports[i - 3].channel = strtol(val, NULL, 16);
13184 } else if (j == 4)
13185 {
13186 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
13187 } else {
13188 printf("Insufficient arguments]n\n");
13189 exit(-1);
13190 }
13191 val = strtok(NULL, ";");
13192 j++;
13193 }
13194 }
13195
13196 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
13197 if (ret != RETURN_OK)
13198 {
13199 printf("wifi_setNeighborReports ret = %d", ret);
13200 exit(-1);
13201 }
13202 }
13203 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
13204 {
13205 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
13206 printf("%s.\n", buf);
13207 else
13208 printf("Error returned\n");
13209 }
13210 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
13211 {
13212 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
13213 printf("%s.\n", buf);
13214 else
13215 printf("Error returned\n");
13216 }
13217 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
13218 {
13219 if (argc <= 2)
13220 {
13221 printf("Insufficient arguments\n");
13222 exit(-1);
13223 }
13224 char buf[64]= {'\0'};
13225 wifi_getRadioOperatingChannelBandwidth(index,buf);
13226 printf("Current bandwidth is %s \n",buf);
13227 return 0;
13228 }
13229 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
13230 {
13231 if (argc <= 5)
13232 {
13233 printf("Insufficient arguments\n");
13234 exit(-1);
13235 }
13236 UINT channel = atoi(argv[3]);
13237 UINT width = atoi(argv[4]);
13238 UINT beacon = atoi(argv[5]);
13239 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
13240 printf("Result = %d", ret);
13241 }
13242
13243 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13244 return 0;
13245}
13246
13247#endif
13248
13249#ifdef WIFI_HAL_VERSION_3
13250
13251INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
13252{
13253 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13254 if (bitMap & WIFI_BITRATE_1MBPS)
13255 strcat(BasicRate, "1,");
13256 if (bitMap & WIFI_BITRATE_2MBPS)
13257 strcat(BasicRate, "2,");
13258 if (bitMap & WIFI_BITRATE_5_5MBPS)
13259 strcat(BasicRate, "5.5,");
13260 if (bitMap & WIFI_BITRATE_6MBPS)
13261 strcat(BasicRate, "6,");
13262 if (bitMap & WIFI_BITRATE_9MBPS)
13263 strcat(BasicRate, "9,");
13264 if (bitMap & WIFI_BITRATE_11MBPS)
13265 strcat(BasicRate, "11,");
13266 if (bitMap & WIFI_BITRATE_12MBPS)
13267 strcat(BasicRate, "12,");
13268 if (bitMap & WIFI_BITRATE_18MBPS)
13269 strcat(BasicRate, "18,");
13270 if (bitMap & WIFI_BITRATE_24MBPS)
13271 strcat(BasicRate, "24,");
13272 if (bitMap & WIFI_BITRATE_36MBPS)
13273 strcat(BasicRate, "36,");
13274 if (bitMap & WIFI_BITRATE_48MBPS)
13275 strcat(BasicRate, "48,");
13276 if (bitMap & WIFI_BITRATE_54MBPS)
13277 strcat(BasicRate, "54,");
13278 if (strlen(BasicRate) != 0) // remove last comma
13279 BasicRate[strlen(BasicRate) - 1] = '\0';
13280 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13281 return RETURN_OK;
13282}
13283
13284INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
13285{
13286 UINT BitMap = 0;
13287 char *rate;
13288
13289 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13290 rate = strtok(BasicRatesList, ",");
13291 while(rate != NULL)
13292 {
13293 if (strcmp(rate, "1") == 0)
13294 BitMap |= WIFI_BITRATE_1MBPS;
13295 else if (strcmp(rate, "2") == 0)
13296 BitMap |= WIFI_BITRATE_2MBPS;
13297 else if (strcmp(rate, "5.5") == 0)
13298 BitMap |= WIFI_BITRATE_5_5MBPS;
13299 else if (strcmp(rate, "6") == 0)
13300 BitMap |= WIFI_BITRATE_6MBPS;
13301 else if (strcmp(rate, "9") == 0)
13302 BitMap |= WIFI_BITRATE_9MBPS;
13303 else if (strcmp(rate, "11") == 0)
13304 BitMap |= WIFI_BITRATE_11MBPS;
13305 else if (strcmp(rate, "12") == 0)
13306 BitMap |= WIFI_BITRATE_12MBPS;
13307 else if (strcmp(rate, "18") == 0)
13308 BitMap |= WIFI_BITRATE_18MBPS;
13309 else if (strcmp(rate, "24") == 0)
13310 BitMap |= WIFI_BITRATE_24MBPS;
13311 else if (strcmp(rate, "36") == 0)
13312 BitMap |= WIFI_BITRATE_36MBPS;
13313 else if (strcmp(rate, "48") == 0)
13314 BitMap |= WIFI_BITRATE_48MBPS;
13315 else if (strcmp(rate, "54") == 0)
13316 BitMap |= WIFI_BITRATE_54MBPS;
13317 rate = strtok(NULL, ",");
13318 }
13319 *basicRateBitMap = BitMap;
13320 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13321 return RETURN_OK;
13322}
13323
13324// This API is used to configured all radio operation parameter in a single set. it includes channel number, channelWidth, mode and auto chammel configuration.
13325INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
13326{
13327 char buf[128] = {0};
13328 char cmd[128] = {0};
13329 char config_file[64] = {0};
13330 int bandwidth;
13331 int set_mode = 0;
13332 wifi_radio_operationParam_t current_param;
13333
13334 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13335
13336 multiple_set = TRUE;
13337 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
13338 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
13339 return RETURN_ERR;
13340 }
13341 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
13342 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
13343 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
13344 return RETURN_ERR;
13345 }
13346 }
13347
13348 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
13349 bandwidth = 20;
13350 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
13351 bandwidth = 40;
13352 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
13353 bandwidth = 80;
13354 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
13355 bandwidth = 160;
13356 if (operationParam->autoChannelEnabled){
13357 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
13358 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
13359 return RETURN_ERR;
13360 }
developer69b61b02023-03-07 17:17:44 +080013361 }else{
developer72fb0bb2023-01-11 09:46:29 +080013362 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
13363 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
13364 return RETURN_ERR;
13365 }
13366 }
13367
13368 if (current_param.variant != operationParam->variant) {
13369 // Two different definition bit map, so need to check every bit.
13370 if (operationParam->variant & WIFI_80211_VARIANT_A)
13371 set_mode |= WIFI_MODE_A;
13372 if (operationParam->variant & WIFI_80211_VARIANT_B)
13373 set_mode |= WIFI_MODE_B;
13374 if (operationParam->variant & WIFI_80211_VARIANT_G)
13375 set_mode |= WIFI_MODE_G;
13376 if (operationParam->variant & WIFI_80211_VARIANT_N)
13377 set_mode |= WIFI_MODE_N;
13378 if (operationParam->variant & WIFI_80211_VARIANT_AC)
13379 set_mode |= WIFI_MODE_AC;
13380 if (operationParam->variant & WIFI_80211_VARIANT_AX)
13381 set_mode |= WIFI_MODE_AX;
13382 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
13383 memset(buf, 0, sizeof(buf));
developer0f10c772023-05-16 21:43:39 +080013384 if (wifi_setRadioMode_by_dat(index, set_mode) != RETURN_OK) {
developer72fb0bb2023-01-11 09:46:29 +080013385 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
13386 return RETURN_ERR;
13387 }
13388 }
13389 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
13390 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
13391 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
13392 return RETURN_ERR;
13393 }
13394 }
13395 if (current_param.beaconInterval != operationParam->beaconInterval) {
13396 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
13397 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
13398 return RETURN_ERR;
13399 }
13400 }
13401 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
13402 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
13403 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
13404 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
13405 return RETURN_ERR;
13406 }
13407 }
13408 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
13409 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
13410 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
13411 return RETURN_ERR;
13412 }
13413 }
13414 if (current_param.guardInterval != operationParam->guardInterval) {
13415 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
13416 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
13417 return RETURN_ERR;
13418 }
13419 }
13420 if (current_param.transmitPower != operationParam->transmitPower) {
13421 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
13422 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
13423 return RETURN_ERR;
13424 }
13425 }
13426 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
13427 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
13428 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
13429 return RETURN_ERR;
13430 }
13431 }
13432 if (current_param.obssCoex != operationParam->obssCoex) {
13433 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
13434 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
13435 return RETURN_ERR;
13436 }
13437 }
13438 if (current_param.stbcEnable != operationParam->stbcEnable) {
13439 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
13440 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
13441 return RETURN_ERR;
13442 }
13443 }
13444 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
13445 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
13446 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
13447 return RETURN_ERR;
13448 }
13449 }
13450
13451 // if enable is true, then restart the radio
13452 wifi_setRadioEnable(index, FALSE);
13453 if (operationParam->enable == TRUE)
13454 wifi_setRadioEnable(index, TRUE);
13455 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13456
13457 return RETURN_OK;
13458}
13459
13460INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
13461{
13462 char band[64] = {0};
13463 char buf[256] = {0};
13464 char config_file[64] = {0};
13465 char cmd[128] = {0};
13466 int ret = RETURN_ERR;
13467 int mode = 0;
13468 ULONG channel = 0;
13469 BOOL enabled = FALSE;
13470
13471 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13472 printf("Entering %s index = %d\n", __func__, (int)index);
13473
13474 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
13475 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
13476 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
13477 {
13478 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
13479 return RETURN_ERR;
13480 }
13481 operationParam->enable = enabled;
13482
13483 memset(band, 0, sizeof(band));
13484 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
13485 {
13486 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
13487 return RETURN_ERR;
13488 }
13489
13490 if (!strcmp(band, "2.4GHz"))
13491 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
13492 else if (!strcmp(band, "5GHz"))
13493 operationParam->band = WIFI_FREQUENCY_5_BAND;
13494 else if (!strcmp(band, "6GHz"))
13495 operationParam->band = WIFI_FREQUENCY_6_BAND;
13496 else
13497 {
13498 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
13499 band);
13500 }
13501
13502 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
13503 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
13504 operationParam->channel = 0;
13505 operationParam->autoChannelEnabled = TRUE;
13506 } else {
13507 operationParam->channel = strtol(buf, NULL, 10);
13508 operationParam->autoChannelEnabled = FALSE;
13509 }
13510
13511 memset(buf, 0, sizeof(buf));
13512 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
13513 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
13514 return RETURN_ERR;
13515 }
13516 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
13517 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
13518 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
13519 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
13520 else
13521 {
13522 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
13523 return false;
13524 }
13525
13526 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
13527 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
13528 return RETURN_ERR;
13529 }
13530 // Two different definition bit map, so need to check every bit.
13531 if (mode & WIFI_MODE_A)
13532 operationParam->variant |= WIFI_80211_VARIANT_A;
13533 if (mode & WIFI_MODE_B)
13534 operationParam->variant |= WIFI_80211_VARIANT_B;
13535 if (mode & WIFI_MODE_G)
13536 operationParam->variant |= WIFI_80211_VARIANT_G;
13537 if (mode & WIFI_MODE_N)
13538 operationParam->variant |= WIFI_80211_VARIANT_N;
13539 if (mode & WIFI_MODE_AC)
13540 operationParam->variant |= WIFI_80211_VARIANT_AC;
13541 if (mode & WIFI_MODE_AX)
13542 operationParam->variant |= WIFI_80211_VARIANT_AX;
13543 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
13544 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
13545 return RETURN_ERR;
13546 }
13547 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
13548 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
13549 return RETURN_ERR;
13550 }
13551 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
13552 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
13553 return RETURN_ERR;
13554 }
13555
13556 memset(buf, 0, sizeof(buf));
13557 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
13558 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
13559 return RETURN_ERR;
13560 }
13561 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
13562
13563 memset(buf, 0, sizeof(buf));
13564 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
13565 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
13566 return RETURN_ERR;
13567 }
13568 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
13569
13570 memset(buf, 0, sizeof(buf));
13571 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
13572 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
13573
13574 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
13575 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
13576 return RETURN_ERR;
13577 }
developera1255e42023-05-13 17:45:02 +080013578 if (wifi_getRadioPercentageTransmitPower(index, (ULONG *)&operationParam->transmitPower) != RETURN_OK) {
developer72fb0bb2023-01-11 09:46:29 +080013579 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
13580 return RETURN_ERR;
13581 }
13582
13583 memset(buf, 0, sizeof(buf));
13584 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
13585 if (strcmp(buf, "-1") == 0) {
13586 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
13587 operationParam->ctsProtection = FALSE;
13588 } else {
13589 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
13590 operationParam->ctsProtection = TRUE;
13591 }
13592
13593 memset(buf, 0, sizeof(buf));
13594 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
13595 if (strcmp(buf, "0") == 0)
13596 operationParam->obssCoex = FALSE;
13597 else
13598 operationParam->obssCoex = TRUE;
13599
13600 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
13601 _syscmd(cmd, buf, sizeof(buf));
13602 if (strlen(buf) != 0)
13603 operationParam->stbcEnable = TRUE;
13604 else
13605 operationParam->stbcEnable = FALSE;
13606
13607 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
13608 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
13609 return RETURN_ERR;
13610 }
13611
13612 // Below value is hardcoded
13613
13614 operationParam->numSecondaryChannels = 0;
13615 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
13616 operationParam->channelSecondary[i] = 0;
13617 }
13618 operationParam->csa_beacon_count = 15;
13619 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
13620
13621 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13622 return RETURN_OK;
13623}
13624
13625static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
13626{
13627 int max_radio_num = 0;
13628
13629 wifi_getMaxRadioNumber(&max_radio_num);
13630 if (radioIndex >= max_radio_num) {
13631 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
13632 return RETURN_ERR;
13633 }
13634
13635 return (arrayIndex * max_radio_num) + radioIndex;
13636}
13637
developer96b38512023-02-22 11:17:45 +080013638static int vap_index_to_array_index(int vapIndex, int *radioIndex, int *arrayIndex)
13639{
13640 int max_radio_num = 0;
13641
13642 if ((vapIndex < 0) || (vapIndex > MAX_NUM_VAP_PER_RADIO*MAX_NUM_RADIOS))
13643 return -1;
13644
13645 wifi_getMaxRadioNumber(&max_radio_num);
13646
13647 (*radioIndex) = vapIndex % max_radio_num;
13648 (*arrayIndex) = vapIndex / max_radio_num;
13649
13650 return 0;
13651}
13652
13653
developer72fb0bb2023-01-11 09:46:29 +080013654wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
13655 if (strncmp(beaconRate, "1Mbps", 5) == 0)
13656 return WIFI_BITRATE_1MBPS;
13657 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
13658 return WIFI_BITRATE_2MBPS;
13659 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
13660 return WIFI_BITRATE_5_5MBPS;
13661 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
13662 return WIFI_BITRATE_6MBPS;
13663 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
13664 return WIFI_BITRATE_9MBPS;
13665 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
13666 return WIFI_BITRATE_11MBPS;
13667 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
13668 return WIFI_BITRATE_12MBPS;
13669 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
13670 return WIFI_BITRATE_18MBPS;
13671 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
13672 return WIFI_BITRATE_24MBPS;
13673 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
13674 return WIFI_BITRATE_36MBPS;
13675 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
13676 return WIFI_BITRATE_48MBPS;
13677 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
13678 return WIFI_BITRATE_54MBPS;
13679 return WIFI_BITRATE_DEFAULT;
13680}
13681
13682INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
13683{
13684 if (beacon == WIFI_BITRATE_1MBPS)
13685 strcpy(beacon_str, "1Mbps");
13686 else if (beacon == WIFI_BITRATE_2MBPS)
13687 strcpy(beacon_str, "2Mbps");
13688 else if (beacon == WIFI_BITRATE_5_5MBPS)
13689 strcpy(beacon_str, "5.5Mbps");
13690 else if (beacon == WIFI_BITRATE_6MBPS)
13691 strcpy(beacon_str, "6Mbps");
13692 else if (beacon == WIFI_BITRATE_9MBPS)
13693 strcpy(beacon_str, "9Mbps");
13694 else if (beacon == WIFI_BITRATE_11MBPS)
13695 strcpy(beacon_str, "11Mbps");
13696 else if (beacon == WIFI_BITRATE_12MBPS)
13697 strcpy(beacon_str, "12Mbps");
13698 else if (beacon == WIFI_BITRATE_18MBPS)
13699 strcpy(beacon_str, "18Mbps");
13700 else if (beacon == WIFI_BITRATE_24MBPS)
13701 strcpy(beacon_str, "24Mbps");
13702 else if (beacon == WIFI_BITRATE_36MBPS)
13703 strcpy(beacon_str, "36Mbps");
13704 else if (beacon == WIFI_BITRATE_48MBPS)
13705 strcpy(beacon_str, "48Mbps");
13706 else if (beacon == WIFI_BITRATE_54MBPS)
13707 strcpy(beacon_str, "54Mbps");
13708 return RETURN_OK;
13709}
13710
13711INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
13712{
13713 INT mode = 0;
13714 INT ret = -1;
13715 INT output = 0;
13716 int i = 0;
13717 int vap_index = 0;
13718 BOOL enabled = FALSE;
13719 char buf[256] = {0};
13720 wifi_vap_security_t security = {0};
13721 map->num_vaps = 5; // Hardcoded
13722
13723 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13724 printf("Entering %s index = %d\n", __func__, (int)index);
13725
13726 for (i = 0; i < 5; i++)
13727 {
13728 map->vap_array[i].radio_index = index;
13729
13730 vap_index = array_index_to_vap_index(index, i);
13731 if (vap_index < 0)
13732 return RETURN_ERR;
13733
13734 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
13735
13736 map->vap_array[i].vap_index = vap_index;
13737
13738 memset(buf, 0, sizeof(buf));
13739 ret = wifi_getApName(vap_index, buf);
13740 if (ret != RETURN_OK) {
13741 printf("%s: wifi_getApName return error\n", __func__);
13742 return RETURN_ERR;
13743 }
13744 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
13745
13746 memset(buf, 0, sizeof(buf));
13747 ret = wifi_getSSIDName(vap_index, buf);
13748 if (ret != RETURN_OK) {
13749 printf("%s: wifi_getSSIDName return error\n", __func__);
13750 return RETURN_ERR;
13751 }
13752 snprintf(map->vap_array[i].u.bss_info.ssid, sizeof(map->vap_array[i].u.bss_info.ssid), "%s", buf);
13753
13754 ret = wifi_getSSIDEnable(vap_index, &enabled);
13755 if (ret != RETURN_OK) {
13756 printf("%s: wifi_getSSIDEnable return error\n", __func__);
13757 return RETURN_ERR;
13758 }
13759 map->vap_array[i].u.bss_info.enabled = enabled;
13760
13761 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
13762 if (ret != RETURN_OK) {
13763 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
13764 return RETURN_ERR;
13765 }
13766 map->vap_array[i].u.bss_info.showSsid = enabled;
developer69b61b02023-03-07 17:17:44 +080013767
developer72fb0bb2023-01-11 09:46:29 +080013768 ret = wifi_getApIsolationEnable(vap_index, &enabled);
13769 if (ret != RETURN_OK) {
13770 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
13771 return RETURN_ERR;
13772 }
13773 map->vap_array[i].u.bss_info.isolation = enabled;
13774
13775 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
13776 if (ret != RETURN_OK) {
13777 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
13778 return RETURN_ERR;
13779 }
13780 map->vap_array[i].u.bss_info.bssMaxSta = output;
13781
13782 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
13783 if (ret != RETURN_OK) {
13784 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
13785 return RETURN_ERR;
13786 }
13787 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
13788
13789 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
13790 if (ret != RETURN_OK) {
13791 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
13792 return RETURN_ERR;
13793 }
13794 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
13795
13796 ret = wifi_getApSecurity(vap_index, &security);
13797 if (ret != RETURN_OK) {
13798 printf("%s: wifi_getApSecurity return error\n", __func__);
13799 return RETURN_ERR;
13800 }
13801 map->vap_array[i].u.bss_info.security = security;
13802
13803 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
13804 if (ret != RETURN_OK) {
13805 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
13806 return RETURN_ERR;
13807 }
developer69b61b02023-03-07 17:17:44 +080013808 if (mode == 0)
developer72fb0bb2023-01-11 09:46:29 +080013809 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
developer69b61b02023-03-07 17:17:44 +080013810 else
developer72fb0bb2023-01-11 09:46:29 +080013811 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
developer69b61b02023-03-07 17:17:44 +080013812 if (mode == 1)
developer72fb0bb2023-01-11 09:46:29 +080013813 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
developer69b61b02023-03-07 17:17:44 +080013814 else if (mode == 2)
developer72fb0bb2023-01-11 09:46:29 +080013815 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
13816
13817 ret = wifi_getApWmmEnable(vap_index, &enabled);
13818 if (ret != RETURN_OK) {
13819 printf("%s: wifi_getApWmmEnable return error\n", __func__);
13820 return RETURN_ERR;
13821 }
13822 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
13823
13824 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
13825 if (ret != RETURN_OK) {
13826 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
13827 return RETURN_ERR;
13828 }
13829 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
13830
13831 memset(buf, 0, sizeof(buf));
13832 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
13833 if (ret != RETURN_OK) {
13834 printf("%s: wifi_getApBeaconRate return error\n", __func__);
13835 return RETURN_ERR;
13836 }
13837 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
13838
13839 memset(buf, 0, sizeof(buf));
13840 ret = wifi_getBaseBSSID(vap_index, buf);
13841 if (ret != RETURN_OK) {
13842 printf("%s: wifi_getBaseBSSID return error\n", __func__);
13843 return RETURN_ERR;
13844 }
13845 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
13846 &map->vap_array[i].u.bss_info.bssid[0],
13847 &map->vap_array[i].u.bss_info.bssid[1],
13848 &map->vap_array[i].u.bss_info.bssid[2],
13849 &map->vap_array[i].u.bss_info.bssid[3],
13850 &map->vap_array[i].u.bss_info.bssid[4],
13851 &map->vap_array[i].u.bss_info.bssid[5]);
13852 // 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]);
13853
13854 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
13855 if (ret != RETURN_OK) {
13856 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
13857 return RETURN_ERR;
13858 }
13859 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
13860
13861 // TODO: wps, noack
13862 }
13863 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13864 return RETURN_OK;
13865}
13866
developer47cc27a2023-05-17 23:09:58 +080013867void checkVapStatus(int apIndex, BOOL *enable)
developer72fb0bb2023-01-11 09:46:29 +080013868{
13869 char if_name[16] = {0};
13870 char cmd[128] = {0};
13871 char buf[128] = {0};
13872
13873 *enable = FALSE;
13874 if (wifi_GetInterfaceName(apIndex, if_name) != RETURN_OK)
13875 return;
13876
13877 snprintf(cmd, sizeof(cmd), "cat %s | grep ^%s=1", VAP_STATUS_FILE, if_name);
13878 _syscmd(cmd, buf, sizeof(buf));
13879 if (strlen(buf) > 0)
13880 *enable = TRUE;
13881 return;
13882}
13883
13884static int prepareInterface(UINT apIndex, char *new_interface)
13885{
13886 char cur_interface[16] = {0};
13887 char config_file[128] = {0};
developer8a3bbbf2023-03-15 17:47:23 +080013888 char cmd[MAX_CMD_SIZE] = {0};
13889 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +080013890 int max_radio_num = 0;
13891 int radioIndex = -1;
13892 int phyIndex = -1;
developer8a3bbbf2023-03-15 17:47:23 +080013893 struct params params;
developer72fb0bb2023-01-11 09:46:29 +080013894
13895 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
13896 wifi_hostapdRead(config_file, "interface", cur_interface, sizeof(cur_interface));
13897
13898 if (strncmp(cur_interface, new_interface, sizeof(cur_interface)) != 0) {
developer8a3bbbf2023-03-15 17:47:23 +080013899 wifi_getMaxRadioNumber(&max_radio_num);
developer72fb0bb2023-01-11 09:46:29 +080013900 radioIndex = apIndex % max_radio_num;
13901 phyIndex = radio_index_to_phy(radioIndex);
13902 // disable and del old interface, then add new interface
13903 wifi_setApEnable(apIndex, FALSE);
developer8a3bbbf2023-03-15 17:47:23 +080013904
13905 params.name = "interface";
13906 params.value = new_interface;
13907 wifi_hostapdWrite(config_file, &params, 1);
13908
13909 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyIndex, config_file);
13910 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +080013911 }
developer8a3bbbf2023-03-15 17:47:23 +080013912
developer72fb0bb2023-01-11 09:46:29 +080013913 // update the vap status file
13914 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=1' %s", cur_interface, new_interface, VAP_STATUS_FILE);
13915 _syscmd(cmd, buf, sizeof(buf));
13916 return RETURN_OK;
13917}
13918
13919INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
13920{
13921 char interface_name[16] = {0};
13922 unsigned int i;
13923 wifi_vap_info_t *vap_info = NULL;
13924 int acl_mode;
13925 int ret = 0;
13926 char *sec_str = NULL;
13927 char buf[256] = {0};
13928 char cmd[128] = {0};
13929 char config_file[64] = {0};
13930 char bssid[32] = {0};
13931 char psk_file[64] = {0};
developer47cc27a2023-05-17 23:09:58 +080013932 BOOL enable = FALSE;
developer72fb0bb2023-01-11 09:46:29 +080013933
13934 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13935 printf("Entering %s index = %d\n", __func__, (int)index);
13936 for (i = 0; i < map->num_vaps; i++)
13937 {
13938 multiple_set = TRUE;
13939 vap_info = &map->vap_array[i];
13940
13941 // Check vap status file to enable multiple ap if the system boot.
13942 checkVapStatus(vap_info->vap_index, &enable);
13943 if (vap_info->u.bss_info.enabled == FALSE && enable == FALSE)
13944 continue;
13945
13946 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
13947
13948 if (wifi_getApEnable(vap_info->vap_index, &enable) != RETURN_OK)
13949 enable = FALSE;
13950
13951 // multi-ap first up need to copy current radio config
13952 if (vap_info->radio_index != vap_info->vap_index && enable == FALSE) {
13953 snprintf(cmd, sizeof(cmd), "cp %s%d.conf %s%d.conf", CONFIG_PREFIX, vap_info->radio_index, CONFIG_PREFIX, vap_info->vap_index);
13954 _syscmd(cmd, buf, sizeof(buf));
13955 if (strlen(vap_info->vap_name) == 0) // default name of the interface is wifiX
13956 snprintf(vap_info->vap_name, 16, "wifi%d", vap_info->vap_index);
13957 } else {
13958 // Check whether the interface name is valid or this ap change it.
13959 int apIndex = -1;
13960 wifi_getApIndexFromName(vap_info->vap_name, &apIndex);
13961 if (apIndex != -1 && apIndex != vap_info->vap_index)
13962 continue;
13963 prepareInterface(vap_info->vap_index, vap_info->vap_name);
13964 }
13965
13966 struct params params[3];
13967 params[0].name = "interface";
13968 params[0].value = vap_info->vap_name;
13969 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
13970 params[1].name = "bssid";
13971 params[1].value = bssid;
13972 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", vap_info->vap_index);
13973 params[2].name = "wpa_psk_file";
13974 params[2].value = psk_file;
13975
13976 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
13977 wifi_hostapdWrite(config_file, params, 3);
13978
13979 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
13980 _syscmd(cmd, buf, sizeof(buf));
13981
13982 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
13983 if (ret != RETURN_OK) {
13984 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
13985 return RETURN_ERR;
13986 }
13987
13988 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
13989 if (ret != RETURN_OK) {
13990 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
13991 return RETURN_ERR;
13992 }
13993
13994 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
13995 if (ret != RETURN_OK) {
13996 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
13997 return RETURN_ERR;
13998 }
13999
14000 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
14001 if (ret != RETURN_OK) {
14002 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
14003 return RETURN_ERR;
14004 }
14005
14006 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
14007 if (ret != RETURN_OK) {
14008 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
14009 return RETURN_ERR;
14010 }
14011
14012 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
14013 if (ret != RETURN_OK) {
14014 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
14015 return RETURN_ERR;
14016 }
14017
14018 if (vap_info->u.bss_info.mac_filter_enable == false){
14019 acl_mode = 0;
14020 }else {
14021 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
14022 acl_mode = 2;
14023 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
14024 _syscmd(cmd, buf, sizeof(buf));
14025 }else{
14026 acl_mode = 1;
14027 }
14028 }
14029
14030 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
14031 if (ret != RETURN_OK) {
14032 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
14033 return RETURN_ERR;
14034 }
14035
14036 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
14037 if (ret != RETURN_OK) {
14038 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
14039 return RETURN_ERR;
14040 }
14041
developer0f10c772023-05-16 21:43:39 +080014042 memset(buf, 0, sizeof(buf));
14043 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
14044 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
14045 if (ret != RETURN_OK) {
14046 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
14047 return RETURN_ERR;
14048 }
developer72fb0bb2023-01-11 09:46:29 +080014049
14050 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
14051 if (ret != RETURN_OK) {
14052 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable\n", __func__);
14053 return RETURN_ERR;
14054 }
14055
developer72fb0bb2023-01-11 09:46:29 +080014056 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
14057 if (ret != RETURN_OK) {
14058 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
14059 return RETURN_ERR;
14060 }
14061
developer23e71282023-01-18 10:25:19 +080014062 wifi_setApEnable(vap_info->vap_index, FALSE);
14063 wifi_setApEnable(vap_info->vap_index, TRUE);
14064 multiple_set = FALSE;
14065
14066 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
developer72fb0bb2023-01-11 09:46:29 +080014067 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
14068 if (ret != RETURN_OK) {
14069 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
14070 return RETURN_ERR;
14071 }
14072
14073 // TODO mgmtPowerControl, interworking, wps
14074 }
14075 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
14076 return RETURN_OK;
14077}
14078
14079int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
14080{
14081 char *token, *next;
14082 const char s[2] = ",";
14083 int count =0;
14084
14085 /* get the first token */
14086 token = strtok_r(pchannels, s, &next);
14087
14088 /* walk through other tokens */
14089 while( token != NULL && count < MAX_CHANNELS) {
14090 chlistptr->channels_list[count++] = atoi(token);
14091 token = strtok_r(NULL, s, &next);
14092 }
14093
14094 return count;
14095}
14096
14097static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
14098{
14099 INT status;
14100 wifi_channels_list_t *chlistp;
14101 CHAR output_string[64];
14102 CHAR pchannels[128];
14103 CHAR interface_name[16] = {0};
14104 wifi_band band;
14105
14106 if(rcap == NULL)
14107 {
14108 return RETURN_ERR;
14109 }
14110
14111 rcap->numSupportedFreqBand = 1;
14112 band = wifi_index_to_band(radioIndex);
14113
14114 if (band == band_2_4)
14115 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
14116 else if (band == band_5)
14117 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
14118 else if (band == band_6)
14119 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
14120
14121 chlistp = &(rcap->channel_list[0]);
14122 memset(pchannels, 0, sizeof(pchannels));
14123
14124 /* possible number of radio channels */
14125 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
14126 {
14127 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
14128 }
14129 /* Number of channels and list*/
14130 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
14131
14132 /* autoChannelSupported */
14133 /* always ON with wifi_getRadioAutoChannelSupported */
14134 rcap->autoChannelSupported = TRUE;
14135
14136 /* DCSSupported */
14137 /* always ON with wifi_getRadioDCSSupported */
14138 rcap->DCSSupported = TRUE;
14139
14140 /* zeroDFSSupported - TBD */
14141 rcap->zeroDFSSupported = FALSE;
14142
14143 /* Supported Country List*/
14144 memset(output_string, 0, sizeof(output_string));
14145 status = wifi_getRadioCountryCode(radioIndex, output_string);
14146 if( status != 0 ) {
14147 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
14148 return RETURN_ERR;
14149 } else {
14150 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
14151 }
14152 if(!strcmp(output_string,"US")){
14153 rcap->countrySupported[0] = wifi_countrycode_US;
14154 rcap->countrySupported[1] = wifi_countrycode_CA;
14155 } else if (!strcmp(output_string,"CA")) {
14156 rcap->countrySupported[0] = wifi_countrycode_CA;
14157 rcap->countrySupported[1] = wifi_countrycode_US;
14158 } else {
14159 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
14160 }
14161
14162 rcap->numcountrySupported = 2;
14163
14164 /* csi */
14165 rcap->csi.maxDevices = 8;
14166 rcap->csi.soudingFrameSupported = TRUE;
14167
14168 wifi_GetInterfaceName(radioIndex, interface_name);
14169 snprintf(rcap->ifaceName, sizeof(interface_name), "%s",interface_name);
14170
14171 /* channelWidth - all supported bandwidths */
14172 int i=0;
14173 rcap->channelWidth[i] = 0;
14174 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
14175 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
14176 WIFI_CHANNELBANDWIDTH_40MHZ);
14177
14178 }
14179 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
14180 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
14181 WIFI_CHANNELBANDWIDTH_40MHZ |
14182 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
14183 }
14184
14185
14186 /* mode - all supported variants */
14187 // rcap->mode[i] = WIFI_80211_VARIANT_H;
14188 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
14189 rcap->mode[i] = ( WIFI_80211_VARIANT_B | WIFI_80211_VARIANT_G | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AX );
14190 }
14191 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
14192 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
14193 }
14194 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
14195 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
14196 }
14197 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
14198 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
14199
14200 /* supportedBitRate - all supported bitrates */
14201 rcap->supportedBitRate[i] = 0;
14202 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
14203 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
14204 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
14205 }
14206 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
14207 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
14208 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
14209 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
14210 }
14211
14212
14213 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
14214 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
14215 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
14216 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
14217 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
14218 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
14219 rcap->cipherSupported = 0;
14220 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
14221 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
14222
14223 return RETURN_OK;
14224}
14225
14226INT wifi_getHalCapability(wifi_hal_capability_t *cap)
14227{
14228 INT status = 0, radioIndex = 0;
14229 char cmd[MAX_BUF_SIZE] = {0}, output[MAX_BUF_SIZE] = {0};
14230 int iter = 0;
14231 unsigned int j = 0;
14232 int max_num_radios;
14233 wifi_interface_name_idex_map_t *iface_info = NULL;
14234
14235 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
14236
14237 memset(cap, 0, sizeof(wifi_hal_capability_t));
14238
14239 /* version */
14240 cap->version.major = WIFI_HAL_MAJOR_VERSION;
14241 cap->version.minor = WIFI_HAL_MINOR_VERSION;
14242
14243 /* number of radios platform property */
14244 wifi_getMaxRadioNumber(&max_num_radios);
14245 cap->wifi_prop.numRadios = max_num_radios;
14246
14247 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
14248 {
14249 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
14250 if (status != 0) {
14251 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
14252 return RETURN_ERR;
14253 }
14254
14255 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
14256 {
14257 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
14258 {
14259 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
14260 return RETURN_ERR;
14261 }
14262 iface_info = &cap->wifi_prop.interface_map[iter];
14263 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
14264 iface_info->rdk_radio_index = radioIndex;
14265 memset(output, 0, sizeof(output));
14266 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
14267 {
14268 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
14269 }
14270 // TODO: bridge name
14271 // TODO: vlan id
14272 // TODO: primary
14273 iface_info->index = array_index_to_vap_index(radioIndex, j);
14274 memset(output, 0, sizeof(output));
14275 if (wifi_getApName(iface_info->index, output) == RETURN_OK)
14276 {
14277 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
14278 }
14279 iter++;
14280 }
14281 }
14282
14283 cap->BandSteeringSupported = FALSE;
14284 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
14285 return RETURN_OK;
14286}
14287
14288INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
14289{
14290 struct params h_config={0};
14291 char config_file[64] = {0};
14292
14293 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
14294
14295 h_config.name = "okc";
14296 h_config.value = okc_enable?"1":"0";
14297
14298 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
14299 wifi_hostapdWrite(config_file, &h_config, 1);
14300 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
14301
14302 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
14303 return RETURN_OK;
14304}
14305
14306INT wifi_setSAEMFP(int ap_index, BOOL enable)
14307{
14308 struct params h_config={0};
14309 char config_file[64] = {0};
14310 char buf[128] = {0};
14311
14312 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
14313
14314 h_config.name = "sae_require_mfp";
14315 h_config.value = enable?"1":"0";
14316
14317 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
14318 wifi_hostapdWrite(config_file, &h_config, 1);
14319 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
14320
14321 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
14322 return RETURN_OK;
14323}
14324
14325INT wifi_setSAEpwe(int ap_index, int sae_pwe)
14326{
14327 struct params h_config={0};
14328 char config_file[64] = {0};
14329 char buf[128] = {0};
14330
14331 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
14332
14333 h_config.name = "sae_pwe";
14334 snprintf(buf, sizeof(buf), "%d", sae_pwe);
14335 h_config.value = buf;
14336
14337 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
14338 wifi_hostapdWrite(config_file, &h_config, 1);
14339 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
14340
14341 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
14342 return RETURN_OK;
14343}
14344
14345INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
14346{
14347 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
14348 struct params h_config={0};
14349 char config_file[64] = {0};
14350
14351 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
14352
14353 h_config.name = "wpa_disable_eapol_key_retries";
14354 h_config.value = disable_EAPOL_retries?"1":"0";
14355
14356 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
14357 wifi_hostapdWrite(config_file, &h_config, 1);
14358 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
14359
14360 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
14361 return RETURN_OK;
14362}
14363
14364INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
14365{
14366 char buf[128] = {0};
14367 char config_file[128] = {0};
developere5750452023-05-15 16:46:42 +080014368 char cmd[128] = {0};
developer72fb0bb2023-01-11 09:46:29 +080014369 char password[64] = {0};
14370 char mfp[32] = {0};
14371 char wpa_mode[32] = {0};
14372 BOOL okc_enable = FALSE;
14373 BOOL sae_MFP = FALSE;
14374 BOOL disable_EAPOL_retries = TRUE;
14375 int sae_pwe = 0;
14376 struct params params = {0};
14377 wifi_band band = band_invalid;
14378
14379 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
14380
14381 multiple_set = TRUE;
14382 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
14383 if (security->mode == wifi_security_mode_none) {
14384 strcpy(wpa_mode, "None");
14385 } else if (security->mode == wifi_security_mode_wpa_personal)
14386 strcpy(wpa_mode, "WPA-Personal");
14387 else if (security->mode == wifi_security_mode_wpa2_personal)
14388 strcpy(wpa_mode, "WPA2-Personal");
14389 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
14390 strcpy(wpa_mode, "WPA-WPA2-Personal");
14391 else if (security->mode == wifi_security_mode_wpa_enterprise)
14392 strcpy(wpa_mode, "WPA-Enterprise");
14393 else if (security->mode == wifi_security_mode_wpa2_enterprise)
14394 strcpy(wpa_mode, "WPA2-Enterprise");
14395 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
14396 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
14397 else if (security->mode == wifi_security_mode_wpa3_personal) {
14398 strcpy(wpa_mode, "WPA3-Personal");
14399 okc_enable = TRUE;
14400 sae_MFP = TRUE;
14401 sae_pwe = 2;
14402 disable_EAPOL_retries = FALSE;
14403 } else if (security->mode == wifi_security_mode_wpa3_transition) {
14404 strcpy(wpa_mode, "WPA3-Personal-Transition");
14405 okc_enable = TRUE;
14406 sae_MFP = TRUE;
14407 sae_pwe = 2;
14408 disable_EAPOL_retries = FALSE;
14409 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
14410 strcpy(wpa_mode, "WPA3-Enterprise");
14411 sae_MFP = TRUE;
14412 sae_pwe = 2;
14413 disable_EAPOL_retries = FALSE;
developerd01e3e82023-04-26 19:10:38 +080014414 } else if (security->mode == wifi_security_mode_enhanced_open) {
developer3086e2f2023-01-17 09:40:01 +080014415 strcpy(wpa_mode, "OWE");
14416 sae_MFP = TRUE;
14417 sae_pwe = 2;
14418 disable_EAPOL_retries = FALSE;
developer72fb0bb2023-01-11 09:46:29 +080014419 }
14420
14421 band = wifi_index_to_band(ap_index);
14422 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
14423 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
14424 return RETURN_ERR;
14425 }
14426
14427 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
14428 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
14429 wifi_setSAEMFP(ap_index, sae_MFP);
14430 wifi_setSAEpwe(ap_index, sae_pwe);
14431 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
14432
developerd01e3e82023-04-26 19:10:38 +080014433 if (security->mode != wifi_security_mode_none && security->mode != wifi_security_mode_enhanced_open) {
developere5750452023-05-15 16:46:42 +080014434 if (security->u.key.type == wifi_security_key_type_psk || security->u.key.type == wifi_security_key_type_pass || security->u.key.type == wifi_security_key_type_psk_sae) {
14435 int key_len = strlen(security->u.key.key);
14436 // wpa_psk and wpa_passphrase cann;t use at the same time, the command replace one with the other.
14437 if (key_len == 64) { // set wpa_psk
14438 strncpy(password, security->u.key.key, 64); // 64 characters
14439 password[64] = '\0';
14440 wifi_setApSecurityPreSharedKey(ap_index, password);
14441 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_passphrase=/!p' %s", config_file);
14442 } else if (key_len >= 8 && key_len < 64) { // set wpa_passphrase
14443 strncpy(password, security->u.key.key, 63);
14444 password[63] = '\0';
14445 wifi_setApSecurityKeyPassphrase(ap_index, password);
14446 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_psk=/!p' %s", config_file);
14447 } else
14448 return RETURN_ERR;
14449 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +080014450 }
14451 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
14452 params.name = "sae_password";
14453 params.value = security->u.key.key;
14454 wifi_hostapdWrite(config_file, &params, 1);
developere5750452023-05-15 16:46:42 +080014455 } else { // remove sae_password
14456 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^sae_password=/!p' %s", config_file);
14457 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +080014458 }
14459 }
14460
14461 if (security->mode != wifi_security_mode_none) {
14462 memset(&params, 0, sizeof(params));
14463 params.name = "wpa_pairwise";
14464 if (security->encr == wifi_encryption_tkip)
14465 params.value = "TKIP";
14466 else if (security->encr == wifi_encryption_aes)
14467 params.value = "CCMP";
14468 else if (security->encr == wifi_encryption_aes_tkip)
14469 params.value = "TKIP CCMP";
14470 wifi_hostapdWrite(config_file, &params, 1);
14471 }
14472
14473 if (security->mfp == wifi_mfp_cfg_disabled)
14474 strcpy(mfp, "Disabled");
14475 else if (security->mfp == wifi_mfp_cfg_optional)
14476 strcpy(mfp, "Optional");
14477 else if (security->mfp == wifi_mfp_cfg_required)
14478 strcpy(mfp, "Required");
14479 wifi_setApSecurityMFPConfig(ap_index, mfp);
14480
14481 memset(&params, 0, sizeof(params));
14482 params.name = "transition_disable";
14483 if (security->wpa3_transition_disable == TRUE)
14484 params.value = "0x01";
14485 else
14486 params.value = "0x00";
14487 wifi_hostapdWrite(config_file, &params, 1);
14488
14489 memset(&params, 0, sizeof(params));
14490 params.name = "wpa_group_rekey";
14491 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
14492 params.value = buf;
14493 wifi_hostapdWrite(config_file, &params, 1);
14494
14495 memset(&params, 0, sizeof(params));
14496 params.name = "wpa_strict_rekey";
14497 params.value = security->strict_rekey?"1":"0";
14498 wifi_hostapdWrite(config_file, &params, 1);
14499
14500 memset(&params, 0, sizeof(params));
14501 params.name = "wpa_pairwise_update_count";
developere5750452023-05-15 16:46:42 +080014502 if (security->eapol_key_retries == 0)
14503 security->eapol_key_retries = 4; // 0 is invalid, set to default value.
developer72fb0bb2023-01-11 09:46:29 +080014504 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
14505 params.value = buf;
14506 wifi_hostapdWrite(config_file, &params, 1);
14507
14508 memset(&params, 0, sizeof(params));
14509 params.name = "disable_pmksa_caching";
14510 params.value = security->disable_pmksa_caching?"1":"0";
14511 wifi_hostapdWrite(config_file, &params, 1);
14512
developer23e71282023-01-18 10:25:19 +080014513 if (multiple_set == FALSE) {
14514 wifi_setApEnable(ap_index, FALSE);
14515 wifi_setApEnable(ap_index, TRUE);
14516 }
developer72fb0bb2023-01-11 09:46:29 +080014517
14518 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
14519
14520 return RETURN_OK;
14521}
14522
14523INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
14524{
14525 char buf[256] = {0};
14526 char config_file[128] = {0};
14527 int disable = 0;
developere5750452023-05-15 16:46:42 +080014528 bool set_sae = FALSE;
developer72fb0bb2023-01-11 09:46:29 +080014529
14530 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
14531 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
14532 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
14533 security->mode = wifi_security_mode_none;
14534 if (strlen(buf) != 0) {
14535 if (!strcmp(buf, "WPA-Personal"))
14536 security->mode = wifi_security_mode_wpa_personal;
14537 else if (!strcmp(buf, "WPA2-Personal"))
14538 security->mode = wifi_security_mode_wpa2_personal;
14539 else if (!strcmp(buf, "WPA-WPA2-Personal"))
14540 security->mode = wifi_security_mode_wpa_wpa2_personal;
14541 else if (!strcmp(buf, "WPA-Enterprise"))
14542 security->mode = wifi_security_mode_wpa_enterprise;
14543 else if (!strcmp(buf, "WPA2-Enterprise"))
14544 security->mode = wifi_security_mode_wpa2_enterprise;
14545 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
14546 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
14547 else if (!strcmp(buf, "WPA3-Personal"))
14548 security->mode = wifi_security_mode_wpa3_personal;
14549 else if (!strcmp(buf, "WPA3-Personal-Transition"))
14550 security->mode = wifi_security_mode_wpa3_transition;
14551 else if (!strcmp(buf, "WPA3-Enterprise"))
14552 security->mode = wifi_security_mode_wpa3_enterprise;
developer3086e2f2023-01-17 09:40:01 +080014553 else if (!strcmp(buf, "OWE"))
developerd01e3e82023-04-26 19:10:38 +080014554 security->mode = wifi_security_mode_enhanced_open;
developer72fb0bb2023-01-11 09:46:29 +080014555 }
14556
14557 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
14558 if (security->mode == wifi_security_mode_none)
14559 security->encr = wifi_encryption_none;
14560 else {
14561 if (strcmp(buf, "TKIP") == 0)
14562 security->encr = wifi_encryption_tkip;
14563 else if (strcmp(buf, "CCMP") == 0)
14564 security->encr = wifi_encryption_aes;
14565 else
14566 security->encr = wifi_encryption_aes_tkip;
14567 }
14568
14569 if (security->mode != wifi_encryption_none) {
14570 memset(buf, 0, sizeof(buf));
14571 // wpa3 can use one or both configs as password, so we check sae_password first.
14572 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
developere5750452023-05-15 16:46:42 +080014573 if (strlen(buf) != 0) {
14574 if (security->mode == wifi_security_mode_wpa3_personal || security->mode == wifi_security_mode_wpa3_transition)
14575 security->u.key.type = wifi_security_key_type_sae;
14576 set_sae = TRUE;
14577 strncpy(security->u.key.key, buf, sizeof(buf));
14578 }
14579 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
14580 if (strlen(buf) != 0){
14581 if (set_sae == TRUE)
14582 security->u.key.type = wifi_security_key_type_psk_sae;
14583 else if (strlen(buf) == 64)
14584 security->u.key.type = wifi_security_key_type_psk;
14585 else
14586 security->u.key.type = wifi_security_key_type_pass;
14587 strncpy(security->u.key.key, buf, sizeof(security->u.key.key));
developer72fb0bb2023-01-11 09:46:29 +080014588 }
developer72fb0bb2023-01-11 09:46:29 +080014589 security->u.key.key[255] = '\0';
14590 }
14591
14592 memset(buf, 0, sizeof(buf));
14593 wifi_getApSecurityMFPConfig(ap_index, buf);
14594 if (strcmp(buf, "Disabled") == 0)
14595 security->mfp = wifi_mfp_cfg_disabled;
14596 else if (strcmp(buf, "Optional") == 0)
14597 security->mfp = wifi_mfp_cfg_optional;
14598 else if (strcmp(buf, "Required") == 0)
14599 security->mfp = wifi_mfp_cfg_required;
14600
14601 memset(buf, 0, sizeof(buf));
14602 security->wpa3_transition_disable = FALSE;
14603 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
14604 disable = strtol(buf, NULL, 16);
14605 if (disable != 0)
14606 security->wpa3_transition_disable = TRUE;
14607
14608 memset(buf, 0, sizeof(buf));
14609 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
14610 if (strlen(buf) == 0)
14611 security->rekey_interval = 86400;
14612 else
14613 security->rekey_interval = strtol(buf, NULL, 10);
14614
14615 memset(buf, 0, sizeof(buf));
14616 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
14617 if (strlen(buf) == 0)
14618 security->strict_rekey = 1;
14619 else
14620 security->strict_rekey = strtol(buf, NULL, 10);
14621
14622 memset(buf, 0, sizeof(buf));
14623 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
14624 if (strlen(buf) == 0)
14625 security->eapol_key_retries = 4;
14626 else
14627 security->eapol_key_retries = strtol(buf, NULL, 10);
14628
14629 memset(buf, 0, sizeof(buf));
14630 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
14631 if (strlen(buf) == 0)
14632 security->disable_pmksa_caching = FALSE;
14633 else
14634 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
14635
14636 /* TODO
14637 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
14638 */
14639 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
14640 security->eap_identity_req_timeout = 0;
14641 security->eap_identity_req_retries = 0;
14642 security->eap_req_timeout = 0;
14643 security->eap_req_retries = 0;
14644 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
14645 return RETURN_OK;
14646}
14647
14648#endif /* WIFI_HAL_VERSION_3 */
14649
14650#ifdef WIFI_HAL_VERSION_3_PHASE2
14651INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
14652{
14653 char interface_name[16] = {0};
14654 char cmd[128] = {0};
14655 char buf[128] = {0};
14656 char *mac_addr = NULL;
14657 BOOL status = FALSE;
14658 size_t len = 0;
14659
14660 if(ap_index > MAX_APS)
14661 return RETURN_ERR;
14662
14663 *output_numDevices = 0;
14664 wifi_getApEnable(ap_index, &status);
14665 if (status == FALSE)
14666 return RETURN_OK;
14667
14668 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
14669 return RETURN_ERR;
14670 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
14671 _syscmd(cmd, buf, sizeof(buf));
14672
14673 mac_addr = strtok(buf, "\n");
14674 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
14675 *output_numDevices = i + 1;
14676 fprintf(stderr, "mac_addr: %s\n", mac_addr);
14677 addr_ptr = output_deviceMacAddressArray[i];
14678 mac_addr_aton(addr_ptr, mac_addr);
14679 mac_addr = strtok(NULL, "\n");
14680 }
14681
14682 return RETURN_OK;
14683}
14684#else
14685INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
14686{
14687 char interface_name[16] = {0};
14688 char cmd[128];
14689 BOOL status = false;
14690
14691 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
14692 return RETURN_ERR;
14693
14694 output_buf[0] = '\0';
14695
14696 wifi_getApEnable(ap_index,&status);
14697 if (!status)
14698 return RETURN_OK;
14699
14700 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
14701 return RETURN_ERR;
14702 sprintf(cmd, "hostapd_cli -i %s list_sta | tr '\\n' ',' | sed 's/.$//'", interface_name);
14703 _syscmd(cmd, output_buf, output_buf_size);
developer69b61b02023-03-07 17:17:44 +080014704
developer72fb0bb2023-01-11 09:46:29 +080014705 return RETURN_OK;
14706}
14707#endif
14708
14709INT wifi_getProxyArp(INT apIndex, BOOL *enable)
14710{
14711 char output[16]={'\0'};
14712 char config_file[MAX_BUF_SIZE] = {0};
14713
14714 if (!enable)
14715 return RETURN_ERR;
14716
14717 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
14718 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
14719
14720 if (strlen(output) == 0)
14721 *enable = FALSE;
14722 else if (strncmp(output, "1", 1) == 0)
14723 *enable = TRUE;
14724 else
14725 *enable = FALSE;
14726
14727 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
14728 return RETURN_OK;
14729}
14730
14731INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
14732{
14733 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
14734 return RETURN_ERR;
14735 *output_enable=TRUE;
14736 return RETURN_OK;
14737}
14738
14739INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
14740{
14741 char cmd[128] = {0};
14742 char buf[128] = {0};
14743 char line[128] = {0};
14744 size_t len = 0;
14745 FILE *f = NULL;
14746 int index = 0;
14747 int exp = 0;
14748 int mantissa = 0;
14749 int duration = 0;
14750 int radio_index = 0;
14751 int max_radio_num = 0;
14752 uint twt_wake_interval = 0;
14753 int phyId = 0;
14754 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
14755
14756 wifi_getMaxRadioNumber(&max_radio_num);
14757
14758 radio_index = ap_index % max_radio_num;
14759
14760 phyId = radio_index_to_phy(radio_index);
14761 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", phyId);
14762 _syscmd(cmd, buf, sizeof(buf));
14763 *numSessionReturned = strtol(buf, NULL, 10) - 1;
14764 if (*numSessionReturned > maxNumberSessions)
14765 *numSessionReturned = maxNumberSessions;
14766 else if (*numSessionReturned < 1) {
14767 *numSessionReturned = 0;
14768 return RETURN_OK;
14769 }
14770
14771 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | tail -n %d | tr '|' ' ' | tr -s ' '", phyId, *numSessionReturned);
14772 if ((f = popen(cmd, "r")) == NULL) {
14773 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
14774 return RETURN_ERR;
14775 }
14776
14777 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
14778 while((fgets(line, sizeof(line), f)) != NULL) {
14779 char *tmp = NULL;
14780 strcpy(buf, line);
14781 tmp = strtok(buf, " ");
14782 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
14783 tmp = strtok(NULL, " ");
14784 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
14785 tmp = strtok(NULL, " ");
14786 if (strstr(tmp, "t")) {
14787 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
14788 }
14789 if (strstr(tmp, "a")) {
14790 twtSessions[index].twtParameters.operation.announced = TRUE;
14791 }
14792 tmp = strtok(NULL, " ");
14793 exp = strtol(tmp, NULL, 10);
14794 tmp = strtok(NULL, " ");
14795 mantissa = strtol(tmp, NULL, 10);
14796 tmp = strtok(NULL, " ");
14797 duration = strtol(tmp, NULL, 10);
14798
14799 // only implicit supported
14800 twtSessions[index].twtParameters.operation.implicit = TRUE;
14801 // only individual agreement supported
14802 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
14803
14804 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
14805 twt_wake_interval = mantissa * (1 << exp);
14806 if (mantissa == 0 || twt_wake_interval/mantissa != (1 << exp)) {
14807 // Overflow handling
14808 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
14809 } else {
14810 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
14811 }
14812 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
14813 index++;
14814 }
14815
14816 pclose(f);
14817 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
14818 return RETURN_OK;
14819}