blob: 0b1b0460e3126341d1e202123d205ca1c8dc2911 [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"
developerb2977562023-05-24 17:54:12 +080088#define ROM_LOGAN_DAT_FILE "/rom/etc/wireless/mediatek/mt7990.b"
developera1255e42023-05-13 17:45:02 +080089
developer72fb0bb2023-01-11 09:46:29 +080090#define NOACK_MAP_FILE "/tmp/NoAckMap"
developerfead3972023-05-25 20:15:02 +080091#define RADIO_RESET_FILE "/nvram/radio_reset"
developerf6a87542023-05-16 15:47:28 +080092
developer72fb0bb2023-01-11 09:46:29 +080093#define BRIDGE_NAME "brlan0"
developerd1824452023-05-18 12:30:04 +080094#define BASE_PHY_INDEX 1
95#define BASE_RADIO_INDEX 0
developer72fb0bb2023-01-11 09:46:29 +080096
97/*
98 MAX_APS - Number of all AP available in system
99 2x Home AP
100 2x Backhaul AP
101 2x Guest AP
102 2x Secure Onboard AP
103 2x Service AP
104
105*/
106
107
108#define MAX_APS MAX_NUM_RADIOS*5
developer7e4a2a62023-04-06 19:56:03 +0800109
110#define PREFIX_WIFI2G "ra"
111#define PREFIX_WIFI5G "rai"
112#define PREFIX_WIFI6G "rax"
developer72fb0bb2023-01-11 09:46:29 +0800113
developer47cc27a2023-05-17 23:09:58 +0800114#define PREFIX_SSID_2G "RDKB_2G"
115#define PREFIX_SSID_5G "RDKB_5G"
116#define PREFIX_SSID_6G "RDKB_6G"
117
developer72fb0bb2023-01-11 09:46:29 +0800118#ifndef RADIO_PREFIX
119#define RADIO_PREFIX "wlan"
120#endif
121
122#define MAX_ASSOCIATED_STA_NUM 2007
123
124//Uncomment to enable debug logs
125//#define WIFI_DEBUG
developer49b17232023-05-19 16:35:19 +0800126enum {
127 DEBUG_OFF = 0,
128 DEBUG_ERROR = 1,
129 DEBUG_WARN = 2,
130 DEBUG_NOTICE = 3,
131 DEBUG_INFO = 4
132};
133int wifi_debug_level = DEBUG_NOTICE;
134#define wifi_debug(level, fmt, args...) \
135{ \
136 if (level <= wifi_debug_level) \
137 { \
developer2edaf012023-05-24 14:24:53 +0800138 printf("[%s][%d]"fmt"", __func__, __LINE__, ##args); \
developer49b17232023-05-19 16:35:19 +0800139 } \
140}
developer72fb0bb2023-01-11 09:46:29 +0800141
142#ifdef WIFI_DEBUG
143#define wifi_dbg_printf printf
144#define WIFI_ENTRY_EXIT_DEBUG printf
145#else
developer2f79c922023-06-02 17:33:42 +0800146#define wifi_dbg_printf(format, args...)
147#define WIFI_ENTRY_EXIT_DEBUG(format, args...)
developer72fb0bb2023-01-11 09:46:29 +0800148#endif
149
150#define HOSTAPD_CONF_0 "/nvram/hostapd0.conf" //private-wifi-2g
151#define HOSTAPD_CONF_1 "/nvram/hostapd1.conf" //private-wifi-5g
152#define HOSTAPD_CONF_4 "/nvram/hostapd4.conf" //public-wifi-2g
153#define HOSTAPD_CONF_5 "/nvram/hostapd5.conf" //public-wifi-5g
154#define DEF_HOSTAPD_CONF_0 "/usr/ccsp/wifi/hostapd0.conf"
155#define DEF_HOSTAPD_CONF_1 "/usr/ccsp/wifi/hostapd1.conf"
156#define DEF_HOSTAPD_CONF_4 "/usr/ccsp/wifi/hostapd4.conf"
157#define DEF_HOSTAPD_CONF_5 "/usr/ccsp/wifi/hostapd5.conf"
158#define DEF_RADIO_PARAM_CONF "/usr/ccsp/wifi/radio_param_def.cfg"
159#define LM_DHCP_CLIENT_FORMAT "%63d %17s %63s %63s"
160
161#define HOSTAPD_HT_CAPAB "[LDPC][SHORT-GI-20][SHORT-GI-40][MAX-AMSDU-7935]"
162
163#define BW_FNAME "/nvram/bw_file.txt"
164
165#define PS_MAX_TID 16
166
developer96b38512023-02-22 11:17:45 +0800167#define MAX_CARD_INDEX 3
168
developer72fb0bb2023-01-11 09:46:29 +0800169static wifi_radioQueueType_t _tid_ac_index_get[PS_MAX_TID] = {
170 WIFI_RADIO_QUEUE_TYPE_BE, /* 0 */
171 WIFI_RADIO_QUEUE_TYPE_BK, /* 1 */
172 WIFI_RADIO_QUEUE_TYPE_BK, /* 2 */
173 WIFI_RADIO_QUEUE_TYPE_BE, /* 3 */
174 WIFI_RADIO_QUEUE_TYPE_VI, /* 4 */
175 WIFI_RADIO_QUEUE_TYPE_VI, /* 5 */
176 WIFI_RADIO_QUEUE_TYPE_VO, /* 6 */
177 WIFI_RADIO_QUEUE_TYPE_VO, /* 7 */
178 WIFI_RADIO_QUEUE_TYPE_BE, /* 8 */
179 WIFI_RADIO_QUEUE_TYPE_BK, /* 9 */
180 WIFI_RADIO_QUEUE_TYPE_BK, /* 10 */
181 WIFI_RADIO_QUEUE_TYPE_BE, /* 11 */
182 WIFI_RADIO_QUEUE_TYPE_VI, /* 12 */
183 WIFI_RADIO_QUEUE_TYPE_VI, /* 13 */
184 WIFI_RADIO_QUEUE_TYPE_VO, /* 14 */
185 WIFI_RADIO_QUEUE_TYPE_VO, /* 15 */
186};
187
188typedef unsigned long long u64;
189
190/* Enum to define WiFi Bands */
191typedef enum
192{
193 band_invalid = -1,
194 band_2_4 = 0,
195 band_5 = 1,
196 band_6 = 2,
197} wifi_band;
198
developer17038e62023-03-02 14:43:43 +0800199char* wifi_band_str[] = {
200 "2G",
201 "5G",
202 "6G",
203};
204
developer72fb0bb2023-01-11 09:46:29 +0800205typedef enum {
206 WIFI_MODE_A = 0x01,
207 WIFI_MODE_B = 0x02,
208 WIFI_MODE_G = 0x04,
209 WIFI_MODE_N = 0x08,
210 WIFI_MODE_AC = 0x10,
211 WIFI_MODE_AX = 0x20,
developera1255e42023-05-13 17:45:02 +0800212 WIFI_MODE_BE = 0x40,
developer72fb0bb2023-01-11 09:46:29 +0800213} wifi_ieee80211_Mode;
214
developer2f79c922023-06-02 17:33:42 +0800215typedef enum {
developerd1824452023-05-18 12:30:04 +0800216 HT_BW_20,
217 HT_BW_40,
developer2f79c922023-06-02 17:33:42 +0800218} ht_config_bw;
developerd1824452023-05-18 12:30:04 +0800219
developer2f79c922023-06-02 17:33:42 +0800220typedef enum {
developerd1824452023-05-18 12:30:04 +0800221 VHT_BW_2040,
222 VHT_BW_80,
223 VHT_BW_160,
224 VHT_BW_8080,
developer2f79c922023-06-02 17:33:42 +0800225} vht_config_bw;
developerd1824452023-05-18 12:30:04 +0800226
developer2f79c922023-06-02 17:33:42 +0800227typedef enum {
developerd1824452023-05-18 12:30:04 +0800228 EHT_BW_20,
229 EHT_BW_40,
230 EHT_BW_80,
231 EHT_BW_160,
232 EHT_BW_320,
developer2f79c922023-06-02 17:33:42 +0800233} eht_config_bw;
developerd1824452023-05-18 12:30:04 +0800234
developer72fb0bb2023-01-11 09:46:29 +0800235#ifdef WIFI_HAL_VERSION_3
236
237// Return number of elements in array
238#ifndef ARRAY_SIZE
239#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
240#endif /* ARRAY_SIZE */
241
242#ifndef ARRAY_AND_SIZE
243#define ARRAY_AND_SIZE(x) (x),ARRAY_SIZE(x)
244#endif /* ARRAY_AND_SIZE */
245
246#define WIFI_ITEM_STR(key, str) {0, sizeof(str)-1, (int)key, (intptr_t)str}
247
248typedef struct {
249 int32_t value;
250 int32_t param;
251 intptr_t key;
252 intptr_t data;
253} wifi_secur_list;
254
255static int util_unii_5g_centerfreq(const char *ht_mode, int channel);
256static int util_unii_6g_centerfreq(const char *ht_mode, int channel);
257wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key);
258wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str);
259char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key);
260static int ieee80211_channel_to_frequency(int channel, int *freqMHz);
developer47cc27a2023-05-17 23:09:58 +0800261static void wifi_PrepareDefaultHostapdConfigs(void);
262static void wifi_psk_file_reset();
developerb2977562023-05-24 17:54:12 +0800263static void wifi_psk_file_reset_by_radio(char radio_idx);
264static void wifi_dat_file_reset();
265static void wifi_dat_file_reset_by_radio(char radio_idx);
developer262f4cb2023-05-24 12:22:04 +0800266static int util_get_sec_chan_offset(int channel, const char* ht_mode);
developer2f79c922023-06-02 17:33:42 +0800267int hostapd_raw_add_bss(int apIndex);
268int hostapd_raw_remove_bss(int apIndex);
developer47cc27a2023-05-17 23:09:58 +0800269
developer49b17232023-05-19 16:35:19 +0800270/*type define the nl80211 call back func*/
271typedef int (*mtk_nl80211_cb) (struct nl_msg *, void *);
272
273/**
274*struct mtk_nl80211_param
275* init mtk nl80211 using parameters
276* @sub_cmd: the cmd define in the mtk_vendor_nl80211.h.
277* @if_type: now only support the NL80211_ATTR_IFINDEX/NL80211_ATTR_WIPHY.
278* @if_idx: the index should match the interface or wiphy.
279* Note: NA
280**/
281struct mtk_nl80211_param {
282 unsigned int sub_cmd;
283 int if_type;
284 int if_idx;
285};
286
287/**
developer121a8e72023-05-22 09:19:39 +0800288*struct mtk_nl80211_cb_data
289* init mtk nl80211 call back parameters
290* @out_buf: store the mtk vendor output msg for wifi hal buffer.
291* @out_len: the output buffer length.
292* Note: NA
293**/
294struct mtk_nl80211_cb_data {
295 char * out_buf;
296 unsigned int out_len;
297};
298
299/**
developer49b17232023-05-19 16:35:19 +0800300*mtk_nl80211_init
301* init mtk nl80211 netlink and init the vendor msg common part.
302* @nl: netlink, just init it.
303* @msg: netlink message will alloc it.
304* the msg send success/fails is not free by app
305* only the nla_put etc api fails should use nlmsg_free.
306* @msg_data: vendor data msg attr pointer.
307* @param: init using interface and sub_cmd parameter.
308*
309*init the netlink context and mtk netlink vendor msg.
310*
311*return:
312* 0: success
313* other: fail
314**/
315
316int mtk_nl80211_init(struct unl *nl, struct nl_msg **msg,
317 struct nlattr **msg_data, struct mtk_nl80211_param *param) {
318 /*sanity check here*/
319 if (!nl || !param) {
320 (void)fprintf(stderr,
developerdaf24792023-06-06 11:40:04 +0800321 "[%s][%d]:nl(%p) or param(%p) is null, error!\n",
developer49b17232023-05-19 16:35:19 +0800322 __func__, __LINE__, nl, param);
323 return -1;
324 }
325 /*if_type check*/
326 if ( param->if_type != NL80211_ATTR_IFINDEX && param->if_type != NL80211_ATTR_WIPHY) {
327 (void)fprintf(stderr,
328 "[%s][%d]:if_type(0x%x) is not supported, only 0x%x and 0x%x supported.\n",
329 __func__, __LINE__, param->if_type, NL80211_ATTR_IFINDEX, NL80211_ATTR_WIPHY);
330 return -1;
331 }
332 /*init the nl*/
333 if (unl_genl_init(nl, "nl80211") < 0) {
334 (void)fprintf(stderr, "[%s][%d]::Failed to connect to nl80211\n",
335 __func__, __LINE__);
336 return -1;
337 }
338 /*init the msg*/
339 *msg = unl_genl_msg(nl, NL80211_CMD_VENDOR, false);
340
341 if (nla_put_u32(*msg, param->if_type, param->if_idx) ||
342 nla_put_u32(*msg, NL80211_ATTR_VENDOR_ID, MTK_NL80211_VENDOR_ID) ||
343 nla_put_u32(*msg, NL80211_ATTR_VENDOR_SUBCMD, param->sub_cmd)) {
344 (void)fprintf(stderr,
345 "[%s][%d]:Nla put error: if_type: 0x%x, if_idx: 0x%x, sub_cmd: 0x%x\n",
346 __func__, __LINE__, param->if_type, param->if_idx, param->sub_cmd);
347 goto err;
348 }
349
350 *msg_data = nla_nest_start(*msg, NL80211_ATTR_VENDOR_DATA);
351 if (!*msg_data) {
352 (void)fprintf(stderr, "[%s][%d]:Nla put NL80211_ATTR_VENDOR_DATA start error\n",
353 __func__, __LINE__);
354 goto err;
355 }
356
357 return 0;
358err:
developer49b17232023-05-19 16:35:19 +0800359 nlmsg_free(*msg);
360 unl_free(nl);
361 return -1;
362}
363
364/**
365*mtk_nl80211_send
366* set the vendor cmd call back and sent the vendor msg.
367* @nl: netlink.
368* @msg: netlink message.
369* @msg_data: vendor data msg attr pointer.
370* @handler: if the msg have call back shoud add the call back func
371* the event msg will handle by the call back func(exp:get cmd)
372* other set it as NULL(exp:set cmd).
373* @arg:call back func arg parameter.
374*add end of the netlink msg, set the call back and send msg
375*
376*return:
377* 0: success
378* other: fail
379**/
380int mtk_nl80211_send(struct unl *nl, struct nl_msg *msg,
381 struct nlattr *msg_data, mtk_nl80211_cb handler, void *arg) {
382 int ret = 0;
383 /*sanity check*/
384 if (!nl || !msg || !msg_data) {
385 (void)fprintf(stderr,
developerdaf24792023-06-06 11:40:04 +0800386 "[%s][%d]:nl(%p),msg(%p) or msg_data(%p) is null, error!\n",
developer49b17232023-05-19 16:35:19 +0800387 __func__, __LINE__, nl, msg, msg_data);
388 return -1;
389 }
390 /*end the msg attr of vendor data*/
391 nla_nest_end(msg, msg_data);
392 /*send the msg and set call back */
393 ret = unl_genl_request(nl, msg, handler, arg);
394 if (ret)
395 (void)fprintf(stderr, "send nl80211 cmd fails\n");
396 return ret;
397}
398
399/**
400*mtk_nl80211_deint
developer2edaf012023-05-24 14:24:53 +0800401* deinit the netlink.
developer49b17232023-05-19 16:35:19 +0800402* @nl: netlink.
403*
developer2edaf012023-05-24 14:24:53 +0800404*free deinit the netlink.
developer49b17232023-05-19 16:35:19 +0800405*
406*return:
407* 0: success
408**/
409
410int mtk_nl80211_deint(struct unl *nl) {
411 unl_free(nl);
412 return 0;
413}
414
developer72fb0bb2023-01-11 09:46:29 +0800415
416static wifi_secur_list map_security[] =
417{
418 WIFI_ITEM_STR(wifi_security_mode_none, "None"),
419 WIFI_ITEM_STR(wifi_security_mode_wep_64, "WEP-64"),
420 WIFI_ITEM_STR(wifi_security_mode_wep_128, "WEP-128"),
421 WIFI_ITEM_STR(wifi_security_mode_wpa_personal, "WPA-Personal"),
422 WIFI_ITEM_STR(wifi_security_mode_wpa_enterprise, "WPA-Enterprise"),
423 WIFI_ITEM_STR(wifi_security_mode_wpa2_personal, "WPA2-Personal"),
424 WIFI_ITEM_STR(wifi_security_mode_wpa2_enterprise, "WPA2-Enterprise"),
425 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_personal, "WPA-WPA2-Personal"),
426 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_enterprise, "WPA-WPA2-Enterprise"),
427 WIFI_ITEM_STR(wifi_security_mode_wpa3_personal, "WPA3-Personal"),
428 WIFI_ITEM_STR(wifi_security_mode_wpa3_transition, "WPA3-Personal-Transition"),
429 WIFI_ITEM_STR(wifi_security_mode_wpa3_enterprise, "WPA3-Enterprise")
430};
431
432wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key)
433{
434 wifi_secur_list *item;
435 int i;
436
437 for (item = list,i = 0;i < list_sz; item++, i++) {
438 if ((int)(item->key) == key) {
439 return item;
440 }
441 }
442
443 return NULL;
444}
445
446char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key)
447{
448 wifi_secur_list *item = wifi_get_item_by_key(list, list_sz, key);
449
450 if (!item) {
451 return "";
452 }
453
454 return (char *)(item->data);
455}
456
457wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str)
458{
459 wifi_secur_list *item;
460 int i;
461
462 for (item = list,i = 0;i < list_sz; item++, i++) {
463 if (strcmp((char *)(item->data), str) == 0) {
464 return item;
465 }
466 }
467
468 return NULL;
469}
470#endif /* WIFI_HAL_VERSION_3 */
471
developer96b38512023-02-22 11:17:45 +0800472
473static char l1profile[32] = "/etc/wireless/l1profile.dat";
developer17038e62023-03-02 14:43:43 +0800474char main_prefix[MAX_NUM_RADIOS][IFNAMSIZ];
475char ext_prefix[MAX_NUM_RADIOS][IFNAMSIZ];
476#define MAX_SSID_LEN 64
477char default_ssid[MAX_NUM_RADIOS][MAX_SSID_LEN];;
developer745f0bd2023-03-06 14:32:53 +0800478int radio_band[MAX_NUM_RADIOS];
developer17038e62023-03-02 14:43:43 +0800479
480static int array_index_to_vap_index(UINT radioIndex, int arrayIndex);
481static int vap_index_to_array_index(int vapIndex, int *radioIndex, int *arrayIndex);
482
developer96b38512023-02-22 11:17:45 +0800483
484static int
485get_value(const char *conf_file, const char *param, char *value, int len)
486{
487 FILE *fp;
488 int ret = -1;
489 int param_len = strlen(param);
490 int buf_len;
491 char buf[256];
492
493 fp = fopen(conf_file, "r");
494 if (!fp) {
495 return -1;
496 }
497
498 while (fgets(buf, sizeof(buf), fp)) {
499 buf_len = strlen(buf);
500 if (buf[buf_len - 1] == '\n') {
501 buf_len--;
502 buf[buf_len] = '\0';
503 }
504 if ((buf_len > param_len) &&
505 (strncmp(buf, param, param_len) == 0) &&
506 (buf[param_len] == '=')) {
507
508 if (buf_len == (param_len + 1)) {
509 value[0] = '\0';
510 ret = 0;
511 } else {
512 ret = snprintf(value, len, "%s", buf + (param_len + 1));
513 }
514 fclose(fp);
515 return ret;
516 }
517 }
518 fclose(fp);
519 return -1;
520}
521
522static int
523get_value_by_idx(const char *conf_file, const char *param, int idx, char *value, int len)
524{
525 char buf[256];
526 int ret;
527 char *save_ptr = NULL;
528 char *tok = NULL;
529
530 ret = get_value(conf_file, param, buf, sizeof(buf));
531 if (ret < 0)
532 return ret;
533
534 tok = strtok_r(buf, ";", &save_ptr);
535 do {
536 if (idx == 0 || tok == NULL)
537 break;
538 else
539 idx--;
540
541 tok = strtok_r(NULL, ";", &save_ptr);
542 } while (tok != NULL);
543
544 if (tok) {
545 ret = snprintf(value, len, "%s", tok);
546 } else {
547 ret = 0;
548 value[0] = '\0';
549 }
550
551 return ret;
552}
553
554
developer72fb0bb2023-01-11 09:46:29 +0800555#ifdef HAL_NETLINK_IMPL
556typedef struct {
557 int id;
558 struct nl_sock* socket;
559 struct nl_cb* cb;
560} Netlink;
561
562static int mac_addr_aton(unsigned char *mac_addr, char *arg)
563{
developerdaf24792023-06-06 11:40:04 +0800564 unsigned char mac_addr_int[6]={};
developer72fb0bb2023-01-11 09:46:29 +0800565 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);
566 mac_addr[0] = mac_addr_int[0];
567 mac_addr[1] = mac_addr_int[1];
568 mac_addr[2] = mac_addr_int[2];
569 mac_addr[3] = mac_addr_int[3];
570 mac_addr[4] = mac_addr_int[4];
571 mac_addr[5] = mac_addr_int[5];
572 return 0;
573}
574
575static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
576{
577 unsigned int mac_addr_int[6]={};
578 mac_addr_int[0] = arg[0];
579 mac_addr_int[1] = arg[1];
580 mac_addr_int[2] = arg[2];
581 mac_addr_int[3] = arg[3];
582 mac_addr_int[4] = arg[4];
583 mac_addr_int[5] = arg[5];
584 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]);
585 return;
586}
587
588static int ieee80211_frequency_to_channel(int freq)
589{
590 /* see 802.11-2007 17.3.8.3.2 and Annex J */
591 if (freq == 2484)
592 return 14;
593 /* see 802.11ax D6.1 27.3.23.2 and Annex E */
594 else if (freq == 5935)
595 return 2;
596 else if (freq < 2484)
597 return (freq - 2407) / 5;
598 else if (freq >= 4910 && freq <= 4980)
599 return (freq - 4000) / 5;
600 else if (freq < 5950)
601 return (freq - 5000) / 5;
602 else if (freq <= 45000) /* DMG band lower limit */
603 /* see 802.11ax D6.1 27.3.23.2 */
604 return (freq - 5950) / 5;
605 else if (freq >= 58320 && freq <= 70200)
606 return (freq - 56160) / 2160;
607 else
608 return 0;
609}
610
611static int initSock80211(Netlink* nl) {
612 nl->socket = nl_socket_alloc();
613 if (!nl->socket) {
614 fprintf(stderr, "Failing to allocate the sock\n");
615 return -ENOMEM;
616 }
617
618 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
619
620 if (genl_connect(nl->socket)) {
621 fprintf(stderr, "Failed to connect\n");
622 nl_close(nl->socket);
623 nl_socket_free(nl->socket);
624 return -ENOLINK;
625 }
626
627 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
628 if (nl->id< 0) {
629 fprintf(stderr, "interface not found.\n");
630 nl_close(nl->socket);
631 nl_socket_free(nl->socket);
632 return -ENOENT;
633 }
634
635 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
636 if ((!nl->cb)) {
637 fprintf(stderr, "Failed to allocate netlink callback.\n");
638 nl_close(nl->socket);
639 nl_socket_free(nl->socket);
640 return ENOMEM;
641 }
642
643 return nl->id;
644}
645
646static int nlfree(Netlink *nl)
647{
648 nl_cb_put(nl->cb);
649 nl_close(nl->socket);
650 nl_socket_free(nl->socket);
651 return 0;
652}
653
654static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
655 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
656 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
657 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
658};
659
660static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
661};
662
663static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
664};
665
666typedef struct _wifi_channelStats_loc {
667 INT array_size;
668 INT ch_number;
669 BOOL ch_in_pool;
670 INT ch_noise;
671 BOOL ch_radar_noise;
672 INT ch_max_80211_rssi;
673 INT ch_non_80211_noise;
674 INT ch_utilization;
675 ULLONG ch_utilization_total;
676 ULLONG ch_utilization_busy;
677 ULLONG ch_utilization_busy_tx;
678 ULLONG ch_utilization_busy_rx;
679 ULLONG ch_utilization_busy_self;
680 ULLONG ch_utilization_busy_ext;
681} wifi_channelStats_t_loc;
682
683typedef struct wifi_device_info {
684 INT wifi_devIndex;
685 UCHAR wifi_devMacAddress[6];
686 CHAR wifi_devIPAddress[64];
687 BOOL wifi_devAssociatedDeviceAuthentiationState;
688 INT wifi_devSignalStrength;
689 INT wifi_devTxRate;
690 INT wifi_devRxRate;
691} wifi_device_info_t;
692
693#endif
694
695//For 5g Alias Interfaces
696static BOOL priv_flag = TRUE;
697static BOOL pub_flag = TRUE;
698static BOOL Radio_flag = TRUE;
699//wifi_setApBeaconRate(1, beaconRate);
700
701BOOL multiple_set = FALSE;
702
703struct params
704{
705 char * name;
706 char * value;
707};
708
709static int _syscmd(char *cmd, char *retBuf, int retBufSize)
710{
711 FILE *f;
712 char *ptr = retBuf;
713 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
714
715 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
716 if((f = popen(cmd, "r")) == NULL) {
717 fprintf(stderr,"\npopen %s error\n", cmd);
718 return RETURN_ERR;
719 }
720
721 while(!feof(f))
722 {
723 *ptr = 0;
724 if(bufSize>=128) {
725 bufbytes=128;
726 } else {
727 bufbytes=bufSize-1;
728 }
729
730 fgets(ptr,bufbytes,f);
731 readbytes=strlen(ptr);
732
733 if(!readbytes)
734 break;
735
736 bufSize-=readbytes;
737 ptr += readbytes;
738 }
739 cmd_ret = pclose(f);
740 retBuf[retBufSize-1]=0;
741 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
742
743 return cmd_ret >> 8;
744}
745
746INT radio_index_to_phy(int radioIndex)
747{
developer17038e62023-03-02 14:43:43 +0800748 /* TODO */
749 return radioIndex;
developer72fb0bb2023-01-11 09:46:29 +0800750}
751
752INT wifi_getMaxRadioNumber(INT *max_radio_num)
753{
754 char cmd[64] = {0};
755 char buf[4] = {0};
756
757 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
758
759 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
760 _syscmd(cmd, buf, sizeof(buf));
761 *max_radio_num = strtoul(buf, NULL, 10) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS:strtoul(buf, NULL, 10);
762
763 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
764
765 return RETURN_OK;
766}
767
developer17038e62023-03-02 14:43:43 +0800768wifi_band radio_index_to_band(int radioIndex)
769{
developer745f0bd2023-03-06 14:32:53 +0800770 return radio_band[radioIndex];
developer17038e62023-03-02 14:43:43 +0800771}
772
developer72fb0bb2023-01-11 09:46:29 +0800773wifi_band wifi_index_to_band(int apIndex)
774{
775 char cmd[128] = {0};
776 char buf[64] = {0};
777 int nl80211_band = 0;
778 int i = 0;
779 int phyIndex = 0;
780 int radioIndex = 0;
781 int max_radio_num = 0;
782 wifi_band band = band_invalid;
783
784 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
785
786 wifi_getMaxRadioNumber(&max_radio_num);
787 radioIndex = apIndex % max_radio_num;
788 phyIndex = radio_index_to_phy(radioIndex);
789 while(i < 10){
790 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Band .:' | tail -n 1 | tr -d ':\\n' | awk '{print $2}'", phyIndex);
791 _syscmd(cmd, buf, sizeof(buf));
792 nl80211_band = strtol(buf, NULL, 10);
793 if (nl80211_band == 1)
794 band = band_2_4;
795 else if (nl80211_band == 2)
796 band = band_5;
797 else if (nl80211_band == 4) // band == 3 is 60GHz
798 band = band_6;
799
800 if(band != band_invalid)
801 break;
developer69b61b02023-03-07 17:17:44 +0800802
developer72fb0bb2023-01-11 09:46:29 +0800803 i++;
804 sleep(1);
805 }
806
807 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
808 return band;
809}
810
811static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
812{
developer7e4a2a62023-04-06 19:56:03 +0800813 char cmd[MAX_CMD_SIZE] = {0};
814 char buf[MAX_BUF_SIZE] = {0};
815 int ret = 0;
developer72fb0bb2023-01-11 09:46:29 +0800816
developer7e4a2a62023-04-06 19:56:03 +0800817 ret = snprintf(cmd, MAX_CMD_SIZE, "cat %s 2> /dev/null | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"",
818 conf_file, param);
developer72fb0bb2023-01-11 09:46:29 +0800819
developer7e4a2a62023-04-06 19:56:03 +0800820 if (ret < 0) {
821 printf("%s: snprintf error!", __func__);
822 return -1;
823 }
824
825 ret = _syscmd(cmd, buf, sizeof(buf));
826 if ((ret != 0) && (strlen(buf) == 0)) {
827 printf("%s: _syscmd error!", __func__);
828 return -1;
829 }
830
831 snprintf(output, output_size, "%s", buf);
832
833 return 0;
developer72fb0bb2023-01-11 09:46:29 +0800834}
835
836static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
837{
developer7e4a2a62023-04-06 19:56:03 +0800838 char cmd[MAX_CMD_SIZE] = {0};
839 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +0800840
developer7e4a2a62023-04-06 19:56:03 +0800841 for (int i = 0; i < item_count; i++) {
developer72fb0bb2023-01-11 09:46:29 +0800842 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
developer7e4a2a62023-04-06 19:56:03 +0800843 if (strlen(buf) == 0) /*no such item, insert it*/
developera1255e42023-05-13 17:45:02 +0800844 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 +0800845 else /*find the item, update it*/
developer72fb0bb2023-01-11 09:46:29 +0800846 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 +0800847
developer72fb0bb2023-01-11 09:46:29 +0800848 if(_syscmd(cmd, buf, sizeof(buf)))
849 return -1;
850 }
851
developera1255e42023-05-13 17:45:02 +0800852 return 0;
853}
developerfde01262023-05-22 15:15:24 +0800854
developera1255e42023-05-13 17:45:02 +0800855static int wifi_datfileRead(char *conf_file, char *param, char *output, int output_size)
856{
857 char cmd[MAX_CMD_SIZE] = {0};
developera1255e42023-05-13 17:45:02 +0800858 int ret = 0;
developerfde01262023-05-22 15:15:24 +0800859 int len;
860
861 ret = snprintf(cmd, sizeof(cmd), "datconf -f %s get %s", conf_file, param);
862 if (ret < 0) {
863 printf("%s: snprintf error!", __func__);
864 return -1;
865 }
866
867 ret = _syscmd(cmd, output, output_size);
868 if ((ret != 0) && (strlen(output) == 0)) {
869 printf("%s: _syscmd error!", __func__);
870 return -1;
871 }
developera1255e42023-05-13 17:45:02 +0800872
developerfde01262023-05-22 15:15:24 +0800873 len = strlen(output);
874 if ((len > 0) && (output[len - 1] == '\n')) {
875 output[len - 1] = '\0';
876 }
877
878 return 0;
879}
developera1255e42023-05-13 17:45:02 +0800880
developer3a85ab82023-05-25 11:59:38 +0800881static int wifi_datfileRead2(char *conf_file, int idx, char *param, char *output, int output_size)
developerfde01262023-05-22 15:15:24 +0800882{
883 char cmd[MAX_CMD_SIZE] = {0};
884 int ret = 0;
885 int len;
886
developer3a85ab82023-05-25 11:59:38 +0800887 ret = snprintf(cmd, sizeof(cmd), "datconf -f %s get %s %d", conf_file, param, idx);
developera1255e42023-05-13 17:45:02 +0800888 if (ret < 0) {
889 printf("%s: snprintf error!", __func__);
890 return -1;
891 }
892
developerfde01262023-05-22 15:15:24 +0800893 ret = _syscmd(cmd, output, output_size);
894 if ((ret != 0) && (strlen(output) == 0)) {
developera1255e42023-05-13 17:45:02 +0800895 printf("%s: _syscmd error!", __func__);
896 return -1;
897 }
898
developerfde01262023-05-22 15:15:24 +0800899 len = strlen(output);
900 if ((len > 0) && (output[len - 1] == '\n')) {
901 output[len - 1] = '\0';
902 }
developera1255e42023-05-13 17:45:02 +0800903
developer72fb0bb2023-01-11 09:46:29 +0800904 return 0;
905}
906
developera1255e42023-05-13 17:45:02 +0800907static int wifi_datfileWrite(char *conf_file, struct params *list, int item_count)
908{
developerfde01262023-05-22 15:15:24 +0800909 int ret;
developera1255e42023-05-13 17:45:02 +0800910 char cmd[MAX_CMD_SIZE] = {0};
911 char buf[MAX_BUF_SIZE] = {0};
912
913 for (int i = 0; i < item_count; i++) {
developerfde01262023-05-22 15:15:24 +0800914 ret = snprintf(cmd, sizeof(cmd), "datconf -f %s set %s \"%s\"", conf_file, list[i].name, list[i].value);
915 if (ret < 0) {
916 printf("%s: snprintf error!", __func__);
917 return -1;
918 }
developera1255e42023-05-13 17:45:02 +0800919
920 if(_syscmd(cmd, buf, sizeof(buf)))
921 return -1;
922 }
923
924 return 0;
925}
926
developer3a85ab82023-05-25 11:59:38 +0800927static int wifi_datfileWrite2(char *conf_file, int idx, struct params *list, int item_count)
developerfde01262023-05-22 15:15:24 +0800928{
929 int ret;
930 char cmd[MAX_CMD_SIZE] = {0};
931 char buf[MAX_BUF_SIZE] = {0};
932
933 for (int i = 0; i < item_count; i++) {
developer3a85ab82023-05-25 11:59:38 +0800934 ret = snprintf(cmd, sizeof(cmd), "datconf -f %s set %s %d \"%s\"", conf_file, list[i].name, idx, list[i].value);
developerfde01262023-05-22 15:15:24 +0800935 if (ret < 0) {
936 printf("%s: snprintf error!", __func__);
937 return -1;
938 }
939
940 if(_syscmd(cmd, buf, sizeof(buf)))
941 return -1;
942 }
943
944 return 0;
945}
946
947static int wifi_l1ProfileRead(char *param, char *output, int output_size)
948{
developerfde01262023-05-22 15:15:24 +0800949 int ret;
950
951 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
952 if (!param || !output || (output_size <= 0)) {
953 fprintf(stderr, "%s: invalid parameters", __func__);
954 return RETURN_ERR;
955 }
956
957 ret = wifi_datfileRead(l1profile, param, output, output_size);
958 if (ret != 0) {
959 fprintf(stderr, "%s: wifi_datfileRead %s from %s failed, ret:%d", __func__, param, l1profile, ret);
960 return RETURN_ERR;
961 }
962
963 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
964 return RETURN_OK;
965}
966
developer3a85ab82023-05-25 11:59:38 +0800967static int wifi_l1ProfileRead2(char *param, int idx, char *output, int output_size)
968{
developer3a85ab82023-05-25 11:59:38 +0800969 int ret;
970
971 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
972 if (!param || !output || (output_size <= 0)) {
973 fprintf(stderr, "%s: invalid parameters", __func__);
974 return RETURN_ERR;
975 }
976
977 ret = wifi_datfileRead2(l1profile, idx, param, output, output_size);
978 if (ret != 0) {
979 fprintf(stderr, "%s: wifi_datfileRead2 %s from %s failed, ret:%d", __func__, param, l1profile, ret);
980 return RETURN_ERR;
981 }
982
983 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
984 return RETURN_OK;
985}
986
987
developerfde01262023-05-22 15:15:24 +0800988static int wifi_CardProfileRead(int card_idx, char *param, char *output, int output_size)
989{
990 char option[64];
991 char card_profile_path[64];
992 int ret;
993
994 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
995
996 if (!param || !output || (output_size <= 0)) {
997 fprintf(stderr, "%s: invalid parameters", __func__);
998 return RETURN_ERR;
999 }
1000
1001 snprintf(option, sizeof(option), "INDEX%d_profile_path", card_idx);
1002 ret = wifi_l1ProfileRead(option, card_profile_path, sizeof(card_profile_path));
1003 if (ret != 0) {
1004 fprintf(stderr, "%s: wifi_l1ProfileRead %s failed, ret:%d", __func__, option, ret);
1005 return RETURN_ERR;
1006 }
1007
1008 ret = wifi_datfileRead(card_profile_path, param, output, output_size);
1009 if (ret != 0) {
1010 fprintf(stderr, "%s: wifi_datfileRead %s from %s failed, ret:%d", __func__, param, card_profile_path, ret);
1011 return RETURN_ERR;
1012 }
1013
1014 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1015 return RETURN_OK;
1016}
1017
1018static int wifi_BandProfileRead(int card_idx,
1019 int radio_idx,
1020 char *param,
1021 char *output,
1022 int output_size,
1023 char *default_value)
1024{
1025 char option[64];
1026 char band_profile_path[64];
1027 int ret;
1028
1029 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1030 if (!param || !output || (output_size <= 0)) {
1031 fprintf(stderr, "%s: invalid parameters", __func__);
1032 return RETURN_ERR;
1033 }
1034
1035 snprintf(option, sizeof(option), "BN%d_profile_path", radio_idx);
1036 ret = wifi_CardProfileRead(card_idx, option, band_profile_path, sizeof(band_profile_path));
1037 if (ret != 0) {
developerdaf24792023-06-06 11:40:04 +08001038 fprintf(stderr, "%s: wifi_CardProfileRead %s failed, ret:%d", __func__, option, ret);
developerfde01262023-05-22 15:15:24 +08001039 return RETURN_ERR;
1040 }
1041
1042 ret = wifi_datfileRead(band_profile_path, param, output, output_size);
1043 if (ret != 0) {
1044 if (default_value) {
1045 snprintf(output, output_size, "%s", default_value);
1046 } else {
1047 output[0] = '\0';
1048 }
1049 }
1050
1051 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1052 return RETURN_OK;
1053}
1054
1055static int wifi_BandProfileRead2(int card_idx,
1056 int radio_idx,
developer3a85ab82023-05-25 11:59:38 +08001057 int idx,
developerfde01262023-05-22 15:15:24 +08001058 char *param,
1059 char *output,
1060 int output_size,
1061 char* default_value)
1062{
1063 char option[64];
1064 char band_profile_path[64];
1065 int ret;
1066
1067 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1068 if (!param || !output || (output_size <= 0)) {
1069 fprintf(stderr, "%s: invalid parameters", __func__);
1070 return RETURN_ERR;
1071 }
1072
1073 snprintf(option, sizeof(option), "BN%d_profile_path", radio_idx);
1074 ret = wifi_CardProfileRead(card_idx, option, band_profile_path, sizeof(band_profile_path));
1075 if (ret != 0) {
developerdaf24792023-06-06 11:40:04 +08001076 fprintf(stderr, "%s: wifi_CardProfileRead %s failed, ret:%d", __func__, option, ret);
developerfde01262023-05-22 15:15:24 +08001077 return RETURN_ERR;
1078 }
1079
developer3a85ab82023-05-25 11:59:38 +08001080 ret = wifi_datfileRead2(band_profile_path, idx, param, output, output_size);
developerfde01262023-05-22 15:15:24 +08001081 if (ret != 0) {
1082 if (default_value) {
1083 snprintf(output, output_size, "%s", default_value);
1084 } else {
1085 output[0] = '\0';
1086 }
1087 }
1088
1089 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1090 return RETURN_OK;
1091
1092}
1093
1094static int wifi_BandProfileWrite(int card_idx, int radio_idx, struct params *list, int item_count)
1095{
1096 char option[64];
1097 char band_profile_path[64];
1098 int ret;
1099
1100 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1101
1102 snprintf(option, sizeof(option), "BN%d_profile_path", radio_idx);
1103 ret = wifi_CardProfileRead(card_idx, option, band_profile_path, sizeof(band_profile_path));
1104 if (ret != 0) {
developerdaf24792023-06-06 11:40:04 +08001105 fprintf(stderr, "%s: wifi_CardProfileRead %s failed, ret:%d", __func__, option, ret);
developerfde01262023-05-22 15:15:24 +08001106 return RETURN_ERR;
1107 }
1108
1109 for (int i = 0; i < item_count; i++) {
1110 }
1111 ret = wifi_datfileWrite(band_profile_path, list, item_count);
1112 if (ret != 0) {
developerdaf24792023-06-06 11:40:04 +08001113 fprintf(stderr, "%s: wifi_datfileWrite failed, ret:%d", __func__, ret);
developerfde01262023-05-22 15:15:24 +08001114 return RETURN_ERR;
1115 }
1116
1117 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1118 return RETURN_OK;
1119
1120}
1121
1122static int wifi_BandProfileWrite2(int card_idx,
1123 int radio_idx,
developer3a85ab82023-05-25 11:59:38 +08001124 int idx,
developerfde01262023-05-22 15:15:24 +08001125 struct params *list,
1126 int item_count)
1127{
1128 char option[64];
1129 char band_profile_path[64];
developerfde01262023-05-22 15:15:24 +08001130 int ret;
1131
1132 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1133
1134 snprintf(option, sizeof(option), "BN%d_profile_path", radio_idx);
1135 ret = wifi_CardProfileRead(card_idx, option, band_profile_path, sizeof(band_profile_path));
1136 if (ret != 0) {
developerdaf24792023-06-06 11:40:04 +08001137 fprintf(stderr, "%s: wifi_CardProfileRead %s failed, ret:%d", __func__, option, ret);
developerfde01262023-05-22 15:15:24 +08001138 return RETURN_ERR;
1139 }
1140
developer3a85ab82023-05-25 11:59:38 +08001141 ret = wifi_datfileWrite2(band_profile_path, idx, list, item_count);
developerfde01262023-05-22 15:15:24 +08001142 if (ret != 0) {
developerdaf24792023-06-06 11:40:04 +08001143 fprintf(stderr, "%s: wifi_datfileWrite failed, ret:%d", __func__, ret);
developerfde01262023-05-22 15:15:24 +08001144 return RETURN_ERR;
1145 }
1146
1147 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1148 return RETURN_OK;
1149
1150}
1151
1152
1153
developer72fb0bb2023-01-11 09:46:29 +08001154//For Getting Current Interface Name from corresponding hostapd configuration
1155static int wifi_GetInterfaceName(int apIndex, char *interface_name)
1156{
1157 char config_file[128] = {0};
1158
1159 if (interface_name == NULL)
1160 return RETURN_ERR;
1161
1162 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1163
1164 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
1165 wifi_hostapdRead(config_file, "interface", interface_name, 16);
1166 if (strlen(interface_name) == 0)
1167 return RETURN_ERR;
1168
1169 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1170 return RETURN_OK;
1171}
1172
developera1255e42023-05-13 17:45:02 +08001173static UCHAR get_bssnum_byindex(INT radio_index, UCHAR *bss_cnt)
1174{
1175 char interface_name[IF_NAME_SIZE] = {0};
1176 char cmd[MAX_BUF_SIZE]={'\0'};
1177 char buf[MAX_CMD_SIZE]={'\0'};
1178 UCHAR channel = 0;
1179
1180 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
1181 return RETURN_ERR;
1182 /*interface name to channel number*/
1183 snprintf(cmd, sizeof(cmd), "iw dev %s info | grep -i 'channel' | cut -d ' ' -f2", interface_name);
1184 _syscmd(cmd, buf, sizeof(buf));
1185 channel = atoi(buf);
1186 WIFI_ENTRY_EXIT_DEBUG("%s:channel=%d\n", __func__, channel);
1187 /*count dev number with the same channel*/
1188 snprintf(cmd, sizeof(cmd), "iw dev | grep -i 'channel %d' | wc -l", channel);
1189 _syscmd(cmd, buf, sizeof(buf));
1190 *bss_cnt = atoi(buf) - 1;/*1 for apcli interface*/
1191 WIFI_ENTRY_EXIT_DEBUG("%s:bss_cnt=%d\n", __func__, *bss_cnt);
1192 return RETURN_OK;
1193}
developer72fb0bb2023-01-11 09:46:29 +08001194
1195static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
1196{
1197 char interface_name[16] = {0};
1198 if (multiple_set == TRUE)
1199 return RETURN_OK;
1200 char cmd[MAX_CMD_SIZE]="", output[32]="";
1201 FILE *fp;
1202 int i;
1203 //NOTE RELOAD should be done in ApplySSIDSettings
1204 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
1205 return RETURN_ERR;
1206 for(i=0; i<item_count; i++, list++)
1207 {
developerf6a87542023-05-16 15:47:28 +08001208 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s SET %s %s", interface_name, list->name, list->value);
developer72fb0bb2023-01-11 09:46:29 +08001209 if((fp = popen(cmd, "r"))==NULL)
1210 {
1211 perror("popen failed");
1212 return -1;
1213 }
1214 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
1215 {
1216 pclose(fp);
1217 perror("fgets failed");
1218 return -1;
1219 }
1220 pclose(fp);
1221 }
1222 return 0;
1223}
1224
developer7e4a2a62023-04-06 19:56:03 +08001225static int wifi_quick_reload_ap(int apIndex)
1226{
1227 char interface_name[IF_NAME_SIZE] = {0};
1228 char cmd[MAX_CMD_SIZE] = {0};
1229 char buf[MAX_BUF_SIZE] = {0};
1230
1231 if (multiple_set == TRUE)
1232 return RETURN_OK;
1233
1234 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
1235 return RETURN_ERR;
1236
1237 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s reload", interface_name);
1238 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
1239 return RETURN_ERR;
1240
1241 return RETURN_OK;
1242}
1243
developer72fb0bb2023-01-11 09:46:29 +08001244static int wifi_reloadAp(int apIndex)
1245{
1246 char interface_name[16] = {0};
1247 if (multiple_set == TRUE)
1248 return RETURN_OK;
1249 char cmd[MAX_CMD_SIZE]="";
1250 char buf[MAX_BUF_SIZE]="";
1251
1252 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
1253 return RETURN_ERR;
1254 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s reload", interface_name);
1255 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
1256 return RETURN_ERR;
1257
1258 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s disable", interface_name);
1259 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
1260 return RETURN_ERR;
1261
1262 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s enable", interface_name);
1263 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
1264 return RETURN_ERR;
1265
1266 return RETURN_OK;
1267}
1268
1269INT File_Reading(CHAR *file, char *Value)
1270{
1271 FILE *fp = NULL;
1272 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
1273 int count = 0;
1274
1275 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1276 fp = popen(file,"r");
1277 if(fp == NULL)
1278 return RETURN_ERR;
1279
1280 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
1281 {
1282 for(count=0;buf[count]!='\n';count++)
1283 copy_buf[count]=buf[count];
1284 copy_buf[count]='\0';
1285 }
1286 strcpy(Value,copy_buf);
1287 pclose(fp);
1288 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1289
1290 return RETURN_OK;
1291}
1292
1293void wifi_RestartHostapd_2G()
1294{
1295 int Public2GApIndex = 4;
1296
1297 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1298 wifi_setApEnable(Public2GApIndex, FALSE);
1299 wifi_setApEnable(Public2GApIndex, TRUE);
1300 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1301}
1302
1303void wifi_RestartHostapd_5G()
1304{
1305 int Public5GApIndex = 5;
1306
1307 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1308 wifi_setApEnable(Public5GApIndex, FALSE);
1309 wifi_setApEnable(Public5GApIndex, TRUE);
1310 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1311}
1312
1313void wifi_RestartPrivateWifi_2G()
1314{
1315 int PrivateApIndex = 0;
1316
1317 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1318 wifi_setApEnable(PrivateApIndex, FALSE);
1319 wifi_setApEnable(PrivateApIndex, TRUE);
1320 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1321}
1322
1323void wifi_RestartPrivateWifi_5G()
1324{
1325 int Private5GApIndex = 1;
1326
1327 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1328 wifi_setApEnable(Private5GApIndex, FALSE);
1329 wifi_setApEnable(Private5GApIndex, TRUE);
1330 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1331}
1332
1333static int writeBandWidth(int radioIndex,char *bw_value)
1334{
1335 char buf[MAX_BUF_SIZE];
1336 char cmd[MAX_CMD_SIZE];
1337
1338 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
1339 if(_syscmd(cmd, buf, sizeof(buf)))
1340 {
1341 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
1342 _syscmd(cmd, buf, sizeof(buf));
1343 return RETURN_OK;
1344 }
1345
1346 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
1347 _syscmd(cmd,buf,sizeof(buf));
1348 return RETURN_OK;
1349}
1350
1351static int readBandWidth(int radioIndex,char *bw_value)
1352{
1353 char buf[MAX_BUF_SIZE] = {0};
1354 char cmd[MAX_CMD_SIZE] = {0};
1355 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
1356 _syscmd(cmd,buf,sizeof(buf));
1357 if(NULL!=strstr(buf,"20MHz"))
developer72fb0bb2023-01-11 09:46:29 +08001358 strcpy(bw_value,"20MHz");
developer72fb0bb2023-01-11 09:46:29 +08001359 else if(NULL!=strstr(buf,"40MHz"))
developer72fb0bb2023-01-11 09:46:29 +08001360 strcpy(bw_value,"40MHz");
developer72fb0bb2023-01-11 09:46:29 +08001361 else if(NULL!=strstr(buf,"80MHz"))
developer72fb0bb2023-01-11 09:46:29 +08001362 strcpy(bw_value,"80MHz");
developerd1824452023-05-18 12:30:04 +08001363 else if(NULL!=strstr(buf,"160MHz"))
1364 strcpy(bw_value,"160MHz");
1365 else if(NULL!=strstr(buf,"320MHz"))
1366 strcpy(bw_value,"320MHz");
developer72fb0bb2023-01-11 09:46:29 +08001367 else
developer72fb0bb2023-01-11 09:46:29 +08001368 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08001369 return RETURN_OK;
1370}
1371
1372// Input could be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
1373INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
1374{
1375 struct params params={'\0'};
1376 char config_file[MAX_BUF_SIZE] = {0};
1377 char buf[MAX_BUF_SIZE] = {'\0'};
1378
1379 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1380 // Copy the numeric value
1381 if (strlen (beaconRate) >= 5) {
1382 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
1383 buf[strlen(beaconRate) - 4] = '\0';
1384 } else if (strlen(beaconRate) > 0)
1385 strcpy(buf, beaconRate);
1386 else
1387 return RETURN_ERR;
1388
1389 params.name = "beacon_rate";
1390 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
1391 if (strncmp(buf, "5.5", 3) == 0) {
1392 snprintf(buf, sizeof(buf), "55");
1393 params.value = buf;
1394 } else {
1395 strcat(buf, "0");
1396 params.value = buf;
1397 }
1398
1399 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1400 wifi_hostapdWrite(config_file, &params, 1);
1401 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1402 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1403
1404 return RETURN_OK;
1405}
1406
1407INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
1408{
1409 char config_file[128] = {'\0'};
1410 char temp_output[128] = {'\0'};
1411 char buf[128] = {'\0'};
1412 char cmd[128] = {'\0'};
1413 int rate = 0;
1414 int phyId = 0;
1415
1416 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1417 if (NULL == beaconRate)
1418 return RETURN_ERR;
1419
1420 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1421 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
1422 phyId = radio_index_to_phy(radioIndex);
1423 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
1424 if(strlen(buf) > 0) {
1425 if (strncmp(buf, "55", 2) == 0)
1426 snprintf(temp_output, sizeof(temp_output), "5.5Mbps");
1427 else {
1428 rate = strtol(buf, NULL, 10)/10;
1429 snprintf(temp_output, sizeof(temp_output), "%dMbps", rate);
1430 }
1431 } else {
1432 // config not set, so we would use lowest rate as default
1433 sprintf(cmd, "iw phy%d info | grep Bitrates -A1 | tail -n 1 | awk '{print $2}' | tr -d '.0\\n'", phyId);
1434 _syscmd(cmd, buf, sizeof(buf));
1435 snprintf(temp_output, sizeof(temp_output), "%sMbps", buf);
1436 }
developerdaf24792023-06-06 11:40:04 +08001437 strncpy(beaconRate, temp_output, strlen(temp_output));
developer72fb0bb2023-01-11 09:46:29 +08001438 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1439
1440 return RETURN_OK;
1441}
1442
1443INT wifi_setLED(INT radioIndex, BOOL enable)
1444{
1445 return 0;
1446}
1447INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
1448{
1449 return RETURN_OK;
1450}
1451/**********************************************************************************
1452 *
developer69b61b02023-03-07 17:17:44 +08001453 * Wifi Subsystem level function prototypes
developer72fb0bb2023-01-11 09:46:29 +08001454 *
1455**********************************************************************************/
1456//---------------------------------------------------------------------------------------------------
1457//Wifi system api
1458//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 +08001459INT wifi_getHalVersion(CHAR *output_string) //RDKB
developer72fb0bb2023-01-11 09:46:29 +08001460{
1461 if(!output_string)
1462 return RETURN_ERR;
1463 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
1464
1465 return RETURN_OK;
1466}
1467
1468
1469/* wifi_factoryReset() function */
1470/**
developer69b61b02023-03-07 17:17:44 +08001471* @description Clears internal variables to implement a factory reset of the Wi-Fi
developer72fb0bb2023-01-11 09:46:29 +08001472* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
1473*
1474* @param None
1475*
1476* @return The status of the operation.
1477* @retval RETURN_OK if successful.
1478* @retval RETURN_ERR if any error is detected
1479*
1480* @execution Synchronous
1481* @sideeffect None
1482*
1483* @note This function must not suspend and must not invoke any blocking system
1484* calls. It should probably just send a message to a driver event handler task.
1485*
1486*/
1487INT wifi_factoryReset()
1488{
developer47cc27a2023-05-17 23:09:58 +08001489 char cmd[MAX_CMD_SIZE] = {0};
1490 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08001491
developer47cc27a2023-05-17 23:09:58 +08001492 /*delete running hostapd conf files*/
1493 wifi_dbg_printf("\n[%s]: deleting hostapd conf file.", __func__);
1494 snprintf(cmd, MAX_CMD_SIZE, "rm -rf /nvram/*.conf");
1495 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08001496
developer47cc27a2023-05-17 23:09:58 +08001497 wifi_PrepareDefaultHostapdConfigs();
1498 wifi_psk_file_reset();
1499
1500 memset(cmd, 0, MAX_CMD_SIZE);
1501 memset(buf, 0, MAX_BUF_SIZE);
1502
1503 snprintf(cmd, MAX_CMD_SIZE, "systemctl restart hostapd.service");
1504 _syscmd(cmd, buf, sizeof(buf));
1505
1506 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08001507}
1508
1509/* wifi_factoryResetRadios() function */
1510/**
1511* @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.
1512*
1513* @param None
1514* @return The status of the operation
1515* @retval RETURN_OK if successful
1516* @retval RETURN_ERR if any error is detected
1517*
1518* @execution Synchronous
1519*
1520* @sideeffect None
1521*
1522* @note This function must not suspend and must not invoke any blocking system
1523* calls. It should probably just send a message to a driver event handler task.
1524*
1525*/
1526INT wifi_factoryResetRadios()
1527{
1528 if((RETURN_OK == wifi_factoryResetRadio(0)) && (RETURN_OK == wifi_factoryResetRadio(1)))
1529 return RETURN_OK;
1530
1531 return RETURN_ERR;
1532}
1533
developerfead3972023-05-25 20:15:02 +08001534ULONG get_radio_reset_cnt(int radioIndex)
1535{
1536 char cmd[MAX_CMD_SIZE] = {0};
1537 char buf[MAX_BUF_SIZE] = {0};
1538 ULONG reset_count = 0;
1539
1540 snprintf(cmd, MAX_CMD_SIZE, "cat %s 2> /dev/null | grep \"^reset%d=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"",
1541 RADIO_RESET_FILE, radioIndex);
1542 _syscmd(cmd, buf, sizeof(buf));
1543
1544 if (strlen(buf) == 0)
1545 return 0;
1546 else {
1547 reset_count = atol(buf);
1548 return reset_count;
1549 }
1550}
1551void update_radio_reset_cnt(int radioIndex)
1552{
1553 char cmd[MAX_CMD_SIZE] = {0};
1554 char buf[MAX_BUF_SIZE] = {0};
1555 ULONG reset_count = 0;
1556
1557 snprintf(cmd, MAX_CMD_SIZE, "cat %s 2> /dev/null | grep \"^reset%d=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"",
1558 RADIO_RESET_FILE, radioIndex);
1559 _syscmd(cmd, buf, sizeof(buf));
1560
1561 if (strlen(buf) == 0)
1562 snprintf(cmd, sizeof(cmd), "sed -i -e '$a reset%d=1' %s", radioIndex, RADIO_RESET_FILE);
1563 else {
1564 reset_count = atol(buf);
1565 reset_count++;
1566 snprintf(cmd, sizeof(cmd), "sed -i \"s/^reset%d=.*/reset%d=%lu/\" %s", radioIndex, radioIndex, reset_count, RADIO_RESET_FILE);
1567 }
1568 _syscmd(cmd, buf, sizeof(buf));
1569}
developer72fb0bb2023-01-11 09:46:29 +08001570
1571/* wifi_factoryResetRadio() function */
1572/**
1573* @description Restore selected radio parameters without touching access point parameters
1574*
1575* @param radioIndex - Index of Wi-Fi Radio channel
1576*
1577* @return The status of the operation.
1578* @retval RETURN_OK if successful.
1579* @retval RETURN_ERR if any error is detected
1580*
1581* @execution Synchronous.
1582* @sideeffect None.
1583*
1584* @note This function must not suspend and must not invoke any blocking system
1585* calls. It should probably just send a message to a driver event handler task.
1586*
1587*/
1588INT wifi_factoryResetRadio(int radioIndex) //RDKB
1589{
developer47cc27a2023-05-17 23:09:58 +08001590 char cmd[MAX_CMD_SIZE] = {0};
1591 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08001592
developer47cc27a2023-05-17 23:09:58 +08001593 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08001594
developerb2977562023-05-24 17:54:12 +08001595 wifi_dat_file_reset_by_radio(radioIndex);
developer47cc27a2023-05-17 23:09:58 +08001596
developerb2977562023-05-24 17:54:12 +08001597 /*reset gi setting*/
1598 snprintf(cmd, sizeof(cmd), "echo 'Auto' > %s%d.txt", GUARD_INTERVAL_FILE, radioIndex);
developer47cc27a2023-05-17 23:09:58 +08001599 _syscmd(cmd, buf, sizeof(buf));
1600
developerb2977562023-05-24 17:54:12 +08001601 /*TBD: check mbss issue*/
1602 wifi_factoryResetAP(radioIndex);
developerfead3972023-05-25 20:15:02 +08001603 update_radio_reset_cnt(radioIndex);
developerb2977562023-05-24 17:54:12 +08001604
developer47cc27a2023-05-17 23:09:58 +08001605 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
1606 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08001607}
1608
1609/* wifi_initRadio() function */
1610/**
1611* Description: This function call initializes the specified radio.
developer69b61b02023-03-07 17:17:44 +08001612* Implementation specifics may dictate the functionality since
developer72fb0bb2023-01-11 09:46:29 +08001613* different hardware implementations may have different initilization requirements.
1614* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
1615*
1616* @return The status of the operation.
1617* @retval RETURN_OK if successful.
1618* @retval RETURN_ERR if any error is detected
1619*
1620* @execution Synchronous.
1621* @sideeffect None.
1622*
1623* @note This function must not suspend and must not invoke any blocking system
1624* calls. It should probably just send a message to a driver event handler task.
1625*
1626*/
1627INT wifi_initRadio(INT radioIndex)
1628{
1629 //TODO: Initializes the wifi subsystem (for specified radio)
1630 return RETURN_OK;
1631}
1632void macfilter_init()
1633{
1634 char count[4]={'\0'};
1635 char buf[253]={'\0'};
1636 char tmp[19]={'\0'};
1637 int dev_count,block,mac_entry=0;
1638 char res[4]={'\0'};
1639 char acl_file_path[64] = {'\0'};
1640 FILE *fp = NULL;
1641 int index=0;
1642 char iface[10]={'\0'};
1643 char config_file[MAX_BUF_SIZE] = {0};
1644
1645
1646 sprintf(acl_file_path,"/tmp/mac_filter.sh");
1647
1648 fp=fopen(acl_file_path,"w+");
1649 if (fp == NULL) {
1650 fprintf(stderr, "%s: failed to open file %s.\n", __func__, acl_file_path);
developer17038e62023-03-02 14:43:43 +08001651 return;
developer72fb0bb2023-01-11 09:46:29 +08001652 }
1653 sprintf(buf,"#!/bin/sh \n");
1654 fprintf(fp,"%s\n",buf);
1655
1656 system("chmod 0777 /tmp/mac_filter.sh");
1657
1658 for(index=0;index<=1;index++)
1659 {
1660 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
1661 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
1662 sprintf(buf,"syscfg get %dcountfilter",index);
1663 _syscmd(buf,count,sizeof(count));
1664 mac_entry=atoi(count);
1665
1666 sprintf(buf,"syscfg get %dblockall",index);
1667 _syscmd(buf,res,sizeof(res));
1668 block = atoi(res);
1669
1670 //Allow only those macs mentioned in ACL
1671 if(block==1)
1672 {
1673 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1674 fprintf(fp,"%s\n",buf);
1675 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1676 {
1677 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1678 _syscmd(buf,tmp,sizeof(tmp));
1679 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
1680 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
1681 fprintf(fp,"%s\n",buf);
1682 }
1683 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
1684 fprintf(fp,"%s\n",buf);
1685 }
1686
1687 //Block all the macs mentioned in ACL
1688 else if(block==2)
1689 {
1690 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1691 fprintf(fp,"%s\n",buf);
1692
1693 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1694 {
1695 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1696 _syscmd(buf,tmp,sizeof(tmp));
1697 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
1698 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
1699 fprintf(fp,"%s\n",buf);
1700 }
1701 }
1702 }
1703 fclose(fp);
1704}
1705
developer17038e62023-03-02 14:43:43 +08001706
1707static void
1708wifi_ParseProfile(void)
1709{
1710 int i;
1711 int max_radio_num = 0;
1712 int card_idx;
1713 int band_idx;
1714 int phy_idx = 0;
developer745f0bd2023-03-06 14:32:53 +08001715 int wireless_mode = 0;
developer17038e62023-03-02 14:43:43 +08001716 char buf[MAX_BUF_SIZE] = {0};
1717 char chip_name[12];
1718 char card_profile[MAX_BUF_SIZE] = {0};
1719 char band_profile[MAX_BUF_SIZE] = {0};
developer17038e62023-03-02 14:43:43 +08001720
1721 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1722
1723 memset(main_prefix, 0, sizeof(main_prefix));
1724 memset(ext_prefix, 0, sizeof(ext_prefix));
1725 memset(default_ssid, 0, sizeof(default_ssid));
developer745f0bd2023-03-06 14:32:53 +08001726 for (i = 0; i < MAX_NUM_RADIOS; i++)
1727 radio_band[i] = band_invalid;
developer17038e62023-03-02 14:43:43 +08001728
1729 if (wifi_getMaxRadioNumber(&max_radio_num) != RETURN_OK) {
1730 /* LOG */
1731 return;
1732 }
1733
1734 for (card_idx = 0; card_idx < 3; card_idx++) {
1735 snprintf(buf, sizeof(buf), "INDEX%d", card_idx);
1736 if (get_value(l1profile, buf, chip_name, sizeof(chip_name)) < 0) {
1737 break;
1738 }
1739 snprintf(buf, sizeof(buf), "INDEX%d_profile_path", card_idx);
1740 if (get_value(l1profile, buf, card_profile, sizeof(card_profile)) < 0) {
1741 break;
1742 }
1743 for (band_idx = 0; band_idx < 3; band_idx++) {
1744 snprintf(buf, sizeof(buf), "BN%d_profile_path", band_idx);
1745 if (get_value(card_profile, buf, band_profile, sizeof(band_profile)) < 0) {
1746 /* LOG */
1747 break;
1748 }
1749
1750 snprintf(buf, sizeof(buf), "INDEX%d_main_ifname", card_idx);
1751 if (get_value_by_idx(l1profile, buf, band_idx, main_prefix[phy_idx], IFNAMSIZ) < 0) {
1752 /* LOG */
1753 }
1754
1755 snprintf(buf, sizeof(buf), "INDEX%d_ext_ifname", card_idx);
1756 if (get_value_by_idx(l1profile, buf, band_idx, ext_prefix[phy_idx], IFNAMSIZ) < 0) {
1757 /* LOG */
1758 }
1759
1760 if (get_value(band_profile, "SSID1", default_ssid[phy_idx], sizeof(default_ssid[phy_idx])) < 0) {
1761 /* LOG */
1762 }
developer745f0bd2023-03-06 14:32:53 +08001763 if (get_value(band_profile, "WirelessMode", buf, sizeof(buf)) < 0) {
1764 /* LOG */
1765 }
1766
1767 wireless_mode = atoi(buf);
1768 switch (wireless_mode) {
1769 case 22:
1770 case 16:
1771 case 6:
1772 case 4:
1773 case 1:
1774 radio_band[phy_idx] = band_2_4;
1775 break;
1776 case 23:
1777 case 17:
1778 case 14:
1779 case 11:
1780 case 2:
1781 radio_band[phy_idx] = band_5;
1782 break;
1783 case 24:
1784 case 18:
1785 radio_band[phy_idx] = band_6;
1786 break;
1787 }
developer17038e62023-03-02 14:43:43 +08001788 phy_idx++;
1789 }
1790 }
1791
1792 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1793}
1794
1795static void
1796wifi_PrepareDefaultHostapdConfigs(void)
1797{
developer0132ed92023-03-21 13:48:53 +08001798 int radio_idx;
1799 int bss_idx;
1800 int ap_idx;
developer0132ed92023-03-21 13:48:53 +08001801 char buf[MAX_BUF_SIZE] = {0};
1802 char config_file[MAX_BUF_SIZE] = {0};
1803 char ssid[MAX_BUF_SIZE] = {0};
1804 char interface[32] = {0};
1805 char ret_buf[MAX_BUF_SIZE] = {0};
1806 char psk_file[64] = {0};
1807 struct params params[3];
developer17038e62023-03-02 14:43:43 +08001808
developer0132ed92023-03-21 13:48:53 +08001809 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1810 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++) {
developer47cc27a2023-05-17 23:09:58 +08001811
developer0132ed92023-03-21 13:48:53 +08001812 for (bss_idx = 0; bss_idx < 5; bss_idx++) {
developer47cc27a2023-05-17 23:09:58 +08001813 ap_idx = array_index_to_vap_index(radio_idx, bss_idx);
developer0132ed92023-03-21 13:48:53 +08001814
developer47cc27a2023-05-17 23:09:58 +08001815 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_idx);
developere740c2a2023-05-23 18:34:32 +08001816 snprintf(buf, sizeof(buf), "cp /etc/hostapd-%s.conf %s", wifi_band_str[radio_idx], config_file);
developer47cc27a2023-05-17 23:09:58 +08001817 _syscmd(buf, ret_buf, sizeof(ret_buf));
developer17038e62023-03-02 14:43:43 +08001818
developer47cc27a2023-05-17 23:09:58 +08001819 if (radio_idx == band_2_4) {
1820 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_2G, bss_idx);
1821 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI2G, bss_idx);
1822 } else if (radio_idx == band_5) {
1823 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_5G, bss_idx);
1824 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI5G, bss_idx);
1825 } else if (radio_idx == band_6) {
1826 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_6G, bss_idx);
1827 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI6G, bss_idx);
1828 }
developer17038e62023-03-02 14:43:43 +08001829
developer47cc27a2023-05-17 23:09:58 +08001830 /* fix wpa_psk_file path */
1831 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", ap_idx);
developer17038e62023-03-02 14:43:43 +08001832
developer47cc27a2023-05-17 23:09:58 +08001833 params[0].name = "ssid";
1834 params[0].value = ssid;
1835 params[1].name = "interface";
1836 params[1].value = interface;
1837 params[2].name = "wpa_psk_file";
1838 params[2].value = psk_file;
developer17038e62023-03-02 14:43:43 +08001839
developer47cc27a2023-05-17 23:09:58 +08001840 wifi_hostapdWrite(config_file, params, 3);
developer0132ed92023-03-21 13:48:53 +08001841 }
1842 }
1843 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer17038e62023-03-02 14:43:43 +08001844}
1845
1846static void
1847wifiBringUpInterfacesForRadio(int radio_idx)
1848{
developer0132ed92023-03-21 13:48:53 +08001849 int bss_idx;
1850 int ap_idx;
developer0132ed92023-03-21 13:48:53 +08001851 char cmd[MAX_CMD_SIZE] = {0};
1852 char config_file[MAX_BUF_SIZE] = {0};
1853 char ret_buf[MAX_BUF_SIZE] = {0};
developer8a3bbbf2023-03-15 17:47:23 +08001854 char inf_name[IF_NAME_SIZE] = {0};
developer17038e62023-03-02 14:43:43 +08001855
1856 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer8a3bbbf2023-03-15 17:47:23 +08001857
developered997d32023-04-18 22:45:39 +08001858 bss_idx = 0;
1859 /*TBD: we need refine setup flow and mbss flow*/
1860// for (bss_idx = 0; bss_idx < 5; bss_idx++) {
developer0132ed92023-03-21 13:48:53 +08001861 ap_idx = array_index_to_vap_index(radio_idx, bss_idx);
1862
1863 snprintf(cmd, sizeof(cmd), "touch %s%d.psk", PSK_FILE, ap_idx);
1864 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1865
1866 memset(cmd, 0, MAX_CMD_SIZE);
1867 memset(ret_buf, 0, MAX_BUF_SIZE);
developer17038e62023-03-02 14:43:43 +08001868
developer0132ed92023-03-21 13:48:53 +08001869 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_idx);
1870 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:%s", radio_idx, config_file);
1871 _syscmd(cmd, ret_buf, sizeof(ret_buf));
developer8a3bbbf2023-03-15 17:47:23 +08001872
1873 wifi_GetInterfaceName(ap_idx, inf_name);
1874
1875 memset(cmd, 0, MAX_CMD_SIZE);
1876 memset(ret_buf, 0, MAX_BUF_SIZE);
1877
1878 /* fix vap-status file */
1879 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=1/\" %s", inf_name, inf_name, VAP_STATUS_FILE);
1880 _syscmd(cmd, ret_buf, sizeof(ret_buf));
developered997d32023-04-18 22:45:39 +08001881// }
1882
1883 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer17038e62023-03-02 14:43:43 +08001884}
1885
1886static void
1887wifi_BringUpInterfaces(void)
1888{
1889 int radio_idx;
developer17038e62023-03-02 14:43:43 +08001890 int band_idx;
developer17038e62023-03-02 14:43:43 +08001891
1892 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1893 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++) {
1894 band_idx = radio_index_to_band(radio_idx);
1895 if (band_idx < 0) {
1896 break;
1897 }
1898 wifiBringUpInterfacesForRadio(radio_idx);
1899 }
1900 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1901}
1902
1903static void
1904wifi_BringDownInterfacesForRadio(int radio_idx)
1905{
developer17038e62023-03-02 14:43:43 +08001906 char cmd[MAX_BUF_SIZE] = {0};
developer17038e62023-03-02 14:43:43 +08001907 char ret_buf[MAX_BUF_SIZE]={'\0'};
1908
1909 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer17038e62023-03-02 14:43:43 +08001910
developer8a3bbbf2023-03-15 17:47:23 +08001911 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s", main_prefix[radio_idx]);
1912 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1913
developer17038e62023-03-02 14:43:43 +08001914 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1915}
1916
1917
1918static void
1919wifi_BringDownInterfaces(void)
1920{
1921 int radio_idx;
developer17038e62023-03-02 14:43:43 +08001922 int band_idx;
developer17038e62023-03-02 14:43:43 +08001923
1924 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1925 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++) {
1926 band_idx = radio_index_to_band(radio_idx);
1927 if (band_idx < 0) {
1928 break;
1929 }
1930 wifi_BringDownInterfacesForRadio(radio_idx);
1931 }
1932 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1933}
1934
developerb2977562023-05-24 17:54:12 +08001935static void wifi_dat_file_reset()
1936{
1937 char radio_idx = 0;
1938
1939 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++)
1940 wifi_dat_file_reset_by_radio(radio_idx);
1941}
1942
1943static void wifi_dat_file_reset_by_radio(char radio_idx)
1944{
1945 char cmd[MAX_CMD_SIZE] = {0};
1946 char ret_buf[MAX_BUF_SIZE] = {0};
1947 char rom_dat_file[MAX_CMD_SIZE]= {0};
1948 char dat_file[MAX_CMD_SIZE]= {0};
1949
1950 snprintf(rom_dat_file, sizeof(rom_dat_file), "%s%d.dat", ROM_LOGAN_DAT_FILE, radio_idx);
1951 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, radio_idx);
1952 snprintf(cmd, MAX_CMD_SIZE, "cp -rf %s %s", rom_dat_file, dat_file);
1953 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1954
1955}
1956
developer47cc27a2023-05-17 23:09:58 +08001957static void wifi_psk_file_reset()
1958{
1959 char cmd[MAX_CMD_SIZE] = {0};
1960 char ret_buf[MAX_BUF_SIZE] = {0};
1961 char psk_file[MAX_CMD_SIZE]= {0};
1962 char vap_idx = 0;
1963
1964 for (vap_idx = 0; vap_idx < MAX_APS; vap_idx++) {
1965 snprintf(psk_file, sizeof(psk_file), "%s%d.psk", PSK_FILE, vap_idx);
1966
1967 if (access(psk_file, F_OK) != 0) {
1968 snprintf(cmd, MAX_CMD_SIZE, "touch %s", psk_file);
1969 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1970 } else {
1971 snprintf(cmd, MAX_CMD_SIZE, "echo '' > %s", psk_file);
1972 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1973 }
1974 }
1975}
1976
developerb2977562023-05-24 17:54:12 +08001977static void wifi_psk_file_reset_by_radio(char radio_idx)
1978{
1979 char cmd[MAX_CMD_SIZE] = {0};
1980 char ret_buf[MAX_BUF_SIZE] = {0};
1981 char psk_file[MAX_CMD_SIZE]= {0};
1982 char vap_idx = 0;
1983
1984 for (vap_idx = radio_idx; vap_idx < MAX_APS; vap_idx += MAX_NUM_RADIOS) {
1985 snprintf(psk_file, sizeof(psk_file), "%s%d.psk", PSK_FILE, vap_idx);
1986
1987 if (access(psk_file, F_OK) != 0) {
1988 snprintf(cmd, MAX_CMD_SIZE, "touch %s", psk_file);
1989 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1990 } else {
1991 snprintf(cmd, MAX_CMD_SIZE, "echo '' > %s", psk_file);
1992 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1993 }
1994 }
1995
1996}
1997
1998
developer8a3bbbf2023-03-15 17:47:23 +08001999static void wifi_vap_status_reset()
2000{
2001 char cmd[MAX_CMD_SIZE] = {0};
2002 char ret_buf[MAX_BUF_SIZE] = {0};
2003 char radio_idx = 0;
2004 char bss_idx = 0;
developer8666b312023-03-24 14:05:31 +08002005
developer8a3bbbf2023-03-15 17:47:23 +08002006 if (access(VAP_STATUS_FILE, F_OK) != 0) {
2007 snprintf(cmd, MAX_CMD_SIZE, "touch %s", VAP_STATUS_FILE);
2008 _syscmd(cmd, ret_buf, sizeof(ret_buf));
2009 } else {
2010 snprintf(cmd, MAX_CMD_SIZE, "echo '' > %s", VAP_STATUS_FILE);
2011 _syscmd(cmd, ret_buf, sizeof(ret_buf));
2012 }
2013
2014 memset(cmd, 0, MAX_CMD_SIZE);
2015 memset(ret_buf, 0, MAX_BUF_SIZE);
2016
2017 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++)
2018 for (bss_idx = 0; bss_idx < 5; bss_idx++) {
2019 snprintf(cmd, MAX_CMD_SIZE, "echo %s%d=0 >> %s", ext_prefix[radio_idx], bss_idx, VAP_STATUS_FILE);
2020 _syscmd(cmd, ret_buf, sizeof(ret_buf));
2021 }
2022
developerfead3972023-05-25 20:15:02 +08002023}
2024
2025static void wifi_radio_reset_count_reset()
2026{
2027 char cmd[MAX_CMD_SIZE] = {0};
2028 char ret_buf[MAX_BUF_SIZE] = {0};
2029
2030 if (access(VAP_STATUS_FILE, F_OK) != 0) {
2031 snprintf(cmd, MAX_CMD_SIZE, "touch %s", RADIO_RESET_FILE);
2032 _syscmd(cmd, ret_buf, sizeof(ret_buf));
2033 } else {
2034 snprintf(cmd, MAX_CMD_SIZE, "echo '' > %s", RADIO_RESET_FILE);
2035 _syscmd(cmd, ret_buf, sizeof(ret_buf));
2036 }
developer8a3bbbf2023-03-15 17:47:23 +08002037}
developer17038e62023-03-02 14:43:43 +08002038
developer72fb0bb2023-01-11 09:46:29 +08002039// Initializes the wifi subsystem (all radios)
2040INT wifi_init() //RDKB
2041{
developer96b38512023-02-22 11:17:45 +08002042 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developercc9a4f32023-05-30 17:40:02 +08002043 static int CallOnce = 1;
developer96b38512023-02-22 11:17:45 +08002044 //Not intitializing macfilter for Turris-Omnia Platform for now
2045 //macfilter_init();
developercc9a4f32023-05-30 17:40:02 +08002046 if (CallOnce) {
2047 wifi_ParseProfile();
2048 wifi_PrepareDefaultHostapdConfigs();
2049 wifi_psk_file_reset();
2050 //system("/usr/sbin/iw reg set US");
2051 system("systemctl start hostapd.service");
2052 sleep(2);
developer8a3bbbf2023-03-15 17:47:23 +08002053
developercc9a4f32023-05-30 17:40:02 +08002054 wifi_vap_status_reset();
2055 wifi_radio_reset_count_reset();
2056 CallOnce = 0;
2057 }
developer96b38512023-02-22 11:17:45 +08002058
2059 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08002060
2061 return RETURN_OK;
2062}
2063
2064/* wifi_reset() function */
2065/**
2066* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
developer69b61b02023-03-07 17:17:44 +08002067* Implementation specifics may dictate what is actualy reset since
developer72fb0bb2023-01-11 09:46:29 +08002068* different hardware implementations may have different requirements.
2069* Parameters : None
2070*
2071* @return The status of the operation.
2072* @retval RETURN_OK if successful.
2073* @retval RETURN_ERR if any error is detected
2074*
2075* @execution Synchronous.
2076* @sideeffect None.
2077*
2078* @note This function must not suspend and must not invoke any blocking system
2079* calls. It should probably just send a message to a driver event handler task.
2080*
2081*/
2082INT wifi_reset()
2083{
developer17038e62023-03-02 14:43:43 +08002084
2085 wifi_BringDownInterfaces();
2086 sleep(2);
2087
developer96b38512023-02-22 11:17:45 +08002088 //TODO: resets the wifi subsystem, deletes all APs
2089 system("systemctl stop hostapd.service");
2090 sleep(2);
developer17038e62023-03-02 14:43:43 +08002091
developer96b38512023-02-22 11:17:45 +08002092 system("systemctl start hostapd.service");
2093 sleep(5);
developer17038e62023-03-02 14:43:43 +08002094
2095 wifi_PrepareDefaultHostapdConfigs();
developer47cc27a2023-05-17 23:09:58 +08002096 wifi_psk_file_reset();
developer17038e62023-03-02 14:43:43 +08002097 sleep(2);
developer8a3bbbf2023-03-15 17:47:23 +08002098
2099 wifi_vap_status_reset();
2100
developer72fb0bb2023-01-11 09:46:29 +08002101 return RETURN_OK;
2102}
2103
2104/* wifi_down() function */
2105/**
2106* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
developer69b61b02023-03-07 17:17:44 +08002107* Implementation specifics may dictate some functionality since
developer72fb0bb2023-01-11 09:46:29 +08002108* different hardware implementations may have different requirements.
2109*
2110* @param None
2111*
2112* @return The status of the operation
2113* @retval RETURN_OK if successful
2114* @retval RETURN_ERR if any error is detected
2115*
2116* @execution Synchronous
2117* @sideeffect None
2118*
2119* @note This function must not suspend and must not invoke any blocking system
2120* calls. It should probably just send a message to a driver event handler task.
2121*
2122*/
2123INT wifi_down()
2124{
developer96b38512023-02-22 11:17:45 +08002125 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developerb2977562023-05-24 17:54:12 +08002126 int max_num_radios = 0;
2127 wifi_getMaxRadioNumber(&max_num_radios);
developer17038e62023-03-02 14:43:43 +08002128
developerb2977562023-05-24 17:54:12 +08002129 for (int radioIndex = 0; radioIndex < max_num_radios; radioIndex++)
2130 wifi_setRadioEnable(radioIndex, FALSE);
2131
developer72fb0bb2023-01-11 09:46:29 +08002132 return RETURN_OK;
2133}
2134
2135
2136/* wifi_createInitialConfigFiles() function */
2137/**
2138* @description This function creates wifi configuration files. The format
developer69b61b02023-03-07 17:17:44 +08002139* and content of these files are implementation dependent. This function call is
2140* used to trigger this task if necessary. Some implementations may not need this
2141* function. If an implementation does not need to create config files the function call can
developer72fb0bb2023-01-11 09:46:29 +08002142* do nothing and return RETURN_OK.
2143*
2144* @param None
2145*
2146* @return The status of the operation
2147* @retval RETURN_OK if successful
2148* @retval RETURN_ERR if any error is detected
2149*
2150* @execution Synchronous
2151* @sideeffect None
2152*
2153* @note This function must not suspend and must not invoke any blocking system
2154* calls. It should probably just send a message to a driver event handler task.
2155*
2156*/
2157INT wifi_createInitialConfigFiles()
2158{
2159 //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)
2160 return RETURN_OK;
2161}
2162
developer7e4a2a62023-04-06 19:56:03 +08002163/* outputs the country code to a max 64 character string */
developer72fb0bb2023-01-11 09:46:29 +08002164INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
2165{
developerfde01262023-05-22 15:15:24 +08002166 int ret;
developer72fb0bb2023-01-11 09:46:29 +08002167
developerfde01262023-05-22 15:15:24 +08002168 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer7e4a2a62023-04-06 19:56:03 +08002169
developerfde01262023-05-22 15:15:24 +08002170 ret = wifi_BandProfileRead(0, radioIndex, "CountryCode", output_string, 64, NULL);
2171 if (ret != 0) {
2172 fprintf(stderr, "%s: wifi_BandProfileRead CountryCode failed\n", __func__);
2173 return RETURN_ERR;
2174 }
developer7e4a2a62023-04-06 19:56:03 +08002175
developerfde01262023-05-22 15:15:24 +08002176 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer7e4a2a62023-04-06 19:56:03 +08002177
developerfde01262023-05-22 15:15:24 +08002178 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08002179}
2180
2181INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
2182{
developer7e4a2a62023-04-06 19:56:03 +08002183 /*Set wifi config. Wait for wifi reset to apply*/
developer7e4a2a62023-04-06 19:56:03 +08002184 struct params params;
2185 char config_file[MAX_BUF_SIZE] = {0};
2186 int ret = 0;
developer72fb0bb2023-01-11 09:46:29 +08002187
developer7e4a2a62023-04-06 19:56:03 +08002188 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08002189
developer7e4a2a62023-04-06 19:56:03 +08002190 if(NULL == CountryCode || strlen(CountryCode) >= 32 ) {
2191 printf("%s: input para error!!!\n", __func__);
2192 return RETURN_ERR;
2193 }
developer72fb0bb2023-01-11 09:46:29 +08002194
developer7e4a2a62023-04-06 19:56:03 +08002195 if (!strlen(CountryCode))
developerdaf24792023-06-06 11:40:04 +08002196 strncpy(CountryCode, "US", strlen("US")); /*default set the code to US*/
developer72fb0bb2023-01-11 09:46:29 +08002197
developer7e4a2a62023-04-06 19:56:03 +08002198 params.name = "country_code";
2199 params.value = CountryCode;
developer72fb0bb2023-01-11 09:46:29 +08002200
developer7e4a2a62023-04-06 19:56:03 +08002201 snprintf(config_file, MAX_BUF_SIZE, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2202 ret = wifi_hostapdWrite(config_file, &params, 1);
2203
2204 if (ret) {
2205 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n",
2206 __func__, ret);
2207 }
2208
2209 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2210
2211 if (ret) {
2212 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n",
2213 __func__, ret);
2214 }
2215
2216 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
2217
2218 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08002219}
2220
2221INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
2222{
2223 char interface_name[16] = {0};
2224 char channel_util_file[64] = {0};
2225 char cmd[128] = {0};
2226 char buf[128] = {0};
developer2f79c922023-06-02 17:33:42 +08002227 char *line = NULL;
developer72fb0bb2023-01-11 09:46:29 +08002228 char *param = NULL, *value = NULL;
2229 int read = 0;
2230 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
2231 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
2232 size_t len = 0;
2233 FILE *f = NULL;
2234
2235 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2236
2237 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
2238 return RETURN_ERR;
2239 snprintf(cmd, sizeof(cmd), "iw %s scan | grep signal | awk '{print $2}' | sort -n | tail -n1", interface_name);
2240 _syscmd(cmd, buf, sizeof(buf));
2241 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
2242
2243 memset(cmd, 0, sizeof(cmd));
2244 memset(buf, 0, sizeof(buf));
2245 snprintf(cmd, sizeof(cmd), "iw %s survey dump | grep 'in use' -A6", interface_name);
2246 if ((f = popen(cmd, "r")) == NULL) {
2247 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
2248 return RETURN_ERR;
2249 }
2250
2251 read = getline(&line, &len, f);
2252 while (read != -1) {
2253 param = strtok(line, ":\t");
2254 value = strtok(NULL, " ");
2255 if(strstr(param, "frequency") != NULL) {
2256 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
2257 }
2258 if(strstr(param, "noise") != NULL) {
2259 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
2260 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
2261 }
2262 if(strstr(param, "channel active time") != NULL) {
2263 ActiveTime = strtol(value, NULL, 10);
2264 }
2265 if(strstr(param, "channel busy time") != NULL) {
2266 BusyTime = strtol(value, NULL, 10);
2267 }
2268 if(strstr(param, "channel transmit time") != NULL) {
2269 TransmitTime = strtol(value, NULL, 10);
2270 }
2271 read = getline(&line, &len, f);
2272 }
2273 pclose(f);
2274
2275 // The file should store the last active, busy and transmit time
2276 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
2277 f = fopen(channel_util_file, "r");
2278 if (f != NULL) {
2279 read = getline(&line, &len, f);
2280 preActiveTime = strtol(line, NULL, 10);
2281 read = getline(&line, &len, f);
2282 preBusyTime = strtol(line, NULL, 10);
2283 read = getline(&line, &len, f);
2284 preTransmitTime = strtol(line, NULL, 10);
2285 fclose(f);
2286 }
2287
2288 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
2289 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
2290
2291 f = fopen(channel_util_file, "w");
2292 if (f != NULL) {
2293 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
2294 fclose(f);
2295 }
2296 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2297 return RETURN_OK;
2298}
2299
2300/**********************************************************************************
2301 *
2302 * Wifi radio level function prototypes
2303 *
2304**********************************************************************************/
2305
2306//Get the total number of radios in this wifi subsystem
2307INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
2308{
2309 if (NULL == output)
2310 return RETURN_ERR;
2311 *output = MAX_NUM_RADIOS;
2312
2313 return RETURN_OK;
2314}
2315
developer69b61b02023-03-07 17:17:44 +08002316//Get the total number of SSID entries in this wifi subsystem
developer72fb0bb2023-01-11 09:46:29 +08002317INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
2318{
2319 if (NULL == output)
2320 return RETURN_ERR;
2321 *output = MAX_APS;
2322
2323 return RETURN_OK;
2324}
2325
2326//Get the Radio enable config parameter
2327INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
2328{
developer56fbedb2023-05-30 16:47:05 +08002329 char interface_name[16] = {0};
2330 char buf[128] = {0}, cmd[128] = {0};
2331 int apIndex;
2332 int max_radio_num = 0;
developer3a85ab82023-05-25 11:59:38 +08002333
developer56fbedb2023-05-30 16:47:05 +08002334 if (NULL == output_bool)
2335 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08002336
developer56fbedb2023-05-30 16:47:05 +08002337 *output_bool = FALSE;
developer72fb0bb2023-01-11 09:46:29 +08002338
developer56fbedb2023-05-30 16:47:05 +08002339 wifi_getMaxRadioNumber(&max_radio_num);
developer72fb0bb2023-01-11 09:46:29 +08002340
developer56fbedb2023-05-30 16:47:05 +08002341 if (radioIndex >= max_radio_num)
2342 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08002343
developer56fbedb2023-05-30 16:47:05 +08002344 /* loop all interface in radio, if any is enable, reture true, else return false */
2345 for(apIndex = radioIndex; apIndex < MAX_APS; apIndex += max_radio_num)
2346 {
2347 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
2348 continue;
2349 memset(cmd, 0, sizeof(cmd));
2350 sprintf(cmd, "ifconfig %s 2> /dev/null | grep UP", interface_name);
2351 *output_bool = _syscmd(cmd, buf, sizeof(buf)) ? FALSE : TRUE;
2352 if (*output_bool == TRUE)
2353 break;
2354 }
2355
2356 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08002357}
2358
developere82c0ca2023-05-10 16:25:35 +08002359typedef long time_t;
2360static time_t radio_up_time[MAX_NUM_RADIOS];
2361
developer72fb0bb2023-01-11 09:46:29 +08002362INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
2363{
2364 char interface_name[16] = {0};
2365 char cmd[MAX_CMD_SIZE] = {0};
developer8a3bbbf2023-03-15 17:47:23 +08002366 char buf[MAX_BUF_SIZE] = {0};
developer2f79c922023-06-02 17:33:42 +08002367 int apIndex;
developer69b61b02023-03-07 17:17:44 +08002368 int max_radio_num = 0;
developer72fb0bb2023-01-11 09:46:29 +08002369 int phyId = 0;
2370
2371 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2372
2373 phyId = radio_index_to_phy(radioIndex);
2374
2375 wifi_getMaxRadioNumber(&max_radio_num);
2376
developer8a3bbbf2023-03-15 17:47:23 +08002377 if(enable == FALSE) {
developer47cc27a2023-05-17 23:09:58 +08002378
2379 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
2380 return RETURN_ERR;
2381
2382 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s", interface_name);
developer8a3bbbf2023-03-15 17:47:23 +08002383 _syscmd(cmd, buf, sizeof(buf));
developer56fbedb2023-05-30 16:47:05 +08002384 memset(cmd, 0, sizeof(cmd));
2385 snprintf(cmd, MAX_CMD_SIZE, "ifconfig %s down", interface_name);
2386 _syscmd(cmd, buf, sizeof(buf));
developere82c0ca2023-05-10 16:25:35 +08002387 if(strncmp(buf, "OK", 2))
2388 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
developer8a3bbbf2023-03-15 17:47:23 +08002389 } else {
developere82c0ca2023-05-10 16:25:35 +08002390 for (apIndex = radioIndex; apIndex < MAX_APS; apIndex += max_radio_num) {
developer72fb0bb2023-01-11 09:46:29 +08002391 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
2392 return RETURN_ERR;
2393
developer8a3bbbf2023-03-15 17:47:23 +08002394 memset(cmd, 0, MAX_CMD_SIZE);
2395 memset(buf, 0, MAX_BUF_SIZE);
2396
developer72fb0bb2023-01-11 09:46:29 +08002397 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
2398 _syscmd(cmd, buf, sizeof(buf));
developer8a3bbbf2023-03-15 17:47:23 +08002399
2400 if(*buf == '1') {
developer56fbedb2023-05-30 16:47:05 +08002401 snprintf(cmd, MAX_CMD_SIZE, "ifconfig %s up", interface_name);
2402 _syscmd(cmd, buf, sizeof(buf));
developer8a3bbbf2023-03-15 17:47:23 +08002403
2404 memset(cmd, 0, MAX_CMD_SIZE);
2405 memset(buf, 0, MAX_BUF_SIZE);
2406
developer72fb0bb2023-01-11 09:46:29 +08002407 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
2408 phyId, apIndex);
2409 _syscmd(cmd, buf, sizeof(buf));
developer8a3bbbf2023-03-15 17:47:23 +08002410
developer72fb0bb2023-01-11 09:46:29 +08002411 }
2412 }
developere82c0ca2023-05-10 16:25:35 +08002413 time(&radio_up_time[radioIndex]);
developer72fb0bb2023-01-11 09:46:29 +08002414 }
2415
2416 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2417 return RETURN_OK;
2418}
2419
2420//Get the Radio enable status
2421INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
2422{
2423 if (NULL == output_bool)
2424 return RETURN_ERR;
2425
2426 return wifi_getRadioEnable(radioIndex, output_bool);
2427}
2428
2429//Get the Radio Interface name from platform, eg "wlan0"
2430INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
2431{
2432 if (NULL == output_string || radioIndex>=MAX_NUM_RADIOS || radioIndex<0)
2433 return RETURN_ERR;
2434 return wifi_GetInterfaceName(radioIndex, output_string);
2435}
2436
2437//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
2438//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.
2439INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
2440{
2441 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
2442 // For max bit rate, we should always choose the best MCS
2443 char mode[64] = {0};
2444 char channel_bandwidth_str[64] = {0};
developer72fb0bb2023-01-11 09:46:29 +08002445 UINT mode_map = 0;
2446 UINT num_subcarrier = 0;
2447 UINT code_bits = 0;
2448 float code_rate = 0; // use max code rate
2449 int NSS = 0;
2450 UINT Symbol_duration = 0;
developer69b61b02023-03-07 17:17:44 +08002451 UINT GI_duration = 0;
developer72fb0bb2023-01-11 09:46:29 +08002452 wifi_guard_interval_t gi = wifi_guard_interval_auto;
2453 BOOL enable = FALSE;
2454 float bit_rate = 0;
developera1255e42023-05-13 17:45:02 +08002455 int ant_bitmap = 0;
developer72fb0bb2023-01-11 09:46:29 +08002456
2457 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2458 if (NULL == output_string)
2459 return RETURN_ERR;
2460
2461 wifi_getRadioEnable(radioIndex, &enable);
2462 if (enable == FALSE) {
2463 snprintf(output_string, 64, "0 Mb/s");
2464 return RETURN_OK;
2465 }
2466
2467 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
2468 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
2469 return RETURN_ERR;
2470 }
2471
2472 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
2473 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
2474 return RETURN_ERR;
2475 }
2476
2477 if (gi == wifi_guard_interval_3200)
2478 GI_duration = 32;
2479 else if (gi == wifi_guard_interval_1600)
2480 GI_duration = 16;
2481 else if (gi == wifi_guard_interval_800)
2482 GI_duration = 8;
2483 else // auto, 400
2484 GI_duration = 4;
2485
2486 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
2487 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
2488 return RETURN_ERR;
2489 }
2490
2491 if (strstr(channel_bandwidth_str, "80+80") != NULL)
2492 strcpy(channel_bandwidth_str, "160");
2493
2494 if (mode_map & WIFI_MODE_AX) {
2495 if (strstr(channel_bandwidth_str, "160") != NULL)
2496 num_subcarrier = 1960;
2497 else if (strstr(channel_bandwidth_str, "80") != NULL)
2498 num_subcarrier = 980;
2499 else if (strstr(channel_bandwidth_str, "40") != NULL)
2500 num_subcarrier = 468;
2501 else if (strstr(channel_bandwidth_str, "20") != NULL)
2502 num_subcarrier = 234;
2503 code_bits = 10;
2504 code_rate = (float)5/6;
2505 Symbol_duration = 128;
developera1255e42023-05-13 17:45:02 +08002506 GI_duration = 8;/*HE no GI 400ns*/
developer72fb0bb2023-01-11 09:46:29 +08002507 } else if (mode_map & WIFI_MODE_AC) {
2508 if (strstr(channel_bandwidth_str, "160") != NULL)
2509 num_subcarrier = 468;
2510 else if (strstr(channel_bandwidth_str, "80") != NULL)
2511 num_subcarrier = 234;
2512 else if (strstr(channel_bandwidth_str, "40") != NULL)
2513 num_subcarrier = 108;
2514 else if (strstr(channel_bandwidth_str, "20") != NULL)
2515 num_subcarrier = 52;
2516 code_bits = 8;
2517 code_rate = (float)5/6;
2518 Symbol_duration = 32;
2519 } else if (mode_map & WIFI_MODE_N) {
2520 if (strstr(channel_bandwidth_str, "160") != NULL)
2521 num_subcarrier = 468;
2522 else if (strstr(channel_bandwidth_str, "80") != NULL)
2523 num_subcarrier = 234;
2524 else if (strstr(channel_bandwidth_str, "40") != NULL)
2525 num_subcarrier = 108;
2526 else if (strstr(channel_bandwidth_str, "20") != NULL)
2527 num_subcarrier = 52;
2528 code_bits = 6;
2529 code_rate = (float)3/4;
2530 Symbol_duration = 32;
2531 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
2532 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
2533 snprintf(output_string, 64, "65 Mb/s");
2534 return RETURN_OK;
2535 } else {
2536 snprintf(output_string, 64, "0 Mb/s");
2537 return RETURN_OK;
2538 }
2539
2540 // Spatial streams
developera1255e42023-05-13 17:45:02 +08002541 if (wifi_getRadioTxChainMask(radioIndex, &ant_bitmap) != RETURN_OK) {
developer72fb0bb2023-01-11 09:46:29 +08002542 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
2543 return RETURN_ERR;
2544 }
developera1255e42023-05-13 17:45:02 +08002545 for (; ant_bitmap > 0; ant_bitmap >>= 1)
2546 NSS += ant_bitmap & 1;
developer72fb0bb2023-01-11 09:46:29 +08002547
2548 // multiple 10 is to align duration unit (0.1 us)
2549 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
2550 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
developera1255e42023-05-13 17:45:02 +08002551 WIFI_ENTRY_EXIT_DEBUG("%s:num_subcarrier=%d, code_bits=%d, code_rate=%.3f, nss=%d, symbol time=%u, %.1f Mb/s\n",
2552 __func__, num_subcarrier, code_bits, code_rate, NSS, Symbol_duration + GI_duration, bit_rate);
developer72fb0bb2023-01-11 09:46:29 +08002553 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2554
2555 return RETURN_OK;
2556}
2557#if 0
2558INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
2559{
2560 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2561 char cmd[64];
2562 char buf[1024];
2563 int apIndex;
2564
developer69b61b02023-03-07 17:17:44 +08002565 if (NULL == output_string)
developer72fb0bb2023-01-11 09:46:29 +08002566 return RETURN_ERR;
2567
2568 apIndex=(radioIndex==0)?0:1;
2569
2570 snprintf(cmd, sizeof(cmd), "iwconfig %s | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", interface_name);
2571 _syscmd(cmd,buf, sizeof(buf));
2572
2573 snprintf(output_string, 64, "%s", buf);
2574 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2575 return RETURN_OK;
2576}
2577#endif
2578
2579
2580//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
2581//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.
2582INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
2583{
2584 wifi_band band = band_invalid;
2585
2586 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2587 if (NULL == output_string)
2588 return RETURN_ERR;
2589
2590 band = wifi_index_to_band(radioIndex);
2591
2592 memset(output_string, 0, 10);
2593 if (band == band_2_4)
2594 strcpy(output_string, "2.4GHz");
2595 else if (band == band_5)
2596 strcpy(output_string, "5GHz");
2597 else if (band == band_6)
2598 strcpy(output_string, "6GHz");
2599 else
2600 return RETURN_ERR;
2601 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2602
2603 return RETURN_OK;
2604#if 0
2605 char buf[MAX_BUF_SIZE]={'\0'};
2606 char str[MAX_BUF_SIZE]={'\0'};
2607 char cmd[MAX_CMD_SIZE]={'\0'};
2608 char *ch=NULL;
2609 char *ch2=NULL;
2610
2611 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2612 if (NULL == output_string)
2613 return RETURN_ERR;
2614
2615
2616 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2617
2618 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
2619 {
2620 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2621 return RETURN_ERR;
2622 }
2623 ch=strchr(buf,'\n');
2624 *ch='\0';
2625 ch=strchr(buf,'=');
2626 if(ch==NULL)
2627 return RETURN_ERR;
2628
2629
2630 ch++;
2631
2632 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
2633 strcpy(buf,"0");
2634 if(strlen(ch) == 1)
2635 ch=strcat(buf,ch);
2636
2637
2638 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2639
2640 if(_syscmd(cmd,str,64) == RETURN_ERR)
2641 {
2642 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2643 return RETURN_ERR;
2644 }
2645
2646
2647 ch2=strchr(str,'\n');
2648 //replace \n with \0
2649 *ch2='\0';
2650 ch2=strchr(str,'=');
2651 if(ch2==NULL)
2652 {
2653 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2654 return RETURN_ERR;
2655 }
2656 else
2657 wifi_dbg_printf("%s",ch2+1);
2658
2659
2660 ch2++;
2661
2662
2663 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
2664
2665 memset(buf,'\0',sizeof(buf));
2666 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
2667 {
2668 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2669 return RETURN_ERR;
2670 }
2671 if (strstr(buf,"2.4") != NULL )
2672 strcpy(output_string,"2.4GHz");
2673 else if(strstr(buf,"5.") != NULL )
2674 strcpy(output_string,"5GHz");
2675 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2676
2677 return RETURN_OK;
2678#endif
2679}
2680
2681//Get the frequency band at which the radio is operating, eg: "2.4GHz"
2682//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.
2683INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
2684{
2685 wifi_band band = band_invalid;
2686 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2687 if (NULL == output_string)
2688 return RETURN_ERR;
2689 band = wifi_index_to_band(radioIndex);
2690
developer69b61b02023-03-07 17:17:44 +08002691 if (band == band_2_4)
developer72fb0bb2023-01-11 09:46:29 +08002692 snprintf(output_string, 64, "2.4GHz");
2693 else if (band == band_5)
developer69b61b02023-03-07 17:17:44 +08002694 snprintf(output_string, 64, "5GHz");
developer72fb0bb2023-01-11 09:46:29 +08002695 else if (band == band_6)
2696 snprintf(output_string, 64, "6GHz");
2697
2698 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2699
2700 return RETURN_OK;
2701#if 0
2702 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2703 char buf[MAX_BUF_SIZE]={'\0'};
2704 char str[MAX_BUF_SIZE]={'\0'};
2705 char cmd[MAX_CMD_SIZE]={'\0'};
2706 char *ch=NULL;
2707 char *ch2=NULL;
2708 char ch1[5]="0";
2709
2710 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2711
2712 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
2713 {
2714 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2715 return RETURN_ERR;
2716 }
2717
2718 ch=strchr(buf,'\n');
2719 *ch='\0';
2720 ch=strchr(buf,'=');
2721 if(ch==NULL)
2722 return RETURN_ERR;
2723 ch++;
2724
2725 if(strlen(ch)==1)
2726 {
2727 strcat(ch1,ch);
2728
2729 }
2730 else
2731 {
2732 strcpy(ch1,ch);
2733 }
2734
2735
2736
2737 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2738 if(_syscmd(cmd,str,64) == RETURN_ERR)
2739 {
2740 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2741 return RETURN_ERR;
2742 }
2743
2744
2745 ch2=strchr(str,'\n');
2746 //replace \n with \0
2747 *ch2='\0';
2748 ch2=strchr(str,'=');
2749 if(ch2==NULL)
2750 {
2751 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2752 return RETURN_ERR;
2753 }
2754 else
2755 wifi_dbg_printf("%s",ch2+1);
2756 ch2++;
2757
2758
2759 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
2760 memset(buf,'\0',sizeof(buf));
2761 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
2762 {
2763 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2764 return RETURN_ERR;
2765 }
2766
2767
2768 if(strstr(buf,"2.4")!=NULL)
2769 {
2770 strcpy(output_string,"2.4GHz");
2771 }
2772 if(strstr(buf,"5.")!=NULL)
2773 {
2774 strcpy(output_string,"5GHz");
2775 }
2776 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2777 return RETURN_OK;
2778#endif
2779}
2780
2781//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
2782//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.
2783INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
2784{
2785 char cmd[128]={0};
2786 char buf[128]={0};
2787 char temp_output[128] = {0};
2788 wifi_band band;
2789 int phyId = 0;
2790
2791 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer69b61b02023-03-07 17:17:44 +08002792 if (NULL == output_string)
developer72fb0bb2023-01-11 09:46:29 +08002793 return RETURN_ERR;
2794
2795 band = wifi_index_to_band(radioIndex);
2796 if (band == band_2_4) {
2797 strcat(temp_output, "b,g,");
2798 } else if (band == band_5) {
2799 strcat(temp_output, "a,");
2800 }
2801 phyId = radio_index_to_phy(radioIndex);
2802 // ht capabilities
2803 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);
2804 _syscmd(cmd, buf, sizeof(buf));
2805 if (strlen(buf) >= 4 && strncmp(buf, "0x00", 4) != 0) {
2806 strcat(temp_output, "n,");
2807 }
2808
2809 // vht capabilities
2810 if (band == band_5) {
2811 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'VHT Capabilities' | cut -d '(' -f2 | cut -c1-10 | tr -d '\\n'", phyId);
2812 _syscmd(cmd, buf, sizeof(buf));
2813 if (strlen(buf) >= 10 && strncmp(buf, "0x00000000", 10) != 0) {
2814 strcat(temp_output, "ac,");
2815 }
2816 }
2817
2818 // he capabilities
2819 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);
2820 _syscmd(cmd, buf, sizeof(buf));
2821 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
2822 strcat(temp_output, "ax,");
2823 }
2824
developere82c0ca2023-05-10 16:25:35 +08002825 // eht capabilities
2826 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);
2827 _syscmd(cmd, buf, sizeof(buf));
2828 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
2829 strcat(temp_output, "be,");
2830 }
2831
developer72fb0bb2023-01-11 09:46:29 +08002832 // Remove the last comma
2833 if (strlen(temp_output) != 0)
2834 temp_output[strlen(temp_output)-1] = '\0';
2835 strncpy(output_string, temp_output, strlen(temp_output));
2836 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2837 return RETURN_OK;
2838}
2839
2840//Get the radio operating mode, and pure mode flag. eg: "ac"
2841//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.
2842INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
2843{
2844 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2845 if (NULL == output_string)
2846 return RETURN_ERR;
2847
2848 if (radioIndex == 0) {
2849 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
2850 *gOnly = FALSE;
2851 *nOnly = TRUE;
2852 *acOnly = FALSE;
2853 } else {
2854 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
2855 *gOnly = FALSE;
2856 *nOnly = FALSE;
2857 *acOnly = FALSE;
2858 }
2859 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2860
2861 return RETURN_OK;
2862#if 0
2863 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2864 char buf[64] = {0};
2865 char config_file[MAX_BUF_SIZE] = {0};
2866
developer69b61b02023-03-07 17:17:44 +08002867 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
developer72fb0bb2023-01-11 09:46:29 +08002868 return RETURN_ERR;
2869
2870 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2871 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
2872
2873 wifi_dbg_printf("\nhw_mode=%s\n",buf);
developer69b61b02023-03-07 17:17:44 +08002874 if (strlen(buf) == 0)
developer72fb0bb2023-01-11 09:46:29 +08002875 {
2876 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
2877 return RETURN_ERR;
2878 }
2879 if(strcmp(buf,"g")==0)
2880 {
2881 wifi_dbg_printf("\nG\n");
2882 *gOnly=TRUE;
2883 *nOnly=FALSE;
2884 *acOnly=FALSE;
2885 }
2886 else if(strcmp(buf,"n")==0)
2887 {
2888 wifi_dbg_printf("\nN\n");
2889 *gOnly=FALSE;
2890 *nOnly=TRUE;
2891 *acOnly=FALSE;
2892 }
2893 else if(strcmp(buf,"ac")==0)
2894 {
2895 wifi_dbg_printf("\nac\n");
2896 *gOnly=FALSE;
2897 *nOnly=FALSE;
2898 *acOnly=TRUE;
2899 }
2900 /* hostapd-5G.conf has "a" as hw_mode */
2901 else if(strcmp(buf,"a")==0)
2902 {
2903 wifi_dbg_printf("\na\n");
2904 *gOnly=FALSE;
2905 *nOnly=FALSE;
2906 *acOnly=FALSE;
2907 }
2908 else
2909 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
2910
2911 //for a,n mode
2912 if(radioIndex == 1)
2913 {
2914 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
2915 if(strcmp(buf,"1")==0)
2916 {
2917 strncpy(output_string, "n", 1);
2918 *nOnly=FALSE;
2919 }
2920 }
2921
2922 wifi_dbg_printf("\nReturning from getRadioStandard\n");
2923 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2924 return RETURN_OK;
2925#endif
2926}
2927
developer0f10c772023-05-16 21:43:39 +08002928enum WIFI_MODE {
2929 WMODE_INVALID = 0,
2930 WMODE_A = 1 << 0,
2931 WMODE_B = 1 << 1,
2932 WMODE_G = 1 << 2,
2933 WMODE_GN = 1 << 3,
2934 WMODE_AN = 1 << 4,
2935 WMODE_AC = 1 << 5,
2936 WMODE_AX_24G = 1 << 6,
2937 WMODE_AX_5G = 1 << 7,
2938 WMODE_AX_6G = 1 << 8,
2939 WMODE_BE_24G = 1 << 9,
2940 WMODE_BE_5G = 1 << 10,
2941 WMODE_BE_6G = 1 << 11,
2942 /*
2943 * total types of supported wireless mode,
2944 * add this value once yow add new type
2945 */
2946 WMODE_COMP = 12,
2947};
2948
2949#define RADIO_MODE_LEN 32
developerfead3972023-05-25 20:15:02 +08002950
2951int get_radio_mode_handler(struct nl_msg *msg, void *cb)
developer72fb0bb2023-01-11 09:46:29 +08002952{
developerfead3972023-05-25 20:15:02 +08002953 struct nlattr *tb[NL80211_ATTR_MAX + 1];
2954 struct nlattr *vndr_tb[MTK_NL80211_VENDOR_ATTR_GET_RUNTIME_INFO_MAX + 1];
2955 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
2956 unsigned int *phymode;
2957 int err = 0;
2958 struct mtk_nl80211_cb_data *cb_data = cb;
developer72fb0bb2023-01-11 09:46:29 +08002959
developerfead3972023-05-25 20:15:02 +08002960 if (!msg || !cb_data) {
developerdaf24792023-06-06 11:40:04 +08002961 wifi_debug(DEBUG_ERROR, "msg(%p) or cb_data(%p) is null,error.\n", msg, cb_data);
developerfead3972023-05-25 20:15:02 +08002962 return NL_SKIP;
2963 }
developer72fb0bb2023-01-11 09:46:29 +08002964
developerfead3972023-05-25 20:15:02 +08002965 err = nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
2966 genlmsg_attrlen(gnlh, 0), NULL);
2967 if (err < 0) {
2968 wifi_debug(DEBUG_ERROR, "nla_parse radio nl80211 msg fails,error.\n");
2969 return NL_SKIP;
2970 }
developer0f10c772023-05-16 21:43:39 +08002971
developerfead3972023-05-25 20:15:02 +08002972 if (tb[NL80211_ATTR_VENDOR_DATA]) {
2973 err = nla_parse_nested(vndr_tb, MTK_NL80211_VENDOR_ATTR_GET_RUNTIME_INFO_MAX,
2974 tb[NL80211_ATTR_VENDOR_DATA], NULL);
2975 if (err < 0)
2976 return NL_SKIP;
developer72fb0bb2023-01-11 09:46:29 +08002977
developerfead3972023-05-25 20:15:02 +08002978 if (vndr_tb[MTK_NL80211_VENDOR_ATTR_GET_RUNTIME_INFO_GET_WMODE]) {
2979 phymode = (unsigned int *)nla_data(vndr_tb[MTK_NL80211_VENDOR_ATTR_GET_RUNTIME_INFO_GET_WMODE]);
2980
2981 memset(cb_data->out_buf, 0, cb_data->out_len);
2982 memmove(cb_data->out_buf, phymode, sizeof(unsigned int));
2983 }
2984 } else
2985 wifi_debug(DEBUG_ERROR, "No Stats from driver.\n");
2986
2987 return NL_OK;
2988}
developer0f10c772023-05-16 21:43:39 +08002989
developerfead3972023-05-25 20:15:02 +08002990void phymode_to_puremode(INT radioIndex, CHAR *output_string, UINT *pureMode, UINT phymode)
2991{
2992 wifi_band band;
2993 unsigned char radio_mode_tem_len;
2994
2995 band = wifi_index_to_band(radioIndex);
developer0f10c772023-05-16 21:43:39 +08002996 // puremode is a bit map
developer72fb0bb2023-01-11 09:46:29 +08002997 *pureMode = 0;
developer0f10c772023-05-16 21:43:39 +08002998 memset(output_string, 0, RADIO_MODE_LEN);
2999
3000 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
3001
3002 switch (band) {
3003 case band_2_4:
3004 if (phymode & WMODE_B) {
3005 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "b,");
3006 *pureMode |= WIFI_MODE_B;
3007 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
3008 }
3009 if (phymode & WMODE_G) {
3010 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "g,");
3011 *pureMode |= WIFI_MODE_G;
3012 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
3013 }
3014 if (phymode & WMODE_GN) {
3015 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "n,");
3016 *pureMode |= WIFI_MODE_N;
3017 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
3018 }
3019 if (phymode & WMODE_AX_24G) {
3020 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "ax,");
3021 *pureMode |= WIFI_MODE_AX;
3022 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
3023 }
3024 if (phymode & WMODE_BE_24G) {
3025 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "be,");
3026 *pureMode |= WIFI_MODE_BE;
3027 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
3028 }
3029 break;
3030 case band_5:
3031 if (phymode & WMODE_A) {
3032 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "a,");
3033 *pureMode |= WIFI_MODE_A;
3034 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
3035 }
3036 if (phymode & WMODE_AN) {
3037 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "n,");
3038 *pureMode |= WIFI_MODE_N;
3039 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
3040 }
3041 if (phymode & WMODE_AC) {
3042 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "ac,");
3043 *pureMode |= WIFI_MODE_AC;
3044 }
3045 if (phymode & WMODE_AX_5G) {
3046 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "ax,");
3047 *pureMode |= WIFI_MODE_AX;
3048 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
3049 }
3050 if (phymode & WMODE_BE_5G) {
3051 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "be,");
3052 *pureMode |= WIFI_MODE_BE;
3053 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
3054 }
3055 break;
3056 case band_6:
3057 if (phymode & WMODE_AX_6G) {
3058 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "ax,");
3059 *pureMode |= WIFI_MODE_AX;
3060 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
3061 }
3062 if (phymode & WMODE_BE_6G) {
3063 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "be,");
3064 *pureMode |= WIFI_MODE_BE;
3065 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
3066 }
3067 break;
3068 default:
3069 fprintf(stderr, "%s band_idx invalid\n", __func__);
3070 break;
3071 }
3072
3073 /* Remove the last comma */
3074 if (strlen(output_string) != 0)
3075 output_string[strlen(output_string)-1] = '\0';
developer72fb0bb2023-01-11 09:46:29 +08003076
developerfead3972023-05-25 20:15:02 +08003077}
3078
3079INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
3080{
3081 unsigned int phymode;
3082 char interface_name[IF_NAME_SIZE] = {0};
developerfead3972023-05-25 20:15:02 +08003083 int ret = -1;
3084 unsigned int if_idx = 0;
3085 struct unl unl_ins;
3086 struct nl_msg *msg = NULL;
3087 struct nlattr * msg_data = NULL;
3088 struct mtk_nl80211_param param;
3089 struct mtk_nl80211_cb_data cb_data;
3090
3091 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developerdaf24792023-06-06 11:40:04 +08003092 if (NULL == output_string || NULL == pureMode)
3093 return RETURN_ERR;
developerfead3972023-05-25 20:15:02 +08003094
3095 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3096 return RETURN_ERR;
3097
3098 if_idx = if_nametoindex(interface_name);
3099 if (!if_idx) {
3100 wifi_debug(DEBUG_ERROR, "can't finde ifname(%s) index,ERROR\n", interface_name);
3101 return RETURN_ERR;
3102 }
3103 /*init mtk nl80211 vendor cmd*/
3104 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_GET_RUNTIME_INFO;
3105 param.if_type = NL80211_ATTR_IFINDEX;
3106 param.if_idx = if_idx;
3107
3108 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
3109 if (ret) {
3110 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
3111 return RETURN_ERR;
3112 }
3113
3114 /*add mtk vendor cmd data*/
3115 if (nla_put_u16(msg, MTK_NL80211_VENDOR_ATTR_GET_RUNTIME_INFO_GET_WMODE, 0)) {
3116 wifi_debug(DEBUG_ERROR, "Nla put GET_RUNTIME_INFO_GET_WMODE attribute error\n");
3117 nlmsg_free(msg);
3118 goto err;
3119 }
3120
3121 /*send mtk nl80211 vendor msg*/
3122 cb_data.out_buf = (char *)&phymode;
3123 cb_data.out_len = sizeof(unsigned int);
3124
3125 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, get_radio_mode_handler, &cb_data);
3126
3127 if (ret) {
3128 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
3129 goto err;
3130 }
3131 /*deinit mtk nl80211 vendor msg*/
3132 mtk_nl80211_deint(&unl_ins);
3133
3134 phymode_to_puremode(radioIndex, output_string, pureMode, phymode);
3135 wifi_debug(DEBUG_NOTICE,"send cmd success\n");
3136
developer72fb0bb2023-01-11 09:46:29 +08003137 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3138 return RETURN_OK;
developerfead3972023-05-25 20:15:02 +08003139err:
3140 mtk_nl80211_deint(&unl_ins);
3141 wifi_debug(DEBUG_ERROR,"send cmd fails\n");
3142 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08003143}
3144
3145// Set the radio operating mode, and pure mode flag.
3146INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
3147{
developer69b61b02023-03-07 17:17:44 +08003148 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
developer72fb0bb2023-01-11 09:46:29 +08003149 if (strcmp (channelMode,"11A") == 0)
3150 {
3151 writeBandWidth(radioIndex,"20MHz");
3152 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
3153 printf("\nChannel Mode is 802.11a (5GHz)\n");
3154 }
3155 else if (strcmp (channelMode,"11NAHT20") == 0)
3156 {
3157 writeBandWidth(radioIndex,"20MHz");
3158 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
3159 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
3160 }
3161 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
3162 {
3163 writeBandWidth(radioIndex,"40MHz");
3164 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
3165 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
3166 }
3167 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
3168 {
3169 writeBandWidth(radioIndex,"40MHz");
3170 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
3171 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
3172 }
3173 else if (strcmp (channelMode,"11ACVHT20") == 0)
3174 {
3175 writeBandWidth(radioIndex,"20MHz");
3176 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
3177 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
3178 }
3179 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
3180 {
3181 writeBandWidth(radioIndex,"40MHz");
3182 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
3183 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
3184 }
3185 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
3186 {
3187 writeBandWidth(radioIndex,"40MHz");
3188 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
3189 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
3190 }
3191 else if (strcmp (channelMode,"11ACVHT80") == 0)
3192 {
3193 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
3194 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
3195 }
3196 else if (strcmp (channelMode,"11ACVHT160") == 0)
3197 {
3198 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
3199 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
developer69b61b02023-03-07 17:17:44 +08003200 }
developer72fb0bb2023-01-11 09:46:29 +08003201 else if (strcmp (channelMode,"11B") == 0)
3202 {
3203 writeBandWidth(radioIndex,"20MHz");
3204 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
3205 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
3206 }
3207 else if (strcmp (channelMode,"11G") == 0)
3208 {
3209 writeBandWidth(radioIndex,"20MHz");
3210 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
3211 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
3212 }
3213 else if (strcmp (channelMode,"11NGHT20") == 0)
3214 {
3215 writeBandWidth(radioIndex,"20MHz");
3216 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
3217 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
3218 }
3219 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
3220 {
3221 writeBandWidth(radioIndex,"40MHz");
3222 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
3223 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
3224 }
3225 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
3226 {
3227 writeBandWidth(radioIndex,"40MHz");
3228 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
3229 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
3230 }
developer69b61b02023-03-07 17:17:44 +08003231 else
developer72fb0bb2023-01-11 09:46:29 +08003232 {
3233 return RETURN_ERR;
3234 }
3235 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3236
3237 return RETURN_OK;
3238}
3239
developer0f10c772023-05-16 21:43:39 +08003240typedef enum _RT_802_11_PHY_MODE {
3241 PHY_11BG_MIXED = 0,
3242 PHY_11B = 1,
3243 PHY_11A = 2,
3244 PHY_11ABG_MIXED = 3,
3245 PHY_11G = 4,
3246 PHY_11ABGN_MIXED = 5, /* both band 5 */
3247 PHY_11N_2_4G = 6, /* 11n-only with 2.4G band 6 */
3248 PHY_11GN_MIXED = 7, /* 2.4G band 7 */
3249 PHY_11AN_MIXED = 8, /* 5G band 8 */
3250 PHY_11BGN_MIXED = 9, /* if check 802.11b. 9 */
3251 PHY_11AGN_MIXED = 10, /* if check 802.11b. 10 */
3252 PHY_11N_5G = 11, /* 11n-only with 5G band 11 */
3253 PHY_11VHT_N_ABG_MIXED = 12, /* 12 -> AC/A/AN/B/G/GN mixed */
3254 PHY_11VHT_N_AG_MIXED = 13, /* 13 -> AC/A/AN/G/GN mixed */
3255 PHY_11VHT_N_A_MIXED = 14, /* 14 -> AC/AN/A mixed in 5G band */
3256 PHY_11VHT_N_MIXED = 15, /* 15 -> AC/AN mixed in 5G band */
3257 PHY_11AX_24G = 16,
3258 PHY_11AX_5G = 17,
3259 PHY_11AX_6G = 18,
3260 PHY_11AX_24G_6G = 19,
3261 PHY_11AX_5G_6G = 20,
3262 PHY_11AX_24G_5G_6G = 21,
3263 PHY_11BE_24G = 22,
3264 PHY_11BE_5G = 23,
3265 PHY_11BE_6G = 24,
3266 PHY_11BE_24G_6G = 25,
3267 PHY_11BE_5G_6G = 26,
3268 PHY_11BE_24G_5G_6G = 27,
3269 PHY_MODE_MAX,
3270} RT_802_11_PHY_MODE;
3271
3272unsigned int puremode_to_wireless_mode(INT radioIndex, UINT pureMode)
3273{
3274 int band_idx = 0;
developerfead3972023-05-25 20:15:02 +08003275 unsigned char wireless_mode = PHY_MODE_MAX;
developer0f10c772023-05-16 21:43:39 +08003276
3277 band_idx = radio_index_to_band(radioIndex);
3278
3279 switch (band_idx) {
3280 case band_2_4:
3281 if (pureMode == (WIFI_MODE_G | WIFI_MODE_N))
3282 wireless_mode = PHY_11GN_MIXED;
3283 if (pureMode == (WIFI_MODE_B | WIFI_MODE_G | WIFI_MODE_N))
3284 wireless_mode = PHY_11BGN_MIXED;
3285 if (pureMode & WIFI_MODE_AX)
3286 wireless_mode = PHY_11AX_24G;
3287 if (pureMode & WIFI_MODE_BE)
3288 wireless_mode = PHY_11BE_24G;
3289 break;
3290 case band_5:
3291 if (pureMode == WIFI_MODE_N)
3292 wireless_mode = PHY_11N_5G;
3293 if ((pureMode == WIFI_MODE_AC) || (pureMode == (WIFI_MODE_N | WIFI_MODE_AC)))
3294 wireless_mode = PHY_11VHT_N_MIXED;
3295 if (pureMode == (WIFI_MODE_A | WIFI_MODE_N | WIFI_MODE_AC))
3296 wireless_mode = PHY_11VHT_N_A_MIXED;
3297 if (pureMode & WIFI_MODE_AX)
3298 wireless_mode = PHY_11AX_5G;
3299 if (pureMode & WIFI_MODE_BE)
3300 wireless_mode = PHY_11BE_5G;
3301 break;
3302 case band_6:
3303 if (pureMode & WIFI_MODE_AX)
3304 wireless_mode = PHY_11AX_6G;
3305 if (pureMode & WIFI_MODE_BE)
3306 wireless_mode = PHY_11BE_6G;
3307 break;
3308 default:
3309 fprintf(stderr, "%s band_idx invalid\n", __func__);
3310 break;
3311 }
3312
3313 return wireless_mode;
3314}
3315
developer72fb0bb2023-01-11 09:46:29 +08003316// Set the radio operating mode, and pure mode flag.
3317INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
3318{
developerfead3972023-05-25 20:15:02 +08003319 unsigned char wireless_mode = PHY_MODE_MAX;
developer69b61b02023-03-07 17:17:44 +08003320
developer0f10c772023-05-16 21:43:39 +08003321 char interface_name[IF_NAME_SIZE] = {0};
developerfead3972023-05-25 20:15:02 +08003322 int ret = -1;
3323 unsigned int if_idx = 0;
3324 struct unl unl_ins;
3325 struct nl_msg *msg = NULL;
3326 struct nlattr * msg_data = NULL;
3327 struct mtk_nl80211_param param;
developer72fb0bb2023-01-11 09:46:29 +08003328
developer0f10c772023-05-16 21:43:39 +08003329 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08003330
developer0f10c772023-05-16 21:43:39 +08003331 wireless_mode = puremode_to_wireless_mode(radioIndex, pureMode);
developer72fb0bb2023-01-11 09:46:29 +08003332
developer0f10c772023-05-16 21:43:39 +08003333 if (wireless_mode == PHY_MODE_MAX) {
3334 fprintf(stderr, "%s wireless_mode invalid pureMode = %x\n", __func__, pureMode);
3335 return RETURN_ERR;
3336 }
developer72fb0bb2023-01-11 09:46:29 +08003337
developer0f10c772023-05-16 21:43:39 +08003338 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3339 return RETURN_ERR;
developerfead3972023-05-25 20:15:02 +08003340
3341 if_idx = if_nametoindex(interface_name);
3342 if (!if_idx) {
3343 wifi_debug(DEBUG_ERROR,"can't finde ifname(%s) index,ERROR\n", interface_name);
3344 return RETURN_ERR;
3345 }
3346 /*init mtk nl80211 vendor cmd*/
3347 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_AP_BSS;
3348 param.if_type = NL80211_ATTR_IFINDEX;
3349 param.if_idx = if_idx;
3350
3351 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
3352 if (ret) {
3353 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
3354 return RETURN_ERR;
3355 }
3356
3357 /*add mtk vendor cmd data*/
3358 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_AP_WIRELESS_MODE, wireless_mode)) {
3359 wifi_debug(DEBUG_ERROR, "Nla put AP_WIRELESS_MODE attribute error\n");
3360 nlmsg_free(msg);
3361 goto err;
3362 }
3363 /*send mtk nl80211 vendor msg*/
3364 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
3365 if (ret) {
3366 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
3367 goto err;
3368 }
3369 /*deinit mtk nl80211 vendor msg*/
3370 mtk_nl80211_deint(&unl_ins);
3371 wifi_debug(DEBUG_NOTICE, "set cmd success.\n");
developer72fb0bb2023-01-11 09:46:29 +08003372
developer0f10c772023-05-16 21:43:39 +08003373 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3374
3375 return RETURN_OK;
developerfead3972023-05-25 20:15:02 +08003376err:
3377 mtk_nl80211_deint(&unl_ins);
3378 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
3379 return RETURN_ERR;
developer0f10c772023-05-16 21:43:39 +08003380}
3381
3382INT wifi_setRadioMode_by_dat(INT radioIndex, UINT pureMode)
3383{
developerfead3972023-05-25 20:15:02 +08003384 unsigned char wireless_mode = PHY_MODE_MAX;
developer0f10c772023-05-16 21:43:39 +08003385 char buf[MAX_BUF_SIZE] = {0};
developer0f10c772023-05-16 21:43:39 +08003386 char dat_file[MAX_BUF_SIZE] = {0};
3387 struct params params={0};
3388
3389 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, pureMode, __LINE__);
3390
3391 wireless_mode = puremode_to_wireless_mode(radioIndex, pureMode);
3392
3393 if (wireless_mode == PHY_MODE_MAX) {
3394 fprintf(stderr, "%s wireless_mode invalid pureMode = %x\n", __func__, pureMode);
3395 return RETURN_ERR;
3396 }
3397
3398 params.name = "WirelessMode";
3399 snprintf(buf, sizeof(buf), "%d", wireless_mode);
3400 params.value = buf;
3401
3402 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, radioIndex);
3403 wifi_datfileWrite(dat_file, &params, 1);
3404
developer72fb0bb2023-01-11 09:46:29 +08003405 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3406
3407 return RETURN_OK;
3408}
3409
3410INT wifi_setRadioHwMode(INT radioIndex, CHAR *hw_mode) {
3411
3412 char config_file[64] = {0};
3413 char buf[64] = {0};
3414 struct params params = {0};
3415 wifi_band band = band_invalid;
3416
3417 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3418
3419 band = wifi_index_to_band(radioIndex);
3420
3421 if (strncmp(hw_mode, "a", 1) == 0 && (band != band_5 && band != band_6))
3422 return RETURN_ERR;
3423 else if ((strncmp(hw_mode, "b", 1) == 0 || strncmp(hw_mode, "g", 1) == 0) && band != band_2_4)
3424 return RETURN_ERR;
3425 else if ((strncmp(hw_mode, "a", 1) && strncmp(hw_mode, "b", 1) && strncmp(hw_mode, "g", 1)) || band == band_invalid)
3426 return RETURN_ERR;
3427
3428 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3429 params.name = "hw_mode";
3430 params.value = hw_mode;
3431 wifi_hostapdWrite(config_file, &params, 1);
3432 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3433
3434 if (band == band_2_4) {
3435 if (strncmp(hw_mode, "b", 1) == 0) {
3436 wifi_setRadioMode(radioIndex, "20MHz", WIFI_MODE_B);
3437 snprintf(buf, sizeof(buf), "%s", "1,2,5.5,11");
3438 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
3439 snprintf(buf, sizeof(buf), "%s", "1,2");
3440 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
3441 } else {
3442 // We don't set mode here, because we don't know whitch mode should be set (g, n or ax?).
3443
3444 snprintf(buf, sizeof(buf), "%s", "6,9,12,18,24,36,48,54");
3445 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
3446 snprintf(buf, sizeof(buf), "%s", "6,12,24");
3447 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
3448 }
3449 }
3450
3451 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3452 return RETURN_OK;
3453}
3454
3455INT wifi_setNoscan(INT radioIndex, CHAR *noscan)
3456{
3457 char config_file[64] = {0};
3458 struct params params = {0};
3459 wifi_band band = band_invalid;
3460
3461 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3462
3463 band = wifi_index_to_band(radioIndex);
3464 if (band != band_2_4)
3465 return RETURN_OK;
3466
3467 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3468 params.name = "noscan";
3469 params.value = noscan;
3470 wifi_hostapdWrite(config_file, &params, 1);
3471 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3472
3473 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3474 return RETURN_OK;
3475}
3476
3477//Get the list of supported channel. eg: "1-11"
3478//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.
3479INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
3480{
3481 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer69b61b02023-03-07 17:17:44 +08003482 if (NULL == output_string)
developer72fb0bb2023-01-11 09:46:29 +08003483 return RETURN_ERR;
3484 char cmd[256] = {0};
3485 char buf[128] = {0};
3486 BOOL dfs_enable = false;
3487 int phyId = 0;
3488
3489 // Parse possible channel number and separate them with commas.
3490 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
3491 phyId = radio_index_to_phy(radioIndex);
3492 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
3493 if (dfs_enable)
3494 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 +08003495 else
developer72fb0bb2023-01-11 09:46:29 +08003496 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);
3497
3498 _syscmd(cmd,buf,sizeof(buf));
developerdaf24792023-06-06 11:40:04 +08003499 strncpy(output_string, buf, strlen(buf));
developer72fb0bb2023-01-11 09:46:29 +08003500
3501 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3502 return RETURN_OK;
3503}
developerd1824452023-05-18 12:30:04 +08003504//Getting current radio extension channel
3505INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
3506{
3507 CHAR buf[150] = {0};
developerd1824452023-05-18 12:30:04 +08003508
3509 wifi_datfileRead(file, "HT_EXTCHA", buf, sizeof(buf));
developer262f4cb2023-05-24 12:22:04 +08003510 if (strncmp(buf, "Below", 5) == 0) //below
developerd1824452023-05-18 12:30:04 +08003511 strcpy(Value,"BelowControlChannel");
developer262f4cb2023-05-24 12:22:04 +08003512 if(strncmp(buf, "Above", 5) == 0) //above
developerd1824452023-05-18 12:30:04 +08003513 strcpy(Value,"AboveControlChannel");
3514 return RETURN_OK;
3515}
developerf6a87542023-05-16 15:47:28 +08003516
developer72fb0bb2023-01-11 09:46:29 +08003517//Get the list for used channel. eg: "1,6,9,11"
3518//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.
3519INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
3520{
3521 char interface_name[16] = {0};
3522 char cmd[128] = {0};
3523 char buf[128] = {0};
3524 char config_file[64] = {0};
3525 int channel = 0;
3526 int freq = 0;
3527 int bandwidth = 0;
3528 int center_freq = 0;
3529 int center_channel = 0;
3530 int channel_delta = 0;
3531 wifi_band band = band_invalid;
3532
3533 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3534
3535 if (NULL == output_string)
3536 return RETURN_ERR;
3537
3538 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3539 return RETURN_ERR;
3540 sprintf(cmd, "iw %s info | grep channel | sed -e 's/[^0-9 ]//g'", interface_name);
3541 _syscmd(cmd, buf, sizeof(buf));
3542 if (strlen(buf) == 0) {
3543 fprintf(stderr, "%s: failed to get channel information from iw.\n", __func__);
3544 return RETURN_ERR;
3545 }
3546 sscanf(buf, "%d %d %d %*d %d", &channel, &freq, &bandwidth, &center_freq);
3547
3548 if (bandwidth == 20) {
3549 snprintf(output_string, 256, "%d", channel);
3550 return RETURN_OK;
3551 }
3552
3553 center_channel = ieee80211_frequency_to_channel(center_freq);
3554
3555 band = wifi_index_to_band(radioIndex);
3556 if (band == band_2_4 && bandwidth == 40) {
developerd1824452023-05-18 12:30:04 +08003557 sprintf(config_file, "%s%d.dat", LOGAN_DAT_FILE, band);
developer72fb0bb2023-01-11 09:46:29 +08003558 memset(buf, 0, sizeof(buf));
3559 wifi_halgetRadioExtChannel(config_file, buf); // read ht_capab for HT40+ or -
3560
3561 if (strncmp(buf, "AboveControlChannel", strlen("AboveControlChannel")) == 0 && channel < 10) {
3562 snprintf(output_string, 256, "%d,%d", channel, channel+4);
3563 } else if (strncmp(buf, "BelowControlChannel", strlen("BelowControlChannel")) == 0 && channel > 4) {
3564 snprintf(output_string, 256, "%d,%d", channel-4, channel);
3565 } else {
3566 fprintf(stderr, "%s: invalid channel %d set with %s\n.", __func__, channel, buf);
3567 return RETURN_ERR;
3568 }
3569 } else if (band == band_5 || band == band_6){
3570 // 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 +08003571 // 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 +08003572 channel_delta = (bandwidth-20)/10;
developerd1824452023-05-18 12:30:04 +08003573 memset(output_string, 0, 256);
3574 for (int i = center_channel-channel_delta; i <= center_channel+channel_delta; i+=4) {
3575 // If i is not the last channel, we add a comma.
3576 snprintf(buf, sizeof(buf), "%d%s", i, i==center_channel+channel_delta?"":",");
3577 strncat(output_string, buf, strlen(buf));
3578 }
developer72fb0bb2023-01-11 09:46:29 +08003579 } else
3580 return RETURN_ERR;
3581
3582 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3583 return RETURN_OK;
3584}
3585
developer69b61b02023-03-07 17:17:44 +08003586//Get the running channel number
developerd1824452023-05-18 12:30:04 +08003587INT wifi_getRadioChannel(INT radioIndex, ULONG *output_ulong) //RDKB
developer72fb0bb2023-01-11 09:46:29 +08003588{
3589 char channel_str[16] = {0};
3590 char config_file[128] = {0};
developer47a56bf2023-05-30 13:38:57 +08003591 char buf[MAX_BUF_SIZE] = {0};
3592 char cmd[MAX_CMD_SIZE] = {0};
3593 char interface_name[IF_NAME_SIZE] = {0};
developerd1824452023-05-18 12:30:04 +08003594 wifi_band band = band_invalid;
developer47a56bf2023-05-30 13:38:57 +08003595 ULONG iwChannel = 0;
3596
developer72fb0bb2023-01-11 09:46:29 +08003597 if (output_ulong == NULL)
3598 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08003599 band = wifi_index_to_band(radioIndex);
3600 snprintf(config_file, sizeof(config_file), "%s%d.dat", LOGAN_DAT_FILE, band);
3601 wifi_datfileRead(config_file, "Channel", channel_str, sizeof(channel_str));
developer72fb0bb2023-01-11 09:46:29 +08003602 *output_ulong = strtoul(channel_str, NULL, 10);
developer47a56bf2023-05-30 13:38:57 +08003603 if (*output_ulong == 0) {
3604 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3605 return RETURN_ERR;
3606 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2", interface_name);
3607 _syscmd(cmd,buf,sizeof(buf));
3608 sscanf(buf, "%lu", &iwChannel);
3609 *output_ulong = iwChannel;
3610 }
developer72fb0bb2023-01-11 09:46:29 +08003611
3612 return RETURN_OK;
3613}
3614
developer72fb0bb2023-01-11 09:46:29 +08003615INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
3616{
3617 char cmd[1024] = {0}, buf[5] = {0};
3618 char interface_name[16] = {0};
3619
3620 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3621 if (NULL == output_ulong)
3622 return RETURN_ERR;
3623
developer47a56bf2023-05-30 13:38:57 +08003624 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72fb0bb2023-01-11 09:46:29 +08003625 return RETURN_ERR;
developer47a56bf2023-05-30 13:38:57 +08003626
3627 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2", interface_name);
developer72fb0bb2023-01-11 09:46:29 +08003628 _syscmd(cmd,buf,sizeof(buf));
3629 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
3630 if (*output_ulong == 0) {
3631 return RETURN_ERR;
3632 }
3633
3634 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3635 return RETURN_OK;
3636}
developer72fb0bb2023-01-11 09:46:29 +08003637//Storing the previous channel value
3638INT wifi_storeprevchanval(INT radioIndex)
3639{
3640 char buf[256] = {0};
3641 char output[4]={'\0'};
3642 char config_file[MAX_BUF_SIZE] = {0};
developerd1824452023-05-18 12:30:04 +08003643 wifi_band band = band_invalid;
3644
3645 band = wifi_index_to_band(radioIndex);
3646 if (band == band_invalid) {
3647 return RETURN_ERR;
3648 wifi_dbg_printf("[%s]: Invalid radio index", __func__);
3649 }
3650 snprintf(config_file, sizeof(config_file), "%s%d.dat",LOGAN_DAT_FILE, band);
3651 wifi_datfileRead(config_file, "Channel", output, sizeof(output));
3652
3653 if(band == band_2_4)
developer72fb0bb2023-01-11 09:46:29 +08003654 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
developerd1824452023-05-18 12:30:04 +08003655 else if(band == band_5)
developer72fb0bb2023-01-11 09:46:29 +08003656 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
developerd1824452023-05-18 12:30:04 +08003657 else
3658 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval6G_AutoChannelEnable");
developer72fb0bb2023-01-11 09:46:29 +08003659 system(buf);
3660 Radio_flag = FALSE;
3661 return RETURN_OK;
3662}
3663
3664//Set the running channel number
3665INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
3666{
3667 // We only write hostapd config here
3668 char str_channel[8]={0};
3669 char *list_channel;
developer72fb0bb2023-01-11 09:46:29 +08003670 char possible_channels[256] = {0};
developerd1824452023-05-18 12:30:04 +08003671 char config_file_dat[128] = {0};
developerd1824452023-05-18 12:30:04 +08003672 struct params dat = {0};
3673 struct params acs = {0};
3674 wifi_band band = band_invalid;
3675 bool acs_channel = false;
developer72fb0bb2023-01-11 09:46:29 +08003676
3677 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3678
developerd1824452023-05-18 12:30:04 +08003679 if (channel == 0)
3680 acs_channel = true;
developer72fb0bb2023-01-11 09:46:29 +08003681 // Check valid
3682 sprintf(str_channel, "%lu", channel);
3683
developerd1824452023-05-18 12:30:04 +08003684
developer72fb0bb2023-01-11 09:46:29 +08003685 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
3686 list_channel = strtok(possible_channels, ",");
3687 while(true)
3688 {
3689 if(list_channel == NULL) { // input not in the list
3690 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
3691 return RETURN_ERR;
3692 }
3693 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
3694 break;
3695 list_channel = strtok(NULL, ",");
3696 }
developerd1824452023-05-18 12:30:04 +08003697 /*
developer72fb0bb2023-01-11 09:46:29 +08003698 list.name = "channel";
3699 list.value = str_channel;
3700 wifi_getMaxRadioNumber(&max_radio_num);
3701 for(int i=0; i<=MAX_APS/max_radio_num;i++)
3702 {
3703 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
3704 wifi_hostapdWrite(config_file, &list, 1);
3705 }
developerd1824452023-05-18 12:30:04 +08003706 */
3707 dat.name = "Channel";
3708 dat.value = str_channel;
3709 band = wifi_index_to_band(radioIndex);
3710 snprintf(config_file_dat, sizeof(config_file_dat), "%s%d.dat", LOGAN_DAT_FILE, band);
3711 wifi_datfileWrite(config_file_dat, &dat, 1);
3712 if (acs_channel == true) {
3713 acs.name = "AutoChannelSelect";
3714 acs.value = "3";
3715 } else {
3716 acs.name = "AutoChannelSelect";
3717 acs.value = "0";
3718 }
3719 wifi_datfileWrite(config_file_dat, &acs, 1);
developerc0772e62023-05-18 15:10:48 +08003720 wifi_reloadAp(radioIndex);
developer72fb0bb2023-01-11 09:46:29 +08003721 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3722 return RETURN_OK;
3723}
3724
3725INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
3726{
3727 struct params list[2];
3728 char str_idx[16];
3729 char config_file[64];
3730 int max_num_radios = 0;
3731 wifi_band band = band_invalid;
3732
3733 band = wifi_index_to_band(radioIndex);
3734 if (band == band_2_4)
3735 return RETURN_OK;
3736
3737 snprintf(str_idx, sizeof(str_idx), "%lu", channel);
3738 list[0].name = "vht_oper_centr_freq_seg0_idx";
3739 list[0].value = str_idx;
3740 list[1].name = "he_oper_centr_freq_seg0_idx";
3741 list[1].value = str_idx;
3742
3743 wifi_getMaxRadioNumber(&max_num_radios);
3744 for(int i=0; i<=MAX_APS/max_num_radios; i++)
3745 {
3746 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
3747 if (band == band_6)
3748 wifi_hostapdWrite(config_file, &list[1], 1);
3749 else
3750 wifi_hostapdWrite(config_file, list, 2);
3751 }
3752
3753 return RETURN_OK;
3754}
3755
3756//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
3757//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
3758INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
3759{
3760 //Set to wifi config only. Wait for wifi reset to apply.
developer72fb0bb2023-01-11 09:46:29 +08003761 ULONG Value = 0;
developer47a56bf2023-05-30 13:38:57 +08003762 char config_file_dat[128] = {0};
3763 struct params acs = {0};
3764 wifi_band band = band_invalid;
3765
3766 if(enable == TRUE) {
developer72fb0bb2023-01-11 09:46:29 +08003767 wifi_setRadioChannel(radioIndex,Value);
developer47a56bf2023-05-30 13:38:57 +08003768 } else {
3769 acs.name = "AutoChannelSelect";
3770 acs.value = "0";
3771 band = wifi_index_to_band(radioIndex);
3772 snprintf(config_file_dat, sizeof(config_file_dat), "%s%d.dat", LOGAN_DAT_FILE, band);
3773 wifi_datfileWrite(config_file_dat, &acs, 1);
developer72fb0bb2023-01-11 09:46:29 +08003774 }
3775 return RETURN_OK;
3776}
3777
3778INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
3779{
3780 if (output_bool == NULL)
3781 return RETURN_ERR;
3782
3783 *output_bool = TRUE;
3784
3785 return RETURN_OK;
3786}
3787
3788INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
3789{
developer69b61b02023-03-07 17:17:44 +08003790 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08003791 return RETURN_ERR;
3792 *output_bool=FALSE;
3793 return RETURN_OK;
3794}
3795
3796INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
3797{
developer69b61b02023-03-07 17:17:44 +08003798 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08003799 return RETURN_ERR;
3800 *output_bool=FALSE;
3801 return RETURN_OK;
3802}
3803
3804INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
3805{
3806 //Set to wifi config only. Wait for wifi reset to apply.
3807 return RETURN_OK;
3808}
3809
3810INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
3811{
3812 return RETURN_OK;
3813}
3814
3815INT wifi_factoryResetAP(int apIndex)
3816{
developer47cc27a2023-05-17 23:09:58 +08003817 char ap_config_file[MAX_CMD_SIZE] = {0};
3818 char cmd[MAX_CMD_SIZE] = {0};
3819 char ret_buf[MAX_BUF_SIZE] = {0};
3820 int radio_idx = 0;
3821 int bss_idx = 0;
3822 char ssid[32] = {0};
3823 char interface[IF_NAME_SIZE] = {0};
3824 char psk_file[MAX_CMD_SIZE] = {0};
3825 struct params params[3] = {0};
developer72fb0bb2023-01-11 09:46:29 +08003826
3827 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3828
developer47cc27a2023-05-17 23:09:58 +08003829 /*del old config file*/
3830 snprintf(ap_config_file, MAX_CMD_SIZE, "%s%d.conf", CONFIG_PREFIX, apIndex);
3831 snprintf(cmd, MAX_CMD_SIZE, "rm %s", ap_config_file);
3832 _syscmd(cmd, ret_buf, sizeof(ret_buf));
developer72fb0bb2023-01-11 09:46:29 +08003833
developer47cc27a2023-05-17 23:09:58 +08003834 memset(cmd, 0, sizeof(cmd));
3835 memset(ret_buf, 0, sizeof(ret_buf));
developer72fb0bb2023-01-11 09:46:29 +08003836
developer47cc27a2023-05-17 23:09:58 +08003837 vap_index_to_array_index(apIndex, &radio_idx, &bss_idx);
3838
3839 /*prepare new config file*/
developere740c2a2023-05-23 18:34:32 +08003840 snprintf(cmd, sizeof(cmd), "cp /etc/hostapd-%s.conf %s", wifi_band_str[radio_idx], ap_config_file);
developer47cc27a2023-05-17 23:09:58 +08003841 _syscmd(cmd, ret_buf, sizeof(ret_buf));
3842
3843 if (radio_idx == band_2_4) {
3844 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_2G, bss_idx);
3845 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI2G, bss_idx);
3846 } else if (radio_idx == band_5) {
3847 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_5G, bss_idx);
3848 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI5G, bss_idx);
3849 } else if (radio_idx == band_6) {
3850 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_6G, bss_idx);
3851 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI6G, bss_idx);
3852 }
3853
3854 /* fix wpa_psk_file path */
3855 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", apIndex);
3856
3857 params[0].name = "ssid";
3858 params[0].value = ssid;
3859 params[1].name = "interface";
3860 params[1].value = interface;
3861 params[2].name = "wpa_psk_file";
3862 params[2].value = psk_file;
3863
3864 wifi_hostapdWrite(ap_config_file, params, 3);
3865
3866 /*clear psk file*/
3867 memset(cmd, 0, sizeof(cmd));
3868 memset(ret_buf, 0, sizeof(ret_buf));
3869
3870 snprintf(psk_file, sizeof(psk_file), "%s%d.psk", PSK_FILE, apIndex);
3871
3872 if (access(psk_file, F_OK) != 0) {
3873 snprintf(cmd, MAX_CMD_SIZE, "touch %s", psk_file);
3874 _syscmd(cmd, ret_buf, sizeof(ret_buf));
3875 } else {
3876 snprintf(cmd, MAX_CMD_SIZE, "echo '' > %s", psk_file);
3877 _syscmd(cmd, ret_buf, sizeof(ret_buf));
3878 }
3879
developer429ba832023-05-31 11:03:35 +08003880 wifi_setApEnable(apIndex, FALSE);
3881 wifi_setApEnable(apIndex, TRUE);
developer47cc27a2023-05-17 23:09:58 +08003882 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3883
3884 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08003885}
3886
3887//To set Band Steering AP group
3888//To-do
3889INT wifi_setBandSteeringApGroup(char *ApGroup)
3890{
3891 return RETURN_OK;
3892}
3893
3894INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
3895{
3896 char config_file[128] = {'\0'};
3897 char buf[128] = {'\0'};
3898
3899 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3900 if (dtimInterval == NULL)
3901 return RETURN_ERR;
3902
3903 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developer885b56c2023-05-22 15:02:46 +08003904 wifi_hostapdRead(config_file, "dtim_period", buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08003905
3906 if (strlen(buf) == 0) {
3907 *dtimInterval = 2;
3908 } else {
3909 *dtimInterval = strtoul(buf, NULL, 10);
3910 }
3911
3912 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3913 return RETURN_OK;
3914}
3915
3916INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
3917{
3918 struct params params={0};
3919 char config_file[MAX_BUF_SIZE] = {'\0'};
3920 char buf[MAX_BUF_SIZE] = {'\0'};
3921
3922 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3923 if (dtimInterval < 1 || dtimInterval > 255) {
3924 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
3925 return RETURN_ERR;
3926 }
developer69b61b02023-03-07 17:17:44 +08003927
developer72fb0bb2023-01-11 09:46:29 +08003928 params.name = "dtim_period";
3929 snprintf(buf, sizeof(buf), "%d", dtimInterval);
3930 params.value = buf;
3931
3932 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
3933 wifi_hostapdWrite(config_file, &params, 1);
3934 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3935
3936 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3937 return RETURN_OK;
3938}
3939
3940//Check if the driver support the Dfs
3941INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
3942{
3943 wifi_band band = band_invalid;
developer69b61b02023-03-07 17:17:44 +08003944 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08003945 return RETURN_ERR;
3946 *output_bool=FALSE;
3947
3948 band = wifi_index_to_band(radioIndex);
3949 if (band == band_5)
3950 *output_bool = TRUE;
3951 return RETURN_OK;
3952}
3953
3954//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.
3955//The value of this parameter is a comma seperated list of channel number
3956INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
3957{
developer69b61b02023-03-07 17:17:44 +08003958 if (NULL == output_pool)
developer72fb0bb2023-01-11 09:46:29 +08003959 return RETURN_ERR;
3960 if (radioIndex==1)
developer69b61b02023-03-07 17:17:44 +08003961 return RETURN_OK;//TODO need to handle for 5GHz band, i think
developer72fb0bb2023-01-11 09:46:29 +08003962 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
3963
3964 return RETURN_OK;
3965}
3966
3967INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
3968{
3969 //Set to wifi config. And apply instantly.
3970 return RETURN_OK;
3971}
3972
3973INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
3974{
developer69b61b02023-03-07 17:17:44 +08003975 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
developer72fb0bb2023-01-11 09:46:29 +08003976 return RETURN_ERR;
3977 *output_interval_seconds=1800;
3978 *output_dwell_milliseconds=40;
3979
3980 return RETURN_OK;
3981}
3982
3983INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
3984{
3985 //Set to wifi config. And apply instantly.
3986 return RETURN_OK;
3987}
3988
3989INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
3990{
3991 if (output_bool == NULL)
3992 return RETURN_ERR;
developer69b61b02023-03-07 17:17:44 +08003993 *output_bool = true;
3994 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08003995}
3996
3997INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
3998{
3999 return RETURN_OK;
4000}
4001
4002//Get the Dfs enable status
4003INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
4004{
4005 char buf[16] = {0};
developerd1824452023-05-18 12:30:04 +08004006 char config_file_dat[128] = {0};
developerd1824452023-05-18 12:30:04 +08004007 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08004008
4009 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4010
4011 if (output_bool == NULL)
4012 return RETURN_ERR;
developerf6a87542023-05-16 15:47:28 +08004013 *output_bool = TRUE; // default
developerd1824452023-05-18 12:30:04 +08004014 band = wifi_index_to_band(radioIndex);
4015 snprintf(config_file_dat, sizeof(config_file_dat), "%s%d.dat", LOGAN_DAT_FILE, band);
4016
developer262f4cb2023-05-24 12:22:04 +08004017 wifi_datfileRead(config_file_dat, "DfsEnable", buf, sizeof(buf));
developerd1824452023-05-18 12:30:04 +08004018
4019 if (strncmp(buf, "0", 1) == 0)
4020 *output_bool = FALSE;
developer72fb0bb2023-01-11 09:46:29 +08004021 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4022 return RETURN_OK;
4023}
4024
4025//Set the Dfs enable status
4026INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
4027{
developerd1824452023-05-18 12:30:04 +08004028 char config_dat_file[128] = {0};
developer72fb0bb2023-01-11 09:46:29 +08004029 FILE *f = NULL;
developerd1824452023-05-18 12:30:04 +08004030 struct params dat = {0};
4031 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08004032
4033 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4034
4035 f = fopen(DFS_ENABLE_FILE, "w");
4036 if (f == NULL)
4037 return RETURN_ERR;
4038 fprintf(f, "%d", enable);
4039 fclose(f);
4040
developer72fb0bb2023-01-11 09:46:29 +08004041 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
4042
developerd1824452023-05-18 12:30:04 +08004043 dat.name = "DfsEnable";
developer262f4cb2023-05-24 12:22:04 +08004044 dat.value = enable?"1":"0";
developerd1824452023-05-18 12:30:04 +08004045 band = wifi_index_to_band(radioIndex);
4046 snprintf(config_dat_file, sizeof(config_dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
4047 wifi_datfileWrite(config_dat_file, &dat, 1);
developer72fb0bb2023-01-11 09:46:29 +08004048 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4049 return RETURN_OK;
4050}
4051
4052//Check if the driver support the AutoChannelRefreshPeriod
4053INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
4054{
developer69b61b02023-03-07 17:17:44 +08004055 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08004056 return RETURN_ERR;
4057 *output_bool=FALSE; //not support
4058
4059 return RETURN_OK;
4060}
4061
4062//Get the ACS refresh period in seconds
4063INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
4064{
developer69b61b02023-03-07 17:17:44 +08004065 if (NULL == output_ulong)
developer72fb0bb2023-01-11 09:46:29 +08004066 return RETURN_ERR;
4067 *output_ulong=300;
4068
4069 return RETURN_OK;
4070}
4071
4072//Set the ACS refresh period in seconds
4073INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
4074{
4075 return RETURN_ERR;
4076}
4077
4078//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
4079//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.
4080INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
4081{
developer8666b312023-03-24 14:05:31 +08004082 char cmd[MAX_CMD_SIZE] = {0}, buf[64] = {0};
developer72fb0bb2023-01-11 09:46:29 +08004083 char extchannel[128] = {0};
developer8666b312023-03-24 14:05:31 +08004084 char interface_name[64] = {0};
4085 int ret = 0, len=0;
developer72fb0bb2023-01-11 09:46:29 +08004086 BOOL radio_enable = FALSE;
4087 wifi_band band;
4088
4089 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4090
developerd1824452023-05-18 12:30:04 +08004091 if (NULL == output_string) {
4092 WIFI_ENTRY_EXIT_DEBUG("output_string is nuill %s: %d \n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08004093 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08004094 }
4095 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR) {
4096 WIFI_ENTRY_EXIT_DEBUG("wifi_getRadioEnable failed %s: %d \n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08004097 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08004098 }
4099 if (radio_enable != TRUE) {
4100 WIFI_ENTRY_EXIT_DEBUG("Radio %d is not enable failed %s: %d \n", radioIndex, __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08004101 return RETURN_OK;
developerd1824452023-05-18 12:30:04 +08004102 }
developer8666b312023-03-24 14:05:31 +08004103 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4104 return RETURN_ERR;
4105 /*IW command get BW320 to do*/
developerd1824452023-05-18 12:30:04 +08004106
developer8666b312023-03-24 14:05:31 +08004107 snprintf(cmd, sizeof(cmd),"iw dev %s info | grep 'width' | cut -d ' ' -f6 | tr -d '\\n'", interface_name);
4108 ret = _syscmd(cmd, buf, sizeof(buf));
4109 len = strlen(buf);
4110 if((ret != 0) || (len == 0))
4111 {
4112 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
4113 return RETURN_ERR;
4114 }
4115
developer72fb0bb2023-01-11 09:46:29 +08004116 band = wifi_index_to_band(radioIndex);
developer8666b312023-03-24 14:05:31 +08004117 if (band == band_2_4 && strncmp(buf, "20", 2) == 0) {
developer72fb0bb2023-01-11 09:46:29 +08004118 wifi_getRadioExtChannel(radioIndex, extchannel);
developer8666b312023-03-24 14:05:31 +08004119 if (strncmp(extchannel, "Auto", 4) != 0) // not auto means we have set HT40+/-
4120 snprintf(buf, sizeof(buf), "40");
developer72fb0bb2023-01-11 09:46:29 +08004121 }
developer8666b312023-03-24 14:05:31 +08004122 snprintf(output_string, 64, "%sMHz", buf);
developer72fb0bb2023-01-11 09:46:29 +08004123 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4124
4125 return RETURN_OK;
developerfead3972023-05-25 20:15:02 +08004126}
4127
4128enum mwctl_chan_width {
4129 MWCTL_CHAN_WIDTH_20,
4130 MWCTL_CHAN_WIDTH_40,
4131 MWCTL_CHAN_WIDTH_80,
4132 MWCTL_CHAN_WIDTH_160,
4133 MWCTL_CHAN_WIDTH_320,
4134};
4135
4136struct bw_option {
4137 unsigned int bandwith;
4138 enum mwctl_chan_width mode;
4139};
4140
4141struct bw_option bw_opt[] = {
4142 {20, MWCTL_CHAN_WIDTH_20},
4143 {40, MWCTL_CHAN_WIDTH_40},
4144 {80, MWCTL_CHAN_WIDTH_80},
4145 {160, MWCTL_CHAN_WIDTH_160},
4146 {320, MWCTL_CHAN_WIDTH_320},
4147};
4148
4149INT wifi_setChannel_netlink(INT radioIndex, UINT* channel, UINT *bandwidth)
4150{
4151 int ret = -1;
4152 int i;
4153 struct unl unl_ins;
4154 struct nl_msg *msg = NULL;
4155 struct nlattr * msg_data = NULL;
4156 struct mtk_nl80211_param param;
4157 bool b_match = FALSE;
4158
4159 /*init mtk nl80211 vendor cmd*/
4160 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_CHANNEL;
4161 param.if_type = NL80211_ATTR_WIPHY;
4162 param.if_idx = radio_index_to_phy(radioIndex);
4163
4164 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
4165 if (ret) {
4166 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
4167 return RETURN_ERR;
4168 }
4169
4170 /*add mtk vendor cmd data*/
4171 if (channel != NULL)
4172 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_CHAN_SET_NUM, *channel)) {
4173 wifi_debug(DEBUG_ERROR, "Nla put CHAN_SET_NUM attribute error\n");
4174 nlmsg_free(msg);
4175 goto err;
4176 }
4177
4178 if (bandwidth != NULL) {
4179 for (i = 0; i < (sizeof(bw_opt)/sizeof(bw_opt[0])); i++) {
4180 if (bw_opt[i].bandwith == *bandwidth) {
4181 b_match = true;
4182 if (nla_put_u32(msg, MTK_NL80211_VENDOR_ATTR_CHAN_SET_BW, bw_opt[i].mode)) {
4183 wifi_debug(DEBUG_ERROR, "Nla put CHAN_SET_BW attribute error\n");
4184 nlmsg_free(msg);
4185 goto err;
4186 }
4187 break;
4188 }
4189 }
4190
4191 if (!b_match) {
4192 wifi_debug(DEBUG_ERROR, "Cannot find bandwith error\n");
4193 nlmsg_free(msg);
4194 goto err;
4195 }
4196 }
4197
4198 /*send mtk nl80211 vendor msg*/
4199 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
4200 if (ret) {
4201 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
4202 goto err;
4203 }
4204 /*deinit mtk nl80211 vendor msg*/
4205 mtk_nl80211_deint(&unl_ins);
4206 wifi_debug(DEBUG_NOTICE, "set cmd success.\n");
4207 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4208
4209 return RETURN_OK;
4210err:
4211 mtk_nl80211_deint(&unl_ins);
4212 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
4213 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08004214}
developerfead3972023-05-25 20:15:02 +08004215
developer72fb0bb2023-01-11 09:46:29 +08004216//Set the Operating Channel Bandwidth.
4217INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
4218{
4219 char config_file[128];
developerd1824452023-05-18 12:30:04 +08004220 char ht_value[16];
4221 char vht_value[16];
4222 char eht_value[16];
4223 struct params dat[3];
4224 wifi_band band = band_invalid;
developerfead3972023-05-25 20:15:02 +08004225 unsigned int bw = 20;
4226 int ret = 0;
developer72fb0bb2023-01-11 09:46:29 +08004227
4228 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4229
4230 if(NULL == bandwidth)
4231 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08004232 band = wifi_index_to_band(radioIndex);
developer72fb0bb2023-01-11 09:46:29 +08004233
developerd1824452023-05-18 12:30:04 +08004234 if(strstr(bandwidth,"320") != NULL) {
4235 snprintf(ht_value, sizeof(ht_value), "%d", HT_BW_40);
4236 snprintf(vht_value, sizeof(vht_value), "%d", VHT_BW_160);
4237 snprintf(eht_value, sizeof(eht_value), "%d", EHT_BW_320);
developer262f4cb2023-05-24 12:22:04 +08004238 bw = 320;
developerd1824452023-05-18 12:30:04 +08004239 } else if(strstr(bandwidth,"160") != NULL) {
4240 snprintf(ht_value, sizeof(ht_value), "%d", HT_BW_40);
4241 snprintf(vht_value, sizeof(vht_value), "%d", VHT_BW_160);
4242 snprintf(eht_value, sizeof(eht_value), "%d", EHT_BW_160);
developer262f4cb2023-05-24 12:22:04 +08004243 bw = 160;
developerd1824452023-05-18 12:30:04 +08004244 } else if(strstr(bandwidth,"80") != NULL) {
4245 snprintf(ht_value, sizeof(ht_value), "%d", HT_BW_40);
4246 snprintf(vht_value, sizeof(vht_value), "%d", VHT_BW_80);
4247 snprintf(eht_value, sizeof(eht_value), "%d", EHT_BW_80);
developer262f4cb2023-05-24 12:22:04 +08004248 bw = 80;
developerd1824452023-05-18 12:30:04 +08004249 } else if(strstr(bandwidth,"40") != NULL) {
4250 snprintf(ht_value, sizeof(ht_value), "%d", HT_BW_40);
4251 snprintf(vht_value, sizeof(vht_value), "%d", VHT_BW_2040);
4252 snprintf(eht_value, sizeof(eht_value), "%d", EHT_BW_40);
developerfead3972023-05-25 20:15:02 +08004253 bw = 40;
developerd1824452023-05-18 12:30:04 +08004254 } else if(strstr(bandwidth,"20") != NULL) {
4255 snprintf(ht_value, sizeof(ht_value), "%d", HT_BW_20);
4256 snprintf(vht_value, sizeof(vht_value), "%d", VHT_BW_2040);
4257 snprintf(eht_value, sizeof(eht_value), "%d", EHT_BW_20);
developer262f4cb2023-05-24 12:22:04 +08004258 bw = 20;
developerd1824452023-05-18 12:30:04 +08004259 } else {
developer72fb0bb2023-01-11 09:46:29 +08004260 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
4261 return RETURN_ERR;
4262 }
4263
developerd1824452023-05-18 12:30:04 +08004264 snprintf(config_file, sizeof(config_file), "%s%d.dat", LOGAN_DAT_FILE, band);
4265 dat[0].name = "HT_BW";
4266 dat[0].value = ht_value;
4267 dat[1].name = "VHT_BW";
4268 dat[1].value = vht_value;
4269 dat[2].name = "EHT_ApBw";
4270 dat[2].value = eht_value;
4271 wifi_datfileWrite(config_file, dat, 3);
developerfead3972023-05-25 20:15:02 +08004272 ret = wifi_setChannel_netlink(radioIndex, NULL, &bw);
4273 if (ret != RETURN_OK) {
4274 fprintf(stderr, "%s: wifi_setChannel return error.\n", __func__);
4275 return RETURN_ERR;
4276 }
developer72fb0bb2023-01-11 09:46:29 +08004277
4278 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4279 return RETURN_OK;
4280}
4281
developer72fb0bb2023-01-11 09:46:29 +08004282//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
4283//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.
4284INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
4285{
4286 char config_file[64] = {0};
developerd1824452023-05-18 12:30:04 +08004287 char config_dat_file[64] = {0};
developer72fb0bb2023-01-11 09:46:29 +08004288 char mode_str[16] = {0};
4289 char buf[64] = {0};
developerd1824452023-05-18 12:30:04 +08004290 char cmd[MAX_CMD_SIZE] = {0};
4291 char interface_name[64] = {0};
4292 int ret = 0, len=0;
developer72fb0bb2023-01-11 09:46:29 +08004293 wifi_band band;
developerd1824452023-05-18 12:30:04 +08004294 ULONG channel = 0;
4295 int centr_channel = 0;
developer72fb0bb2023-01-11 09:46:29 +08004296 UINT mode_map = 0;
developerd1824452023-05-18 12:30:04 +08004297 int freq=0;
developer72fb0bb2023-01-11 09:46:29 +08004298
4299 if (output_string == NULL)
4300 return RETURN_ERR;
4301
4302 wifi_getRadioMode(radioIndex, mode_str, &mode_map);
4303
4304 band = wifi_index_to_band(radioIndex);
4305 if (band == band_invalid)
4306 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08004307 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4308 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08004309
4310 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4311
4312 snprintf(output_string, 64, "Auto");
developer23e71282023-01-18 10:25:19 +08004313 if (band == band_2_4 || (!(mode_map&WIFI_MODE_AC) && !(mode_map&WIFI_MODE_AX))) {
developerd1824452023-05-18 12:30:04 +08004314 // 2G band or ac and ax mode is disable, we will check HT_EXTCHA
4315 snprintf(config_dat_file, sizeof(config_dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
4316 wifi_halgetRadioExtChannel(config_dat_file, output_string);
developer23e71282023-01-18 10:25:19 +08004317 if (!(mode_map&WIFI_MODE_N))
developer72fb0bb2023-01-11 09:46:29 +08004318 snprintf(output_string, 64, "Auto");
4319 } else {
4320 // 5G and 6G band with ac or ax mode.
4321 wifi_getRadioChannel(radioIndex, &channel);
developerd1824452023-05-18 12:30:04 +08004322 snprintf(cmd, sizeof(cmd),"iw dev %s info | grep 'center1' | cut -d ' ' -f9 | tr -d '\\n'", interface_name);
4323
4324 ret = _syscmd(cmd, buf, sizeof(buf));
4325 len = strlen(buf);
4326 if((ret != 0) || (len == 0))
4327 {
4328 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
4329 return RETURN_ERR;
4330 }
4331 sscanf(buf, "%d", &freq);
4332 centr_channel = ieee80211_frequency_to_channel(freq);
4333 if (centr_channel > (int)channel)
developer72fb0bb2023-01-11 09:46:29 +08004334 snprintf(output_string, 64, "AboveControlChannel");
4335 else
4336 snprintf(output_string, 64, "BelowControlChannel");
4337 }
4338
4339 return RETURN_OK;
4340}
4341
4342//Set the extension channel.
4343INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
developer69b61b02023-03-07 17:17:44 +08004344{
developer72fb0bb2023-01-11 09:46:29 +08004345 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4346 struct params params={0};
4347 char config_file[64] = {0};
developerd1824452023-05-18 12:30:04 +08004348 char config_dat_file[64] = {0};
4349 char ext_channel[64] = {0};
developer72fb0bb2023-01-11 09:46:29 +08004350 char buf[128] = {0};
4351 char cmd[128] = {0};
4352 int max_radio_num =0, ret = 0, bandwidth = 0;
developer2f79c922023-06-02 17:33:42 +08004353 unsigned long channel = 0;
developer72fb0bb2023-01-11 09:46:29 +08004354 bool stbcEnable = FALSE;
4355 params.name = "ht_capab";
4356 wifi_band band;
4357
4358 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
4359 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
4360 _syscmd(cmd, buf, sizeof(buf));
4361 if (strlen(buf) != 0)
4362 stbcEnable = TRUE;
4363 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, buf) != RETURN_OK)
4364 return RETURN_ERR;
4365 bandwidth = strtol(buf, NULL, 10);
4366 // TDK expected to get error with 20MHz
developer262f4cb2023-05-24 12:22:04 +08004367 // we handle 20MHz in function wifi_RemoveRadioExtChannel().
developer72fb0bb2023-01-11 09:46:29 +08004368 if (bandwidth == 20 || strstr(buf, "80+80") != NULL)
4369 return RETURN_ERR;
4370
4371 band = wifi_index_to_band(radioIndex);
4372 if (band == band_invalid)
4373 return RETURN_ERR;
4374
4375 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK)
4376 return RETURN_ERR;
4377
developer262f4cb2023-05-24 12:22:04 +08004378 snprintf(buf, sizeof(buf), "HT%d", bandwidth);
4379 ret = util_get_sec_chan_offset(channel, buf);
4380 if (ret == -EINVAL)
4381 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08004382
4383 if(NULL!= strstr(string,"Above")) {
developer262f4cb2023-05-24 12:22:04 +08004384 if ((band == band_2_4 && channel > 9) || (band == band_5 && ret == -1))
4385 return RETURN_OK;
4386 strcpy(ext_channel, "Above");
developer72fb0bb2023-01-11 09:46:29 +08004387 } else if(NULL!= strstr(string,"Below")) {
developer262f4cb2023-05-24 12:22:04 +08004388 if ((band == band_2_4 && channel < 5) || (band == band_5 && ret == -1))
4389 return RETURN_OK;
4390 strcpy(ext_channel, "Below");
4391 } else {
developerd1824452023-05-18 12:30:04 +08004392 printf("%s: invalid EXT_CHA:%s\n", __func__, string);
developer262f4cb2023-05-24 12:22:04 +08004393 return RETURN_ERR;
4394 }
developerd1824452023-05-18 12:30:04 +08004395 params.name = "HT_EXTCHA";
developer72fb0bb2023-01-11 09:46:29 +08004396 params.value = ext_channel;
4397
developerd1824452023-05-18 12:30:04 +08004398 snprintf (config_dat_file, sizeof(config_dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
4399 wifi_datfileWrite(config_dat_file, &params, 1);
4400
developer72fb0bb2023-01-11 09:46:29 +08004401 wifi_getMaxRadioNumber(&max_radio_num);
4402 for(int i=0; i<=MAX_APS/max_radio_num; i++)
4403 {
4404 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(max_radio_num*i));
developer72fb0bb2023-01-11 09:46:29 +08004405 wifi_setRadioSTBCEnable(radioIndex+(max_radio_num*i), stbcEnable);
4406 }
4407
4408 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
4409 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4410 return RETURN_OK;
4411}
4412
4413//Get the guard interval value. eg "400nsec" or "800nsec"
4414//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.
4415INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
4416{
4417 wifi_guard_interval_t GI;
4418
4419 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4420
4421 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
4422 return RETURN_ERR;
4423
4424 if (GI == wifi_guard_interval_400)
4425 strcpy(output_string, "400nsec");
4426 else if (GI == wifi_guard_interval_800)
4427 strcpy(output_string, "800nsec");
4428 else if (GI == wifi_guard_interval_1600)
4429 strcpy(output_string, "1600nsec");
4430 else if (GI == wifi_guard_interval_3200)
4431 strcpy(output_string, "3200nsec");
4432 else
4433 strcpy(output_string, "Auto");
4434
4435 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4436 return RETURN_OK;
4437}
4438
4439//Set the guard interval value.
4440INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
4441{
4442 wifi_guard_interval_t GI;
4443 int ret = 0;
4444
4445 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4446
4447 if (strcmp(string, "400nsec") == 0)
4448 GI = wifi_guard_interval_400;
4449 else if (strcmp(string , "800nsec") == 0)
4450 GI = wifi_guard_interval_800;
4451 else if (strcmp(string , "1600nsec") == 0)
4452 GI = wifi_guard_interval_1600;
4453 else if (strcmp(string , "3200nsec") == 0)
4454 GI = wifi_guard_interval_3200;
4455 else
4456 GI = wifi_guard_interval_auto;
4457
4458 ret = wifi_setGuardInterval(radioIndex, GI);
4459
4460 if (ret == RETURN_ERR) {
4461 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
4462 return RETURN_ERR;
4463 }
4464
4465 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4466 return RETURN_OK;
4467}
4468
4469//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
4470INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
4471{
4472 char buf[32]={0};
4473 char mcs_file[64] = {0};
4474 char cmd[64] = {0};
4475 int mode_bitmap = 0;
4476
4477 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4478 if(output_int == NULL)
4479 return RETURN_ERR;
4480 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
4481
4482 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
4483 _syscmd(cmd, buf, sizeof(buf));
4484 if (strlen(buf) > 0)
4485 *output_int = strtol(buf, NULL, 10);
4486 else {
4487 // output the max MCS for the current radio mode
4488 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
4489 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
4490 return RETURN_ERR;
4491 }
4492 if (mode_bitmap & WIFI_MODE_AX) {
4493 *output_int = 11;
4494 } else if (mode_bitmap & WIFI_MODE_AC) {
4495 *output_int = 9;
4496 } else if (mode_bitmap & WIFI_MODE_N) {
4497 *output_int = 7;
4498 }
4499 }
4500 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4501
4502 return RETURN_OK;
4503}
4504
4505//Set the Modulation Coding Scheme index
4506INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
4507{
developera1255e42023-05-13 17:45:02 +08004508 /*Only HE mode can specify MCS capability. We don't support MCS in HT mode,
4509 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 +08004510 char config_file[64] = {0};
4511 char set_value[16] = {0};
4512 char mcs_file[32] = {0};
developer72fb0bb2023-01-11 09:46:29 +08004513 struct params set_config = {0};
4514 FILE *f = NULL;
developera1255e42023-05-13 17:45:02 +08004515 INT nss = 0;
4516 int ant_bitmap = 0;
4517 unsigned short cal_value = 0;
4518 UCHAR tval = 0, i = 0;
developer72fb0bb2023-01-11 09:46:29 +08004519
4520 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4521
4522 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4523
4524 // -1 means auto
4525 if (MCS > 15 || MCS < -1) {
4526 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
4527 return RETURN_ERR;
4528 }
developera1255e42023-05-13 17:45:02 +08004529 wifi_getRadioTxChainMask(radioIndex, &ant_bitmap);/*nss is a bit map value,1111*/
4530 for(; ant_bitmap > 0; ant_bitmap >>= 1)
4531 nss += 1;
4532 //printf("%s:nss = %d\n", __func__, nss);
4533 /*16-bit combination of 2-bit values of Max HE-MCS For 1..8 SS;each 2-bit value have following meaning:
4534 0 = HE-MCS 0-7, 1 = HE-MCS 0-9, 2 = HE-MCS 0-11, 3 = not supported*/
developer72fb0bb2023-01-11 09:46:29 +08004535 if (MCS > 9 || MCS == -1)
developera1255e42023-05-13 17:45:02 +08004536 tval = 2;/*one stream value*/
developer72fb0bb2023-01-11 09:46:29 +08004537 else if (MCS > 7)
developera1255e42023-05-13 17:45:02 +08004538 tval = 1;
developer72fb0bb2023-01-11 09:46:29 +08004539 else
developera1255e42023-05-13 17:45:02 +08004540 tval = 0;
4541 for (i = 0; i < nss; i++)
4542 cal_value |= (tval << (2*i));
4543 snprintf(set_value, sizeof(set_value), "%x", cal_value);
4544 WIFI_ENTRY_EXIT_DEBUG("%s:set=%s, cal=%x\n", __func__, set_value, cal_value);
4545 set_config.name = "he_basic_mcs_nss_set";/*He capability in beacon or response*/
developer72fb0bb2023-01-11 09:46:29 +08004546 set_config.value = set_value;
4547
4548 wifi_hostapdWrite(config_file, &set_config, 1);
4549 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
4550
4551 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
4552 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
4553 f = fopen(mcs_file, "w");
4554 if (f == NULL) {
4555 fprintf(stderr, "%s: fopen failed\n", __func__);
4556 return RETURN_ERR;
4557 }
4558 fprintf(f, "%d", MCS);
4559 fclose(f);
4560
4561 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4562 return RETURN_OK;
4563}
4564
4565//Get supported Transmit Power list, eg : "0,25,50,75,100"
4566//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.
4567INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
4568{
4569 if (NULL == output_list)
4570 return RETURN_ERR;
4571 snprintf(output_list, 64,"0,25,50,75,100");
4572 return RETURN_OK;
4573}
4574
4575//Get current Transmit Power in dBm units.
4576//The transmite power level is in units of full power for this radio.
4577INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
4578{
4579 char interface_name[16] = {0};
4580 char cmd[128]={0};
4581 char buf[16]={0};
developera1255e42023-05-13 17:45:02 +08004582 char pwr_file[128]={0};
4583
developer72fb0bb2023-01-11 09:46:29 +08004584 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4585
4586 if(output_ulong == NULL)
4587 return RETURN_ERR;
4588
4589 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4590 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +08004591/*
developer72fb0bb2023-01-11 09:46:29 +08004592 snprintf(cmd, sizeof(cmd), "iw %s info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", interface_name);
4593 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08004594 *output_ulong = strtol(buf, NULL, 10);
developera1255e42023-05-13 17:45:02 +08004595*/
4596 snprintf(pwr_file, sizeof(pwr_file), "%s%d.txt", POWER_PERCENTAGE, radioIndex);
4597 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", pwr_file);
4598 _syscmd(cmd, buf, sizeof(buf));
4599 if (strlen(buf) > 0)
4600 *output_ulong = strtol(buf, NULL, 10);
4601 else
4602 *output_ulong = 100;
developer72fb0bb2023-01-11 09:46:29 +08004603 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4604 return RETURN_OK;
4605}
4606
4607//Set Transmit Power
4608//The transmite power level is in units of full power for this radio.
4609INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
4610{
4611 char interface_name[16] = {0};
4612 char *support;
developer72fb0bb2023-01-11 09:46:29 +08004613 char buf[128]={0};
4614 char txpower_str[64] = {0};
developera1255e42023-05-13 17:45:02 +08004615 char pwr_file[128]={0};
4616 FILE *f = NULL;
developerfead3972023-05-25 20:15:02 +08004617 int if_idx, ret = 0;
4618 struct nl_msg *msg = NULL;
4619 struct nlattr * msg_data = NULL;
4620 struct mtk_nl80211_param param;
4621 struct unl unl_ins;
developer72fb0bb2023-01-11 09:46:29 +08004622
4623 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4624
4625 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4626 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +08004627 // Get the Tx power supported list and check that is the input in the list
4628 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
4629 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
4630 support = strtok(buf, ",");
4631 while(true)
4632 {
4633 if(support == NULL) { // input not in the list
4634 wifi_dbg_printf("Input value is invalid.\n");
4635 return RETURN_ERR;
4636 }
4637 if (strncmp(txpower_str, support, strlen(support)) == 0) {
4638 break;
4639 }
4640 support = strtok(NULL, ",");
4641 }
developerfead3972023-05-25 20:15:02 +08004642
4643 if_idx = if_nametoindex(interface_name);
4644 /*init mtk nl80211 vendor cmd*/
4645 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_TXPOWER;
4646 param.if_type = NL80211_ATTR_IFINDEX;
4647 param.if_idx = if_idx;
4648 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
4649 if (ret) {
4650 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
4651 return RETURN_ERR;
4652 }
4653 /*add mtk vendor cmd data*/
4654 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_TXPWR_PERCENTAGE_EN, 1)) {
4655 wifi_debug(DEBUG_ERROR, "Nla put attribute error\n");
4656 nlmsg_free(msg);
4657 goto err;
4658 }
4659
4660 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_TXPWR_DROP_CTRL, TransmitPower)) {
4661 wifi_debug(DEBUG_ERROR, "Nla put attribute error\n");
4662 nlmsg_free(msg);
4663 goto err;
4664 }
4665
4666 /*send mtk nl80211 vendor msg*/
4667 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
4668 if (ret) {
4669 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
4670 goto err;
4671 }
4672 /*deinit mtk nl80211 vendor msg*/
4673 mtk_nl80211_deint(&unl_ins);
4674 wifi_debug(DEBUG_NOTICE, "set cmd success.\n");
4675
developera1255e42023-05-13 17:45:02 +08004676 snprintf(pwr_file, sizeof(pwr_file), "%s%d.txt", POWER_PERCENTAGE, radioIndex);
4677 f = fopen(pwr_file, "w");
4678 if (f == NULL) {
4679 fprintf(stderr, "%s: fopen failed\n", __func__);
4680 return RETURN_ERR;
4681 }
developerdaf24792023-06-06 11:40:04 +08004682 fprintf(f, "%lu", TransmitPower);
developera1255e42023-05-13 17:45:02 +08004683 fclose(f);
4684/* 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 +08004685 _syscmd(cmd, buf, sizeof(buf));
4686 maximum_tx = strtol(buf, NULL, 10);
4687
4688 // Get the Tx power supported list and check that is the input in the list
4689 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
4690 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
4691 support = strtok(buf, ",");
4692 while(true)
4693 {
4694 if(support == NULL) { // input not in the list
4695 wifi_dbg_printf("Input value is invalid.\n");
4696 return RETURN_ERR;
4697 }
4698 if (strncmp(txpower_str, support, strlen(support)) == 0) {
4699 break;
4700 }
4701 support = strtok(NULL, ",");
4702 }
4703 txpower = TransmitPower*maximum_tx/100;
4704 phyId = radio_index_to_phy(radioIndex);
4705 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", phyId, txpower);
4706 _syscmd(cmd, buf, sizeof(buf));
4707 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera1255e42023-05-13 17:45:02 +08004708*/
4709 return RETURN_OK;
developerfead3972023-05-25 20:15:02 +08004710err:
4711 mtk_nl80211_deint(&unl_ins);
4712 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
4713 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08004714}
4715
4716//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
4717INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
4718{
developer69b61b02023-03-07 17:17:44 +08004719 if (NULL == Supported)
developer72fb0bb2023-01-11 09:46:29 +08004720 return RETURN_ERR;
4721 *Supported = TRUE;
4722
4723 return RETURN_OK;
4724}
4725
4726//Get 80211h feature enable
4727INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
4728{
4729 char buf[64]={'\0'};
4730 char config_file[64] = {'\0'};
4731
4732 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4733 if(enable == NULL)
4734 return RETURN_ERR;
4735
4736 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
developerd1824452023-05-18 12:30:04 +08004737 /* wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf)); */
4738 wifi_datfileRead(config_file, "IEEE80211H", buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08004739
4740 if (strncmp(buf, "1", 1) == 0)
4741 *enable = TRUE;
4742 else
4743 *enable = FALSE;
4744
4745 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4746 return RETURN_OK;
4747}
4748
4749//Set 80211h feature enable
4750INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
4751{
4752 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4753 struct params params={'\0'};
developerd1824452023-05-18 12:30:04 +08004754 struct params dat={0};
developer72fb0bb2023-01-11 09:46:29 +08004755 char config_file[MAX_BUF_SIZE] = {0};
developerd1824452023-05-18 12:30:04 +08004756 char config_dat_file[MAX_BUF_SIZE] = {0};
4757 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08004758
4759 params.name = "ieee80211h";
4760
4761 if (enable) {
4762 params.value = "1";
4763 } else {
4764 params.value = "0";
4765 }
4766
developerd1824452023-05-18 12:30:04 +08004767 dat.name = "IEEE80211H";
4768 dat.value = params.value;
4769
4770 band = wifi_index_to_band(radioIndex);
4771 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4772 snprintf(config_dat_file, sizeof(config_dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
developer69b61b02023-03-07 17:17:44 +08004773
developerd1824452023-05-18 12:30:04 +08004774 wifi_hostapdWrite(config_file, &params, 1);
4775 wifi_datfileWrite(config_dat_file, &dat, 1);
developer72fb0bb2023-01-11 09:46:29 +08004776 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
4777 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4778 return RETURN_OK;
4779}
4780
4781//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.
4782INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
4783{
4784 if (NULL == output)
4785 return RETURN_ERR;
4786 *output=100;
4787
4788 return RETURN_OK;
4789}
4790
4791//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.
4792INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
4793{
4794 if (NULL == output)
4795 return RETURN_ERR;
4796 *output = -99;
4797
4798 return RETURN_OK;
4799}
4800
4801INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
4802{
4803 return RETURN_ERR;
4804}
4805
4806
4807//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
4808INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
4809{
4810 char interface_name[16] = {0};
4811 char cmd[MAX_BUF_SIZE]={'\0'};
4812 char buf[MAX_CMD_SIZE]={'\0'};
4813
4814 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4815 if(output == NULL)
4816 return RETURN_ERR;
4817
4818 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4819 return RETURN_ERR;
4820 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", interface_name);
4821 _syscmd(cmd, buf, sizeof(buf));
4822 *output = atoi(buf);
4823
4824 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4825 return RETURN_OK;
4826}
developer69b61b02023-03-07 17:17:44 +08004827
developer72fb0bb2023-01-11 09:46:29 +08004828INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
4829{
4830 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4831 struct params params={'\0'};
4832 char buf[MAX_BUF_SIZE] = {'\0'};
4833 char config_file[MAX_BUF_SIZE] = {'\0'};
4834
4835 if (BeaconPeriod < 15 || BeaconPeriod > 65535)
4836 return RETURN_ERR;
4837
4838 params.name = "beacon_int";
4839 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
4840 params.value = buf;
4841
4842 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
4843 wifi_hostapdWrite(config_file, &params, 1);
developer69b61b02023-03-07 17:17:44 +08004844
developer72fb0bb2023-01-11 09:46:29 +08004845 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
4846 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4847 return RETURN_OK;
4848}
4849
4850//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.
4851INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
4852{
4853 //TODO: need to revisit below implementation
4854 char *temp;
4855 char temp_output[128] = {0};
4856 char temp_TransmitRates[64] = {0};
4857 char config_file[64] = {0};
4858
4859 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4860 if (NULL == output)
4861 return RETURN_ERR;
4862 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
4863 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
developer69b61b02023-03-07 17:17:44 +08004864
developer72fb0bb2023-01-11 09:46:29 +08004865 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
4866 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
4867 } else {
4868 temp = strtok(temp_TransmitRates," ");
4869 while(temp!=NULL)
4870 {
4871 // Convert 100 kbps to Mbps
4872 temp[strlen(temp)-1]=0;
4873 if((temp[0]=='5') && (temp[1]=='\0'))
4874 {
4875 temp="5.5";
4876 }
4877 strcat(temp_output,temp);
4878 temp = strtok(NULL," ");
4879 if(temp!=NULL)
4880 {
4881 strcat(temp_output,",");
4882 }
4883 }
4884 strcpy(output,temp_output);
4885 }
4886 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4887 return RETURN_OK;
4888}
4889
4890INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
4891{
4892 char *temp;
4893 char temp1[128];
4894 char temp_output[128];
4895 char temp_TransmitRates[128];
4896 char set[128];
4897 char sub_set[128];
4898 int set_count=0,subset_count=0;
4899 int set_index=0,subset_index=0;
4900 char *token;
4901 int flag=0, i=0;
4902 struct params params={'\0'};
4903 char config_file[MAX_BUF_SIZE] = {0};
4904 wifi_band band = wifi_index_to_band(radioIndex);
4905
4906 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4907 if(NULL == TransmitRates)
4908 return RETURN_ERR;
4909 strcpy(sub_set,TransmitRates);
4910
4911 //Allow only supported Data transmit rate to be set
4912 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
4913 token = strtok(sub_set,",");
4914 while( token != NULL ) /* split the basic rate to be set, by comma */
4915 {
4916 sub_set[subset_count]=atoi(token);
4917 subset_count++;
4918 token=strtok(NULL,",");
4919 }
4920 token=strtok(set,",");
4921 while(token!=NULL) /* split the supported rate by comma */
4922 {
4923 set[set_count]=atoi(token);
4924 set_count++;
4925 token=strtok(NULL,",");
4926 }
4927 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
4928 {
4929 for(set_index=0;set_index < set_count;set_index++)
4930 {
4931 flag=0;
4932 if(sub_set[subset_index]==set[set_index])
4933 break;
4934 else
4935 flag=1; /* No match found */
4936 }
4937 if(flag==1)
4938 return RETURN_ERR; //If value not found return Error
4939 }
4940 strcpy(temp_TransmitRates,TransmitRates);
4941
4942 for(i=0;i<strlen(temp_TransmitRates);i++)
4943 {
4944 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
4945 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
4946 {
4947 continue;
4948 }
4949 else
4950 {
4951 return RETURN_ERR;
4952 }
4953 }
4954 strcpy(temp_output,"");
4955 temp = strtok(temp_TransmitRates,",");
4956 while(temp!=NULL)
4957 {
4958 strcpy(temp1,temp);
4959 if(band == band_5)
4960 {
4961 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
4962 {
4963 return RETURN_ERR;
4964 }
4965 }
4966
4967 if(strcmp(temp,"5.5")==0)
4968 {
4969 strcpy(temp1,"55");
4970 }
4971 else
4972 {
4973 strcat(temp1,"0");
4974 }
4975 strcat(temp_output,temp1);
4976 temp = strtok(NULL,",");
4977 if(temp!=NULL)
4978 {
4979 strcat(temp_output," ");
4980 }
4981 }
4982 strcpy(TransmitRates,temp_output);
4983
4984 params.name= "basic_rates";
4985 params.value =TransmitRates;
4986
4987 wifi_dbg_printf("\n%s:",__func__);
4988 wifi_dbg_printf("\nparams.value=%s\n",params.value);
4989 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
4990 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
4991 wifi_hostapdWrite(config_file,&params,1);
4992 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4993 return RETURN_OK;
4994}
4995
4996//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
4997INT wifi_GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
4998{
4999 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5000 FILE *fp = NULL;
5001 char path[256] = {0}, output_string[256] = {0};
5002 int count = 0;
5003 char *interface = NULL;
5004
5005 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
5006 if (fp == NULL)
5007 {
5008 printf("Failed to run command in Function %s\n", __FUNCTION__);
5009 return RETURN_ERR;
5010 }
5011 if (fgets(path, sizeof(path) - 1, fp) != NULL)
5012 {
5013 interface = strchr(path, '=');
5014
5015 if (interface != NULL)
5016 {
5017 strcpy(output_string, interface + 1);
5018 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
5019 interface_name[count] = output_string[count];
5020
5021 interface_name[count] = '\0';
5022 }
5023 }
5024 pclose(fp);
5025 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5026 return RETURN_OK;
5027}
5028
5029INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
5030{
5031 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5032 output_struct->radio_BytesSent = 0;
5033 output_struct->radio_BytesReceived = 0;
5034 output_struct->radio_PacketsSent = 0;
5035 output_struct->radio_PacketsReceived = 0;
5036 output_struct->radio_ErrorsSent = 0;
5037 output_struct->radio_ErrorsReceived = 0;
5038 output_struct->radio_DiscardPacketsSent = 0;
5039 output_struct->radio_DiscardPacketsReceived = 0;
5040 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5041 return RETURN_OK;
5042}
5043
5044
5045INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
5046{
5047 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5048 CHAR buf[MAX_CMD_SIZE] = {0};
5049 CHAR Value[MAX_BUF_SIZE] = {0};
5050 FILE *fp = NULL;
5051
5052 if (ifname == NULL || strlen(ifname) <= 1)
5053 return RETURN_OK;
5054
5055 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
5056 system(buf);
5057
5058 fp = fopen("/tmp/Radio_Stats.txt", "r");
5059 if(fp == NULL)
5060 {
5061 printf("/tmp/Radio_Stats.txt not exists \n");
5062 return RETURN_ERR;
5063 }
5064 fclose(fp);
5065
5066 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
5067 File_Reading(buf, Value);
5068 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
5069
5070 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
5071 File_Reading(buf, Value);
5072 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
5073
5074 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
5075 File_Reading(buf, Value);
5076 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
5077
5078 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
5079 File_Reading(buf, Value);
5080 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
5081
5082 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
5083 File_Reading(buf, Value);
5084 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
5085
5086 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
5087 File_Reading(buf, Value);
5088 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
5089
5090 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
5091 File_Reading(buf, Value);
5092 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
5093
5094 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
5095 File_Reading(buf, Value);
5096 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
5097
5098 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5099 return RETURN_OK;
5100}
5101
5102INT GetIfacestatus(CHAR *interface_name, CHAR *status)
5103{
developer7e4a2a62023-04-06 19:56:03 +08005104 CHAR buf[MAX_CMD_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08005105
developer7e4a2a62023-04-06 19:56:03 +08005106 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5107
5108 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL) {
5109 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
5110 File_Reading(buf, status);
5111 }
5112
5113 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5114 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08005115}
5116
5117//Get detail radio traffic static info
5118INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
5119{
5120
developer69b61b02023-03-07 17:17:44 +08005121#if 0
5122 //ifconfig radio_x
developer72fb0bb2023-01-11 09:46:29 +08005123 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
5124 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
5125 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
5126 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
5127
5128 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
5129 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
5130 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.
5131 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.
5132
developer69b61b02023-03-07 17:17:44 +08005133 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 +08005134 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].
5135 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
5136 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.
5137 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
5138 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
5139 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
5140 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
5141 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
5142
5143 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
5144 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
5145 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
5146 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.
5147
5148 return RETURN_OK;
5149#endif
5150
5151 CHAR interface_name[64] = {0};
5152 BOOL iface_status = FALSE;
5153 wifi_radioTrafficStats2_t radioTrafficStats = {0};
5154
5155 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5156 if (NULL == output_struct)
5157 return RETURN_ERR;
5158
5159 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
5160 return RETURN_ERR;
5161
5162 wifi_getApEnable(radioIndex, &iface_status);
5163
5164 if (iface_status == TRUE)
5165 wifi_halGetIfStats(interface_name, &radioTrafficStats);
5166 else
5167 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
5168
5169 output_struct->radio_BytesSent = radioTrafficStats.radio_BytesSent;
5170 output_struct->radio_BytesReceived = radioTrafficStats.radio_BytesReceived;
5171 output_struct->radio_PacketsSent = radioTrafficStats.radio_PacketsSent;
5172 output_struct->radio_PacketsReceived = radioTrafficStats.radio_PacketsReceived;
5173 output_struct->radio_ErrorsSent = radioTrafficStats.radio_ErrorsSent;
5174 output_struct->radio_ErrorsReceived = radioTrafficStats.radio_ErrorsReceived;
5175 output_struct->radio_DiscardPacketsSent = radioTrafficStats.radio_DiscardPacketsSent;
5176 output_struct->radio_DiscardPacketsReceived = radioTrafficStats.radio_DiscardPacketsReceived;
5177
5178 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
5179 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].
5180 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
5181 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.
5182 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
5183 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
5184 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
5185 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
5186 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
5187
5188 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
5189 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
5190 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
5191 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.
5192
5193 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5194
5195 return RETURN_OK;
5196}
5197
5198//Set radio traffic static Measureing rules
5199INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
5200{
5201 //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
5202 // Else, save the MeasuringRate and MeasuringInterval for future usage
5203
5204 return RETURN_OK;
5205}
5206
5207//To start or stop RadioTrafficStats
5208INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
5209{
5210 //zqiu: If the RadioTrafficStats process running
5211 // if(enable)
5212 // return RETURN_OK.
5213 // else
5214 // Stop RadioTrafficStats process
developer69b61b02023-03-07 17:17:44 +08005215 // Else
developer72fb0bb2023-01-11 09:46:29 +08005216 // if(enable)
5217 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
5218 // else
5219 // return RETURN_OK.
5220
5221 return RETURN_OK;
5222}
5223
5224//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
5225INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
5226{
5227 //zqiu: Please ignor signalIndex.
developer69b61b02023-03-07 17:17:44 +08005228 if (NULL == SignalLevel)
developer72fb0bb2023-01-11 09:46:29 +08005229 return RETURN_ERR;
developer47cc27a2023-05-17 23:09:58 +08005230
developer72fb0bb2023-01-11 09:46:29 +08005231 *SignalLevel=(radioIndex==0)?-19:-19;
5232
5233 return RETURN_OK;
5234}
5235
5236//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
5237INT wifi_applyRadioSettings(INT radioIndex)
5238{
5239 return RETURN_OK;
5240}
5241
5242//Get the radio index assocated with this SSID entry
5243INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
5244{
5245 if(NULL == radioIndex)
5246 return RETURN_ERR;
5247 int max_radio_num = 0;
5248 wifi_getMaxRadioNumber(&max_radio_num);
5249 *radioIndex = ssidIndex%max_radio_num;
5250 return RETURN_OK;
5251}
5252
5253//Device.WiFi.SSID.{i}.Enable
5254//Get SSID enable configuration parameters (not the SSID enable status)
5255INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
5256{
developer69b61b02023-03-07 17:17:44 +08005257 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08005258 return RETURN_ERR;
5259
5260 return wifi_getApEnable(ssidIndex, output_bool);
5261}
5262
5263//Device.WiFi.SSID.{i}.Enable
5264//Set SSID enable configuration parameters
5265INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
5266{
5267 return wifi_setApEnable(ssidIndex, enable);
5268}
5269
5270//Device.WiFi.SSID.{i}.Status
5271//Get the SSID enable status
5272INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
5273{
developer72fb0bb2023-01-11 09:46:29 +08005274 BOOL output_bool;
5275
5276 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5277 if (NULL == output_string)
5278 return RETURN_ERR;
developer69b61b02023-03-07 17:17:44 +08005279
developer72fb0bb2023-01-11 09:46:29 +08005280 wifi_getApEnable(ssidIndex,&output_bool);
5281 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
5282
5283 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5284 return RETURN_OK;
5285}
5286
5287// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
5288INT wifi_getSSIDName(INT apIndex, CHAR *output)
5289{
5290 char config_file[MAX_BUF_SIZE] = {0};
5291
developer69b61b02023-03-07 17:17:44 +08005292 if (NULL == output)
developer72fb0bb2023-01-11 09:46:29 +08005293 return RETURN_ERR;
5294
5295 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5296 wifi_hostapdRead(config_file,"ssid",output,32);
5297
5298 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
5299 return RETURN_OK;
5300}
5301
developer69b61b02023-03-07 17:17:44 +08005302// Set a max 32 byte string and sets an internal variable to the SSID name
developer72fb0bb2023-01-11 09:46:29 +08005303INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
5304{
developer72fb0bb2023-01-11 09:46:29 +08005305 struct params params;
5306 char config_file[MAX_BUF_SIZE] = {0};
5307
5308 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5309 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
5310 return RETURN_ERR;
5311
5312 params.name = "ssid";
5313 params.value = ssid_string;
5314 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5315 wifi_hostapdWrite(config_file, &params, 1);
5316 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5317 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5318
5319 return RETURN_OK;
5320}
5321
5322//Get the BSSID
5323INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
5324{
developer7e4a2a62023-04-06 19:56:03 +08005325 char cmd[MAX_CMD_SIZE] = {0};
5326 char inf_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08005327
developer7e4a2a62023-04-06 19:56:03 +08005328 if (!output_string)
developerdaf24792023-06-06 11:40:04 +08005329 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08005330
developer47cc27a2023-05-17 23:09:58 +08005331 if (wifi_GetInterfaceName(ssidIndex, inf_name) != RETURN_OK)
5332 return RETURN_ERR;
developer7e4a2a62023-04-06 19:56:03 +08005333
developer5b2f10c2023-05-25 17:02:21 +08005334 if (ssidIndex < 0 || ssidIndex > MAX_APS) {
5335 wifi_debug(DEBUG_ERROR, "innvalide ssidIdex(%d)\n", ssidIndex);
5336 strncpy(output_string, "\0", 1);
5337 return RETURN_ERR;
5338 }
5339 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep bssid | cut -d '=' -f2 | tr -d '\\n'", inf_name);
5340 _syscmd(cmd, output_string, 64);
developer7e4a2a62023-04-06 19:56:03 +08005341
developer5b2f10c2023-05-25 17:02:21 +08005342 /* if hostapd does not control interface even if this interface has been brought up,
5343 * try to get its mac address by iw command.
5344 */
5345 if(strlen(output_string) == 0) {
5346 memset(cmd, 0, sizeof(cmd));
5347 snprintf(cmd, sizeof(cmd), "iw dev %s info | grep \"addr\" | awk \'{print $2}\'", inf_name);
5348 _syscmd(cmd, output_string, 64);
5349 }
developer72fb0bb2023-01-11 09:46:29 +08005350
developer5b2f10c2023-05-25 17:02:21 +08005351 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08005352}
5353
5354//Get the MAC address associated with this Wifi SSID
5355INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
5356{
5357 wifi_getBaseBSSID(ssidIndex,output_string);
5358 return RETURN_OK;
5359}
5360
5361//Get the basic SSID traffic static info
5362//Apply SSID and AP (in the case of Acess Point devices) to the hardware
5363//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
5364INT wifi_applySSIDSettings(INT ssidIndex)
5365{
5366 char interface_name[16] = {0};
5367 BOOL status = false;
5368 char cmd[MAX_CMD_SIZE] = {0};
5369 char buf[MAX_CMD_SIZE] = {0};
5370 int apIndex, ret;
5371 int max_radio_num = 0;
5372 int radioIndex = 0;
5373
5374 wifi_getMaxRadioNumber(&max_radio_num);
5375
5376 radioIndex = ssidIndex % max_radio_num;
5377
5378 wifi_getApEnable(ssidIndex,&status);
5379 // Do not apply when ssid index is disabled
5380 if (status == false)
5381 return RETURN_OK;
5382
5383 /* Doing full remove and add for ssid Index
5384 * Not all hostapd options are supported with reload
5385 * for example macaddr_acl
5386 */
5387 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
5388 return RETURN_ERR;
5389
5390 ret = wifi_setApEnable(ssidIndex,true);
5391
5392 /* Workaround for hostapd issue with multiple bss definitions
5393 * when first created interface will be removed
5394 * then all vaps other vaps on same phy are removed
5395 * after calling setApEnable to false readd all enabled vaps */
5396 for(int i=0; i < MAX_APS/max_radio_num; i++) {
5397 apIndex = max_radio_num*i+radioIndex;
5398 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5399 return RETURN_ERR;
5400 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
5401 _syscmd(cmd, buf, sizeof(buf));
5402 if(*buf == '1')
5403 wifi_setApEnable(apIndex, true);
5404 }
5405
5406 return ret;
5407}
5408
5409struct channels_noise {
5410 int channel;
5411 int noise;
5412};
5413
5414// Return noise array for each channel
5415int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
5416{
5417 char interface_name[16] = {0};
5418 FILE *f = NULL;
5419 char cmd[128] = {0};
5420 char line[256] = {0};
developer72fb0bb2023-01-11 09:46:29 +08005421 int tmp = 0, arr_index = -1;
5422
5423 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
5424 return RETURN_ERR;
5425 sprintf(cmd, "iw dev %s survey dump | grep 'frequency\\|noise' | awk '{print $2}'", interface_name);
5426
5427 if ((f = popen(cmd, "r")) == NULL) {
5428 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
5429 return RETURN_ERR;
5430 }
developer69b61b02023-03-07 17:17:44 +08005431
developer72fb0bb2023-01-11 09:46:29 +08005432 while(fgets(line, sizeof(line), f) != NULL) {
5433 if(arr_index < channels_num){
5434 sscanf(line, "%d", &tmp);
5435 if (tmp > 0) { // channel frequency, the first line must be frequency
5436 arr_index++;
5437 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
5438 } else { // noise
5439 channels_noise_arr[arr_index].noise = tmp;
5440 }
5441 }else{
5442 break;
5443 }
5444 }
5445 pclose(f);
5446 return RETURN_OK;
5447}
5448
5449//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
5450//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
developer69b61b02023-03-07 17:17:44 +08005451INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
developer72fb0bb2023-01-11 09:46:29 +08005452{
5453 int index = -1;
5454 wifi_neighbor_ap2_t *scan_array = NULL;
5455 char cmd[256]={0};
5456 char buf[128]={0};
5457 char file_name[32] = {0};
5458 char filter_SSID[32] = {0};
5459 char line[256] = {0};
5460 char interface_name[16] = {0};
5461 char *ret = NULL;
5462 int freq=0;
5463 FILE *f = NULL;
developer72fb0bb2023-01-11 09:46:29 +08005464 int channels_num = 0;
5465 int vht_channel_width = 0;
5466 int get_noise_ret = RETURN_ERR;
5467 bool filter_enable = false;
5468 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
5469 int phyId = 0;
5470
5471 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
5472
5473 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
5474 return RETURN_ERR;
5475
5476 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
5477 f = fopen(file_name, "r");
5478 if (f != NULL) {
developer47a56bf2023-05-30 13:38:57 +08005479 fgets(buf, sizeof(file_name), f);
5480 if ((strncmp(buf, "0", 1)) != 0) {
5481 fgets(filter_SSID, sizeof(file_name), f);
5482 if (strlen(filter_SSID) != 0)
5483 filter_enable = true;
5484 }
developer72fb0bb2023-01-11 09:46:29 +08005485 fclose(f);
5486 }
5487
5488 phyId = radio_index_to_phy(radioIndex);
5489 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
5490 _syscmd(cmd, buf, sizeof(buf));
5491 channels_num = strtol(buf, NULL, 10);
5492
5493
5494
5495 sprintf(cmd, "iw dev %s scan | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
5496 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", interface_name, interface_name);
5497 fprintf(stderr, "cmd: %s\n", cmd);
5498 if ((f = popen(cmd, "r")) == NULL) {
5499 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
5500 return RETURN_ERR;
5501 }
developer69b61b02023-03-07 17:17:44 +08005502
developer72fb0bb2023-01-11 09:46:29 +08005503 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
5504 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
developer69b61b02023-03-07 17:17:44 +08005505
developer72fb0bb2023-01-11 09:46:29 +08005506 ret = fgets(line, sizeof(line), f);
5507 while (ret != NULL) {
5508 if(strstr(line, "BSS") != NULL) { // new neighbor info
developer69b61b02023-03-07 17:17:44 +08005509 // 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 +08005510 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
5511 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
5512
5513 if (!filter_BSS) {
5514 index++;
5515 wifi_neighbor_ap2_t *tmp;
5516 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
5517 if (tmp == NULL) { // no more memory to use
5518 index--;
5519 wifi_dbg_printf("%s: realloc failed\n", __func__);
5520 break;
5521 }
5522 scan_array = tmp;
5523 }
5524 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
5525
5526 filter_BSS = false;
5527 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
5528 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
5529 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
5530 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
5531 } else if (strstr(line, "freq") != NULL) {
5532 sscanf(line," freq: %d", &freq);
5533 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
5534
5535 if (freq >= 2412 && freq <= 2484) {
5536 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
5537 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
5538 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
5539 }
5540 else if (freq >= 5160 && freq <= 5805) {
5541 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
5542 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
5543 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
5544 }
5545
5546 scan_array[index].ap_Noise = 0;
5547 if (get_noise_ret == RETURN_OK) {
5548 for (int i = 0; i < channels_num; i++) {
5549 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
5550 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
5551 break;
5552 }
5553 }
5554 }
5555 } else if (strstr(line, "beacon interval") != NULL) {
5556 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
5557 } else if (strstr(line, "signal") != NULL) {
5558 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
5559 } else if (strstr(line,"SSID") != NULL) {
5560 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
5561 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
5562 filter_BSS = true;
5563 }
5564 } else if (strstr(line, "Supported rates") != NULL) {
5565 char SRate[80] = {0}, *tmp = NULL;
5566 memset(buf, 0, sizeof(buf));
5567 strcpy(SRate, line);
5568 tmp = strtok(SRate, ":");
5569 tmp = strtok(NULL, ":");
5570 strcpy(buf, tmp);
5571 memset(SRate, 0, sizeof(SRate));
5572
5573 tmp = strtok(buf, " \n");
5574 while (tmp != NULL) {
5575 strcat(SRate, tmp);
5576 if (SRate[strlen(SRate) - 1] == '*') {
5577 SRate[strlen(SRate) - 1] = '\0';
5578 }
5579 strcat(SRate, ",");
5580
5581 tmp = strtok(NULL, " \n");
5582 }
5583 SRate[strlen(SRate) - 1] = '\0';
5584 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
5585 } else if (strstr(line, "DTIM") != NULL) {
developerdaf24792023-06-06 11:40:04 +08005586 sscanf(line,"DTIM Period %u", &(scan_array[index].ap_DTIMPeriod), buf);
developer72fb0bb2023-01-11 09:46:29 +08005587 } else if (strstr(line, "VHT capabilities") != NULL) {
5588 strcat(scan_array[index].ap_SupportedStandards, ",ac");
5589 strcpy(scan_array[index].ap_OperatingStandards, "ac");
5590 } else if (strstr(line, "HT capabilities") != NULL) {
5591 strcat(scan_array[index].ap_SupportedStandards, ",n");
5592 strcpy(scan_array[index].ap_OperatingStandards, "n");
5593 } else if (strstr(line, "VHT operation") != NULL) {
5594 ret = fgets(line, sizeof(line), f);
5595 sscanf(line," * channel width: %d", &vht_channel_width);
5596 if(vht_channel_width == 1) {
5597 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
5598 } else {
5599 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
5600 }
5601 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
5602 continue;
5603 } else if (strstr(line, "HT operation") != NULL) {
5604 ret = fgets(line, sizeof(line), f);
developerdaf24792023-06-06 11:40:04 +08005605 sscanf(line," * secondary channel offset: %s", buf);
developer72fb0bb2023-01-11 09:46:29 +08005606 if (!strcmp(buf, "above")) {
5607 //40Mhz +
5608 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
5609 }
5610 else if (!strcmp(buf, "below")) {
5611 //40Mhz -
5612 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
5613 } else {
5614 //20Mhz
5615 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
5616 }
5617 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
5618 continue;
5619 } else if (strstr(line, "HE capabilities") != NULL) {
5620 strcat(scan_array[index].ap_SupportedStandards, ",ax");
5621 strcpy(scan_array[index].ap_OperatingStandards, "ax");
5622 ret = fgets(line, sizeof(line), f);
5623 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
5624 if (strstr(line, "HE40/2.4GHz") != NULL)
5625 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
5626 else
5627 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
5628 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
5629 if (strstr(line, "HE80/5GHz") != NULL) {
5630 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
5631 ret = fgets(line, sizeof(line), f);
5632 } else
5633 continue;
5634 if (strstr(line, "HE160/5GHz") != NULL)
5635 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
5636 }
5637 continue;
5638 } else if (strstr(line, "WPA") != NULL) {
5639 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
5640 } else if (strstr(line, "RSN") != NULL) {
5641 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
5642 } else if (strstr(line, "Group cipher") != NULL) {
5643 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
5644 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
5645 strcpy(scan_array[index].ap_EncryptionMode, "AES");
5646 }
5647 }
5648 ret = fgets(line, sizeof(line), f);
5649 }
5650
5651 if (!filter_BSS) {
5652 *output_array_size = index + 1;
5653 } else {
5654 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
5655 *output_array_size = index;
5656 }
5657 *neighbor_ap_array = scan_array;
5658 pclose(f);
5659 free(channels_noise_arr);
5660 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5661 return RETURN_OK;
5662}
5663
5664//>> Deprecated: used for old RDKB code.
5665INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
5666{
5667 INT status = RETURN_ERR;
5668
5669 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5670 output_struct->wifi_PLCPErrorCount = 0;
5671 output_struct->wifi_FCSErrorCount = 0;
5672 output_struct->wifi_InvalidMACCount = 0;
5673 output_struct->wifi_PacketsOtherReceived = 0;
5674 output_struct->wifi_Noise = 0;
5675 status = RETURN_OK;
5676 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5677 return status;
5678}
5679
5680INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
5681{
5682 char interface_name[16] = {0};
5683 char cmd[128] = {0};
5684 char buf[1280] = {0};
5685 char *pos = NULL;
5686
5687 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5688 if (NULL == output_struct)
5689 return RETURN_ERR;
5690
5691 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5692 return RETURN_ERR;
5693
5694 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
5695
5696 snprintf(cmd, sizeof(cmd), "ifconfig %s", interface_name);
5697 _syscmd(cmd, buf, sizeof(buf));
5698
5699 pos = buf;
5700 if ((pos = strstr(pos, "RX packets:")) == NULL)
5701 return RETURN_ERR;
5702 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
5703
5704 if ((pos = strstr(pos, "TX packets:")) == NULL)
5705 return RETURN_ERR;
5706 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
5707
5708 if ((pos = strstr(pos, "RX bytes:")) == NULL)
5709 return RETURN_ERR;
5710 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
5711
5712 if ((pos = strstr(pos, "TX bytes:")) == NULL)
5713 return RETURN_ERR;
5714 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
5715
5716 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l | tr -d '\n'", interface_name);
5717 _syscmd(cmd, buf, sizeof(buf));
5718 sscanf(buf, "%lu", &output_struct->wifi_Associations);
5719
5720#if 0
5721 //TODO: need to revisit below implementation
5722 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5723 char interface_name[MAX_BUF_SIZE] = {0};
5724 char interface_status[MAX_BUF_SIZE] = {0};
5725 char Value[MAX_BUF_SIZE] = {0};
5726 char buf[MAX_CMD_SIZE] = {0};
5727 char cmd[MAX_CMD_SIZE] = {0};
5728 FILE *fp = NULL;
5729
5730 if (NULL == output_struct) {
5731 return RETURN_ERR;
5732 }
5733
5734 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
5735
5736 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
5737 {
5738 if(apIndex == 0) //private_wifi for 2.4G
5739 {
5740 wifi_GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
5741 }
5742 else if(apIndex == 1) //private_wifi for 5G
5743 {
5744 wifi_GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
5745 }
5746 else if(apIndex == 4) //public_wifi for 2.4G
5747 {
5748 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
5749 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
5750 {
5751 return RETURN_ERR;
5752 }
5753 if(buf[0] == '#')//tp-link
5754 wifi_GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
5755 else//tenda
5756 wifi_GetInterfaceName_virtualInterfaceName_2G(interface_name);
5757 }
5758 else if(apIndex == 5) //public_wifi for 5G
5759 {
5760 wifi_GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
5761 }
5762
5763 GetIfacestatus(interface_name, interface_status);
5764
5765 if(0 != strcmp(interface_status, "1"))
5766 return RETURN_ERR;
5767
5768 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
5769 system(cmd);
5770
5771 fp = fopen("/tmp/SSID_Stats.txt", "r");
5772 if(fp == NULL)
5773 {
5774 printf("/tmp/SSID_Stats.txt not exists \n");
5775 return RETURN_ERR;
5776 }
5777 fclose(fp);
5778
5779 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
5780 File_Reading(buf, Value);
5781 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
5782
5783 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
5784 File_Reading(buf, Value);
5785 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
5786
5787 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
5788 File_Reading(buf, Value);
5789 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
5790
5791 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
5792 File_Reading(buf, Value);
5793 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
5794
5795 /* There is no specific parameter from caller to associate the value wifi_Associations */
5796 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
5797 //_syscmd(cmd, buf, sizeof(buf));
5798 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
5799 }
5800#endif
5801 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5802 return RETURN_OK;
5803}
5804
5805INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
5806{
5807 char interface_name[MAX_BUF_SIZE] = {0};
5808 char interface_status[MAX_BUF_SIZE] = {0};
5809 char Value[MAX_BUF_SIZE] = {0};
5810 char buf[MAX_CMD_SIZE] = {0};
5811 char cmd[MAX_CMD_SIZE] = {0};
5812 FILE *fp = NULL;
5813
5814 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5815 if (NULL == output_struct)
5816 return RETURN_ERR;
5817
5818 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
5819
5820 if (wifi_GetInterfaceName(apIndex,interface_name) != RETURN_OK)
5821 return RETURN_ERR;
5822 GetIfacestatus(interface_name, interface_status);
5823
5824 if(0 != strcmp(interface_status, "1"))
5825 return RETURN_ERR;
5826
5827 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
5828 system(cmd);
5829
5830 fp = fopen("/tmp/SSID_Stats.txt", "r");
5831 if(fp == NULL)
5832 {
5833 printf("/tmp/SSID_Stats.txt not exists \n");
5834 return RETURN_ERR;
5835 }
5836 fclose(fp);
5837
5838 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
5839 File_Reading(buf, Value);
5840 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
5841
5842 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
5843 File_Reading(buf, Value);
5844 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
5845
5846 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
5847 File_Reading(buf, Value);
5848 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
5849
5850 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
5851 File_Reading(buf, Value);
5852 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
5853
5854 output_struct->wifi_UnicastPacketsSent = 0;
5855 output_struct->wifi_UnicastPacketsReceived = 0;
5856 output_struct->wifi_MulticastPacketsSent = 0;
5857 output_struct->wifi_MulticastPacketsReceived = 0;
5858 output_struct->wifi_BroadcastPacketsSent = 0;
5859 output_struct->wifi_BroadcastPacketsRecevied = 0;
5860 output_struct->wifi_UnknownPacketsReceived = 0;
5861
5862 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5863 return RETURN_OK;
5864}
5865
5866INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
5867{
5868 INT status = RETURN_ERR;
5869
5870 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5871 //Below values should get updated from hal
5872 output_struct->wifi_RetransCount=0;
5873 output_struct->wifi_FailedRetransCount=0;
5874 output_struct->wifi_RetryCount=0;
5875 output_struct->wifi_MultipleRetryCount=0;
5876 output_struct->wifi_ACKFailureCount=0;
5877 output_struct->wifi_AggregatedPacketCount=0;
5878
5879 status = RETURN_OK;
5880 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5881
5882 return status;
5883}
5884
5885INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
5886{
5887 INT status = RETURN_ERR;
5888 UINT index;
5889 wifi_neighbor_ap_t *pt=NULL;
5890
5891 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5892 *output_array_size=2;
5893 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
5894 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
5895 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
5896 strcpy(pt->ap_Radio,"");
5897 strcpy(pt->ap_SSID,"");
5898 strcpy(pt->ap_BSSID,"");
5899 strcpy(pt->ap_Mode,"");
5900 pt->ap_Channel=1;
5901 pt->ap_SignalStrength=0;
5902 strcpy(pt->ap_SecurityModeEnabled,"");
5903 strcpy(pt->ap_EncryptionMode,"");
5904 strcpy(pt->ap_OperatingFrequencyBand,"");
5905 strcpy(pt->ap_SupportedStandards,"");
5906 strcpy(pt->ap_OperatingStandards,"");
5907 strcpy(pt->ap_OperatingChannelBandwidth,"");
5908 pt->ap_BeaconPeriod=1;
5909 pt->ap_Noise=0;
5910 strcpy(pt->ap_BasicDataTransferRates,"");
5911 strcpy(pt->ap_SupportedDataTransferRates,"");
5912 pt->ap_DTIMPeriod=1;
5913 pt->ap_ChannelUtilization = 1;
5914 }
5915
5916 status = RETURN_OK;
5917 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5918
5919 return status;
5920}
5921
5922//----------------- AP HAL -------------------------------
5923
5924//>> Deprecated: used for old RDKB code.
5925INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
5926{
5927 if (NULL == output_ulong || NULL == output_struct)
5928 return RETURN_ERR;
5929 *output_ulong = 0;
5930 *output_struct = NULL;
5931 return RETURN_OK;
5932}
5933
5934#ifdef HAL_NETLINK_IMPL
5935static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
5936 struct nlattr *tb[NL80211_ATTR_MAX + 1];
5937 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
5938 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
5939 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
5940 char mac_addr[20];
5941 static int count=0;
5942 int rate=0;
5943
5944 wifi_device_info_t *out = (wifi_device_info_t*)arg;
5945
5946 nla_parse(tb,
5947 NL80211_ATTR_MAX,
5948 genlmsg_attrdata(gnlh, 0),
5949 genlmsg_attrlen(gnlh, 0),
5950 NULL);
5951
5952 if(!tb[NL80211_ATTR_STA_INFO]) {
5953 fprintf(stderr, "sta stats missing!\n");
5954 return NL_SKIP;
5955 }
5956
5957
5958 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
5959 fprintf(stderr, "failed to parse nested attributes!\n");
5960 return NL_SKIP;
5961 }
5962
5963 //devIndex starts from 1
5964 if( ++count == out->wifi_devIndex )
5965 {
5966 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
5967 //Getting the mac addrress
5968 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
5969
5970 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
5971 fprintf(stderr, "failed to parse nested rate attributes!");
5972 return NL_SKIP;
5973 }
5974
5975 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
developerdaf24792023-06-06 11:40:04 +08005976 if(rinfo[NL80211_RATE_INFO_BITRATE]) {
developer72fb0bb2023-01-11 09:46:29 +08005977 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
5978 out->wifi_devTxRate = rate/10;
developerdaf24792023-06-06 11:40:04 +08005979 }
developer72fb0bb2023-01-11 09:46:29 +08005980 }
5981
5982 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
5983 fprintf(stderr, "failed to parse nested rate attributes!");
5984 return NL_SKIP;
5985 }
5986
5987 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
developerdaf24792023-06-06 11:40:04 +08005988 if(rinfo[NL80211_RATE_INFO_BITRATE]) {
developer72fb0bb2023-01-11 09:46:29 +08005989 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
5990 out->wifi_devRxRate = rate/10;
developerdaf24792023-06-06 11:40:04 +08005991 }
developer72fb0bb2023-01-11 09:46:29 +08005992 }
5993 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
5994 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
5995
5996 out->wifi_devAssociatedDeviceAuthentiationState = 1;
5997 count = 0; //starts the count for next cycle
5998 return NL_STOP;
5999 }
6000
6001 return NL_SKIP;
6002
6003}
6004#endif
6005
6006INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
6007{
6008#ifdef HAL_NETLINK_IMPL
6009 Netlink nl = {0};
6010 char if_name[10] = {0};
6011 char interface_name[16] = {0};
6012
6013 wifi_device_info_t info = {0};
6014 info.wifi_devIndex = devIndex;
6015
6016 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6017 return RETURN_ERR;
6018
6019 snprintf(if_name,sizeof(if_name),"%s", interface_name);
6020
6021 nl.id = initSock80211(&nl);
6022
6023 if (nl.id < 0) {
6024 fprintf(stderr, "Error initializing netlink \n");
6025 return -1;
6026 }
6027
6028 struct nl_msg* msg = nlmsg_alloc();
6029
6030 if (!msg) {
6031 fprintf(stderr, "Failed to allocate netlink message.\n");
6032 nlfree(&nl);
6033 return -2;
6034 }
6035
6036 genlmsg_put(msg,
developer8dd72532023-05-17 19:58:35 +08006037 NL_AUTO_PID,
developer72fb0bb2023-01-11 09:46:29 +08006038 NL_AUTO_SEQ,
6039 nl.id,
6040 0,
6041 NLM_F_DUMP,
6042 NL80211_CMD_GET_STATION,
6043 0);
6044
6045 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
developer8dd72532023-05-17 19:58:35 +08006046 nl_send_auto_complete(nl.socket, msg);
developer72fb0bb2023-01-11 09:46:29 +08006047 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
6048 nl_recvmsgs(nl.socket, nl.cb);
6049 nlmsg_free(msg);
6050 nlfree(&nl);
6051
6052 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
6053 output_struct->wifi_devRxRate = info.wifi_devRxRate;
6054 output_struct->wifi_devTxRate = info.wifi_devTxRate;
6055 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
6056 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
6057 return RETURN_OK;
6058#else
6059 //iw utility to retrieve station information
6060#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
6061#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
6062#define MACFILE "/tmp/wifi_AssoMac.txt"
6063#define TXRATEFILE "/tmp/wifi_txrate.txt"
6064#define RXRATEFILE "/tmp/wifi_rxrate.txt"
6065 FILE *file = NULL;
6066 char if_name[10] = {'\0'};
6067 char pipeCmd[256] = {'\0'};
6068 char line[256] = {0};
6069 char interface_name[16] = {0};
6070 int count = 0, device = 0;
6071
6072 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6073 return RETURN_ERR;
6074
6075 snprintf(if_name,sizeof(if_name),"%s", interface_name);
6076
6077 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
6078 file = popen(pipeCmd, "r");
6079
6080 if(file == NULL)
6081 return RETURN_ERR; //popen failed
6082
6083 fgets(line, sizeof line, file);
6084 device = atoi(line);
6085 pclose(file);
6086
6087 if(device == 0)
6088 return RETURN_ERR; //No devices are connected
6089
6090 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
6091 system(pipeCmd);
6092
6093 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
6094
6095 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
6096
6097 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
6098
6099 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
6100
6101 //devIndex starts from 1, ++count
6102 if((file = fopen(SIGNALFILE, "r")) != NULL )
6103 {
6104 for(count =0;fgets(line, sizeof line, file) != NULL;)
6105 {
6106 if (++count == devIndex)
6107 {
6108 output_struct->wifi_devSignalStrength = atoi(line);
6109 break;
6110 }
6111 }
6112 fclose(file);
6113 }
6114 else
6115 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
6116
6117 if((file = fopen(MACFILE, "r")) != NULL )
6118 {
6119 for(count =0;fgets(line, sizeof line, file) != NULL;)
6120 {
6121 if (++count == devIndex)
6122 {
6123 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]);
6124 break;
6125 }
6126 }
6127 fclose(file);
6128 }
6129 else
6130 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
6131
6132 if((file = fopen(TXRATEFILE, "r")) != NULL )
6133 {
6134 for(count =0;fgets(line, sizeof line, file) != NULL;)
6135 {
6136 if (++count == devIndex)
6137 {
6138 output_struct->wifi_devTxRate = atoi(line);
6139 break;
6140 }
6141 }
6142 fclose(file);
6143 }
6144 else
6145 fprintf(stderr,"fopen wifi_txrate.txt failed");
6146
6147 if((file = fopen(RXRATEFILE, "r")) != NULL)
6148 {
6149 for(count =0;fgets(line, sizeof line, file) != NULL;)
6150 {
6151 if (++count == devIndex)
6152 {
6153 output_struct->wifi_devRxRate = atoi(line);
6154 break;
6155 }
6156 }
6157 fclose(file);
6158 }
6159 else
6160 fprintf(stderr,"fopen wifi_rxrate.txt failed");
6161
6162 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
6163
6164 return RETURN_OK;
6165#endif
6166}
6167
6168INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
6169{
6170 if (NULL == device)
6171 return RETURN_ERR;
6172 return RETURN_OK;
6173}
6174//<<
6175
6176
6177//--------------wifi_ap_hal-----------------------------
6178//enables CTS protection for the radio used by this AP
6179INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
6180{
6181 //save config and Apply instantly
6182 return RETURN_ERR;
6183}
6184
6185// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
6186INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
6187{
6188 char config_file[64] = {'\0'};
developerd1824452023-05-18 12:30:04 +08006189 char config_dat_file[64] = {'\0'};
developer72fb0bb2023-01-11 09:46:29 +08006190 char buf[64] = {'\0'};
developerd1824452023-05-18 12:30:04 +08006191 struct params list = {0};
6192 struct params dat = {0};
6193 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08006194
6195 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6196 list.name = "ht_coex";
6197 snprintf(buf, sizeof(buf), "%d", enable);
6198 list.value = buf;
6199
developerd1824452023-05-18 12:30:04 +08006200 dat.name = "HT_BSSCoexistence";
6201 dat.value = buf;
6202
6203 band = wifi_index_to_band(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08006204 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developerd1824452023-05-18 12:30:04 +08006205 snprintf(config_dat_file, sizeof(config_dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
developer72fb0bb2023-01-11 09:46:29 +08006206 wifi_hostapdWrite(config_file, &list, 1);
developer262f4cb2023-05-24 12:22:04 +08006207 wifi_datfileWrite(config_dat_file, &dat, 1);
developer72fb0bb2023-01-11 09:46:29 +08006208 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6209
6210 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6211
6212 return RETURN_OK;
6213}
6214
6215//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
6216INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
6217{
6218 char config_file[MAX_BUF_SIZE] = {'\0'};
6219 char buf[MAX_BUF_SIZE] = {'\0'};
6220 struct params list;
6221
6222 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6223 if (threshold < 256 || threshold > 2346 )
6224 return RETURN_ERR;
6225 list.name = "fragm_threshold";
6226 snprintf(buf, sizeof(buf), "%d", threshold);
6227 list.value = buf;
6228
6229 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6230 wifi_hostapdWrite(config_file, &list, 1);
6231 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6232
6233 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6234
6235 return RETURN_OK;
6236}
6237
6238// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
6239INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
6240{
6241 char config_file[64] = {'\0'};
6242 char cmd[512] = {'\0'};
6243 char buf[512] = {'\0'};
6244 char stbc_config[16] = {'\0'};
6245 wifi_band band;
6246 int iterator = 0;
6247 BOOL current_stbc = FALSE;
6248 int ant_count = 0;
6249 int ant_bitmap = 0;
6250 struct params list;
developera1255e42023-05-13 17:45:02 +08006251 char dat_file[64] = {'\0'};
developer72fb0bb2023-01-11 09:46:29 +08006252
6253 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6254
6255 band = wifi_index_to_band(radioIndex);
6256 if (band == band_invalid)
6257 return RETURN_ERR;
6258
6259 if (band == band_2_4)
6260 iterator = 1;
developera1255e42023-05-13 17:45:02 +08006261 else if ((band == band_5) || (band == band_6))
developer72fb0bb2023-01-11 09:46:29 +08006262 iterator = 2;
6263 else
6264 return RETURN_OK;
6265
6266 wifi_getRadioTxChainMask(radioIndex, &ant_bitmap);
6267 for (; ant_bitmap > 0; ant_bitmap >>= 1)
6268 ant_count += ant_bitmap & 1;
6269
6270 if (ant_count == 1 && STBC_Enable == TRUE) {
6271 fprintf(stderr, "%s: can not enable STBC when using only one antenna\n", __func__);
6272 return RETURN_OK;
6273 }
6274
6275 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
6276
6277 // set ht and vht config
6278 for (int i = 0; i < iterator; i++) {
6279 memset(stbc_config, 0, sizeof(stbc_config));
6280 memset(cmd, 0, sizeof(cmd));
6281 memset(buf, 0, sizeof(buf));
6282 list.name = (i == 0)?"ht_capab":"vht_capab";
6283 snprintf(stbc_config, sizeof(stbc_config), "%s", list.name);
6284 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
6285 _syscmd(cmd, buf, sizeof(buf));
6286 if (strlen(buf) != 0)
6287 current_stbc = TRUE;
6288 if (current_stbc == STBC_Enable)
6289 continue;
6290
6291 if (STBC_Enable == TRUE) {
6292 // Append the STBC flags in capab config
6293 memset(cmd, 0, sizeof(cmd));
6294 if (i == 0)
6295 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
6296 else
6297 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1][RX-STBC-1]/' %s", config_file);
6298 _syscmd(cmd, buf, sizeof(buf));
6299 } else if (STBC_Enable == FALSE) {
6300 // Remove the STBC flags and remain other flags in capab
6301 memset(cmd, 0, sizeof(cmd));
6302 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
6303 _syscmd(cmd, buf, sizeof(buf));
6304 memset(cmd, 0, sizeof(cmd));
6305 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
6306 _syscmd(cmd, buf, sizeof(buf));
6307 }
6308 wifi_hostapdRead(config_file, list.name, buf, sizeof(buf));
6309 list.value = buf;
6310 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
6311 }
developera1255e42023-05-13 17:45:02 +08006312 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
6313 snprintf(cmd, sizeof(cmd), "sed -r -i 's/^HT_STBC=.*/HT_STBC=%d/g' %s", STBC_Enable, dat_file);
6314 _syscmd(cmd, buf, sizeof(buf));
6315 if ((band == band_5) || (band == band_6)) {
6316 snprintf(cmd, sizeof(cmd), "sed -r -i 's/^VHT_STBC=.*/VHT_STBC=%d/g' %s", STBC_Enable, dat_file);
6317 _syscmd(cmd, buf, sizeof(buf));
6318 }
6319 /*wifi_reloadAp(radioIndex);
6320 the caller do this.*/
developer72fb0bb2023-01-11 09:46:29 +08006321
6322 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6323 return RETURN_OK;
6324}
6325
6326// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
6327INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
6328{
developer2c22d832023-05-18 17:46:26 +08006329 char dat_file[128] = {0};
developer2c22d832023-05-18 17:46:26 +08006330 wifi_band band;
6331 char amdus_buff[8] = {'\0'};
developer72fb0bb2023-01-11 09:46:29 +08006332
developer2c22d832023-05-18 17:46:26 +08006333 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08006334
developer2c22d832023-05-18 17:46:26 +08006335 band = wifi_index_to_band(radioIndex);
6336 if (band == band_invalid) {
6337 printf("%s:Band Error\n", __func__);
6338 return RETURN_ERR;
6339 }
6340 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
6341 wifi_datfileRead(dat_file, "HT_AMSDU", amdus_buff, sizeof(amdus_buff));
6342 if (strncmp(amdus_buff, "1", 1) == 0)
developer72fb0bb2023-01-11 09:46:29 +08006343 *output_bool = TRUE;
developer2c22d832023-05-18 17:46:26 +08006344 else
6345 *output_bool = FALSE;
developer72fb0bb2023-01-11 09:46:29 +08006346
developer2c22d832023-05-18 17:46:26 +08006347 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6348
6349 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006350}
6351
6352// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
6353INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
6354{
developer2c22d832023-05-18 17:46:26 +08006355 char dat_file[128] = {0};
6356 BOOL enable;
6357 wifi_band band;
6358 char amdus_buff[8] = {'\0'};
6359 struct params params = {0};
developer72fb0bb2023-01-11 09:46:29 +08006360
developer2c22d832023-05-18 17:46:26 +08006361 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08006362
developer2c22d832023-05-18 17:46:26 +08006363 band = wifi_index_to_band(radioIndex);
6364 if (band == band_invalid) {
6365 printf("%s:Band Error\n", __func__);
6366 return RETURN_ERR;
6367 }
6368 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
6369 wifi_datfileRead(dat_file, "HT_AMSDU", amdus_buff, sizeof(amdus_buff));
6370 if (strncmp(amdus_buff, "1", 1) == 0)
6371 enable = TRUE;
6372 else
6373 enable = FALSE;
6374 if (amsduEnable == enable)
6375 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006376
developer2c22d832023-05-18 17:46:26 +08006377 params.name = "HT_AMSDU";
6378 if (amsduEnable)
6379 params.value = "1";
6380 else
6381 params.value = "0";
6382 wifi_datfileWrite(dat_file, &params, 1);
6383 wifi_reloadAp(radioIndex);
developer72fb0bb2023-01-11 09:46:29 +08006384
developer2c22d832023-05-18 17:46:26 +08006385 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08006386
developer72fb0bb2023-01-11 09:46:29 +08006387 return RETURN_OK;
6388}
6389
6390//P2 // outputs the number of Tx streams
6391INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
6392{
6393 char buf[8] = {0};
6394 char cmd[128] = {0};
6395 int phyId = 0;
6396
6397 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6398
6399 phyId = radio_index_to_phy(radioIndex);
6400 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Configured Antennas' | awk '{print $4}'", phyId);
6401 _syscmd(cmd, buf, sizeof(buf));
6402
6403 *output_int = (INT)strtol(buf, NULL, 16);
6404
6405 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6406
6407 return RETURN_OK;
6408}
6409
6410INT fitChainMask(INT radioIndex, int antcount)
6411{
6412 char buf[128] = {0};
6413 char cmd[128] = {0};
6414 char config_file[64] = {0};
6415 wifi_band band;
6416 struct params list[2] = {0};
6417
6418 band = wifi_index_to_band(radioIndex);
6419 if (band == band_invalid)
6420 return RETURN_ERR;
6421
6422 list[0].name = "he_mu_beamformer";
6423 list[1].name = "he_su_beamformer";
6424
6425 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
6426 if (antcount == 1) {
6427 // remove config about multiple antennas
6428 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
6429 _syscmd(cmd, buf, sizeof(buf));
6430
6431 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SOUNDING-DIMENSION-.\\]//' %s", config_file);
6432 _syscmd(cmd, buf, sizeof(buf));
6433
6434 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SU-BEAMFORMER\\]//' %s", config_file);
6435 _syscmd(cmd, buf, sizeof(buf));
6436
6437 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[MU-BEAMFORMER\\]//' %s", config_file);
6438 _syscmd(cmd, buf, sizeof(buf));
6439
6440 list[0].value = "0";
6441 list[1].value = "0";
6442 } else {
6443 // 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.
6444 if (band == band_2_4 || band == band_5) {
6445 snprintf(cmd, sizeof(cmd), "cat %s | grep '^ht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
6446 _syscmd(cmd, buf, sizeof(buf));
6447 if (strlen(buf) > 0) {
6448 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC]/' %s", config_file);
6449 _syscmd(cmd, buf, sizeof(buf));
6450 }
6451 }
6452 if (band == band_5) {
6453 snprintf(cmd, sizeof(cmd), "cat %s | grep '^vht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
6454 _syscmd(cmd, buf, sizeof(buf));
6455 if (strlen(buf) > 0) {
6456 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1]/' %s", config_file);
6457 _syscmd(cmd, buf, sizeof(buf));
6458 }
6459 }
6460
6461 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SU-BEAMFORMER\\]'", config_file);
6462 _syscmd(cmd, buf, sizeof(buf));
6463 if (strlen(buf) == 0) {
6464 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SU-BEAMFORMER]/' %s", config_file);
6465 _syscmd(cmd, buf, sizeof(buf));
6466 }
6467
6468 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[MU-BEAMFORMER\\]'", config_file);
6469 _syscmd(cmd, buf, sizeof(buf));
6470 if (strlen(buf) == 0) {
6471 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[MU-BEAMFORMER]/' %s", config_file);
6472 _syscmd(cmd, buf, sizeof(buf));
6473 }
6474
6475 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SOUNDING-DIMENSION-.\\]'", config_file);
6476 _syscmd(cmd, buf, sizeof(buf));
6477 if (strlen(buf) == 0) {
6478 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SOUNDING-DIMENSION-%d]/' %s", antcount, config_file);
6479 } else {
6480 snprintf(cmd, sizeof(cmd), "sed -r -i 's/(SOUNDING-DIMENSION-)./\\1%d/' %s", antcount, config_file);
6481 }
6482 _syscmd(cmd, buf, sizeof(buf));
6483
6484 list[0].value = "1";
6485 list[1].value = "1";
6486 }
6487 wifi_hostapdWrite(config_file, list, 2);
developerdaf24792023-06-06 11:40:04 +08006488 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006489}
6490
6491//P2 // sets the number of Tx streams to an enviornment variable
6492INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
6493{
6494 char cmd[128] = {0};
6495 char buf[128] = {0};
6496 int phyId = 0;
6497 int cur_mask = 0;
developera1255e42023-05-13 17:45:02 +08006498 int antcountmsk = 0;
6499 INT cur_nss = 0;
6500 UCHAR dat_file[64] = {0};
6501 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08006502
6503 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6504
6505 if (numStreams <= 0) {
6506 fprintf(stderr, "%s: chainmask is not supported %d.\n", __func__, numStreams);
6507 return RETURN_ERR;
6508 }
6509
developera1255e42023-05-13 17:45:02 +08006510 wifi_getRadioTxChainMask(radioIndex, &cur_mask);//this is mask value
6511 for(; cur_mask > 0; cur_mask >>= 1)//convert to number of streams.
6512 cur_nss += 1;
6513 WIFI_ENTRY_EXIT_DEBUG("%s:cur_nss=%d, new_nss=%d\n", __func__, cur_nss, numStreams);
6514 if (cur_nss == numStreams)
developer72fb0bb2023-01-11 09:46:29 +08006515 return RETURN_OK;
6516
6517 wifi_setRadioEnable(radioIndex, FALSE);
6518
6519 phyId = radio_index_to_phy(radioIndex);
developera1255e42023-05-13 17:45:02 +08006520 //iw need mask value.
6521 for (;numStreams > 0; numStreams--)
6522 antcountmsk |= 0x1 << (numStreams - 1);
6523 snprintf(cmd, sizeof(cmd), "iw phy%d set antenna 0x%x 2>&1", phyId, antcountmsk);
developer72fb0bb2023-01-11 09:46:29 +08006524 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006525 if (strlen(buf) > 0) {
6526 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
6527 return RETURN_ERR;
6528 }
developera1255e42023-05-13 17:45:02 +08006529 band = wifi_index_to_band(radioIndex);
6530 if (band == band_invalid) {
6531 printf("%s:Band Error\n", __func__);
6532 return RETURN_ERR;
6533 }
6534 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
6535 snprintf(cmd, sizeof(cmd), "sed -r -i 's/^HT_TxStream=.*/HT_TxStream=%d/g' %s", numStreams, dat_file);
6536 _syscmd(cmd, buf, sizeof(buf));
6537 if (strlen(buf) > 0) {
6538 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
6539 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006540 }
developera1255e42023-05-13 17:45:02 +08006541 snprintf(cmd, sizeof(cmd), "sed -r -i 's/^HT_RxStream=.*/HT_RxStream=%d/g' %s", numStreams, dat_file);
6542 _syscmd(cmd, buf, sizeof(buf));
6543 if (strlen(buf) > 0) {
6544 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
6545 return RETURN_ERR;
6546 }
6547 fitChainMask(radioIndex, numStreams);
developer72fb0bb2023-01-11 09:46:29 +08006548 wifi_setRadioEnable(radioIndex, TRUE);
6549
6550 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6551 return RETURN_OK;
6552}
6553
6554//P2 // outputs the number of Rx streams
6555INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
6556{
6557 char buf[8] = {0};
6558 char cmd[128] = {0};
6559 int phyId = 0;
6560
6561 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6562
6563 phyId = radio_index_to_phy(radioIndex);
6564 sprintf(cmd, "iw phy%d info | grep 'Configured Antennas' | awk '{print $6}'", phyId);
6565 _syscmd(cmd, buf, sizeof(buf));
6566
6567 *output_int = (INT)strtol(buf, NULL, 16);
6568
6569 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6570
6571 return RETURN_OK;
6572}
6573
6574//P2 // sets the number of Rx streams to an enviornment variable
6575INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
6576{
6577 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6578 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
6579 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
6580 return RETURN_ERR;
6581 }
6582 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6583 return RETURN_ERR;
6584}
6585
6586//Get radio RDG enable setting
6587INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
6588{
developer47cc27a2023-05-17 23:09:58 +08006589 if (NULL == output_bool)
6590 return RETURN_ERR;
6591
6592 *output_bool = TRUE;
6593 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006594}
6595
6596//Get radio RDG enable setting
6597INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
6598{
developer47cc27a2023-05-17 23:09:58 +08006599 char rdg_status[2] = {0};
6600 char dat_file[MAX_CMD_SIZE] = {0};
developer47cc27a2023-05-17 23:09:58 +08006601
6602 if (NULL == output_bool)
6603 return RETURN_ERR;
6604
6605 /*prepare dat file path*/
6606 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, radioIndex);
6607
6608 wifi_datfileRead(dat_file, "HT_RDG", rdg_status, sizeof(rdg_status));
6609 if (!strncmp(rdg_status, "1", sizeof(rdg_status)))
6610 *output_bool = TRUE;
6611 else
6612 *output_bool = FALSE;
6613
6614 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006615}
6616
6617//Set radio RDG enable setting
6618INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
6619{
developer47cc27a2023-05-17 23:09:58 +08006620 char dat_file[MAX_CMD_SIZE] = {0};
6621 struct params params = {0};
6622
6623 /*prepare dat file path*/
6624 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, radioIndex);
6625
6626 params.name = "HT_RDG";
6627
6628 if (enable) {
6629 params.value = "1";
6630 } else {
6631 params.value = "0";
6632 }
6633
6634 wifi_datfileWrite(dat_file, &params, 1);
6635
6636 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006637}
6638
developer5cd4c862023-05-26 09:34:42 +08006639
6640int mtk_get_ba_auto_status_callback(struct nl_msg *msg, void *data)
developer72fb0bb2023-01-11 09:46:29 +08006641{
developer5cd4c862023-05-26 09:34:42 +08006642 struct nlattr *tb[NL80211_ATTR_MAX + 1];
6643 struct nlattr *vndr_tb[MTK_NL80211_VENDOR_AP_BA_ATTR_MAX + 1];
6644 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
6645 unsigned char status;
6646 unsigned char *out_status = data;
6647 int err = 0;
developer8e6583c2023-05-23 13:36:06 +08006648
developer5cd4c862023-05-26 09:34:42 +08006649 err = nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
6650 genlmsg_attrlen(gnlh, 0), NULL);
6651 if (err < 0){
6652 wifi_debug(DEBUG_ERROR, "get NL80211_ATTR_MAX fails\n");
6653 return err;
6654 }
developer8e6583c2023-05-23 13:36:06 +08006655
developer5cd4c862023-05-26 09:34:42 +08006656 if (tb[NL80211_ATTR_VENDOR_DATA]) {
6657 err = nla_parse_nested(vndr_tb, MTK_NL80211_VENDOR_AP_BA_ATTR_MAX,
6658 tb[NL80211_ATTR_VENDOR_DATA], NULL);
6659 if (err < 0){
6660 wifi_debug(DEBUG_ERROR, "get MTK_NL80211_VENDOR_AP_BA_ATTR_MAX fails\n");
6661 return err;
6662 }
developer8e6583c2023-05-23 13:36:06 +08006663
developer5cd4c862023-05-26 09:34:42 +08006664 if (vndr_tb[MTK_NL80211_VENDOR_ATTR_AP_BA_EN_INFO]) {
6665 status = nla_get_u8(vndr_tb[MTK_NL80211_VENDOR_ATTR_AP_BA_EN_INFO]);
6666 if (status == 0) {
6667 wifi_debug(DEBUG_NOTICE, "disabled\n");
6668 } else {
6669 wifi_debug(DEBUG_NOTICE, "enabled\n");
6670 }
6671 *out_status = status;
6672 }
6673 }
developer8e6583c2023-05-23 13:36:06 +08006674
developer5cd4c862023-05-26 09:34:42 +08006675 return 0;
6676}
developer8e6583c2023-05-23 13:36:06 +08006677
developer5cd4c862023-05-26 09:34:42 +08006678int mtk_get_ba_decline_status_callback(struct nl_msg *msg, void *data)
6679{
6680 struct nlattr *tb[NL80211_ATTR_MAX + 1];
6681 struct nlattr *vndr_tb[MTK_NL80211_VENDOR_AP_BA_ATTR_MAX + 1];
6682 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
6683 unsigned char status;
6684 unsigned char *out_status = data;
6685 int err = 0;
6686
6687 err = nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
6688 genlmsg_attrlen(gnlh, 0), NULL);
6689 if (err < 0) {
6690 wifi_debug(DEBUG_ERROR, "get NL80211_ATTR_MAX fails\n");
6691 return err;
6692 }
6693
6694 if (tb[NL80211_ATTR_VENDOR_DATA]) {
6695 err = nla_parse_nested(vndr_tb, MTK_NL80211_VENDOR_AP_BA_ATTR_MAX,
6696 tb[NL80211_ATTR_VENDOR_DATA], NULL);
6697 if (err < 0) {
6698 wifi_debug(DEBUG_ERROR, "get MTK_NL80211_VENDOR_AP_BA_ATTR_MAX fails\n");
6699 return err;
6700 }
6701
6702 if (vndr_tb[MTK_NL80211_VENDOR_ATTR_AP_BA_DECLINE_INFO]) {
6703 status = nla_get_u8(vndr_tb[MTK_NL80211_VENDOR_ATTR_AP_BA_DECLINE_INFO]);
6704 if (status == 0) {
6705 wifi_debug(DEBUG_NOTICE, "disabled\n");
6706 } else {
6707 wifi_debug(DEBUG_NOTICE, "enabled\n");
6708 }
6709 *out_status = status;
6710 }
6711 }
6712
6713 return NL_OK;
developer72fb0bb2023-01-11 09:46:29 +08006714}
6715
developer5cd4c862023-05-26 09:34:42 +08006716INT mtk_wifi_get_ba_decl_auto_status(
6717 INT apIndex, INT vendor_data_attr, mtk_nl80211_cb call_back, BOOL *output_bool)
6718{
6719 char inf_name[IF_NAME_SIZE] = {0};
developer5cd4c862023-05-26 09:34:42 +08006720 unsigned int if_idx = 0;
6721 int ret = -1;
6722 struct unl unl_ins;
6723 struct nl_msg *msg = NULL;
6724 struct nlattr * msg_data = NULL;
6725 struct mtk_nl80211_param param;
6726
6727 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
6728 return RETURN_ERR;
6729 if_idx = if_nametoindex(inf_name);
6730 if (!if_idx) {
6731 wifi_debug(DEBUG_ERROR,"can't finde ifname(%s) index,ERROR\n", inf_name);
6732 return RETURN_ERR;
6733 }
6734 /*init mtk nl80211 vendor cmd*/
6735 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_BA;
6736 param.if_type = NL80211_ATTR_IFINDEX;
6737 param.if_idx = if_idx;
6738
6739 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
6740 if (ret) {
6741 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
6742 return RETURN_ERR;
6743 }
6744 /*add mtk vendor cmd data*/
6745 if (nla_put_u8(msg, vendor_data_attr, 0xf)) {
6746 wifi_debug(DEBUG_ERROR, "Nla put vendor_data_attr(%d) attribute error\n", vendor_data_attr);
6747 nlmsg_free(msg);
6748 goto err;
6749 }
6750
6751 /*send mtk nl80211 vendor msg*/
6752 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, call_back, output_bool);
6753 if (ret) {
6754 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
6755 goto err;
6756 }
6757 /*deinit mtk nl80211 vendor msg*/
6758 mtk_nl80211_deint(&unl_ins);
6759 wifi_debug(DEBUG_NOTICE,"send cmd success, get output_bool:%d\n", *output_bool);
6760 return RETURN_OK;
6761err:
6762 mtk_nl80211_deint(&unl_ins);
6763 wifi_debug(DEBUG_ERROR,"send cmd fails\n");
6764 return RETURN_ERR;
6765}
6766//Get radio ADDBA enable setting
6767INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
6768{
6769 if (output_bool == NULL) {
6770 wifi_debug(DEBUG_ERROR, "invalid: output_bool is null\n");
6771 return RETURN_ERR;
6772 }
6773 if (mtk_wifi_get_ba_decl_auto_status(radioIndex,
6774 MTK_NL80211_VENDOR_ATTR_AP_BA_DECLINE_INFO, mtk_get_ba_decline_status_callback, output_bool) != RETURN_OK) {
6775 wifi_debug(DEBUG_ERROR, "cmd MTK_NL80211_VENDOR_ATTR_AP_BA_DECLINE_INFO(0x%x) fails\n",
6776 MTK_NL80211_VENDOR_ATTR_AP_BA_DECLINE_INFO);
6777 return RETURN_ERR;
6778 }
6779 wifi_debug(DEBUG_NOTICE, "cmd success:output_bool(%d)\n", *output_bool);
6780 return RETURN_OK;
6781}
6782
developer72fb0bb2023-01-11 09:46:29 +08006783//Set radio ADDBA enable setting
6784INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
6785{
6786 return RETURN_ERR;
6787}
6788
6789//Get radio auto block ack enable setting
6790INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
6791{
developer5cd4c862023-05-26 09:34:42 +08006792 if (output_bool == NULL) {
6793 wifi_debug(DEBUG_ERROR, "invalid: output_bool is null\n");
6794 return RETURN_ERR;
6795 }
developer8e6583c2023-05-23 13:36:06 +08006796
developer5cd4c862023-05-26 09:34:42 +08006797 if (mtk_wifi_get_ba_decl_auto_status(radioIndex,
6798 MTK_NL80211_VENDOR_ATTR_AP_BA_EN_INFO,
6799 mtk_get_ba_auto_status_callback, output_bool) != RETURN_OK) {
6800 wifi_debug(DEBUG_ERROR, "cmd MTK_NL80211_VENDOR_ATTR_AP_BA_EN_INFO(0x%x) fails\n",
6801 MTK_NL80211_VENDOR_ATTR_AP_BA_EN_INFO);
6802 return RETURN_ERR;
6803 }
6804 wifi_debug(DEBUG_NOTICE, "cmd success:output_bool(%d)\n", *output_bool);
6805 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006806}
6807
6808//Set radio auto block ack enable setting
6809INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
6810{
6811 return RETURN_ERR;
6812}
6813
6814//Get radio 11n pure mode enable support
6815INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
6816{
6817 if (NULL == output_bool)
6818 return RETURN_ERR;
6819 *output_bool = TRUE;
6820 return RETURN_OK;
6821}
6822
6823//Get radio 11n pure mode enable setting
6824INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
6825{
6826 if (NULL == output_bool)
6827 return RETURN_ERR;
6828 *output_bool = TRUE;
6829 return RETURN_OK;
6830}
6831
6832//Set radio 11n pure mode enable setting
6833INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
6834{
6835 return RETURN_ERR;
6836}
6837
developer5cd4c862023-05-26 09:34:42 +08006838
6839int mtk_get_igmp_status_callback(struct nl_msg *msg, void *data)
developer72fb0bb2023-01-11 09:46:29 +08006840{
developer5cd4c862023-05-26 09:34:42 +08006841 struct nlattr *tb[NL80211_ATTR_MAX + 1];
6842 struct nlattr *vndr_tb[MTK_NL80211_VENDOR_MCAST_SNOOP_ATTR_MAX + 1];
6843 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
6844 unsigned char status = 0, *out_status = data;
6845 int err = 0;
developer72fb0bb2023-01-11 09:46:29 +08006846
developer5cd4c862023-05-26 09:34:42 +08006847 err = nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
6848 genlmsg_attrlen(gnlh, 0), NULL);
6849 if (err < 0) {
6850 wifi_debug(DEBUG_ERROR, "get NL80211_ATTR_MAX fails\n");
6851 return err;
6852 }
developer72fb0bb2023-01-11 09:46:29 +08006853
developer5cd4c862023-05-26 09:34:42 +08006854 if (tb[NL80211_ATTR_VENDOR_DATA]) {
6855 err = nla_parse_nested(vndr_tb, MTK_NL80211_VENDOR_MCAST_SNOOP_ATTR_MAX,
6856 tb[NL80211_ATTR_VENDOR_DATA], NULL);
6857 if (err < 0){
6858 wifi_debug(DEBUG_ERROR, "get MTK_NL80211_VENDOR_MCAST_SNOOP_ATTR_MAX fails\n");
6859 return err;
6860 }
developer72fb0bb2023-01-11 09:46:29 +08006861
developer5cd4c862023-05-26 09:34:42 +08006862 if (vndr_tb[MTK_NL80211_VENDOR_ATTR_MCAST_SNOOP_ENABLE]) {
6863 status = nla_get_u8(vndr_tb[MTK_NL80211_VENDOR_ATTR_MCAST_SNOOP_ENABLE]);
6864 if (status == 0) {
6865 wifi_debug(DEBUG_NOTICE, "disabled\n");
6866 } else {
6867 wifi_debug(DEBUG_NOTICE, "enabled\n");
6868 }
6869 *out_status = status;
6870 wifi_debug(DEBUG_NOTICE, "status: %d\n", *out_status);
6871 }
6872 }
6873
6874 return 0;
6875}
6876
6877INT mtk_wifi_set_igmp_en_status(
6878 INT apIndex, INT vendor_data_attr, mtk_nl80211_cb call_back,
6879 unsigned char in_en_stat, BOOL *output_bool)
6880{
6881 char inf_name[IF_NAME_SIZE] = {0};
developer5cd4c862023-05-26 09:34:42 +08006882 unsigned int if_idx = 0;
6883 int ret = -1;
6884 struct unl unl_ins;
6885 struct nl_msg *msg = NULL;
6886 struct nlattr * msg_data = NULL;
6887 struct mtk_nl80211_param param;
6888
6889 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
6890 return RETURN_ERR;
6891 if_idx = if_nametoindex(inf_name);
6892 if (!if_idx) {
6893 wifi_debug(DEBUG_ERROR,"can't finde ifname(%s) index,ERROR\n", inf_name);
6894 return RETURN_ERR;
6895 }
6896 /*init mtk nl80211 vendor cmd*/
6897 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_MULTICAST_SNOOPING;
6898 param.if_type = NL80211_ATTR_IFINDEX;
6899 param.if_idx = if_idx;
6900
6901 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
6902 if (ret) {
6903 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
6904 return RETURN_ERR;
6905 }
6906 /*add mtk vendor cmd data*/
6907 if (nla_put_u8(msg, vendor_data_attr, in_en_stat)) {
6908 wifi_debug(DEBUG_ERROR, "Nla put vendor_data_attr(%d) attribute error\n", vendor_data_attr);
6909 nlmsg_free(msg);
6910 goto err;
6911 }
6912
6913 /*send mtk nl80211 vendor msg*/
6914 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, call_back, output_bool);
6915 if (ret) {
6916 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
6917 goto err;
6918 }
6919 /*deinit mtk nl80211 vendor msg*/
6920 mtk_nl80211_deint(&unl_ins);
6921 if (output_bool) {
6922 wifi_debug(DEBUG_NOTICE, "send cmd success, get output_bool:%d\n", *output_bool);
6923 } else {
6924 wifi_debug(DEBUG_NOTICE, "send cmd success.\n");
6925 }
6926 return RETURN_OK;
6927err:
6928 mtk_nl80211_deint(&unl_ins);
6929 wifi_debug(DEBUG_ERROR,"send cmd fails\n");
6930 return RETURN_ERR;
6931}
6932
6933
6934//Get radio IGMP snooping enable setting
6935INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
6936{
6937 if (output_bool == NULL) {
6938 wifi_debug(DEBUG_ERROR, "invalid: output_bool is null\n");
6939 return RETURN_ERR;
6940 }
6941 if (mtk_wifi_set_igmp_en_status
6942 (radioIndex, MTK_NL80211_VENDOR_ATTR_MCAST_SNOOP_ENABLE,
6943 mtk_get_igmp_status_callback, 0xf, output_bool)!= RETURN_OK) {
6944 wifi_debug(DEBUG_ERROR, "send MTK_NL80211_VENDOR_ATTR_MCAST_SNOOP_ENABLE cmd fails\n");
6945 return RETURN_ERR;
6946 }
6947 wifi_debug(DEBUG_ERROR, "send cmd success: get igmp status:(%d)\n", *output_bool);
developer72fb0bb2023-01-11 09:46:29 +08006948 return RETURN_OK;
6949}
6950
6951//Set radio IGMP snooping enable setting
6952INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
6953{
developer5cd4c862023-05-26 09:34:42 +08006954 if (mtk_wifi_set_igmp_en_status
6955 (radioIndex, MTK_NL80211_VENDOR_ATTR_MCAST_SNOOP_ENABLE,
6956 NULL, enable, NULL) != RETURN_OK) {
6957 wifi_debug(DEBUG_ERROR, "send MTK_NL80211_VENDOR_ATTR_MCAST_SNOOP_ENABLE cmd fails\n");
6958 return RETURN_ERR;
6959 }
6960 wifi_debug(DEBUG_ERROR, "send cmd success: set igmp enable(%d)\n", enable);
developer72fb0bb2023-01-11 09:46:29 +08006961 return RETURN_OK;
6962}
6963
6964//Get the Reset count of radio
developer69b61b02023-03-07 17:17:44 +08006965INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
developer72fb0bb2023-01-11 09:46:29 +08006966{
developer69b61b02023-03-07 17:17:44 +08006967 if (NULL == output_int)
developer72fb0bb2023-01-11 09:46:29 +08006968 return RETURN_ERR;
developerfead3972023-05-25 20:15:02 +08006969 *output_int = get_radio_reset_cnt(radioIndex);
developer72fb0bb2023-01-11 09:46:29 +08006970
6971 return RETURN_OK;
6972}
6973
6974
6975//---------------------------------------------------------------------------------------------------
6976//
6977// Additional Wifi AP level APIs used for Access Point devices
6978//
6979//---------------------------------------------------------------------------------------------------
6980
6981// creates a new ap and pushes these parameters to the hardware
6982INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
6983{
6984 // Deprecated when use hal version 3, use wifi_createVap() instead.
6985 return RETURN_OK;
6986}
6987
6988// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
6989INT wifi_deleteAp(INT apIndex)
6990{
developer7e4a2a62023-04-06 19:56:03 +08006991 char interface_name[16] = {0};
6992 char buf[MAX_BUF_SIZE];
6993 char cmd[MAX_CMD_SIZE];
developer72fb0bb2023-01-11 09:46:29 +08006994
developer7e4a2a62023-04-06 19:56:03 +08006995 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6996 return RETURN_ERR;
developer8a3bbbf2023-03-15 17:47:23 +08006997
developer7e4a2a62023-04-06 19:56:03 +08006998 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw REMOVE %s", interface_name);
6999 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08007000
developer7e4a2a62023-04-06 19:56:03 +08007001 wifi_removeApSecVaribles(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08007002
developer7e4a2a62023-04-06 19:56:03 +08007003 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08007004}
7005
7006// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
7007INT wifi_getApName(INT apIndex, CHAR *output_string)
7008{
developer7e4a2a62023-04-06 19:56:03 +08007009 char interface_name[IF_NAME_SIZE] = {0};
developer47cc27a2023-05-17 23:09:58 +08007010 int radio_idx = 0;
7011 int bss_idx = 0;
developer72fb0bb2023-01-11 09:46:29 +08007012
developer7e4a2a62023-04-06 19:56:03 +08007013 if(!output_string)
7014 return RETURN_ERR;
7015
7016 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
7017 vap_index_to_array_index(apIndex, &radio_idx, &bss_idx);
7018
7019 snprintf(output_string, IF_NAME_SIZE, "%s%d", ext_prefix[radio_idx], bss_idx); // For wifiagent generating data model.
7020 } else
7021 snprintf(output_string, IF_NAME_SIZE, "%s", interface_name);
7022
7023 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08007024}
7025
7026// Outputs the index number in that corresponds to the SSID string
7027INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
7028{
developer7e4a2a62023-04-06 19:56:03 +08007029 char cmd [128] = {0};
7030 char buf[32] = {0};
7031 char ap_idx = 0;
7032 char *apIndex_str = NULL;
7033 char radio_idx = 0;
7034 char bss_idx = 0;
developer72fb0bb2023-01-11 09:46:29 +08007035
developer7e4a2a62023-04-06 19:56:03 +08007036 snprintf(cmd, sizeof(cmd), "grep -rn ^interface=%s$ /nvram/hostapd*.conf | cut -d '.' -f1 | cut -d 'd' -f2 | tr -d '\\n'",
7037 inputSsidString);
7038 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08007039
developer7e4a2a62023-04-06 19:56:03 +08007040 if (strlen(buf)) {
7041 apIndex_str = strtok(buf, "\n");
7042 *output_int = strtoul(apIndex_str, NULL, 10);
7043 return RETURN_OK;
7044 }
developer72fb0bb2023-01-11 09:46:29 +08007045
developer7e4a2a62023-04-06 19:56:03 +08007046 /* If interface name is not in hostapd config, the caller maybe wifi agent to generate data model.*/
7047 if (strstr(inputSsidString, PREFIX_WIFI6G)) {
7048 bss_idx = atoi(inputSsidString + strlen(PREFIX_WIFI6G));
7049 radio_idx = 2;
7050 } else if (strstr(inputSsidString, PREFIX_WIFI5G)) {
7051 bss_idx = atoi(inputSsidString + strlen(PREFIX_WIFI5G));
7052 radio_idx = 1;
7053 } else if (strstr(inputSsidString, PREFIX_WIFI2G)) {
7054 bss_idx = atoi(inputSsidString + strlen(PREFIX_WIFI2G));
7055 radio_idx = 0;
7056 } else {
7057 printf("%s: hostapd conf not find, unknow inf(%s), return ERROR!!!(%d).\n",
7058 __func__, inputSsidString, ap_idx);
7059 *output_int = -1;
7060 return RETURN_ERR;
7061 }
7062
7063 ap_idx = array_index_to_vap_index(radio_idx, bss_idx);
7064
7065 if (ap_idx >= 0 && ap_idx < MAX_VAP) {
7066 printf("%s: hostapd conf not find, inf(%s), use inf idx(%d).\n",
7067 __func__, inputSsidString, ap_idx);
7068 *output_int = ap_idx;
7069 return RETURN_OK;
7070 }
7071
7072 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007073}
7074
7075INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
7076{
7077 return wifi_getIndexFromName(inputSsidString, output_int);
7078}
7079
7080// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
7081INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
7082{
7083 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08007084 char config_file[MAX_BUF_SIZE] = {0};
7085
7086 if(NULL == output_string)
7087 return RETURN_ERR;
7088
7089 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7090 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
7091 if((strcmp(buf,"3")==0))
7092 snprintf(output_string, 32, "WPAand11i");
7093 else if((strcmp(buf,"2")==0))
7094 snprintf(output_string, 32, "11i");
7095 else if((strcmp(buf,"1")==0))
7096 snprintf(output_string, 32, "WPA");
7097 else
7098 snprintf(output_string, 32, "None");
7099
7100 return RETURN_OK;
7101}
7102
7103// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
7104INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
7105{
7106 char config_file[MAX_BUF_SIZE] = {0};
7107 struct params list;
7108
7109 if (NULL == beaconTypeString)
7110 return RETURN_ERR;
7111 list.name = "wpa";
7112 list.value = "0";
7113
7114 if((strcmp(beaconTypeString,"WPAand11i")==0))
7115 list.value="3";
7116 else if((strcmp(beaconTypeString,"11i")==0))
7117 list.value="2";
7118 else if((strcmp(beaconTypeString,"WPA")==0))
7119 list.value="1";
7120
7121 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7122 wifi_hostapdWrite(config_file, &list, 1);
7123 wifi_hostapdProcessUpdate(apIndex, &list, 1);
7124 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
7125 return RETURN_OK;
7126}
7127
7128// sets the beacon interval on the hardware for this AP
7129INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
7130{
7131 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7132 struct params params={'\0'};
7133 char buf[MAX_BUF_SIZE] = {'\0'};
7134 char config_file[MAX_BUF_SIZE] = {'\0'};
7135
7136 params.name = "beacon_int";
7137 snprintf(buf, sizeof(buf), "%u", beaconInterval);
7138 params.value = buf;
7139
7140 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7141 wifi_hostapdWrite(config_file, &params, 1);
developer69b61b02023-03-07 17:17:44 +08007142
developer72fb0bb2023-01-11 09:46:29 +08007143 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7144 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7145 return RETURN_OK;
7146}
7147
7148INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
7149{
7150 if (wifi_setApDTIMInterval(apIndex, dtimInterval) != RETURN_OK)
7151 return RETURN_ERR;
7152 return RETURN_OK;
7153}
7154
7155// Get the packet size threshold supported.
7156INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
7157{
7158 //save config and apply instantly
7159 if (NULL == output_bool)
7160 return RETURN_ERR;
7161 *output_bool = TRUE;
7162 return RETURN_OK;
7163}
7164
7165// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
7166INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
7167{
developer72fb0bb2023-01-11 09:46:29 +08007168 char buf[16] = {0};
7169 char config_file[128] = {0};
7170 struct params param = {0};
7171
7172 if (threshold > 65535) {
7173 fprintf(stderr, "%s: rts threshold %u is too big.\n", __func__, threshold);
7174 return RETURN_ERR;
7175 }
7176
developer23e71282023-01-18 10:25:19 +08007177 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developer72fb0bb2023-01-11 09:46:29 +08007178 snprintf(buf, sizeof(buf), "%u", threshold);
7179 param.name = "rts_threshold";
7180 param.value = buf;
7181 wifi_hostapdWrite(config_file, &param, 1);
7182 wifi_hostapdProcessUpdate(apIndex, &param, 1);
7183 wifi_reloadAp(apIndex);
7184
7185 return RETURN_OK;
7186}
7187
7188// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
7189INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
7190{
7191 if (NULL == output_string)
7192 return RETURN_ERR;
7193 snprintf(output_string, 32, "TKIPandAESEncryption");
7194 return RETURN_OK;
7195
7196}
7197
7198// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
7199INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
7200{
7201 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7202 char *param_name = NULL;
7203 char buf[32] = {0}, config_file[MAX_BUF_SIZE] = {0};
7204
7205 if(NULL == output_string)
7206 return RETURN_ERR;
7207
7208 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7209 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
7210
7211 if(strcmp(buf,"0")==0)
7212 {
7213 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
7214 snprintf(output_string, 32, "None");
7215 return RETURN_OK;
7216 }
7217 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
7218 param_name = "rsn_pairwise";
7219 else if((strcmp(buf,"1")==0))
7220 param_name = "wpa_pairwise";
7221 else
7222 return RETURN_ERR;
7223 memset(output_string,'\0',32);
7224 wifi_hostapdRead(config_file,param_name,output_string,32);
7225 if (strlen(output_string) == 0) { // rsn_pairwise is optional. When it is empty use wpa_pairwise instead.
7226 param_name = "wpa_pairwise";
7227 memset(output_string, '\0', 32);
7228 wifi_hostapdRead(config_file, param_name, output_string, 32);
7229 }
7230 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
7231
developere5750452023-05-15 16:46:42 +08007232 if(strcmp(output_string,"TKIP CCMP") == 0)
7233 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
7234 else if(strcmp(output_string,"TKIP") == 0)
developer72fb0bb2023-01-11 09:46:29 +08007235 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
7236 else if(strcmp(output_string,"CCMP") == 0)
7237 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
developer72fb0bb2023-01-11 09:46:29 +08007238
7239 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7240 return RETURN_OK;
7241}
7242
7243// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
7244INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
7245{
7246 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7247 struct params params={'\0'};
7248 char output_string[32];
7249 char config_file[MAX_BUF_SIZE] = {0};
7250
7251 memset(output_string,'\0',32);
developere5750452023-05-15 16:46:42 +08007252 wifi_getApBeaconType(apIndex,output_string);
developer72fb0bb2023-01-11 09:46:29 +08007253
7254 if(strcmp(encMode, "TKIPEncryption") == 0)
7255 params.value = "TKIP";
7256 else if(strcmp(encMode,"AESEncryption") == 0)
7257 params.value = "CCMP";
7258 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
7259 params.value = "TKIP CCMP";
7260
7261 if((strcmp(output_string,"WPAand11i")==0))
7262 {
7263 params.name = "wpa_pairwise";
7264 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7265 wifi_hostapdWrite(config_file, &params, 1);
7266 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7267
7268 params.name = "rsn_pairwise";
7269 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7270 wifi_hostapdWrite(config_file, &params, 1);
7271 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7272
7273 return RETURN_OK;
7274 }
7275 else if((strcmp(output_string,"11i")==0))
7276 {
7277 params.name = "rsn_pairwise";
7278 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7279 wifi_hostapdWrite(config_file, &params, 1);
7280 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7281 return RETURN_OK;
7282 }
7283 else if((strcmp(output_string,"WPA")==0))
7284 {
7285 params.name = "wpa_pairwise";
7286 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7287 wifi_hostapdWrite(config_file, &params, 1);
7288 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7289 return RETURN_OK;
7290 }
7291
7292 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7293 return RETURN_OK;
7294}
7295
7296// deletes internal security varable settings for this ap
7297INT wifi_removeApSecVaribles(INT apIndex)
7298{
7299 //TODO: remove the entry in hostapd config file
7300 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s.conf//g' /tmp/conf_filename", interface_name);
7301 //_syscmd(cmd, buf, sizeof(buf));
7302
7303 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s//g' /tmp/conf_filename", interface_name);
7304 //_syscmd(cmd, buf, sizeof(buf));
7305 return RETURN_ERR;
7306}
7307
7308// changes the hardware settings to disable encryption on this ap
7309INT wifi_disableApEncryption(INT apIndex)
7310{
7311 //Apply instantly
7312 return RETURN_ERR;
7313}
7314
7315// set the authorization mode on this ap
7316// mode mapping as: 1: open, 2: shared, 4:auto
7317INT wifi_setApAuthMode(INT apIndex, INT mode)
7318{
7319 struct params params={0};
7320 char config_file[64] = {0};
developer72fb0bb2023-01-11 09:46:29 +08007321
7322 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
7323
7324 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
7325 params.name = "auth_algs";
7326
developere5750452023-05-15 16:46:42 +08007327 if ((mode & 1 && mode & 2) || mode & 4)
developer72fb0bb2023-01-11 09:46:29 +08007328 params.value = "3";
7329 else if (mode & 2)
7330 params.value = "2";
7331 else if (mode & 1)
7332 params.value = "1";
7333 else
7334 params.value = "0";
7335
7336 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7337 wifi_hostapdWrite(config_file, &params, 1);
7338 wifi_hostapdProcessUpdate(apIndex, &params, 1);
developere5750452023-05-15 16:46:42 +08007339 wifi_reloadAp(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08007340 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
7341
7342 return RETURN_OK;
7343}
7344
7345// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
7346INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
7347{
7348 //save to wifi config, and wait for wifi restart to apply
7349 struct params params={'\0'};
7350 char config_file[MAX_BUF_SIZE] = {0};
7351 int ret;
7352
7353 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7354 if(authMode == NULL)
7355 return RETURN_ERR;
7356
7357 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
7358 params.name = "wpa_key_mgmt";
7359
7360 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
7361 params.value = "WPA-PSK";
7362 else if(strcmp(authMode,"EAPAuthentication") == 0)
7363 params.value = "WPA-EAP";
7364 else if (strcmp(authMode, "SAEAuthentication") == 0)
7365 params.value = "SAE";
7366 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
7367 params.value = "WPA-EAP-SUITE-B-192";
7368 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
7369 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer3086e2f2023-01-17 09:40:01 +08007370 else if (strcmp(authMode, "Enhanced_Open") == 0)
7371 params.value = "OWE";
developer72fb0bb2023-01-11 09:46:29 +08007372 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
7373 return RETURN_OK; //This is taken careof in beaconType
7374
7375 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7376 ret=wifi_hostapdWrite(config_file,&params,1);
7377 if(!ret)
7378 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
7379 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7380
7381 return ret;
7382}
7383
7384// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
7385INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
7386{
7387 //save to wifi config, and wait for wifi restart to apply
7388 char BeaconType[50] = {0};
7389 char config_file[MAX_BUF_SIZE] = {0};
7390
7391 *authMode = 0;
7392 wifi_getApBeaconType(apIndex,BeaconType);
7393 printf("%s____%s \n",__FUNCTION__,BeaconType);
7394
7395 if(strcmp(BeaconType,"None") == 0)
7396 strcpy(authMode,"None");
7397 else
7398 {
7399 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7400 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
7401 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
7402 if(strcmp(authMode,"WPA-PSK") == 0)
7403 strcpy(authMode,"SharedAuthentication");
7404 else if(strcmp(authMode,"WPA-EAP") == 0)
7405 strcpy(authMode,"EAPAuthentication");
7406 }
7407
7408 return RETURN_OK;
7409}
7410
7411// Outputs the number of stations associated per AP
7412INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
7413{
7414 char interface_name[16] = {0};
7415 char cmd[128]={0};
7416 char buf[128]={0};
7417 BOOL status = false;
7418
7419 if(apIndex > MAX_APS)
7420 return RETURN_ERR;
7421
7422 wifi_getApEnable(apIndex,&status);
7423 if (!status)
7424 return RETURN_OK;
7425
7426 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);//alternate method
7427 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7428 return RETURN_ERR;
7429 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l", interface_name);
7430 _syscmd(cmd, buf, sizeof(buf));
7431 sscanf(buf,"%lu", output_ulong);
7432
7433 return RETURN_OK;
7434}
7435
7436// manually removes any active wi-fi association with the device specified on this ap
7437INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
7438{
developer7e4a2a62023-04-06 19:56:03 +08007439 char inf_name[16] = {0};
7440 char cmd[MAX_CMD_SIZE] = {0};
7441 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08007442
developer7e4a2a62023-04-06 19:56:03 +08007443 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
developer72fb0bb2023-01-11 09:46:29 +08007444 return RETURN_ERR;
developer7e4a2a62023-04-06 19:56:03 +08007445
7446 snprintf(cmd, sizeof(cmd),"hostapd_cli -i %s disassociate %s", inf_name, client_mac);
7447 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08007448
7449 return RETURN_OK;
7450}
7451
7452// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
7453INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
7454{
developer7e4a2a62023-04-06 19:56:03 +08007455 int max_radio_num = 0;
7456
7457 if(NULL == output_int)
7458 return RETURN_ERR;
7459
7460 wifi_getMaxRadioNumber(&max_radio_num);
7461 *output_int = apIndex % max_radio_num;
7462
7463 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08007464}
7465
7466// sets the radio index for the specific ap
7467INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
7468{
7469 //set to config only and wait for wifi reset to apply settings
7470 return RETURN_ERR;
7471}
7472
developer121a8e72023-05-22 09:19:39 +08007473
7474#define MAX_ACL_DUMP_LEN 4096
7475int mtk_acl_list_dump_callback(struct nl_msg *msg, void *cb)
7476{
7477 struct nlattr *tb[NL80211_ATTR_MAX + 1];
7478 struct nlattr *vndr_tb[MTK_NL80211_VENDOR_AP_ACL_ATTR_MAX + 1];
7479 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
7480 char *show_str = NULL;
developer2edaf012023-05-24 14:24:53 +08007481 int err = 0;
developer121a8e72023-05-22 09:19:39 +08007482 unsigned short acl_result_len = 0;
7483 struct mtk_nl80211_cb_data *cb_data = cb;
developer121a8e72023-05-22 09:19:39 +08007484 if (!msg || !cb_data) {
developerdaf24792023-06-06 11:40:04 +08007485 wifi_debug(DEBUG_ERROR, "msg(%p) or cb_data(%p) is null,error.\n", msg, cb_data);
developer121a8e72023-05-22 09:19:39 +08007486 return NL_SKIP;
7487 }
developer121a8e72023-05-22 09:19:39 +08007488 err = nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
7489 genlmsg_attrlen(gnlh, 0), NULL);
7490 if (err < 0) {
developer2edaf012023-05-24 14:24:53 +08007491 wifi_debug(DEBUG_ERROR, "nla_parse acl list nl80211 msg fails,error.\n");
developer121a8e72023-05-22 09:19:39 +08007492 return NL_SKIP;
7493 }
developer121a8e72023-05-22 09:19:39 +08007494 if (tb[NL80211_ATTR_VENDOR_DATA]) {
7495 err = nla_parse_nested(vndr_tb, MTK_NL80211_VENDOR_AP_ACL_ATTR_MAX,
7496 tb[NL80211_ATTR_VENDOR_DATA], NULL);
7497 if (err < 0)
7498 return NL_SKIP;
7499 if (vndr_tb[MTK_NL80211_VENDOR_ATTR_ACL_LIST_INFO]) {
7500 acl_result_len = nla_len(vndr_tb[MTK_NL80211_VENDOR_ATTR_ACL_LIST_INFO]);
7501 show_str = nla_data(vndr_tb[MTK_NL80211_VENDOR_ATTR_ACL_LIST_INFO]);
7502 if (acl_result_len > MAX_ACL_DUMP_LEN) {
7503 wifi_debug(DEBUG_ERROR,"the scan result len is invalid !!!\n");
7504 return NL_SKIP;
7505 } else if (*(show_str + acl_result_len - 1) != '\0') {
7506 wifi_debug(DEBUG_INFO, "the result string is not ended with right terminator, handle it!!!\n");
7507 *(show_str + acl_result_len - 1) = '\0';
7508 }
7509 wifi_debug(DEBUG_INFO, "driver msg:%s\n", show_str);
developer2edaf012023-05-24 14:24:53 +08007510
7511 if (cb_data->out_len >= acl_result_len) {
7512 memset(cb_data->out_buf, 0, cb_data->out_len);
7513 /*skip the first line: 'policy=1\n' to find the acl mac addrs*/
7514 memmove(cb_data->out_buf, show_str, acl_result_len);
7515 wifi_debug(DEBUG_INFO, "out buff:%s\n", cb_data->out_buf);
7516 } else {
7517 memset(cb_data->out_buf, 0, cb_data->out_len);
developer121a8e72023-05-22 09:19:39 +08007518 }
developer121a8e72023-05-22 09:19:39 +08007519 } else
7520 wifi_debug(DEBUG_ERROR, "no acl result attr\n");
7521 } else
7522 wifi_debug(DEBUG_ERROR, "no any acl result from driver\n");
7523 return NL_OK;
7524}
developer72fb0bb2023-01-11 09:46:29 +08007525// Get the ACL MAC list per AP
developer2edaf012023-05-24 14:24:53 +08007526INT mtk_wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
developer72fb0bb2023-01-11 09:46:29 +08007527{
developer7e4a2a62023-04-06 19:56:03 +08007528 char inf_name[IF_NAME_SIZE] = {0};
developer121a8e72023-05-22 09:19:39 +08007529 unsigned int if_idx = 0;
7530 int ret = -1;
7531 struct unl unl_ins;
7532 struct nl_msg *msg = NULL;
7533 struct nlattr * msg_data = NULL;
7534 struct mtk_nl80211_param param;
7535 struct mtk_nl80211_cb_data cb_data;
developer7e4a2a62023-04-06 19:56:03 +08007536 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
7537 return RETURN_ERR;
developer121a8e72023-05-22 09:19:39 +08007538 if_idx = if_nametoindex(inf_name);
7539 if (!if_idx) {
developer2edaf012023-05-24 14:24:53 +08007540 wifi_debug(DEBUG_ERROR,"can't finde ifname(%s) index,ERROR\n", inf_name);
developer121a8e72023-05-22 09:19:39 +08007541 return RETURN_ERR;
7542 }
7543 /*init mtk nl80211 vendor cmd*/
7544 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_ACL;
7545 param.if_type = NL80211_ATTR_IFINDEX;
7546 param.if_idx = if_idx;
7547
7548 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
7549 if (ret) {
7550 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
7551 return RETURN_ERR;
7552 }
developer121a8e72023-05-22 09:19:39 +08007553 /*add mtk vendor cmd data*/
7554 if (nla_put_flag(msg, MTK_NL80211_VENDOR_ATTR_ACL_SHOW_ALL)) {
developer2edaf012023-05-24 14:24:53 +08007555 wifi_debug(DEBUG_ERROR, "Nla put ACL_SHOW_ALL attribute error\n");
developer121a8e72023-05-22 09:19:39 +08007556 nlmsg_free(msg);
7557 goto err;
7558 }
developer72fb0bb2023-01-11 09:46:29 +08007559
developer121a8e72023-05-22 09:19:39 +08007560 /*send mtk nl80211 vendor msg*/
7561 cb_data.out_buf = macArray;
7562 cb_data.out_len = buf_size;
7563
7564 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, mtk_acl_list_dump_callback, &cb_data);
7565 if (ret) {
7566 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
7567 goto err;
7568 }
7569 /*deinit mtk nl80211 vendor msg*/
7570 mtk_nl80211_deint(&unl_ins);
developer2edaf012023-05-24 14:24:53 +08007571 wifi_debug(DEBUG_NOTICE,"send cmd success, get out_buf:%s\n", macArray);
developer72fb0bb2023-01-11 09:46:29 +08007572 return RETURN_OK;
developer121a8e72023-05-22 09:19:39 +08007573err:
7574 mtk_nl80211_deint(&unl_ins);
developer2edaf012023-05-24 14:24:53 +08007575 wifi_debug(DEBUG_ERROR,"send cmd fails\n");
developer121a8e72023-05-22 09:19:39 +08007576 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007577}
7578
developer2edaf012023-05-24 14:24:53 +08007579INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
7580{
7581 char *mac_arry_buf = NULL;
7582
7583 mac_arry_buf = malloc(buf_size);
7584 if (!mac_arry_buf) {
7585 wifi_debug(DEBUG_ERROR,"malloc mac_arry_buf fails\n");
7586 return RETURN_ERR;
7587 }
7588 memset(mac_arry_buf, 0, buf_size);
7589 if (mtk_wifi_getApAclDevices(apIndex, mac_arry_buf, buf_size) != RETURN_OK) {
7590 wifi_debug(DEBUG_ERROR,"mtk_wifi_getApAclDevices get fails\n");
7591 free(mac_arry_buf);
7592 mac_arry_buf = NULL;
7593 return RETURN_ERR;
7594 }
7595 /*
7596 mtk format to wifi hal format:
7597 "policy=1
7598 00:11:22:33:44:55
7599 00:11:22:33:44:66
7600 "
7601 -->
7602 "00:11:22:33:44:55
7603 00:11:22:33:44:66
7604 "
7605 */
7606 memset(macArray, 0, buf_size);
7607 if (*mac_arry_buf != '\0' && strchr(mac_arry_buf,'\n')) {
7608 memmove(macArray, strchr(mac_arry_buf,'\n')+1, strlen(strchr(mac_arry_buf,'\n')+1)+1);
7609 wifi_debug(DEBUG_NOTICE,"macArray:\n%s\n", macArray);
7610 }
7611 free(mac_arry_buf);
7612 mac_arry_buf = NULL;
7613 return RETURN_OK;
7614}
7615
developer72fb0bb2023-01-11 09:46:29 +08007616INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
7617{
developer72fb0bb2023-01-11 09:46:29 +08007618
developer7e4a2a62023-04-06 19:56:03 +08007619 wifi_getApAclDevices(apIndex, macArray, buf_size);
developer72fb0bb2023-01-11 09:46:29 +08007620
7621 return RETURN_OK;
7622}
7623
7624
7625// Get the list of stations associated per AP
7626INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
7627{
developer7e4a2a62023-04-06 19:56:03 +08007628 char interface_name[IF_NAME_SIZE] = {0};
7629 char cmd[MAX_CMD_SIZE];
developer72fb0bb2023-01-11 09:46:29 +08007630
developer7e4a2a62023-04-06 19:56:03 +08007631 if(apIndex > 3) //Currently supporting apIndex upto 3
7632 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007633
developer7e4a2a62023-04-06 19:56:03 +08007634 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7635 return RETURN_ERR;
7636
7637 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s list_sta", interface_name);
7638 _syscmd(cmd, macArray, buf_size);
7639 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08007640}
7641
developer8dd72532023-05-17 19:58:35 +08007642int hex2num(char c)
7643{
7644 if (c >= '0' && c <= '9')
7645 return c - '0';
7646 if (c >= 'a' && c <= 'f')
7647 return c - 'a' + 10;
7648 if (c >= 'A' && c <= 'F')
7649 return c - 'A' + 10;
7650 return -1;
7651}
7652
7653/**
7654 * hwaddr_aton2 - Convert ASCII string to MAC address (in any known format)
7655 * @txt: MAC address as a string (e.g., 00:11:22:33:44:55 or 0011.2233.4455)
7656 * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
7657 * Returns: Characters used (> 0) on success, -1 on failure
7658 */
7659int hwaddr_aton2(const char *txt, unsigned char *addr)
7660{
7661 int i;
7662 const char *pos = txt;
7663
7664 for (i = 0; i < 6; i++) {
7665 int a, b;
7666
7667 while (*pos == ':' || *pos == '.' || *pos == '-')
7668 pos++;
7669
7670 a = hex2num(*pos++);
7671 if (a < 0)
7672 return -1;
7673 b = hex2num(*pos++);
7674 if (b < 0)
7675 return -1;
7676 *addr++ = (a << 4) | b;
7677 }
7678
7679 return pos - txt;
7680}
7681
developer72fb0bb2023-01-11 09:46:29 +08007682// adds the mac address to the filter list
7683//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
7684INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
7685{
developer7e4a2a62023-04-06 19:56:03 +08007686 char inf_name[IF_NAME_SIZE] = {0};
developer8dd72532023-05-17 19:58:35 +08007687 int if_idx, ret = 0;
developer49b17232023-05-19 16:35:19 +08007688 struct nl_msg *msg = NULL;
7689 struct nlattr * msg_data = NULL;
7690 struct mtk_nl80211_param param;
developer8dd72532023-05-17 19:58:35 +08007691 unsigned char mac[ETH_ALEN] = {0x00, 0x0c, 0x43, 0x11, 0x22, 0x33};
7692 struct unl unl_ins;
developer7e4a2a62023-04-06 19:56:03 +08007693 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
7694 return RETURN_ERR;
developer7e4a2a62023-04-06 19:56:03 +08007695 if (!DeviceMacAddress)
7696 return RETURN_ERR;
developer8dd72532023-05-17 19:58:35 +08007697 if (hwaddr_aton2(DeviceMacAddress, mac) < 0) {
developer2edaf012023-05-24 14:24:53 +08007698 wifi_debug(DEBUG_ERROR, "error device mac address=%s\n", DeviceMacAddress);
developer8dd72532023-05-17 19:58:35 +08007699 return RETURN_ERR;
7700 }
developer8dd72532023-05-17 19:58:35 +08007701 if_idx = if_nametoindex(inf_name);
developer2edaf012023-05-24 14:24:53 +08007702 if (!if_idx) {
7703 wifi_debug(DEBUG_ERROR, "can't finde ifname(%s) index,ERROR\n", inf_name);
7704 return RETURN_ERR;
7705 }
developer49b17232023-05-19 16:35:19 +08007706 /*init mtk nl80211 vendor cmd*/
7707 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_ACL;
7708 param.if_type = NL80211_ATTR_IFINDEX;
7709 param.if_idx = if_idx;
7710 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
7711 if (ret) {
7712 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
developer8dd72532023-05-17 19:58:35 +08007713 return RETURN_ERR;
7714 }
developer49b17232023-05-19 16:35:19 +08007715 /*add mtk vendor cmd data*/
7716 if (nla_put(msg, MTK_NL80211_VENDOR_ATTR_ACL_ADD_MAC, ETH_ALEN, mac)) {
developer2edaf012023-05-24 14:24:53 +08007717 wifi_debug(DEBUG_ERROR, "Nla put attribute error\n");
developer8dd72532023-05-17 19:58:35 +08007718 nlmsg_free(msg);
7719 goto err;
7720 }
developer49b17232023-05-19 16:35:19 +08007721 /*send mtk nl80211 vendor msg*/
7722 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
7723 if (ret) {
7724 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
developer8dd72532023-05-17 19:58:35 +08007725 goto err;
7726 }
developer49b17232023-05-19 16:35:19 +08007727 /*deinit mtk nl80211 vendor msg*/
7728 mtk_nl80211_deint(&unl_ins);
7729 wifi_debug(DEBUG_NOTICE, "set cmd success.\n");
developer8dd72532023-05-17 19:58:35 +08007730 return RETURN_OK;
7731err:
developer49b17232023-05-19 16:35:19 +08007732 mtk_nl80211_deint(&unl_ins);
7733 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
developer8dd72532023-05-17 19:58:35 +08007734 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007735}
7736
7737// deletes the mac address from the filter list
7738//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
7739INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
7740{
developer2edaf012023-05-24 14:24:53 +08007741 struct unl unl_ins;
7742 int if_idx = 0, ret = 0;
7743 struct nl_msg *msg = NULL;
7744 struct nlattr * msg_data = NULL;
7745 struct mtk_nl80211_param param;
developer7e4a2a62023-04-06 19:56:03 +08007746 char inf_name[IF_NAME_SIZE] = {0};
developer2edaf012023-05-24 14:24:53 +08007747 unsigned char mac[ETH_ALEN] = {0};
developer72fb0bb2023-01-11 09:46:29 +08007748
developer7e4a2a62023-04-06 19:56:03 +08007749 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
7750 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007751
developer7e4a2a62023-04-06 19:56:03 +08007752 if (!DeviceMacAddress)
7753 return RETURN_ERR;
7754
developer2edaf012023-05-24 14:24:53 +08007755 if (hwaddr_aton2(DeviceMacAddress, mac) < 0) {
7756 wifi_debug(DEBUG_ERROR, "error device mac address=%s\n", DeviceMacAddress);
7757 return RETURN_ERR;
7758 }
developer72fb0bb2023-01-11 09:46:29 +08007759
developer2edaf012023-05-24 14:24:53 +08007760 if_idx = if_nametoindex(inf_name);
7761 if (!if_idx) {
7762 wifi_debug(DEBUG_ERROR, "can't finde ifname(%s) index,ERROR\n", inf_name);
7763 return RETURN_ERR;
7764 }
7765 /*init mtk nl80211 vendor cmd*/
7766 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_ACL;
7767 param.if_type = NL80211_ATTR_IFINDEX;
7768 param.if_idx = if_idx;
7769 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
7770 if (ret) {
7771 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
7772 return RETURN_ERR;
7773 }
7774 /*add mtk vendor cmd data*/
7775 if (nla_put(msg, MTK_NL80211_VENDOR_ATTR_ACL_DEL_MAC, ETH_ALEN, mac)) {
7776 wifi_debug(DEBUG_ERROR, "Nla put attribute error\n");
7777 nlmsg_free(msg);
7778 goto err;
7779 }
7780 /*send mtk nl80211 vendor msg*/
7781 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
7782 if (ret) {
7783 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
7784 goto err;
7785 }
7786 /*deinit mtk nl80211 vendor msg*/
7787 mtk_nl80211_deint(&unl_ins);
7788 wifi_debug(DEBUG_NOTICE, "set cmd success.\n");
7789 return RETURN_OK;
7790err:
7791 mtk_nl80211_deint(&unl_ins);
7792 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
7793 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007794}
7795
7796// outputs the number of devices in the filter list
7797INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
7798{
developer2edaf012023-05-24 14:24:53 +08007799 char *mac_arry = NULL, *ptr = NULL, mac_str[18] = {0};
7800 UINT buf_size = 1024;
7801 UINT sta_num = 0;
7802 unsigned char mac[ETH_ALEN] = {0};
developer72fb0bb2023-01-11 09:46:29 +08007803 if(output_uint == NULL)
developerdaf24792023-06-06 11:40:04 +08007804 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007805
developer2edaf012023-05-24 14:24:53 +08007806 mac_arry = (char *)malloc(buf_size);
7807 if (mac_arry == NULL) {
7808 wifi_debug(DEBUG_ERROR, "malloc mac_arry fails\n");
developer7e4a2a62023-04-06 19:56:03 +08007809 return RETURN_ERR;
developer2edaf012023-05-24 14:24:53 +08007810 }
developerdaf24792023-06-06 11:40:04 +08007811 memset(mac_arry, 0, buf_size);
developer2edaf012023-05-24 14:24:53 +08007812 /*mac_arry str format: 00:11:22:33:44:55\n00:11:22:33:44:66\0*/
7813 if (wifi_getApAclDevices(apIndex, mac_arry, buf_size)!= RETURN_OK) {
7814 wifi_debug(DEBUG_ERROR, "get acl list entries fails\n");
7815 return RETURN_ERR;
7816 }
7817 /*count the acl str nums:*/
7818 wifi_debug(DEBUG_NOTICE, "mac_arry: %s\n", mac_arry);
developer7e4a2a62023-04-06 19:56:03 +08007819
developer2edaf012023-05-24 14:24:53 +08007820 /*mac addr string format:
7821 exp1: 00:11:22:33:44:55\0
7822 exp2: 00:11:22:33:44:55\n00:11:22:33:44:66\0
7823 */
7824 ptr = mac_arry;
7825 while (sscanf(ptr, "%17s", mac_str) == 1) {
7826 if (hwaddr_aton2(mac_str, mac) >= 0)
7827 sta_num++;
7828 ptr = strstr(ptr, mac_str) + strlen(mac_str);
7829 }
7830 *output_uint = sta_num;
7831 wifi_debug(DEBUG_NOTICE, "output_uint: %d\n", *output_uint);
7832 free(mac_arry);
7833 mac_arry = NULL;
developer7e4a2a62023-04-06 19:56:03 +08007834 return RETURN_OK;
developer2edaf012023-05-24 14:24:53 +08007835err:
7836 free(mac_arry);
7837 mac_arry = NULL;
7838 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007839}
7840
7841INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
7842{
developer72fb0bb2023-01-11 09:46:29 +08007843 char buf[128]={'\0'};
7844
7845 if(strcmp(action,"DENY")==0)
7846 {
7847 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
7848 system(buf);
7849 return RETURN_OK;
7850 }
7851
7852 if(strcmp(action,"ALLOW")==0)
7853 {
7854 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
7855 system(buf);
7856 return RETURN_OK;
7857 }
7858
7859 return RETURN_ERR;
7860
7861}
7862
7863// enable kick for devices on acl black list
7864INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
7865{
developer47cc27a2023-05-17 23:09:58 +08007866 char aclArray[MAX_BUF_SIZE] = {0}, *acl = NULL;
developer2f79c922023-06-02 17:33:42 +08007867 char assocArray[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08007868
7869 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
7870 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
7871
developer7e4a2a62023-04-06 19:56:03 +08007872 /* if there are no devices connected there is nothing to do */
developer72fb0bb2023-01-11 09:46:29 +08007873 if (strlen(assocArray) < 17)
7874 return RETURN_OK;
7875
developer7e4a2a62023-04-06 19:56:03 +08007876 if (enable == TRUE) {
7877 /* kick off the MAC which is in ACL array (deny list) */
7878 acl = strtok(aclArray, "\n");
developer72fb0bb2023-01-11 09:46:29 +08007879 while (acl != NULL) {
7880 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
7881 wifi_kickApAssociatedDevice(apIndex, acl);
7882
developer7e4a2a62023-04-06 19:56:03 +08007883 acl = strtok(NULL, "\n");
developer72fb0bb2023-01-11 09:46:29 +08007884 }
7885 wifi_setApMacAddressControlMode(apIndex, 2);
developer7e4a2a62023-04-06 19:56:03 +08007886 } else
developer72fb0bb2023-01-11 09:46:29 +08007887 wifi_setApMacAddressControlMode(apIndex, 0);
developer72fb0bb2023-01-11 09:46:29 +08007888
developer72fb0bb2023-01-11 09:46:29 +08007889 return RETURN_OK;
7890}
7891
7892INT wifi_setPreferPrivateConnection(BOOL enable)
7893{
7894 return RETURN_OK;
7895}
7896
7897// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
7898INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
7899{
developer2edaf012023-05-24 14:24:53 +08007900 int if_idx = 0, ret = 0;
7901 struct unl unl_ins;
7902 struct nl_msg *msg = NULL;
7903 struct nlattr * msg_data = NULL;
7904 struct mtk_nl80211_param param;
7905 int acl_policy = -1;
developer7e4a2a62023-04-06 19:56:03 +08007906 char inf_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08007907
developer7e4a2a62023-04-06 19:56:03 +08007908 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
7909 return RETURN_ERR;
developer2edaf012023-05-24 14:24:53 +08007910 if_idx = if_nametoindex(inf_name);
7911 if (!if_idx) {
7912 wifi_debug(DEBUG_ERROR, "can't finde ifname(%s) index,ERROR\n", inf_name);
7913 return RETURN_ERR;
7914 }
7915 /*init mtk nl80211 vendor cmd*/
7916 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_ACL;
7917 param.if_type = NL80211_ATTR_IFINDEX;
7918 param.if_idx = if_idx;
7919 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
7920 if (ret) {
7921 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
7922 return RETURN_ERR;
7923 }
7924 /*add mtk vendor cmd data*/
7925 if (filterMode == 0) {
7926 acl_policy = MTK_NL80211_VENDOR_ATTR_ACL_DISABLE;
7927 } else if (filterMode == 1) {
7928 acl_policy = MTK_NL80211_VENDOR_ATTR_ACL_ENABLE_WHITE_LIST;
7929 } else if (filterMode == 2) {
7930 acl_policy = MTK_NL80211_VENDOR_ATTR_ACL_ENABLE_BLACK_LIST;
7931 } else {
7932 wifi_debug(DEBUG_ERROR, "filtermode(%d) not support error\n", filterMode);
7933 nlmsg_free(msg);
7934 goto err;
7935 }
7936 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_ACL_POLICY, acl_policy)) {
7937 wifi_debug(DEBUG_ERROR, "Nla put attribute error\n");
7938 nlmsg_free(msg);
7939 goto err;
7940 }
7941 /*send mtk nl80211 vendor msg*/
7942 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
7943 if (ret) {
7944 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
7945 goto err;
7946 }
7947 /*deinit mtk nl80211 vendor msg*/
7948 mtk_nl80211_deint(&unl_ins);
7949 wifi_debug(DEBUG_NOTICE, "set cmd success.\n");
developer7e4a2a62023-04-06 19:56:03 +08007950 return RETURN_OK;
developer2edaf012023-05-24 14:24:53 +08007951err:
7952 mtk_nl80211_deint(&unl_ins);
7953 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
7954 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007955}
7956
7957// 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.
7958INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
7959{
7960 return RETURN_ERR;
7961}
7962
7963// gets the vlan ID for this ap from an internal enviornment variable
7964INT wifi_getApVlanID(INT apIndex, INT *output_int)
7965{
7966 if(apIndex==0)
7967 {
7968 *output_int=100;
7969 return RETURN_OK;
7970 }
7971
7972 return RETURN_ERR;
7973}
7974
7975// sets the vlan ID for this ap to an internal enviornment variable
7976INT wifi_setApVlanID(INT apIndex, INT vlanId)
7977{
7978 //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)
7979 return RETURN_ERR;
7980}
7981
7982// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
7983INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
7984{
7985 snprintf(bridgeName, 32, "brlan0");
7986 snprintf(IP, 32, "10.0.0.1");
7987 snprintf(subnet, 32, "255.255.255.0");
7988
7989 return RETURN_OK;
7990}
7991
7992//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
7993INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
7994{
7995 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
7996 return RETURN_ERR;
7997}
7998
7999// reset the vlan configuration for this ap
8000INT wifi_resetApVlanCfg(INT apIndex)
8001{
developera1255e42023-05-13 17:45:02 +08008002 char interface_name[16] = {0};
developer2202b332023-05-24 16:23:22 +08008003 int if_idx, ret = 0;
8004 struct nl_msg *msg = NULL;
8005 struct nlattr * msg_data = NULL;
8006 struct mtk_nl80211_param param;
8007 struct unl unl_ins;
8008 struct vlan_policy_param vlan_param;
developer72fb0bb2023-01-11 09:46:29 +08008009
developer2202b332023-05-24 16:23:22 +08008010 if (apIndex > MAX_APS) {
8011 wifi_debug(DEBUG_ERROR, "Invalid apIndex %d\n", apIndex);
8012 return RETURN_ERR;
8013 }
developer72fb0bb2023-01-11 09:46:29 +08008014
developer2202b332023-05-24 16:23:22 +08008015 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8016 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8017 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08008018
developer2202b332023-05-24 16:23:22 +08008019 /*step 1. mwctl dev %s set vlan_tag 0*/
8020 if_idx = if_nametoindex(interface_name);
8021 /*init mtk nl80211 vendor cmd*/
8022 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_VLAN;
8023 param.if_type = NL80211_ATTR_IFINDEX;
8024 param.if_idx = if_idx;
8025 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
developer72fb0bb2023-01-11 09:46:29 +08008026
developer2202b332023-05-24 16:23:22 +08008027 if (ret) {
8028 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
8029 return RETURN_ERR;
8030 }
developer72fb0bb2023-01-11 09:46:29 +08008031
developer2202b332023-05-24 16:23:22 +08008032 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_VLAN_TAG_INFO, 0)) {
8033 printf("Nla put attribute error\n");
8034 nlmsg_free(msg);
8035 goto err;
8036 }
developer72fb0bb2023-01-11 09:46:29 +08008037
developer2202b332023-05-24 16:23:22 +08008038 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
8039 if (ret) {
8040 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vendor msg fails\n");
8041 goto err;
8042 }
8043 mtk_nl80211_deint(&unl_ins);
8044 wifi_debug(DEBUG_NOTICE, "set vlan_tag 0 cmd success.\n");
developer72fb0bb2023-01-11 09:46:29 +08008045
developer2202b332023-05-24 16:23:22 +08008046 /*step 2. mwctl dev %s set vlan_priority 0*/
8047 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
8048 if (ret) {
8049 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
8050 return RETURN_ERR;
8051 }
developer72fb0bb2023-01-11 09:46:29 +08008052
developer2202b332023-05-24 16:23:22 +08008053 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_VLAN_PRIORITY_INFO, 0)) {
8054 printf("Nla put attribute error\n");
8055 nlmsg_free(msg);
8056 goto err;
8057 }
developer72fb0bb2023-01-11 09:46:29 +08008058
developer2202b332023-05-24 16:23:22 +08008059 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
8060 if (ret) {
8061 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vendor msg fails\n");
8062 goto err;
8063 }
8064 mtk_nl80211_deint(&unl_ins);
8065 wifi_debug(DEBUG_NOTICE, "set vlan_priority 0 cmd success.\n");
8066
8067 /*step 3. mwctl dev %s set vlan_id 0*/
8068 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
8069 if (ret) {
8070 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
developera1255e42023-05-13 17:45:02 +08008071 return RETURN_ERR;
developer2202b332023-05-24 16:23:22 +08008072 }
developer72fb0bb2023-01-11 09:46:29 +08008073
developer2202b332023-05-24 16:23:22 +08008074 if (nla_put_u16(msg, MTK_NL80211_VENDOR_ATTR_VLAN_ID_INFO, 0)) {
8075 printf("Nla put attribute error\n");
8076 nlmsg_free(msg);
8077 goto err;
8078 }
8079
8080 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
8081 if (ret) {
8082 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vendor msg fails\n");
8083 goto err;
8084 }
8085 mtk_nl80211_deint(&unl_ins);
8086 wifi_debug(DEBUG_NOTICE, "set vlan_id cmd success.\n");
8087
8088 /*step 4. mwctl dev %s set vlan_en 0*/
8089 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
8090 if (ret) {
8091 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
8092 return RETURN_ERR;
8093 }
8094
8095 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_VLAN_EN_INFO, 0)) {
8096 printf("Nla put attribute error\n");
8097 nlmsg_free(msg);
8098 goto err;
8099 }
8100
8101 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
8102 if (ret) {
8103 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vendor msg fails\n");
8104 goto err;
8105 }
8106 mtk_nl80211_deint(&unl_ins);
8107 wifi_debug(DEBUG_NOTICE, "set vlan_id cmd success.\n");
8108
8109 /*step 5. mwctl dev %s set vlan_policy 0:4*/
8110 vlan_param.direction = 0;
8111 vlan_param.policy = 4;
8112 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
8113 if (ret) {
8114 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
8115 return RETURN_ERR;
8116 }
8117 if (nla_put(msg, MTK_NL80211_VENDOR_ATTR_VLAN_POLICY_INFO, sizeof(vlan_param), &vlan_param)) {
8118 printf("Nla put attribute error\n");
8119 nlmsg_free(msg);
8120 goto err;
8121 }
8122
8123 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
8124 if (ret) {
8125 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vendor msg fails\n");
8126 goto err;
8127 }
8128 mtk_nl80211_deint(&unl_ins);
8129 wifi_debug(DEBUG_NOTICE, "set vlan_policy 0:4 cmd success.\n");
8130
8131 /*step 6. mwctl dev %s set vlan_policy 1:0*/
8132 vlan_param.direction = 1;
8133 vlan_param.policy = 0;
8134 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
8135 if (ret) {
8136 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
8137 return RETURN_ERR;
8138 }
8139
8140 if (nla_put(msg, MTK_NL80211_VENDOR_ATTR_VLAN_POLICY_INFO, sizeof(vlan_param), &vlan_param)) {
8141 printf("Nla put attribute error\n");
8142 nlmsg_free(msg);
8143 goto err;
8144 }
8145
8146 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
8147 if (ret) {
8148 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vendor msg fails\n");
8149 goto err;
8150 }
8151 /*deinit mtk nl80211 vendor msg*/
8152 mtk_nl80211_deint(&unl_ins);
8153 wifi_debug(DEBUG_NOTICE, "set vlan_policy 1:0 cmd success.\n");
8154
8155 /*TODO need to modify VLAN config in dat file*/
8156 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8157
8158 return RETURN_OK;
8159err:
8160 mtk_nl80211_deint(&unl_ins);
8161 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
8162 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08008163}
8164
8165// 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.
8166INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
8167{
8168 return RETURN_ERR;
8169}
8170
8171// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
8172INT wifi_startHostApd()
8173{
8174 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8175 system("systemctl start hostapd.service");
8176 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8177 return RETURN_OK;
8178 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
8179}
8180
8181// stops hostapd
developer69b61b02023-03-07 17:17:44 +08008182INT wifi_stopHostApd()
developer72fb0bb2023-01-11 09:46:29 +08008183{
8184 char cmd[128] = {0};
8185 char buf[128] = {0};
8186
8187 sprintf(cmd,"systemctl stop hostapd");
8188 _syscmd(cmd, buf, sizeof(buf));
8189
8190 return RETURN_OK;
8191}
8192
8193// restart hostapd dummy function
8194INT wifi_restartHostApd()
8195{
8196 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8197 system("systemctl restart hostapd-global");
8198 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8199
8200 return RETURN_OK;
8201}
8202
8203static int align_hostapd_config(int index)
8204{
8205 ULONG lval;
8206 wifi_getRadioChannel(index%2, &lval);
8207 wifi_setRadioChannel(index%2, lval);
8208 return RETURN_OK;
8209}
8210
8211// sets the AP enable status variable for the specified ap.
8212INT wifi_setApEnable(INT apIndex, BOOL enable)
8213{
developer7e4a2a62023-04-06 19:56:03 +08008214 char interface_name[16] = {0};
8215 char config_file[MAX_BUF_SIZE] = {0};
8216 char cmd[MAX_CMD_SIZE] = {0};
8217 char buf[MAX_BUF_SIZE] = {0};
developer47cc27a2023-05-17 23:09:58 +08008218 BOOL status = FALSE;
developer7e4a2a62023-04-06 19:56:03 +08008219 int max_radio_num = 0;
8220 int phyId = 0;
developer72fb0bb2023-01-11 09:46:29 +08008221
developer7e4a2a62023-04-06 19:56:03 +08008222 wifi_getApEnable(apIndex, &status);
developer72fb0bb2023-01-11 09:46:29 +08008223
developer7e4a2a62023-04-06 19:56:03 +08008224 wifi_getMaxRadioNumber(&max_radio_num);
8225 if (enable == status)
8226 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08008227
developer7e4a2a62023-04-06 19:56:03 +08008228 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8229 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08008230
developer7e4a2a62023-04-06 19:56:03 +08008231 if (enable == TRUE) {
8232 int radioIndex = apIndex % max_radio_num;
8233 phyId = radio_index_to_phy(radioIndex);
developerf3c7d292023-05-29 17:57:16 +08008234 snprintf(cmd, MAX_CMD_SIZE, "ifconfig %s up", interface_name);
8235 _syscmd(cmd, buf, sizeof(buf));
developer8a3bbbf2023-03-15 17:47:23 +08008236
developer7e4a2a62023-04-06 19:56:03 +08008237 snprintf(config_file, MAX_BUF_SIZE, "%s%d.conf", CONFIG_PREFIX, apIndex);
8238 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyId, config_file);
8239 _syscmd(cmd, buf, sizeof(buf));
8240 } else {
8241 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw REMOVE %s", interface_name);
8242 _syscmd(cmd, buf, sizeof(buf));
developerf3c7d292023-05-29 17:57:16 +08008243 snprintf(cmd, MAX_CMD_SIZE, "ifconfig %s down", interface_name);
8244 _syscmd(cmd, buf, sizeof(buf));
developer7e4a2a62023-04-06 19:56:03 +08008245 }
8246 snprintf(cmd, MAX_CMD_SIZE, "sed -i -n -e '/^%s=/!p' -e '$a%s=%d' %s",
8247 interface_name, interface_name, enable, VAP_STATUS_FILE);
8248 _syscmd(cmd, buf, sizeof(buf));
8249 //Wait for wifi up/down to apply
8250 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08008251}
8252
8253// Outputs the setting of the internal variable that is set by wifi_setApEnable().
8254INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
8255{
developer7e4a2a62023-04-06 19:56:03 +08008256 char interface_name[IF_NAME_SIZE] = {0};
8257 char cmd[MAX_CMD_SIZE] = {0};
developere740c2a2023-05-23 18:34:32 +08008258 int ret;
developer72fb0bb2023-01-11 09:46:29 +08008259
developer7e4a2a62023-04-06 19:56:03 +08008260 if ((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
8261 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08008262
developer7e4a2a62023-04-06 19:56:03 +08008263 *output_bool = 0;
developer72fb0bb2023-01-11 09:46:29 +08008264
developer7e4a2a62023-04-06 19:56:03 +08008265 if ((apIndex >= 0) && (apIndex < MAX_APS)) {
8266 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
8267 *output_bool = FALSE;
8268 return RETURN_OK;
8269 }
developere740c2a2023-05-23 18:34:32 +08008270 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status", interface_name);
8271 ret = system(cmd);
8272 if (ret == 0)
8273 *output_bool = 1;
developer7e4a2a62023-04-06 19:56:03 +08008274 }
developer72fb0bb2023-01-11 09:46:29 +08008275
developer7e4a2a62023-04-06 19:56:03 +08008276 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08008277}
8278
developer69b61b02023-03-07 17:17:44 +08008279// Outputs the AP "Enabled" "Disabled" status from driver
8280INT wifi_getApStatus(INT apIndex, CHAR *output_string)
developer72fb0bb2023-01-11 09:46:29 +08008281{
developer7e4a2a62023-04-06 19:56:03 +08008282 BOOL output_bool;
developer72fb0bb2023-01-11 09:46:29 +08008283
developer7e4a2a62023-04-06 19:56:03 +08008284 if (!output_string) {
8285 printf("%s: null pointer!", __func__);
8286 return RETURN_ERR;
8287 }
developer72fb0bb2023-01-11 09:46:29 +08008288
developer7e4a2a62023-04-06 19:56:03 +08008289 wifi_getApEnable(apIndex, &output_bool);
developer72fb0bb2023-01-11 09:46:29 +08008290
developer7e4a2a62023-04-06 19:56:03 +08008291 if(output_bool == 1)
8292 snprintf(output_string, 32, "Up");
8293 else
8294 snprintf(output_string, 32, "Disable");
8295
8296 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08008297}
8298
8299//Indicates whether or not beacons include the SSID name.
8300// outputs a 1 if SSID on the AP is enabled, else outputs 0
8301INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
8302{
8303 //get the running status
8304 char config_file[MAX_BUF_SIZE] = {0};
8305 char buf[16] = {0};
8306
8307 if (!output)
8308 return RETURN_ERR;
8309
8310 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8311 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
8312 // default is enable
8313 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
8314 *output = TRUE;
8315
8316 return RETURN_OK;
8317}
8318
8319// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
8320INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
8321{
8322 //store the config, apply instantly
8323 char config_file[MAX_BUF_SIZE] = {0};
8324 struct params list;
8325
8326 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8327 list.name = "ignore_broadcast_ssid";
8328 list.value = enable?"0":"1";
8329
8330 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8331 wifi_hostapdWrite(config_file, &list, 1);
8332 wifi_hostapdProcessUpdate(apIndex, &list, 1);
8333 //TODO: call hostapd_cli for dynamic_config_control
8334 wifi_reloadAp(apIndex);
8335 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8336
8337 return RETURN_OK;
8338}
8339
8340//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
8341INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
8342{
developer47cc27a2023-05-17 23:09:58 +08008343 /* get the running status */
8344 if(!output_uint)
8345 return RETURN_ERR;
8346
8347 *output_uint = 15;
8348 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08008349}
8350
developer47cc27a2023-05-17 23:09:58 +08008351/*Do not support AP retry limit fix*/
developer72fb0bb2023-01-11 09:46:29 +08008352INT wifi_setApRetryLimit(INT apIndex, UINT number)
8353{
developer47cc27a2023-05-17 23:09:58 +08008354 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08008355}
8356
developer95c045d2023-05-24 19:26:28 +08008357int get_wmm_cap_status_callback(struct nl_msg *msg, void *data)
8358{
8359 struct nlattr *tb[NL80211_ATTR_MAX + 1];
8360 struct nlattr *vndr_tb[MTK_NL80211_VENDOR_WMM_ATTR_MAX + 1];
8361 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
developer2f79c922023-06-02 17:33:42 +08008362 unsigned char *status = (unsigned char *)data;
developer95c045d2023-05-24 19:26:28 +08008363 int err = 0;
developer95c045d2023-05-24 19:26:28 +08008364
8365 err = nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
8366 genlmsg_attrlen(gnlh, 0), NULL);
8367 if (err < 0)
8368 return err;
8369
8370 if (tb[NL80211_ATTR_VENDOR_DATA]) {
8371 err = nla_parse_nested(vndr_tb, MTK_NL80211_VENDOR_WMM_ATTR_MAX,
8372 tb[NL80211_ATTR_VENDOR_DATA], NULL);
8373 if (err < 0)
8374 return err;
8375
8376 if (vndr_tb[MTK_NL80211_VENDOR_ATTR_WMM_AP_CAP_INFO]) {
developer95c045d2023-05-24 19:26:28 +08008377 *status = nla_get_u8(vndr_tb[MTK_NL80211_VENDOR_ATTR_WMM_AP_CAP_INFO]);
8378 }
8379 }
8380
8381 return 0;
8382}
8383
developer72fb0bb2023-01-11 09:46:29 +08008384//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
8385INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
8386{
developer95c045d2023-05-24 19:26:28 +08008387 int if_idx, ret = 0;
developer8e6583c2023-05-23 13:36:06 +08008388 char interface_name[16] = {0};
developer95c045d2023-05-24 19:26:28 +08008389 unsigned char status = 0;
8390 struct nl_msg *msg = NULL;
8391 struct nlattr * msg_data = NULL;
8392 struct mtk_nl80211_param param;
8393 struct unl unl_ins;
developer8e6583c2023-05-23 13:36:06 +08008394
8395 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08008396 if(!output)
developerdaf24792023-06-06 11:40:04 +08008397 return RETURN_ERR;
developer8e6583c2023-05-23 13:36:06 +08008398
developer95c045d2023-05-24 19:26:28 +08008399 if (apIndex > MAX_APS) {
8400 wifi_debug(DEBUG_ERROR, "Invalid apIndex %d\n", apIndex);
8401 return RETURN_ERR;
8402 }
8403
developer8e6583c2023-05-23 13:36:06 +08008404 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerdaf24792023-06-06 11:40:04 +08008405 return RETURN_ERR;
developer95c045d2023-05-24 19:26:28 +08008406
8407 if_idx = if_nametoindex(interface_name);
8408 /*init mtk nl80211 vendor cmd*/
8409 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_WMM;
8410 param.if_type = NL80211_ATTR_IFINDEX;
8411 param.if_idx = if_idx;
8412 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
8413
8414 if (ret) {
8415 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
8416 return RETURN_ERR;
8417 }
8418
8419 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_WMM_AP_CAP_INFO, 0xf)) {
8420 wifi_debug(DEBUG_ERROR, "Nla put attribute error\n");
8421 nlmsg_free(msg);
8422 goto err;
8423 }
8424
8425 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, get_wmm_cap_status_callback,
8426 (void *)&status);
8427 if (ret) {
8428 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vendor msg fails\n");
8429 goto err;
8430 }
8431 mtk_nl80211_deint(&unl_ins);
8432
8433 *output = status == 0 ? FALSE : TRUE;
8434 wifi_debug(DEBUG_NOTICE, "wmm cap (%u).\n", (unsigned int)(*output));
developer8e6583c2023-05-23 13:36:06 +08008435
8436 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08008437 return RETURN_OK;
developer95c045d2023-05-24 19:26:28 +08008438err:
8439 mtk_nl80211_deint(&unl_ins);
8440 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
8441 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08008442}
8443
8444//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
8445INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
8446{
8447 //get the running status from driver
8448 char cmd[128] = {0};
8449 char buf[128] = {0};
8450 int max_radio_num = 0, radioIndex = 0;
8451 int phyId = 0;
8452
8453 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8454
8455 wifi_getMaxRadioNumber(&max_radio_num);
8456 radioIndex = apIndex % max_radio_num;
8457 phyId = radio_index_to_phy(radioIndex);
8458 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", phyId);
8459 _syscmd(cmd,buf, sizeof(buf));
8460
8461 if (strlen(buf) > 0)
8462 *output = true;
8463
8464 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8465
8466 return RETURN_OK;
8467}
8468
8469//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
8470INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
8471{
developer95c045d2023-05-24 19:26:28 +08008472 return wifi_getApWMMCapability(apIndex, output);
developer72fb0bb2023-01-11 09:46:29 +08008473}
8474
8475// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
8476INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
8477{
developer95c045d2023-05-24 19:26:28 +08008478 int if_idx, ret = 0;
8479 char interface_name[16] = {0};
developer95c045d2023-05-24 19:26:28 +08008480 struct nl_msg *msg = NULL;
8481 struct nlattr * msg_data = NULL;
8482 struct mtk_nl80211_param param;
8483 struct unl unl_ins;
developer72fb0bb2023-01-11 09:46:29 +08008484
developer95c045d2023-05-24 19:26:28 +08008485 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08008486
developer95c045d2023-05-24 19:26:28 +08008487 if (apIndex > MAX_APS) {
8488 wifi_debug(DEBUG_ERROR, "Invalid apIndex %d\n", apIndex);
8489 return RETURN_ERR;
8490 }
developer72fb0bb2023-01-11 09:46:29 +08008491
developer95c045d2023-05-24 19:26:28 +08008492 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8493 return RETURN_ERR;
developer8e6583c2023-05-23 13:36:06 +08008494
developer95c045d2023-05-24 19:26:28 +08008495 if_idx = if_nametoindex(interface_name);
8496 /*init mtk nl80211 vendor cmd*/
8497 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_WMM;
8498 param.if_type = NL80211_ATTR_IFINDEX;
8499 param.if_idx = if_idx;
8500 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
8501
8502 if (ret) {
8503 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
8504 return RETURN_ERR;
8505 }
8506
8507 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_WMM_AP_CAP_INFO, enable ? 1 : 0)) {
8508 wifi_debug(DEBUG_ERROR, "Nla put attribute error\n");
8509 nlmsg_free(msg);
8510 goto err;
8511 }
8512
8513 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
8514 if (ret) {
8515 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vendor msg fails\n");
8516 goto err;
8517 }
8518 mtk_nl80211_deint(&unl_ins);
8519
8520 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8521 return RETURN_OK;
8522err:
8523 mtk_nl80211_deint(&unl_ins);
8524 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
8525 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08008526}
8527
developer95c045d2023-05-24 19:26:28 +08008528
developer72fb0bb2023-01-11 09:46:29 +08008529//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.
8530INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
8531{
8532 //get the running status from driver
8533 if(!output)
8534 return RETURN_ERR;
8535
8536 char config_file[128] = {0};
8537 char buf[16] = {0};
8538
8539 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8540 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
8541 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
8542 *output = TRUE;
8543 else
8544 *output = FALSE;
8545
8546 return RETURN_OK;
8547}
8548
8549// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
8550INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
8551{
8552 //save config and apply instantly.
8553 char config_file[MAX_BUF_SIZE] = {0};
8554 struct params list;
8555
8556 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8557 list.name = "uapsd_advertisement_enabled";
8558 list.value = enable?"1":"0";
8559
8560 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8561 wifi_hostapdWrite(config_file, &list, 1);
8562 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developere82c0ca2023-05-10 16:25:35 +08008563 wifi_quick_reload_ap(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08008564 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8565
8566 return RETURN_OK;
8567}
8568
8569// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
8570INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
8571{
8572 char interface_name[16] = {0};
8573 // assume class 0->BE, 1->BK, 2->VI, 3->VO
8574 char cmd[128] = {0};
8575 char buf[128] = {0};
8576 char ack_filepath[128] = {0};
8577 uint16_t bitmap = 0;
8578 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
8579 FILE *f = NULL;
8580
8581 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
8582
8583 // Get current setting
8584 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
8585 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
8586 _syscmd(cmd, buf, sizeof(buf));
8587 if (strlen(buf) > 0)
8588 bitmap = strtoul(buf, NULL, 10);
8589
8590 bitmap = strtoul(buf, NULL, 10);
8591
8592 if (ackPolicy == TRUE) { // True, unset this class
8593 bitmap &= ~class_map[class];
8594 } else { // False, set this class
8595 bitmap |= class_map[class];
8596 }
8597
8598 f = fopen(ack_filepath, "w");
8599 if (f == NULL) {
8600 fprintf(stderr, "%s: fopen failed\n", __func__);
8601 return RETURN_ERR;
8602 }
8603 fprintf(f, "%hu", bitmap);
8604 fclose(f);
8605
8606 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8607 return RETURN_ERR;
8608 snprintf(cmd, sizeof(cmd), "iw dev %s set noack_map 0x%04x\n", interface_name, bitmap);
8609 _syscmd(cmd, buf, sizeof(buf));
8610
8611 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
8612 return RETURN_OK;
8613}
8614
8615//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.
8616INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
8617{
8618 //get the running status from driver
8619 if(!output_uint)
8620 return RETURN_ERR;
8621
8622 char output[16]={'\0'};
8623 char config_file[MAX_BUF_SIZE] = {0};
8624
8625 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8626 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
8627 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
8628 else {
8629 int device_num = atoi(output);
8630 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
8631 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
8632 return RETURN_ERR;
8633 }
8634 else {
8635 *output_uint = device_num;
8636 }
8637 }
8638
8639 return RETURN_OK;
8640}
8641
8642INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
8643{
8644 //store to wifi config, apply instantly
8645 char str[MAX_BUF_SIZE]={'\0'};
developer72fb0bb2023-01-11 09:46:29 +08008646 struct params params;
8647 char config_file[MAX_BUF_SIZE] = {0};
8648
8649 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8650 if (number > MAX_ASSOCIATED_STA_NUM) {
8651 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
8652 return RETURN_ERR;
8653 }
8654 sprintf(str, "%d", number);
8655 params.name = "max_num_sta";
8656 params.value = str;
8657
8658 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
8659 int ret = wifi_hostapdWrite(config_file, &params, 1);
8660 if (ret) {
8661 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
8662 ,__func__, ret);
8663 }
8664
8665 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
8666 if (ret) {
8667 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
8668 ,__func__, ret);
8669 }
8670 wifi_reloadAp(apIndex);
8671 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8672
8673 return RETURN_OK;
8674}
8675
8676//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.
8677INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
8678{
8679 //get the current threshold
8680 if(!output_uint)
8681 return RETURN_ERR;
8682 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
8683 if (*output_uint == 0)
8684 *output_uint = 50;
8685 return RETURN_OK;
8686}
8687
8688INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
8689{
8690 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
8691 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
8692 return RETURN_OK;
8693 return RETURN_ERR;
8694}
8695
8696//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.
8697INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
8698{
8699 if(!output_uint)
8700 return RETURN_ERR;
8701 *output_uint = 3;
8702 return RETURN_OK;
8703}
8704
8705//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
8706INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
8707{
8708 if(!output_uint)
8709 return RETURN_ERR;
8710 *output_uint = 3;
8711 return RETURN_OK;
8712}
8713
8714//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.
8715INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
8716{
8717 if(!output_in_seconds)
8718 return RETURN_ERR;
8719 *output_in_seconds = 0;
8720 return RETURN_OK;
8721}
8722
8723//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
8724INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
8725{
8726 if(!output || apIndex>=MAX_APS)
8727 return RETURN_ERR;
8728 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
8729 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
8730 return RETURN_OK;
developer69b61b02023-03-07 17:17:44 +08008731}
developer72fb0bb2023-01-11 09:46:29 +08008732
8733//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
8734INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
8735{
8736 char config_file[128] = {0};
8737 char wpa[16] = {0};
8738 char key_mgmt[64] = {0};
developer72fb0bb2023-01-11 09:46:29 +08008739 if (!output)
8740 return RETURN_ERR;
8741
8742 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8743 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
8744
8745 strcpy(output, "None");//Copying "None" to output string for default case
8746 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
8747 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
8748 if (!strcmp(wpa, "1"))
8749 snprintf(output, 32, "WPA-Personal");
8750 else if (!strcmp(wpa, "2"))
8751 snprintf(output, 32, "WPA2-Personal");
8752 else if (!strcmp(wpa, "3"))
8753 snprintf(output, 32, "WPA-WPA2-Personal");
8754
developere5750452023-05-15 16:46:42 +08008755 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
8756 snprintf(output, 32, "WPA3-Enterprise");
developer72fb0bb2023-01-11 09:46:29 +08008757 } else if (strstr(key_mgmt, "WPA-EAP")) {
8758 if (!strcmp(wpa, "1"))
8759 snprintf(output, 32, "WPA-Enterprise");
8760 else if (!strcmp(wpa, "2"))
8761 snprintf(output, 32, "WPA2-Enterprise");
8762 else if (!strcmp(wpa, "3"))
8763 snprintf(output, 32, "WPA-WPA2-Enterprise");
8764 } else if (strstr(key_mgmt, "SAE")) {
8765 if (strstr(key_mgmt, "WPA-PSK") == NULL)
8766 snprintf(output, 32, "WPA3-Personal");
8767 else
8768 snprintf(output, 32, "WPA3-Personal-Transition");
developer72fb0bb2023-01-11 09:46:29 +08008769 }
8770
8771 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
8772 return RETURN_OK;
8773#if 0
8774 //TODO: need to revisit below implementation
8775 char securityType[32], authMode[32];
8776 int enterpriseMode=0;
8777
8778 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8779 if(!output)
8780 return RETURN_ERR;
8781
8782 wifi_getApBeaconType(apIndex, securityType);
8783 strcpy(output,"None");//By default, copying "None" to output string
8784 if (strncmp(securityType,"None", strlen("None")) == 0)
8785 return RETURN_OK;
8786
8787 wifi_getApBasicAuthenticationMode(apIndex, authMode);
8788 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
8789
8790 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
8791 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
8792 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
8793 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
8794 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
8795 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
8796 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8797
8798 return RETURN_OK;
8799#endif
8800}
developer69b61b02023-03-07 17:17:44 +08008801
developer72fb0bb2023-01-11 09:46:29 +08008802INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
8803{
8804 char securityType[32];
8805 char authMode[32];
8806
8807 //store settings and wait for wifi up to apply
8808 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8809 if(!encMode)
8810 return RETURN_ERR;
8811
8812 if (strcmp(encMode, "None")==0)
8813 {
8814 strcpy(securityType,"None");
8815 strcpy(authMode,"None");
8816 }
8817 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
8818 {
8819 strcpy(securityType,"WPAand11i");
8820 strcpy(authMode,"PSKAuthentication");
8821 }
8822 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
8823 {
8824 strcpy(securityType,"WPAand11i");
8825 strcpy(authMode,"EAPAuthentication");
8826 }
8827 else if (strcmp(encMode, "WPA-Personal")==0)
8828 {
8829 strcpy(securityType,"WPA");
8830 strcpy(authMode,"PSKAuthentication");
8831 }
8832 else if (strcmp(encMode, "WPA-Enterprise")==0)
8833 {
8834 strcpy(securityType,"WPA");
8835 strcpy(authMode,"EAPAuthentication");
8836 }
8837 else if (strcmp(encMode, "WPA2-Personal")==0)
8838 {
8839 strcpy(securityType,"11i");
8840 strcpy(authMode,"PSKAuthentication");
8841 }
8842 else if (strcmp(encMode, "WPA2-Enterprise")==0)
8843 {
8844 strcpy(securityType,"11i");
8845 strcpy(authMode,"EAPAuthentication");
8846 }
8847 else if (strcmp(encMode, "WPA3-Personal") == 0)
8848 {
8849 strcpy(securityType,"11i");
8850 strcpy(authMode,"SAEAuthentication");
8851 }
8852 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
8853 {
8854 strcpy(securityType, "11i");
8855 strcpy(authMode, "PSK-SAEAuthentication");
8856 }
8857 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
8858 {
8859 strcpy(securityType,"11i");
8860 strcpy(authMode,"EAP_192-bit_Authentication");
8861 }
developer3086e2f2023-01-17 09:40:01 +08008862 else if (strcmp(encMode, "OWE") == 0)
8863 {
8864 strcpy(securityType,"11i");
8865 strcpy(authMode,"Enhanced_Open");
8866 }
developer72fb0bb2023-01-11 09:46:29 +08008867 else
8868 {
8869 strcpy(securityType,"None");
8870 strcpy(authMode,"None");
8871 }
8872 wifi_setApBeaconType(apIndex, securityType);
8873 wifi_setApBasicAuthenticationMode(apIndex, authMode);
8874 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8875
8876 return RETURN_OK;
developer69b61b02023-03-07 17:17:44 +08008877}
developer72fb0bb2023-01-11 09:46:29 +08008878
8879
8880//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
8881// output_string must be pre-allocated as 64 character string by caller
8882// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
8883INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
8884{
8885 char buf[16] = {0};
8886 char config_file[MAX_BUF_SIZE] = {0};
8887
8888 if(output_string==NULL)
8889 return RETURN_ERR;
8890
8891 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8892 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
8893
8894 if(strcmp(buf,"0")==0)
8895 {
8896 printf("wpa_mode is %s ......... \n",buf);
8897 return RETURN_ERR;
8898 }
8899
8900 wifi_dbg_printf("\nFunc=%s\n",__func__);
8901 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developere5750452023-05-15 16:46:42 +08008902 wifi_hostapdRead(config_file,"wpa_psk",output_string,65);
developer72fb0bb2023-01-11 09:46:29 +08008903 wifi_dbg_printf("\noutput_string=%s\n",output_string);
8904
8905 return RETURN_OK;
8906}
8907
8908// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
8909// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
8910INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
8911{
8912 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
8913 struct params params={'\0'};
8914 int ret;
8915 char config_file[MAX_BUF_SIZE] = {0};
8916
8917 if(NULL == preSharedKey)
8918 return RETURN_ERR;
8919
developere5750452023-05-15 16:46:42 +08008920 params.name = "wpa_psk";
developer72fb0bb2023-01-11 09:46:29 +08008921
developere5750452023-05-15 16:46:42 +08008922 if(strlen(preSharedKey) != 64)
developer72fb0bb2023-01-11 09:46:29 +08008923 {
developere5750452023-05-15 16:46:42 +08008924 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 64 chars\n");
developer72fb0bb2023-01-11 09:46:29 +08008925 return RETURN_ERR;
8926 }
8927 params.value = preSharedKey;
8928 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8929 ret = wifi_hostapdWrite(config_file, &params, 1);
developere5750452023-05-15 16:46:42 +08008930 if(!ret) {
developer72fb0bb2023-01-11 09:46:29 +08008931 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
developere5750452023-05-15 16:46:42 +08008932 wifi_reloadAp(apIndex);
8933 }
developer72fb0bb2023-01-11 09:46:29 +08008934 return ret;
8935 //TODO: call hostapd_cli for dynamic_config_control
8936}
8937
8938//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
8939// outputs the passphrase, maximum 63 characters
8940INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
8941{
8942 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
8943
8944 wifi_dbg_printf("\nFunc=%s\n",__func__);
8945 if (NULL == output_string)
8946 return RETURN_ERR;
8947
8948 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8949 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
8950 if(strcmp(buf,"0")==0)
8951 {
8952 printf("wpa_mode is %s ......... \n",buf);
8953 return RETURN_ERR;
8954 }
8955
8956 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
8957 wifi_dbg_printf("\noutput_string=%s\n",output_string);
8958
8959 return RETURN_OK;
8960}
8961
8962// sets the passphrase enviornment variable, max 63 characters
8963INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
8964{
8965 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
8966 struct params params={'\0'};
8967 char config_file[MAX_BUF_SIZE] = {0};
8968 int ret;
8969
8970 if(NULL == passPhrase)
8971 return RETURN_ERR;
8972
8973 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
8974 {
8975 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
8976 return RETURN_ERR;
8977 }
8978 params.name = "wpa_passphrase";
8979 params.value = passPhrase;
8980 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8981 ret=wifi_hostapdWrite(config_file,&params,1);
developere5750452023-05-15 16:46:42 +08008982 if(!ret) {
developer72fb0bb2023-01-11 09:46:29 +08008983 wifi_hostapdProcessUpdate(apIndex, &params, 1);
developere5750452023-05-15 16:46:42 +08008984 wifi_reloadAp(apIndex);
8985 }
developer72fb0bb2023-01-11 09:46:29 +08008986
8987 return ret;
8988}
8989
8990//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.
8991INT wifi_setApSecurityReset(INT apIndex)
8992{
8993 char original_config_file[64] = {0};
8994 char current_config_file[64] = {0};
8995 char buf[64] = {0};
8996 char cmd[64] = {0};
8997 char wpa[4] = {0};
8998 char wpa_psk[64] = {0};
8999 char wpa_passphrase[64] = {0};
9000 char wpa_psk_file[128] = {0};
9001 char wpa_key_mgmt[64] = {0};
9002 char wpa_pairwise[32] = {0};
9003 wifi_band band;
9004 struct params list[6];
9005
9006 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9007
9008 band = wifi_index_to_band(apIndex);
9009 if (band == band_2_4)
9010 sprintf(original_config_file, "/etc/hostapd-2G.conf");
9011 else if (band == band_5)
9012 sprintf(original_config_file, "/etc/hostapd-5G.conf");
9013 else if (band == band_6)
9014 sprintf(original_config_file, "/etc/hostapd-6G.conf");
9015 else
9016 return RETURN_ERR;
9017
9018 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
9019 list[0].name = "wpa";
9020 list[0].value = wpa;
developer69b61b02023-03-07 17:17:44 +08009021
developer72fb0bb2023-01-11 09:46:29 +08009022 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
9023 list[1].name = "wpa_psk";
9024 list[1].value = wpa_psk;
9025
9026 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
9027 list[2].name = "wpa_passphrase";
9028 list[2].value = wpa_passphrase;
9029
9030 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
9031
9032 if (strlen(wpa_psk_file) == 0)
9033 strcpy(wpa_psk_file, PSK_FILE);
9034
9035 if (access(wpa_psk_file, F_OK) != 0) {
developerdaf24792023-06-06 11:40:04 +08009036 snprintf(cmd, MAX_CMD_SIZE, "touch %s", wpa_psk_file);
developer72fb0bb2023-01-11 09:46:29 +08009037 _syscmd(cmd, buf, sizeof(buf));
9038 }
9039 list[3].name = "wpa_psk_file";
9040 list[3].value = wpa_psk_file;
9041
9042 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
9043 list[4].name = "wpa_key_mgmt";
9044 list[4].value = wpa_key_mgmt;
9045
9046 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
9047 list[5].name = "wpa_pairwise";
9048 list[5].value = wpa_pairwise;
9049
9050 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
9051 wifi_hostapdWrite(current_config_file, list, 6);
9052
9053 wifi_setApEnable(apIndex, FALSE);
9054 wifi_setApEnable(apIndex, TRUE);
9055
9056 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9057 return RETURN_OK;
9058}
9059
9060//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).
9061INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
9062{
9063 char config_file[64] = {0};
9064 char buf[64] = {0};
9065 char cmd[256] = {0};
9066
9067 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9068
9069 if(!IP_output || !Port_output || !RadiusSecret_output)
9070 return RETURN_ERR;
9071
9072 // Read the first matched config
9073 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9074 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
9075 _syscmd(cmd, buf, sizeof(buf));
9076 strncpy(IP_output, buf, 64);
9077
9078 memset(buf, 0, sizeof(buf));
9079 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
9080 _syscmd(cmd, buf, sizeof(buf));
9081 *Port_output = atoi(buf);
9082
9083 memset(buf, 0, sizeof(buf));
9084 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
9085 _syscmd(cmd, buf, sizeof(buf));
9086 strncpy(RadiusSecret_output, buf, 64);
9087
9088 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9089 return RETURN_OK;
9090}
9091
9092INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
9093{
9094 char config_file[64] = {0};
9095 char port_str[8] = {0};
9096 char cmd[256] = {0};
9097 char buf[128] = {0};
9098
9099 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9100
developere5750452023-05-15 16:46:42 +08009101 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
9102 return RETURN_ERR;
9103
9104 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
9105 return RETURN_ERR;
9106
developer72fb0bb2023-01-11 09:46:29 +08009107 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9108
9109 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
9110 _syscmd(cmd, buf, sizeof(buf));
9111 memset(cmd, 0, sizeof(cmd));
9112
9113 snprintf(port_str, sizeof(port_str), "%d", port);
9114 if (strlen(buf) == 0)
9115 // Append
9116 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
9117 "auth_server_addr=%s\\n"
9118 "auth_server_port=%s\\n"
9119 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
9120 else {
9121 // Delete the three lines setting after the "# radius 1" comment
9122 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
9123 _syscmd(cmd, buf, sizeof(buf));
9124 memset(cmd, 0, sizeof(cmd));
9125 // Use "# radius 1" comment to find the location to insert the radius setting
9126 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
9127 "# radius 1\\n"
9128 "auth_server_addr=%s\\n"
9129 "auth_server_port=%s\\n"
9130 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
9131 }
9132 if(_syscmd(cmd, buf, sizeof(buf))) {
9133 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
9134 return RETURN_ERR;
9135 }
9136
9137 wifi_reloadAp(apIndex);
9138 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9139 return RETURN_OK;
9140}
9141
9142INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
9143{
9144 char config_file[64] = {0};
9145 char buf[64] = {0};
9146 char cmd[256] = {0};
9147
9148 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9149
9150 if(!IP_output || !Port_output || !RadiusSecret_output)
9151 return RETURN_ERR;
9152
9153 // Read the second matched config
9154 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9155 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
9156 _syscmd(cmd, buf, sizeof(buf));
9157 strncpy(IP_output, buf, 64);
9158
9159 memset(buf, 0, sizeof(buf));
9160 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
9161 _syscmd(cmd, buf, sizeof(buf));
9162 *Port_output = atoi(buf);
9163
9164 memset(buf, 0, sizeof(buf));
9165 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
9166 _syscmd(cmd, buf, sizeof(buf));
9167 strncpy(RadiusSecret_output, buf, 64);
9168
9169 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9170 return RETURN_OK;
9171}
9172
9173INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
9174{
9175 char config_file[64] = {0};
9176 char port_str[8] = {0};
9177 char cmd[256] = {0};
9178 char buf[128] = {0};
9179
9180 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9181
developere5750452023-05-15 16:46:42 +08009182 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
9183 return RETURN_ERR;
9184
9185 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
9186 return RETURN_ERR;
9187
developer72fb0bb2023-01-11 09:46:29 +08009188 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9189
9190 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
9191 _syscmd(cmd, buf, sizeof(buf));
9192 memset(cmd, 0, sizeof(cmd));
9193
9194 snprintf(port_str, sizeof(port_str), "%d", port);
9195 if (strlen(buf) == 0)
9196 // Append
9197 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
9198 "auth_server_addr=%s\\n"
9199 "auth_server_port=%s\\n"
9200 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
9201 else {
9202 // Delete the three lines setting after the "# radius 2" comment
9203 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
9204 _syscmd(cmd, buf, sizeof(buf));
9205 memset(cmd, 0, sizeof(cmd));
9206 // Use "# radius 2" comment to find the location to insert the radius setting
9207 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
9208 "# radius 2\\n"
9209 "auth_server_addr=%s\\n"
9210 "auth_server_port=%s\\n"
9211 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
9212 }
9213 if(_syscmd(cmd, buf, sizeof(buf))) {
9214 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
9215 return RETURN_ERR;
9216 }
9217
9218 wifi_reloadAp(apIndex);
9219 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9220 return RETURN_OK;
9221}
9222
9223//RadiusSettings
9224INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
9225{
9226 if(!output)
9227 return RETURN_ERR;
9228
9229 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
developer69b61b02023-03-07 17:17:44 +08009230 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
9231 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
9232 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
9233 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 +08009234 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 +08009235 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
9236 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
9237 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 +08009238 //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.
9239
9240 return RETURN_OK;
9241}
9242
9243INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
9244{
9245 //store the paramters, and apply instantly
9246 return RETURN_ERR;
9247}
9248
9249//Device.WiFi.AccessPoint.{i}.WPS.Enable
9250//Enables or disables WPS functionality for this access point.
9251// outputs the WPS enable state of this ap in output_bool
9252INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
9253{
9254 char interface_name[16] = {0};
developer2f79c922023-06-02 17:33:42 +08009255 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08009256 if(!output_bool)
9257 return RETURN_ERR;
9258 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9259 return RETURN_ERR;
9260 sprintf(cmd,"hostapd_cli -i %s get_config | grep wps_state | cut -d '=' -f2", interface_name);
9261 _syscmd(cmd, buf, sizeof(buf));
9262 if(strstr(buf, "configured"))
9263 *output_bool=TRUE;
9264 else
9265 *output_bool=FALSE;
9266
9267 return RETURN_OK;
developer69b61b02023-03-07 17:17:44 +08009268}
developer72fb0bb2023-01-11 09:46:29 +08009269
9270//Device.WiFi.AccessPoint.{i}.WPS.Enable
9271// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
9272INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
9273{
9274 char config_file[MAX_BUF_SIZE] = {0};
developere5750452023-05-15 16:46:42 +08009275 char buf[128] = {0};
developer72fb0bb2023-01-11 09:46:29 +08009276 struct params params;
9277
9278 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9279 //store the paramters, and wait for wifi up to apply
9280 params.name = "wps_state";
developere5750452023-05-15 16:46:42 +08009281 if (enable == TRUE) {
9282 wifi_getApBeaconType(apIndex, buf);
9283 if (strncmp(buf, "None", 4) == 0) // If ap didn't set encryption
9284 params.value = "1";
9285 else // If ap set encryption
9286 params.value = "2";
9287 } else {
9288 params.value = "0";
9289 }
developer72fb0bb2023-01-11 09:46:29 +08009290
9291 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9292 wifi_hostapdWrite(config_file, &params, 1);
9293 wifi_hostapdProcessUpdate(apIndex, &params, 1);
9294 wifi_reloadAp(apIndex);
9295
9296 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9297 return RETURN_OK;
9298}
9299
9300//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
9301INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
9302{
9303 if(!output)
9304 return RETURN_ERR;
9305 snprintf(output, 128, "PushButton,PIN");
9306 return RETURN_OK;
9307}
9308
9309//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
9310//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.
9311// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
9312INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
9313{
9314 if(!output)
9315 return RETURN_ERR;
9316 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
9317
9318 return RETURN_OK;
9319}
9320
9321//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
9322// 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
9323INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
9324{
9325 //apply instantly. No setting need to be stored.
9326 char methods[MAX_BUF_SIZE], *token, *next_token;
9327 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
9328 struct params params;
9329
9330 if(!methodString)
9331 return RETURN_ERR;
9332 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9333 //store the paramters, and wait for wifi up to apply
9334
9335 snprintf(methods, sizeof(methods), "%s", methodString);
9336 for(token=methods; *token; token=next_token)
9337 {
9338 strtok_r(token, ",", &next_token);
9339 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
9340 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
9341 else if(*token=='E')
9342 {
9343 if(!strcmp(methods, "Ethernet"))
9344 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
9345 else if(!strcmp(methods, "ExternalNFCToken"))
9346 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
9347 else
9348 printf("%s: Unknown WpsConfigMethod\n", __func__);
9349 }
9350 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
9351 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
9352 else if(*token=='N' && !strcmp(token, "NFCInterface"))
9353 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
9354 else if(*token=='P' )
9355 {
9356 if(!strcmp(token, "PushButton"))
developere5750452023-05-15 16:46:42 +08009357 snprintf(config_methods, sizeof(config_methods), "%s ", "push_button");
developer72fb0bb2023-01-11 09:46:29 +08009358 else if(!strcmp(token, "PIN"))
9359 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
9360 else
9361 printf("%s: Unknown WpsConfigMethod\n", __func__);
9362 }
9363 else
9364 printf("%s: Unknown WpsConfigMethod\n", __func__);
9365 }
9366 params.name = "config_methods";
9367 params.value = config_methods;
9368 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9369 wifi_hostapdWrite(config_file, &params, 1);
9370 wifi_hostapdProcessUpdate(apIndex, &params, 1);
9371 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9372
9373 return RETURN_OK;
9374}
9375
9376// outputs the pin value, ulong_pin must be allocated by the caller
9377INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
9378{
9379 char buf[MAX_BUF_SIZE] = {0};
9380 char cmd[MAX_CMD_SIZE] = {0};
9381
9382 if(!output_ulong)
9383 return RETURN_ERR;
9384 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
9385 _syscmd(cmd, buf, sizeof(buf));
9386 if(strlen(buf) > 0)
9387 *output_ulong=strtoul(buf, NULL, 10);
9388
9389 return RETURN_OK;
9390}
9391
9392// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
9393INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
9394{
9395 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
9396 char ap_pin[16] = {0};
developer72fb0bb2023-01-11 09:46:29 +08009397 char config_file[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08009398 struct params params;
9399
9400 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9401 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
9402 params.name = "ap_pin";
9403 params.value = ap_pin;
9404 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9405 wifi_hostapdWrite(config_file, &params, 1);
9406 wifi_hostapdProcessUpdate(apIndex, &params, 1);
9407 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9408
9409 return RETURN_OK;
9410}
9411
9412// Output string is either Not configured or Configured, max 32 characters
9413INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
9414{
9415 char interface_name[16] = {0};
9416 char cmd[MAX_CMD_SIZE];
9417 char buf[MAX_BUF_SIZE]={0};
9418
9419 if(!output_string)
9420 return RETURN_ERR;
9421 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9422 snprintf(output_string, 32, "Not configured");
9423 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9424 return RETURN_ERR;
9425 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep wps_state | cut -d'=' -f2", interface_name);
9426 _syscmd(cmd, buf, sizeof(buf));
9427
9428 if(!strncmp(buf, "configured", 10))
9429 snprintf(output_string, 32, "Configured");
9430 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9431
9432 return RETURN_OK;
9433}
9434
9435// sets the WPS pin for this AP
9436INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
9437{
9438 char interface_name[16] = {0};
9439 char cmd[MAX_CMD_SIZE];
9440 char buf[MAX_BUF_SIZE]={0};
9441 BOOL enable;
9442
9443 wifi_getApEnable(apIndex, &enable);
9444 if (!enable)
9445 return RETURN_ERR;
9446 wifi_getApWpsEnable(apIndex, &enable);
9447 if (!enable)
9448 return RETURN_ERR;
9449
9450 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9451 return RETURN_ERR;
9452 snprintf(cmd, 64, "hostapd_cli -i%s wps_pin any %s", interface_name, pin);
9453 _syscmd(cmd, buf, sizeof(buf));
9454 if((strstr(buf, "OK"))!=NULL)
9455 return RETURN_OK;
9456
9457 return RETURN_ERR;
9458}
9459
9460// This function is called when the WPS push button has been pressed for this AP
9461INT wifi_setApWpsButtonPush(INT apIndex)
9462{
9463 char cmd[MAX_CMD_SIZE];
9464 char buf[MAX_BUF_SIZE]={0};
9465 char interface_name[16] = {0};
9466 BOOL enable=FALSE;
9467
9468 wifi_getApEnable(apIndex, &enable);
9469 if (!enable)
9470 return RETURN_ERR;
9471
9472 wifi_getApWpsEnable(apIndex, &enable);
9473 if (!enable)
9474 return RETURN_ERR;
9475
9476 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9477 return RETURN_ERR;
9478
9479 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel; hostapd_cli -i%s wps_pbc", interface_name, interface_name);
9480 _syscmd(cmd, buf, sizeof(buf));
9481
9482 if((strstr(buf, "OK"))!=NULL)
9483 return RETURN_OK;
9484 return RETURN_ERR;
9485}
9486
9487// cancels WPS mode for this AP
9488INT wifi_cancelApWPS(INT apIndex)
9489{
9490 char interface_name[16] = {0};
9491 char cmd[MAX_CMD_SIZE];
9492 char buf[MAX_BUF_SIZE]={0};
9493
9494 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9495 return RETURN_ERR;
9496 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel", interface_name);
9497 _syscmd(cmd,buf, sizeof(buf));
9498
9499 if((strstr(buf, "OK"))!=NULL)
9500 return RETURN_OK;
9501 return RETURN_ERR;
9502}
9503
9504//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
9505//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
9506INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
9507{
9508 char interface_name[16] = {0};
9509 FILE *f = NULL;
developer2f79c922023-06-02 17:33:42 +08009510 int read_flag=0, auth_temp=0, mac_temp=0;
developer72fb0bb2023-01-11 09:46:29 +08009511 char cmd[256] = {0}, buf[2048] = {0};
9512 char *param = NULL, *value = NULL, *line=NULL;
9513 size_t len = 0;
developer72fb0bb2023-01-11 09:46:29 +08009514 wifi_associated_dev_t *dev=NULL;
9515
9516 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9517 *associated_dev_array = NULL;
9518 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9519 return RETURN_ERR;
9520 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
9521 _syscmd(cmd,buf,sizeof(buf));
9522 *output_array_size = atoi(buf);
9523
9524 if (*output_array_size <= 0)
9525 return RETURN_OK;
9526
9527 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
9528 *associated_dev_array = dev;
9529 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt" , interface_name);
9530 _syscmd(cmd,buf,sizeof(buf));
9531 f = fopen("/tmp/connected_devices.txt", "r");
9532 if (f==NULL)
9533 {
9534 *output_array_size=0;
9535 return RETURN_ERR;
9536 }
9537 while ((getline(&line, &len, f)) != -1)
9538 {
9539 param = strtok(line,"=");
9540 value = strtok(NULL,"=");
9541
9542 if( strcmp("flags",param) == 0 )
9543 {
9544 value[strlen(value)-1]='\0';
9545 if(strstr (value,"AUTHORIZED") != NULL )
9546 {
9547 dev[auth_temp].cli_AuthenticationState = 1;
9548 dev[auth_temp].cli_Active = 1;
9549 auth_temp++;
9550 read_flag=1;
9551 }
9552 }
9553 if(read_flag==1)
9554 {
9555 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
9556 {
9557 value[strlen(value)-1]='\0';
9558 sscanf(value, "%x:%x:%x:%x:%x:%x",
9559 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
9560 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
9561 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
9562 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
9563 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
9564 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
9565 mac_temp++;
9566 read_flag=0;
9567 }
9568 }
9569 }
9570 *output_array_size = auth_temp;
9571 auth_temp=0;
9572 mac_temp=0;
9573 free(line);
9574 fclose(f);
9575 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9576 return RETURN_OK;
9577}
9578
9579#define MACADDRESS_SIZE 6
9580
9581INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
9582{
9583 FILE *fp = NULL;
9584 char str[MAX_BUF_SIZE] = {0};
9585 int wificlientindex = 0 ;
9586 int count = 0;
9587 int signalstrength = 0;
9588 int arr[MACADDRESS_SIZE] = {0};
9589 unsigned char mac[MACADDRESS_SIZE] = {0};
9590 UINT wifi_count = 0;
developer72fb0bb2023-01-11 09:46:29 +08009591 char pipeCmd[MAX_CMD_SIZE] = {0};
9592
9593 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9594 *output_array_size = 0;
9595 *associated_dev_array = NULL;
9596
9597 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
9598 fp = popen(pipeCmd, "r");
developer69b61b02023-03-07 17:17:44 +08009599 if (fp == NULL)
developer72fb0bb2023-01-11 09:46:29 +08009600 {
9601 printf("Failed to run command inside function %s\n",__FUNCTION__ );
9602 return RETURN_ERR;
9603 }
9604
9605 /* Read the output a line at a time - output it. */
9606 fgets(str, sizeof(str)-1, fp);
9607 wifi_count = (unsigned int) atoi ( str );
9608 *output_array_size = wifi_count;
9609 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
9610 pclose(fp);
9611
9612 if(wifi_count == 0)
9613 {
9614 return RETURN_OK;
9615 }
9616 else
9617 {
9618 wifi_associated_dev3_t* temp = NULL;
9619 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
9620 if(temp == NULL)
9621 {
9622 printf("Error Statement. Insufficient memory \n");
9623 return RETURN_ERR;
9624 }
9625
9626 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
9627 system(pipeCmd);
9628 memset(pipeCmd,0,sizeof(pipeCmd));
9629 if(apIndex == 0)
9630 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
9631 else if(apIndex == 1)
9632 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
9633 system(pipeCmd);
9634
9635 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
9636 if(fp == NULL)
9637 {
9638 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
9639 free(temp);
9640 return RETURN_ERR;
9641 }
9642 fclose(fp);
9643
9644 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
9645 fp = popen(pipeCmd, "r");
9646 if(fp)
9647 {
9648 for(count =0 ; count < wifi_count; count++)
9649 {
9650 fgets(str, MAX_BUF_SIZE, fp);
9651 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
9652 {
9653 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
9654 {
9655 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
9656
9657 }
9658 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
9659 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]);
9660 }
9661 temp[count].cli_AuthenticationState = 1; //TODO
9662 temp[count].cli_Active = 1; //TODO
9663 }
9664 pclose(fp);
9665 }
9666
9667 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt");
9668 fp = popen(pipeCmd, "r");
9669 if(fp)
developer69b61b02023-03-07 17:17:44 +08009670 {
developer72fb0bb2023-01-11 09:46:29 +08009671 pclose(fp);
9672 }
9673 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
9674 if(fp)
9675 {
9676 for(count =0 ; count < wifi_count ;count++)
9677 {
9678 fgets(str, MAX_BUF_SIZE, fp);
9679 signalstrength = atoi(str);
9680 temp[count].cli_SignalStrength = signalstrength;
9681 temp[count].cli_RSSI = signalstrength;
9682 temp[count].cli_SNR = signalstrength + 95;
9683 }
9684 pclose(fp);
9685 }
9686
9687
9688 if((apIndex == 0) || (apIndex == 4))
9689 {
9690 for(count =0 ; count < wifi_count ;count++)
developer69b61b02023-03-07 17:17:44 +08009691 {
developer72fb0bb2023-01-11 09:46:29 +08009692 strcpy(temp[count].cli_OperatingStandard,"g");
9693 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
9694 }
9695
9696 //BytesSent
9697 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt");
9698 fp = popen(pipeCmd, "r");
9699 if(fp)
developer69b61b02023-03-07 17:17:44 +08009700 {
developer72fb0bb2023-01-11 09:46:29 +08009701 pclose(fp);
9702 }
9703 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
9704 if(fp)
9705 {
9706 for (count = 0; count < wifi_count; count++)
9707 {
9708 fgets(str, MAX_BUF_SIZE, fp);
9709 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
9710 }
9711 pclose(fp);
9712 }
9713
9714 //BytesReceived
9715 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt");
9716 fp = popen(pipeCmd, "r");
9717 if (fp)
9718 {
9719 pclose(fp);
9720 }
9721 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
9722 if (fp)
9723 {
9724 for (count = 0; count < wifi_count; count++)
9725 {
9726 fgets(str, MAX_BUF_SIZE, fp);
9727 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
9728 }
9729 pclose(fp);
9730 }
9731
9732 //PacketsSent
9733 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt");
9734 fp = popen(pipeCmd, "r");
9735 if (fp)
9736 {
9737 pclose(fp);
9738 }
9739
9740 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
9741 if (fp)
9742 {
9743 for (count = 0; count < wifi_count; count++)
9744 {
9745 fgets(str, MAX_BUF_SIZE, fp);
9746 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
9747 }
9748 pclose(fp);
9749 }
9750
9751 //PacketsReceived
9752 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt");
9753 fp = popen(pipeCmd, "r");
9754 if (fp)
9755 {
9756 pclose(fp);
9757 }
9758 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
9759 if (fp)
9760 {
9761 for (count = 0; count < wifi_count; count++)
9762 {
9763 fgets(str, MAX_BUF_SIZE, fp);
9764 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
9765 }
9766 pclose(fp);
9767 }
9768
9769 //ErrorsSent
9770 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt");
9771 fp = popen(pipeCmd, "r");
9772 if (fp)
9773 {
9774 pclose(fp);
9775 }
9776 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
9777 if (fp)
9778 {
9779 for (count = 0; count < wifi_count; count++)
9780 {
9781 fgets(str, MAX_BUF_SIZE, fp);
9782 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
9783 }
9784 pclose(fp);
9785 }
9786
9787 //ErrorsSent
9788 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt");
9789 fp = popen(pipeCmd, "r");
9790 if (fp)
9791 {
9792 pclose(fp);
9793 }
9794 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
9795 if (fp)
9796 {
9797 for (count = 0; count < wifi_count; count++)
9798 {
9799 fgets(str, MAX_BUF_SIZE, fp);
9800 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
9801 }
9802 pclose(fp);
9803 }
9804
9805 //LastDataDownlinkRate
9806 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt");
9807 fp = popen(pipeCmd, "r");
9808 if (fp)
9809 {
9810 pclose(fp);
9811 }
9812 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
9813 if (fp)
9814 {
9815 for (count = 0; count < wifi_count; count++)
9816 {
9817 fgets(str, MAX_BUF_SIZE, fp);
9818 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
9819 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
9820 }
9821 pclose(fp);
9822 }
9823
9824 //LastDataUplinkRate
9825 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt");
9826 fp = popen(pipeCmd, "r");
9827 if (fp)
9828 {
9829 pclose(fp);
9830 }
9831 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
9832 if (fp)
9833 {
9834 for (count = 0; count < wifi_count; count++)
9835 {
9836 fgets(str, MAX_BUF_SIZE, fp);
9837 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
9838 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
9839 }
9840 pclose(fp);
9841 }
9842
9843 }
9844 else if ((apIndex == 1) || (apIndex == 5))
9845 {
9846 for (count = 0; count < wifi_count; count++)
9847 {
9848 strcpy(temp[count].cli_OperatingStandard, "a");
9849 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
9850 temp[count].cli_BytesSent = 0;
9851 temp[count].cli_BytesReceived = 0;
9852 temp[count].cli_LastDataUplinkRate = 0;
9853 temp[count].cli_LastDataDownlinkRate = 0;
9854 temp[count].cli_PacketsSent = 0;
9855 temp[count].cli_PacketsReceived = 0;
9856 temp[count].cli_ErrorsSent = 0;
9857 }
9858 }
9859
9860 for (count = 0; count < wifi_count; count++)
9861 {
9862 temp[count].cli_Retransmissions = 0;
9863 temp[count].cli_DataFramesSentAck = 0;
9864 temp[count].cli_DataFramesSentNoAck = 0;
9865 temp[count].cli_MinRSSI = 0;
9866 temp[count].cli_MaxRSSI = 0;
9867 strncpy(temp[count].cli_InterferenceSources, "", 64);
9868 memset(temp[count].cli_IPAddress, 0, 64);
9869 temp[count].cli_RetransCount = 0;
9870 temp[count].cli_FailedRetransCount = 0;
9871 temp[count].cli_RetryCount = 0;
9872 temp[count].cli_MultipleRetryCount = 0;
9873 }
9874 *associated_dev_array = temp;
9875 }
9876 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9877 return RETURN_OK;
9878}
9879
developer7e4a2a62023-04-06 19:56:03 +08009880int wifihal_interfacestatus(CHAR *wifi_status, CHAR *interface_name)
developer72fb0bb2023-01-11 09:46:29 +08009881{
developer7e4a2a62023-04-06 19:56:03 +08009882 char cmd[MAX_CMD_SIZE] = {0};
9883 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08009884
developer7e4a2a62023-04-06 19:56:03 +08009885 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
9886
9887 snprintf(cmd, MAX_CMD_SIZE, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4 | tr -d '\\n'",
9888 interface_name);
9889 _syscmd(cmd, buf, MAX_BUF_SIZE);
9890
9891 strcpy(wifi_status, buf); /* TBD: check wifi_status mem lenth and replace with strcpy later */
9892
9893 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08009894 return RETURN_OK;
9895}
9896
9897/* #define HOSTAPD_STA_PARAM_ENTRIES 29
9898struct hostapd_sta_param {
9899 char key[50];
9900 char value[100];
9901}
9902
9903static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
9904 int i = 0;
9905
9906 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
9907 if (strncmp(params[i].key,key,50) == 0){
9908 return &params[i].value;
9909 }
9910 i++;
9911 }
9912 return NULL;
9913
9914} */
9915
9916static unsigned int count_occurences(const char *buf, const char *word)
9917{
9918 unsigned int n = 0;
9919 char *ptr = strstr(buf, word);
9920
9921 while (ptr++) {
9922 n++;
9923 ptr = strstr(ptr, word);
9924 }
9925
9926 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
9927 return n;
9928}
9929
9930static const char *get_line_from_str_buf(const char *buf, char *line)
9931{
9932 int i;
9933 int n = strlen(buf);
9934
9935 for (i = 0; i < n; i++) {
9936 line[i] = buf[i];
9937 if (buf[i] == '\n') {
9938 line[i] = '\0';
9939 return &buf[i + 1];
9940 }
9941 }
9942
9943 return NULL;
9944}
9945
9946INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
9947{
developer0d26f2c2023-05-25 19:46:36 +08009948 char interface_name[16] = {0};
9949 FILE *f = NULL;
9950 int auth_temp= -1;
9951 char cmd[256] = {0}, buf[2048] = {0};
9952 char *param = NULL, *value = NULL, *line=NULL;
9953 size_t len = 0;
9954 wifi_associated_dev3_t *dev=NULL;
developer72fb0bb2023-01-11 09:46:29 +08009955
9956 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer0d26f2c2023-05-25 19:46:36 +08009957 *associated_dev_array = NULL;
9958 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72fb0bb2023-01-11 09:46:29 +08009959 return RETURN_ERR;
developer0d26f2c2023-05-25 19:46:36 +08009960 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
9961 _syscmd(cmd, buf, sizeof(buf));
9962 *output_array_size = atoi(buf);
developer72fb0bb2023-01-11 09:46:29 +08009963
developer0d26f2c2023-05-25 19:46:36 +08009964 if (*output_array_size <= 0)
9965 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08009966
developer0d26f2c2023-05-25 19:46:36 +08009967 dev=(wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
9968 *associated_dev_array = dev;
9969 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/diagnostic3_devices.txt" , interface_name);
9970 _syscmd(cmd,buf,sizeof(buf));
9971 f = fopen("/tmp/diagnostic3_devices.txt", "r");
9972 if (f == NULL)
9973 {
9974 *output_array_size=0;
developer72fb0bb2023-01-11 09:46:29 +08009975 return RETURN_ERR;
9976 }
developer0d26f2c2023-05-25 19:46:36 +08009977 while ((getline(&line, &len, f)) != -1)
9978 {
9979 param = strtok(line, "=");
9980 value = strtok(NULL, "=");
developer72fb0bb2023-01-11 09:46:29 +08009981
developer0d26f2c2023-05-25 19:46:36 +08009982 if( strcmp("flags",param) == 0 )
9983 {
9984 value[strlen(value)-1]='\0';
9985 if(strstr (value,"AUTHORIZED") != NULL )
9986 {
9987 auth_temp++;
9988 dev[auth_temp].cli_AuthenticationState = 1;
9989 dev[auth_temp].cli_Active = 1;
developer72fb0bb2023-01-11 09:46:29 +08009990 }
developer0d26f2c2023-05-25 19:46:36 +08009991 } else if (auth_temp < 0) {
9992 continue;
9993 } else if( strcmp("dot11RSNAStatsSTAAddress", param) == 0 )
9994 {
9995 value[strlen(value)-1]='\0';
9996 sscanf(value, "%x:%x:%x:%x:%x:%x",
9997 (unsigned int *)&dev[auth_temp].cli_MACAddress[0],
9998 (unsigned int *)&dev[auth_temp].cli_MACAddress[1],
9999 (unsigned int *)&dev[auth_temp].cli_MACAddress[2],
10000 (unsigned int *)&dev[auth_temp].cli_MACAddress[3],
10001 (unsigned int *)&dev[auth_temp].cli_MACAddress[4],
10002 (unsigned int *)&dev[auth_temp].cli_MACAddress[5]);
10003 } else if (strcmp("signal", param) == 0) {
10004 value[strlen(value)-1]='\0';
10005 sscanf(value, "%d", &dev[auth_temp].cli_RSSI);
10006 dev[auth_temp].cli_SNR = 95 + dev[auth_temp].cli_RSSI;
developer72fb0bb2023-01-11 09:46:29 +080010007 }
developer0d26f2c2023-05-25 19:46:36 +080010008 }
10009 if (line)
10010 free(line);
10011 fclose(f);
developer72fb0bb2023-01-11 09:46:29 +080010012 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +080010013 return RETURN_OK;
10014}
10015
10016#if 0
10017//To-do
10018INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
10019{
10020 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10021
10022 //Using different approach to get required WiFi Parameters from system available commands
developer69b61b02023-03-07 17:17:44 +080010023#if 0
developer72fb0bb2023-01-11 09:46:29 +080010024 FILE *f;
10025 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
10026 char cmd[256], buf[2048];
10027 char *param , *value, *line=NULL;
10028 size_t len = 0;
10029 ssize_t nread;
10030 wifi_associated_dev3_t *dev=NULL;
10031 *associated_dev_array = NULL;
10032 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
10033 _syscmd(cmd,buf,sizeof(buf));
10034 *output_array_size = atoi(buf);
10035
10036 if (*output_array_size <= 0)
10037 return RETURN_OK;
10038
10039 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
10040 *associated_dev_array = dev;
10041 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt", interface_name);
10042 _syscmd(cmd,buf,sizeof(buf));
10043 f = fopen("/tmp/connected_devices.txt", "r");
10044 if (f==NULL)
10045 {
10046 *output_array_size=0;
10047 return RETURN_ERR;
10048 }
10049 while ((nread = getline(&line, &len, f)) != -1)
10050 {
10051 param = strtok(line,"=");
10052 value = strtok(NULL,"=");
10053
10054 if( strcmp("flags",param) == 0 )
10055 {
10056 value[strlen(value)-1]='\0';
10057 if(strstr (value,"AUTHORIZED") != NULL )
10058 {
10059 dev[auth_temp].cli_AuthenticationState = 1;
10060 dev[auth_temp].cli_Active = 1;
10061 auth_temp++;
10062 read_flag=1;
10063 }
10064 }
10065 if(read_flag==1)
10066 {
10067 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
10068 {
10069 value[strlen(value)-1]='\0';
10070 sscanf(value, "%x:%x:%x:%x:%x:%x",
10071 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
10072 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
10073 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
10074 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
10075 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
10076 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
10077
10078 }
10079 else if( strcmp("rx_packets",param) == 0 )
10080 {
10081 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
10082 }
10083
10084 else if( strcmp("tx_packets",param) == 0 )
10085 {
developer69b61b02023-03-07 17:17:44 +080010086 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
developer72fb0bb2023-01-11 09:46:29 +080010087 }
10088
10089 else if( strcmp("rx_bytes",param) == 0 )
10090 {
10091 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
10092 }
10093
10094 else if( strcmp("tx_bytes",param) == 0 )
10095 {
developer69b61b02023-03-07 17:17:44 +080010096 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
developer72fb0bb2023-01-11 09:46:29 +080010097 mac_temp++;
10098 read_flag=0;
developer69b61b02023-03-07 17:17:44 +080010099 }
developer72fb0bb2023-01-11 09:46:29 +080010100 }
10101 }
10102
10103 *output_array_size = auth_temp;
10104 auth_temp=0;
10105 mac_temp=0;
10106 free(line);
10107 fclose(f);
10108#endif
10109 char interface_name[MAX_BUF_SIZE] = {0};
10110 char wifi_status[MAX_BUF_SIZE] = {0};
10111 char hostapdconf[MAX_BUF_SIZE] = {0};
10112
10113 wifi_associated_dev3_t *dev_array = NULL;
10114 ULONG wifi_count = 0;
10115
10116 *associated_dev_array = NULL;
10117 *output_array_size = 0;
10118
10119 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
10120 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
10121 {
10122 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
10123
10124 wifi_GetInterfaceName(interface_name, hostapdconf);
10125
10126 if(strlen(interface_name) > 1)
10127 {
10128 wifihal_interfacestatus(wifi_status,interface_name);
10129 if(strcmp(wifi_status,"RUNNING") == 0)
10130 {
10131 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
10132
10133 *associated_dev_array = dev_array;
developer69b61b02023-03-07 17:17:44 +080010134 *output_array_size = wifi_count;
developer72fb0bb2023-01-11 09:46:29 +080010135 }
10136 else
10137 {
10138 *associated_dev_array = NULL;
10139 }
10140 }
10141 }
10142
10143 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10144 return RETURN_OK;
10145}
10146#endif
10147
10148/* getIPAddress function */
10149/**
10150* @description Returning IpAddress of the Matched String
10151*
developer69b61b02023-03-07 17:17:44 +080010152* @param
developer72fb0bb2023-01-11 09:46:29 +080010153* @str Having MacAddress
developer69b61b02023-03-07 17:17:44 +080010154* @ipaddr Having ipaddr
developer72fb0bb2023-01-11 09:46:29 +080010155* @return The status of the operation
10156* @retval RETURN_OK if successful
10157* @retval RETURN_ERR if any error is detected
10158*
10159*/
10160
10161INT getIPAddress(char *str,char *ipaddr)
10162{
10163 FILE *fp = NULL;
10164 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
10165 int LeaseTime = 0,ret = 0;
10166 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
10167 {
10168 return RETURN_ERR;
10169 }
10170
10171 while ( fgets(buf, sizeof(buf), fp)!= NULL )
10172 {
10173 /*
10174 Sample:sss
10175 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
10176 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
10177 */
10178 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
10179 &(LeaseTime),
10180 phyAddr,
10181 ipAddr,
10182 hostName
10183 );
10184 if(ret != 4)
10185 continue;
10186 if(strcmp(str,phyAddr) == 0)
10187 strcpy(ipaddr,ipAddr);
10188 }
10189 fclose(fp);
10190 return RETURN_OK;
10191}
10192
10193/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
10194/**
10195* @description Returning Inactive wireless connected clients informations
10196*
developer69b61b02023-03-07 17:17:44 +080010197* @param
developer72fb0bb2023-01-11 09:46:29 +080010198* @filename Holding private_wifi 2g/5g content files
10199* @associated_dev_array Having inactiv wireless clients informations
10200* @output_array_size Returning Inactive wireless counts
10201* @return The status of the operation
10202* @retval RETURN_OK if successful
10203* @retval RETURN_ERR if any error is detected
10204*
10205*/
10206
10207INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
10208{
10209 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10210 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
10211 FILE *fp = NULL;
10212 int arr[MACADDRESS_SIZE] = {0};
10213 unsigned char mac[MACADDRESS_SIZE] = {0};
10214 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
10215 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
10216 fp = popen(buf,"r");
10217 if(fp == NULL)
10218 return RETURN_ERR;
10219 else
10220 {
10221 fgets(path,sizeof(path),fp);
10222 maccount = atoi(path);
10223 }
10224 pclose(fp);
10225 *output_array_size = maccount;
10226 wifi_associated_dev3_t* temp = NULL;
10227 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
10228 *associated_dev_array = temp;
10229 if(temp == NULL)
10230 {
10231 printf("Error Statement. Insufficient memory \n");
10232 return RETURN_ERR;
10233 }
10234 memset(buf,0,sizeof(buf));
10235 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
10236 fp = popen(buf,"r");
10237 if (fp == NULL) {
10238 fprintf(stderr, "%s: failed pipe command %s.\n", __func__, buf);
10239 return RETURN_ERR;
10240 }
10241 for(count = 0; count < maccount ; count++)
10242 {
10243 fgets(path,sizeof(path),fp);
10244 for(i = 0; path[i]!='\n';i++)
10245 str[i]=path[i];
10246 str[i]='\0';
10247 getIPAddress(str,ipaddr);
10248 memset(buf,0,sizeof(buf));
10249 if(strlen(ipaddr) > 0)
10250 {
10251 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
10252 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
10253 {
10254 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
10255 {
10256 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
10257 {
10258 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
10259
10260 }
10261 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
10262 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]);
10263 }
10264 temp[count].cli_AuthenticationState = 0; //TODO
developer69b61b02023-03-07 17:17:44 +080010265 temp[count].cli_Active = 0; //TODO
developer72fb0bb2023-01-11 09:46:29 +080010266 temp[count].cli_SignalStrength = 0;
10267 }
10268 else //Active wireless clients info
10269 {
10270 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
10271 {
10272 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
10273 {
10274 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
10275
10276 }
10277 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
10278 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]);
10279 }
10280 temp[count].cli_Active = 1;
10281 }
10282 }
10283 memset(ipaddr,0,sizeof(ipaddr));
10284 }
10285 pclose(fp);
10286 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10287 return RETURN_OK;
10288}
10289//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
10290//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
10291//To get Band Steering Capability
10292INT wifi_getBandSteeringCapability(BOOL *support)
10293{
10294 *support = FALSE;
10295 return RETURN_OK;
10296}
10297
10298
10299//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
10300//To get Band Steering enable status
10301INT wifi_getBandSteeringEnable(BOOL *enable)
10302{
10303 *enable = FALSE;
10304 return RETURN_OK;
10305}
10306
10307//To turn on/off Band steering
10308INT wifi_setBandSteeringEnable(BOOL enable)
10309{
10310 return RETURN_OK;
10311}
10312
10313//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
10314//To get Band Steering AP group
10315INT wifi_getBandSteeringApGroup(char *output_ApGroup)
10316{
10317 if (NULL == output_ApGroup)
10318 return RETURN_ERR;
10319
10320 strcpy(output_ApGroup, "1,2");
10321 return RETURN_OK;
10322}
10323
10324//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
10325//to set and read the band steering BandUtilizationThreshold parameters
10326INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
10327{
10328 return RETURN_ERR;
10329}
10330
10331INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
10332{
10333 return RETURN_ERR;
10334}
10335
10336//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
10337//to set and read the band steering RSSIThreshold parameters
10338INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
10339{
10340 return RETURN_ERR;
10341}
10342
10343INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
10344{
10345 return RETURN_ERR;
10346}
10347
10348
10349//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
10350//to set and read the band steering physical modulation rate threshold parameters
10351INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
10352{
10353 //If chip is not support, return -1
10354 return RETURN_ERR;
10355}
10356
10357INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
10358{
10359 //If chip is not support, return -1
10360 return RETURN_ERR;
10361}
10362
10363//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
10364//to set and read the inactivity time (in seconds) for steering under overload condition
10365INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
10366{
10367 return RETURN_ERR;
10368}
10369
10370INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
10371{
10372 return RETURN_ERR;
10373}
10374
10375//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
10376//to set and read the inactivity time (in seconds) for steering under Idle condition
10377INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
10378{
10379 return RETURN_ERR;
10380}
10381
10382INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
10383{
10384 return RETURN_ERR;
10385}
10386
10387//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
10388//pClientMAC[64]
10389//pSourceSSIDIndex[64]
10390//pDestSSIDIndex[64]
10391//pSteeringReason[256]
10392INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
10393{
10394 //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
10395 *pSteeringTime=time(NULL);
10396 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
10397 return RETURN_OK;
10398}
10399
10400INT wifi_ifConfigDown(INT apIndex)
10401{
10402 INT status = RETURN_OK;
10403 char cmd[64];
10404
10405 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
10406 printf("%s: %s\n", __func__, cmd);
10407 system(cmd);
10408
10409 return status;
10410}
10411
10412INT wifi_ifConfigUp(INT apIndex)
10413{
10414 char interface_name[16] = {0};
10415 char cmd[128];
10416 char buf[1024];
10417
10418 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
10419 return RETURN_ERR;
10420 snprintf(cmd, sizeof(cmd), "ifconfig %s up 2>/dev/null", interface_name);
10421 _syscmd(cmd, buf, sizeof(buf));
10422 return 0;
10423}
10424
10425//>> Deprecated. Replace with wifi_applyRadioSettings
10426INT wifi_pushBridgeInfo(INT apIndex)
10427{
developerb2977562023-05-24 17:54:12 +080010428 char ip[32] = {0};
10429 char subnet[32] = {0};
10430 char bridge[32] = {0};
10431 char cmd[128] = {0};
10432 char buf[1024] = {0};
developer72fb0bb2023-01-11 09:46:29 +080010433
developerb2977562023-05-24 17:54:12 +080010434 wifi_getApBridgeInfo(apIndex, bridge, ip, subnet);
developer72fb0bb2023-01-11 09:46:29 +080010435
developerb2977562023-05-24 17:54:12 +080010436 snprintf(cmd, sizeof(cmd), "ifconfig %s %s netmask %s ", bridge, ip, subnet);
10437 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +080010438
developerb2977562023-05-24 17:54:12 +080010439 return 0;
developer72fb0bb2023-01-11 09:46:29 +080010440}
10441
10442INT wifi_pushChannel(INT radioIndex, UINT channel)
10443{
10444 char interface_name[16] = {0};
10445 char cmd[128];
10446 char buf[1024];
10447 int apIndex;
10448
developer69b61b02023-03-07 17:17:44 +080010449 apIndex=(radioIndex==0)?0:1;
developer72fb0bb2023-01-11 09:46:29 +080010450 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
10451 return RETURN_ERR;
10452 snprintf(cmd, sizeof(cmd), "iwconfig %s freq %d",interface_name,channel);
10453 _syscmd(cmd,buf, sizeof(buf));
10454
10455 return 0;
10456}
10457
10458INT wifi_pushChannelMode(INT radioIndex)
10459{
10460 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
10461 return RETURN_ERR;
10462}
10463
10464INT wifi_pushDefaultValues(INT radioIndex)
10465{
10466 //Apply Comcast specified default radio settings instantly
10467 //AMPDU=1
10468 //AMPDUFrames=32
10469 //AMPDULim=50000
10470 //txqueuelen=1000
10471
10472 return RETURN_ERR;
10473}
10474
10475INT wifi_pushTxChainMask(INT radioIndex)
10476{
10477 //Apply default TxChainMask instantly
10478 return RETURN_ERR;
10479}
10480
10481INT wifi_pushRxChainMask(INT radioIndex)
10482{
10483 //Apply default RxChainMask instantly
10484 return RETURN_ERR;
10485}
10486
10487INT wifi_pushSSID(INT apIndex, CHAR *ssid)
10488{
developer7e4a2a62023-04-06 19:56:03 +080010489 INT status;
developer72fb0bb2023-01-11 09:46:29 +080010490
developer7e4a2a62023-04-06 19:56:03 +080010491 status = wifi_setSSIDName(apIndex, ssid);
10492 wifi_quick_reload_ap(apIndex);
developer72fb0bb2023-01-11 09:46:29 +080010493
developer7e4a2a62023-04-06 19:56:03 +080010494 return status;
developer72fb0bb2023-01-11 09:46:29 +080010495}
10496
10497INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
10498{
10499 //Apply default Ssid Advertisement instantly
10500 return RETURN_ERR;
10501}
10502
10503INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
10504{
developere82c0ca2023-05-10 16:25:35 +080010505 time_t now;
10506
10507 time(&now);
10508 if (now > radio_up_time[radioIndex])
10509 *output = now - radio_up_time[radioIndex];
10510 else {
10511 *output = 0;
10512 return RETURN_ERR;
10513 }
10514
10515 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +080010516}
10517
10518INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
10519{
10520 return RETURN_OK;
10521}
10522
10523INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
10524{
10525 return RETURN_OK;
10526}
10527
10528//To-do
10529INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
10530{
10531 char output[16]={'\0'};
10532 char config_file[MAX_BUF_SIZE] = {0};
10533
10534 if (!output_string)
10535 return RETURN_ERR;
10536
10537 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
10538 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
10539
10540 if (strlen(output) == 0)
10541 snprintf(output_string, 64, "Disabled");
10542 else if (strncmp(output, "0", 1) == 0)
10543 snprintf(output_string, 64, "Disabled");
10544 else if (strncmp(output, "1", 1) == 0)
10545 snprintf(output_string, 64, "Optional");
10546 else if (strncmp(output, "2", 1) == 0)
10547 snprintf(output_string, 64, "Required");
10548 else {
10549 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
10550 return RETURN_ERR;
10551 }
10552
10553 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
10554 return RETURN_OK;
10555}
10556INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
10557{
developer72fb0bb2023-01-11 09:46:29 +080010558 struct params params;
10559 char config_file[MAX_BUF_SIZE] = {0};
10560
10561 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10562 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
10563 return RETURN_ERR;
10564
10565 params.name = "ieee80211w";
10566 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
10567 params.value = "0";
10568 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
10569 params.value = "1";
10570 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
10571 params.value = "2";
10572 else{
10573 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
10574 return RETURN_ERR;
10575 }
10576 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
10577 wifi_hostapdWrite(config_file, &params, 1);
10578 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
10579 return RETURN_OK;
10580}
10581INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
10582{
10583 char output[16]={'\0'};
10584 char config_file[MAX_BUF_SIZE] = {0};
developer84c3d782023-05-31 16:08:21 +080010585 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +080010586
10587 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer84c3d782023-05-31 16:08:21 +080010588 band = wifi_index_to_band(radioIndex);
10589 snprintf(config_file, sizeof(config_file), "%s%d.dat", LOGAN_DAT_FILE, band);
developer262f4cb2023-05-24 12:22:04 +080010590 wifi_datfileRead(config_file, "AutoChannelSelect" , output, sizeof(output));
developer72fb0bb2023-01-11 09:46:29 +080010591
developer84c3d782023-05-31 16:08:21 +080010592 if (strncmp(output, "0", 1) == 0)
developer47a56bf2023-05-30 13:38:57 +080010593 *output_bool = FALSE;
developer262f4cb2023-05-24 12:22:04 +080010594 else if (strncmp(output, "1", 1) == 0)
10595 *output_bool = TRUE;
10596 else if (strncmp(output, "2", 1) == 0)
10597 *output_bool = TRUE;
10598 else if (strncmp(output, "3", 1) == 0)
10599 *output_bool = TRUE;
10600 else
10601 *output_bool = FALSE;
developer72fb0bb2023-01-11 09:46:29 +080010602 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
10603
10604 return RETURN_OK;
10605}
10606
10607INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
10608{
10609 return RETURN_OK;
10610}
10611
10612INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
10613{
10614 return RETURN_OK;
10615}
10616
10617INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
10618{
10619 return RETURN_OK;
10620}
10621
10622INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
10623{
10624 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10625 char config_file[MAX_BUF_SIZE] = {0};
10626
10627 if (NULL == output)
10628 return RETURN_ERR;
10629 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
10630 wifi_hostapdRead(config_file,"hw_mode",output,64);
10631
10632 if(strcmp(output,"b")==0)
10633 sprintf(output, "%s", "1,2,5.5,11");
10634 else if (strcmp(output,"a")==0)
10635 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
10636 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
10637 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
10638
10639 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10640 return RETURN_OK;
10641}
10642
10643INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
10644{
10645 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10646 char *temp;
10647 char temp_output[128];
10648 char temp_TransmitRates[128];
10649 char config_file[MAX_BUF_SIZE] = {0};
10650
10651 if (NULL == output)
10652 return RETURN_ERR;
10653
10654 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
10655 wifi_hostapdRead(config_file,"supported_rates",output,64);
10656
10657 if (strlen(output) == 0) {
10658 wifi_getRadioSupportedDataTransmitRates(wlanIndex, output);
10659 return RETURN_OK;
10660 }
10661 strcpy(temp_TransmitRates,output);
10662 strcpy(temp_output,"");
10663 temp = strtok(temp_TransmitRates," ");
10664 while(temp!=NULL)
10665 {
10666 temp[strlen(temp)-1]=0;
10667 if((temp[0]=='5') && (temp[1]=='\0'))
10668 {
10669 temp="5.5";
10670 }
10671 strcat(temp_output,temp);
10672 temp = strtok(NULL," ");
10673 if(temp!=NULL)
10674 {
10675 strcat(temp_output,",");
10676 }
10677 }
10678 strcpy(output,temp_output);
10679 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10680
10681 return RETURN_OK;
10682}
10683
10684INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
10685{
10686 return RETURN_OK;
10687}
10688
10689
10690INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
10691{
10692 int i=0;
10693 char *temp;
10694 char temp1[128] = {0};
10695 char temp_output[128] = {0};
10696 char temp_TransmitRates[128] = {0};
10697 struct params params={'\0'};
10698 char config_file[MAX_BUF_SIZE] = {0};
10699 wifi_band band = wifi_index_to_band(wlanIndex);
10700
10701 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10702 if(NULL == output)
10703 return RETURN_ERR;
10704 strcpy(temp_TransmitRates,output);
10705
10706 for(i=0;i<strlen(temp_TransmitRates);i++)
10707 {
10708 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
10709 {
10710 continue;
10711 }
10712 else
10713 {
10714 return RETURN_ERR;
10715 }
10716 }
10717 strcpy(temp_output,"");
10718 temp = strtok(temp_TransmitRates,",");
10719 while(temp!=NULL)
10720 {
10721 strcpy(temp1,temp);
10722 if(band == band_5)
10723 {
10724 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
10725 {
10726 return RETURN_ERR;
10727 }
10728 }
10729
10730 if(strcmp(temp,"5.5")==0)
10731 {
10732 strcpy(temp1,"55");
10733 }
10734 else
10735 {
10736 strcat(temp1,"0");
10737 }
10738 strcat(temp_output,temp1);
10739 temp = strtok(NULL,",");
10740 if(temp!=NULL)
10741 {
10742 strcat(temp_output," ");
10743 }
10744 }
10745 strcpy(output,temp_output);
10746
10747 params.name = "supported_rates";
10748 params.value = output;
10749
10750 wifi_dbg_printf("\n%s:",__func__);
10751 wifi_dbg_printf("params.value=%s\n",params.value);
10752 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
10753 wifi_hostapdWrite(config_file,&params,1);
10754 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10755
10756 return RETURN_OK;
10757}
10758
10759
10760static char *sncopy(char *dst, int dst_sz, const char *src)
10761{
10762 if (src && dst && dst_sz > 0) {
10763 strncpy(dst, src, dst_sz);
10764 dst[dst_sz - 1] = '\0';
10765 }
10766 return dst;
10767}
10768
10769static int util_get_sec_chan_offset(int channel, const char* ht_mode)
10770{
10771 if (0 == strcmp(ht_mode, "HT40") ||
10772 0 == strcmp(ht_mode, "HT80") ||
10773 0 == strcmp(ht_mode, "HT160")) {
10774 switch (channel) {
10775 case 1 ... 7:
10776 case 36:
10777 case 44:
10778 case 52:
10779 case 60:
10780 case 100:
10781 case 108:
10782 case 116:
10783 case 124:
10784 case 132:
10785 case 140:
10786 case 149:
10787 case 157:
10788 return 1;
10789 case 8 ... 13:
10790 case 40:
10791 case 48:
10792 case 56:
10793 case 64:
10794 case 104:
10795 case 112:
10796 case 120:
10797 case 128:
10798 case 136:
10799 case 144:
10800 case 153:
10801 case 161:
10802 return -1;
10803 default:
10804 return -EINVAL;
10805 }
10806 }
10807
10808 return -EINVAL;
10809}
10810
10811static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
10812{
10813 int idx = channel%8;
10814 if (0 == strcmp(ht_mode, "HT40") ||
10815 0 == strcmp(ht_mode, "HT80") ||
10816 0 == strcmp(ht_mode, "HT160")) {
10817 switch (idx) {
10818 case 1:
10819 return 1;
10820 case 5:
10821 return -1;
10822 default:
10823 return -EINVAL;
10824 }
10825 }
10826
10827 return -EINVAL;
10828}
10829static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
10830{
10831 if (NULL == hw_mode) return;
10832
10833 if (0 == strcmp(hw_mode, "ac"))
10834 sncopy(bw_mode, bw_mode_len, "ht vht");
10835
10836 if (0 == strcmp(hw_mode, "n"))
10837 sncopy(bw_mode, bw_mode_len, "ht");
10838
10839 return;
10840}
10841
10842static int util_chan_to_freq(int chan)
10843{
10844 if (chan == 14)
10845 return 2484;
10846 else if (chan < 14)
10847 return 2407 + chan * 5;
10848 else if (chan >= 182 && chan <= 196)
10849 return 4000 + chan * 5;
10850 else
10851 return 5000 + chan * 5;
10852 return 0;
10853}
10854
10855static int util_6G_chan_to_freq(int chan)
10856{
10857 if (chan)
10858 return 5950 + chan * 5;
10859 else
10860 return 0;
developer69b61b02023-03-07 17:17:44 +080010861
developer72fb0bb2023-01-11 09:46:29 +080010862}
10863const int *util_unii_5g_chan2list(int chan, int width)
10864{
10865 static const int lists[] = {
10866 // <width>, <chan1>, <chan2>..., 0,
10867 20, 36, 0,
10868 20, 40, 0,
10869 20, 44, 0,
10870 20, 48, 0,
10871 20, 52, 0,
10872 20, 56, 0,
10873 20, 60, 0,
10874 20, 64, 0,
10875 20, 100, 0,
10876 20, 104, 0,
10877 20, 108, 0,
10878 20, 112, 0,
10879 20, 116, 0,
10880 20, 120, 0,
10881 20, 124, 0,
10882 20, 128, 0,
10883 20, 132, 0,
10884 20, 136, 0,
10885 20, 140, 0,
10886 20, 144, 0,
10887 20, 149, 0,
10888 20, 153, 0,
10889 20, 157, 0,
10890 20, 161, 0,
10891 20, 165, 0,
10892 40, 36, 40, 0,
10893 40, 44, 48, 0,
10894 40, 52, 56, 0,
10895 40, 60, 64, 0,
10896 40, 100, 104, 0,
10897 40, 108, 112, 0,
10898 40, 116, 120, 0,
10899 40, 124, 128, 0,
10900 40, 132, 136, 0,
10901 40, 140, 144, 0,
10902 40, 149, 153, 0,
10903 40, 157, 161, 0,
10904 80, 36, 40, 44, 48, 0,
10905 80, 52, 56, 60, 64, 0,
10906 80, 100, 104, 108, 112, 0,
10907 80, 116, 120, 124, 128, 0,
10908 80, 132, 136, 140, 144, 0,
10909 80, 149, 153, 157, 161, 0,
10910 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
10911 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
10912 -1 // final delimiter
10913 };
10914 const int *start;
10915 const int *p;
10916
10917 for (p = lists; *p != -1; p++) {
10918 if (*p == width) {
10919 for (start = ++p; *p != 0; p++) {
10920 if (*p == chan)
10921 return start;
10922 }
10923 }
10924 // move to the end of channel list of given width
10925 while (*p != 0) {
10926 p++;
10927 }
10928 }
10929
10930 return NULL;
10931}
10932
10933static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
10934{
10935 if (NULL == ht_mode)
10936 return 0;
10937
10938 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
10939 const int *chans = util_unii_5g_chan2list(channel, width);
10940 int sum = 0;
10941 int cnt = 0;
10942
10943 if (NULL == chans)
10944 return 0;
10945
10946 while (*chans) {
10947 sum += *chans;
10948 cnt++;
10949 chans++;
10950 }
10951 if (cnt == 0)
10952 return 0;
10953 return sum / cnt;
10954}
10955
10956static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
10957{
10958 if (NULL == ht_mode)
10959 return 0;
10960
10961 int width = strtol((ht_mode + 2), NULL, 10);
10962
10963 int idx = 0 ;
10964 int centerchan = 0;
10965 int chan_ofs = 1;
10966
10967 if (width == 40){
10968 idx = ((channel/4) + chan_ofs)%2;
10969 switch (idx) {
10970 case 0:
10971 centerchan = (channel - 2);
10972 break;
10973 case 1:
10974 centerchan = (channel + 2);
developer69b61b02023-03-07 17:17:44 +080010975 break;
developer72fb0bb2023-01-11 09:46:29 +080010976 default:
10977 return -EINVAL;
10978 }
10979 }else if (width == 80){
developer69b61b02023-03-07 17:17:44 +080010980 idx = ((channel/4) + chan_ofs)%4;
developer72fb0bb2023-01-11 09:46:29 +080010981 switch (idx) {
10982 case 0:
10983 centerchan = (channel - 6);
10984 break;
10985 case 1:
10986 centerchan = (channel + 6);
10987 break;
10988 case 2:
10989 centerchan = (channel + 2);
10990 break;
10991 case 3:
10992 centerchan = (channel - 2);
10993 break;
10994 default:
10995 return -EINVAL;
developer69b61b02023-03-07 17:17:44 +080010996 }
developer72fb0bb2023-01-11 09:46:29 +080010997 }else if (width == 160){
10998 switch (channel) {
10999 case 1 ... 29:
11000 centerchan = 15;
11001 break;
11002 case 33 ... 61:
11003 centerchan = 47;
11004 break;
11005 case 65 ... 93:
11006 centerchan = 79;
11007 break;
11008 case 97 ... 125:
11009 centerchan = 111;
11010 break;
11011 case 129 ... 157:
11012 centerchan = 143;
11013 break;
11014 case 161 ... 189:
11015 centerchan = 175;
11016 break;
11017 case 193 ... 221:
11018 centerchan = 207;
11019 break;
11020 default:
11021 return -EINVAL;
developer69b61b02023-03-07 17:17:44 +080011022 }
developer72fb0bb2023-01-11 09:46:29 +080011023 }
11024 return centerchan;
11025}
11026static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
11027{
11028 BOOL onlyG, onlyN, onlyA;
11029 CHAR tmp[64];
11030 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
11031 if (ret == RETURN_OK) {
11032 sncopy(hw_mode, hw_mode_size, tmp);
11033 }
11034 return ret;
11035}
11036
11037INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
11038{
11039 // Sample commands:
11040 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
11041 // hostapd_cli -i wifi0 chan_switch 30 2437
developer72fb0bb2023-01-11 09:46:29 +080011042 int freq = 0, ret = 0;
11043 char center_freq1_str[32] = ""; // center_freq1=%d
11044 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
11045 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
11046 char hw_mode[16] = ""; // n|ac
11047 char bw_mode[16] = ""; // ht|ht vht
11048 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
11049 char interface_name[16] = {0};
11050 int sec_chan_offset;
11051 int width;
11052 char config_file[64] = {0};
developer72fb0bb2023-01-11 09:46:29 +080011053 char *ext_str = "None";
11054 wifi_band band = band_invalid;
11055 int center_chan = 0;
11056 int center_freq1 = 0;
11057
11058 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
11059
11060 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
11061 return RETURN_ERR;
11062
11063 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11064
11065 band = wifi_index_to_band(radioIndex);
11066
11067 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
11068
11069 // Get radio mode HT20|HT40|HT80 etc.
11070 if (channel){
11071 if (band == band_6){
11072 freq = util_6G_chan_to_freq(channel);
11073 }else{
11074 freq = util_chan_to_freq(channel);
11075 }
11076 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
11077
11078 // Provide bandwith if specified
11079 if (channel_width_MHz > 20) {
11080 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
11081 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
11082 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
11083
11084 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
11085 }else if (channel_width_MHz == 20){
11086 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
11087 }
11088
11089
11090 if (channel_width_MHz > 20) {
11091 if (band == band_6){
11092 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
11093 if(center_chan){
11094 center_freq1 = util_6G_chan_to_freq(center_chan);
11095 }
11096 }else{
11097 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
11098 if(center_chan){
11099 center_freq1 = util_chan_to_freq(center_chan);
11100 }
11101 }
developer69b61b02023-03-07 17:17:44 +080011102
developer72fb0bb2023-01-11 09:46:29 +080011103 if (center_freq1)
11104 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
developer69b61b02023-03-07 17:17:44 +080011105
developer72fb0bb2023-01-11 09:46:29 +080011106 }
11107
11108 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
11109 if (band == band_6){
11110 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
11111 }else{
11112 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
11113 }
11114 if (sec_chan_offset != -EINVAL)
11115 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
11116
11117 // Only the first AP, other are hanging on the same radio
developerfead3972023-05-25 20:15:02 +080011118 ret = wifi_setChannel_netlink(radioIndex, &channel, NULL);
developerd1824452023-05-18 12:30:04 +080011119 if (ret != RETURN_OK) {
developerfead3972023-05-25 20:15:02 +080011120 fprintf(stderr, "%s: wifi_setChannel return error.\n", __func__);
developerd1824452023-05-18 12:30:04 +080011121 return RETURN_ERR;
11122 }
11123 /* wifi_dbg_printf("execute: '%s'\n", cmd);
developerf6a87542023-05-16 15:47:28 +080011124 ret = _syscmd(cmd, buf, sizeof(buf));
developerd1824452023-05-18 12:30:04 +080011125 wifi_reloadAp(radioIndex); */
developer72fb0bb2023-01-11 09:46:29 +080011126
11127 ret = wifi_setRadioChannel(radioIndex, channel);
11128 if (ret != RETURN_OK) {
11129 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
11130 return RETURN_ERR;
11131 }
11132
developer262f4cb2023-05-24 12:22:04 +080011133 if (sec_chan_offset == 1)
11134 ext_str = "Above";
11135 else if (sec_chan_offset == -1)
11136 ext_str = "Below";
developer72fb0bb2023-01-11 09:46:29 +080011137
developerd1824452023-05-18 12:30:04 +080011138 /*wifi_setRadioCenterChannel(radioIndex, center_chan); */
developer72fb0bb2023-01-11 09:46:29 +080011139
11140 } else {
11141 if (channel_width_MHz > 20)
11142 ext_str = "Above";
11143 }
11144
11145 wifi_setRadioExtChannel(radioIndex, ext_str);
11146
11147 char mhz_str[16];
11148 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
11149 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
11150
11151 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11152
11153 return RETURN_OK;
11154}
11155
11156INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
11157{
11158 int index = -1;
11159 wifi_neighbor_ap2_t *scan_array = NULL;
11160 char cmd[256]={0};
11161 char buf[128]={0};
11162 char file_name[32] = {0};
11163 char filter_SSID[32] = {0};
11164 char line[256] = {0};
11165 char interface_name[16] = {0};
11166 char *ret = NULL;
11167 int freq=0;
11168 FILE *f = NULL;
developer72fb0bb2023-01-11 09:46:29 +080011169 int channels_num = 0;
11170 int vht_channel_width = 0;
11171 int get_noise_ret = RETURN_ERR;
11172 bool filter_enable = false;
11173 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
11174 int phyId = 0;
11175
11176 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
11177
11178 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
11179 f = fopen(file_name, "r");
11180 if (f != NULL) {
11181 fgets(filter_SSID, sizeof(file_name), f);
11182 if (strlen(filter_SSID) != 0)
11183 filter_enable = true;
11184 fclose(f);
11185 }
11186
11187 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
11188 return RETURN_ERR;
11189
11190 phyId = radio_index_to_phy(radio_index);
11191
11192 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
11193 _syscmd(cmd, buf, sizeof(buf));
11194 channels_num = strtol(buf, NULL, 10);
11195
11196 sprintf(cmd, "iw dev %s scan dump | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
11197 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", interface_name, interface_name);
11198 fprintf(stderr, "cmd: %s\n", cmd);
11199 if ((f = popen(cmd, "r")) == NULL) {
11200 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
11201 return RETURN_ERR;
11202 }
developer69b61b02023-03-07 17:17:44 +080011203
developer72fb0bb2023-01-11 09:46:29 +080011204 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
11205 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
developer69b61b02023-03-07 17:17:44 +080011206
developer72fb0bb2023-01-11 09:46:29 +080011207 ret = fgets(line, sizeof(line), f);
11208 while (ret != NULL) {
11209 if(strstr(line, "BSS") != NULL) { // new neighbor info
developer69b61b02023-03-07 17:17:44 +080011210 // 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 +080011211 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
11212 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
11213
11214 if (!filter_BSS) {
11215 index++;
11216 wifi_neighbor_ap2_t *tmp;
11217 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
11218 if (tmp == NULL) { // no more memory to use
11219 index--;
11220 wifi_dbg_printf("%s: realloc failed\n", __func__);
11221 break;
11222 }
11223 scan_array = tmp;
11224 }
11225 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
11226
11227 filter_BSS = false;
11228 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
11229 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
11230 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
11231 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
11232 } else if (strstr(line, "freq") != NULL) {
11233 sscanf(line," freq: %d", &freq);
11234 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
11235
11236 if (freq >= 2412 && freq <= 2484) {
11237 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
11238 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
11239 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
11240 }
11241 else if (freq >= 5160 && freq <= 5805) {
11242 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
11243 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
11244 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
11245 }
11246
11247 scan_array[index].ap_Noise = 0;
11248 if (get_noise_ret == RETURN_OK) {
11249 for (int i = 0; i < channels_num; i++) {
11250 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
11251 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
11252 break;
11253 }
11254 }
11255 }
11256 } else if (strstr(line, "beacon interval") != NULL) {
11257 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
11258 } else if (strstr(line, "signal") != NULL) {
11259 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
11260 } else if (strstr(line,"SSID") != NULL) {
11261 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
11262 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
11263 filter_BSS = true;
11264 }
11265 } else if (strstr(line, "Supported rates") != NULL) {
11266 char SRate[80] = {0}, *tmp = NULL;
11267 memset(buf, 0, sizeof(buf));
11268 strcpy(SRate, line);
11269 tmp = strtok(SRate, ":");
11270 tmp = strtok(NULL, ":");
11271 strcpy(buf, tmp);
11272 memset(SRate, 0, sizeof(SRate));
11273
11274 tmp = strtok(buf, " \n");
11275 while (tmp != NULL) {
11276 strcat(SRate, tmp);
11277 if (SRate[strlen(SRate) - 1] == '*') {
11278 SRate[strlen(SRate) - 1] = '\0';
11279 }
11280 strcat(SRate, ",");
11281
11282 tmp = strtok(NULL, " \n");
11283 }
11284 SRate[strlen(SRate) - 1] = '\0';
11285 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
11286 } else if (strstr(line, "DTIM") != NULL) {
developerdaf24792023-06-06 11:40:04 +080011287 sscanf(line,"DTIM Period %u", &(scan_array[index].ap_DTIMPeriod), buf);
developer72fb0bb2023-01-11 09:46:29 +080011288 } else if (strstr(line, "VHT capabilities") != NULL) {
11289 strcat(scan_array[index].ap_SupportedStandards, ",ac");
11290 strcpy(scan_array[index].ap_OperatingStandards, "ac");
11291 } else if (strstr(line, "HT capabilities") != NULL) {
11292 strcat(scan_array[index].ap_SupportedStandards, ",n");
11293 strcpy(scan_array[index].ap_OperatingStandards, "n");
11294 } else if (strstr(line, "VHT operation") != NULL) {
11295 ret = fgets(line, sizeof(line), f);
11296 sscanf(line," * channel width: %d", &vht_channel_width);
11297 if(vht_channel_width == 1) {
11298 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
11299 } else {
11300 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
11301 }
11302 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
11303 continue;
11304 } else if (strstr(line, "HT operation") != NULL) {
11305 ret = fgets(line, sizeof(line), f);
developerdaf24792023-06-06 11:40:04 +080011306 sscanf(line," * secondary channel offset: %s", buf);
developer72fb0bb2023-01-11 09:46:29 +080011307 if (!strcmp(buf, "above")) {
11308 //40Mhz +
11309 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radio_index%1 ? "A": "G");
11310 }
11311 else if (!strcmp(buf, "below")) {
11312 //40Mhz -
11313 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
11314 } else {
11315 //20Mhz
11316 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radio_index%1 ? "A": "G");
11317 }
11318 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
11319 continue;
11320 } else if (strstr(line, "HE capabilities") != NULL) {
11321 strcat(scan_array[index].ap_SupportedStandards, ",ax");
11322 strcpy(scan_array[index].ap_OperatingStandards, "ax");
11323 ret = fgets(line, sizeof(line), f);
11324 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
11325 if (strstr(line, "HE40/2.4GHz") != NULL)
11326 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
11327 else
11328 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
11329 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
11330 if (strstr(line, "HE80/5GHz") != NULL) {
11331 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
11332 ret = fgets(line, sizeof(line), f);
11333 } else
11334 continue;
11335 if (strstr(line, "HE160/5GHz") != NULL)
11336 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
11337 }
11338 continue;
11339 } else if (strstr(line, "WPA") != NULL) {
11340 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
11341 } else if (strstr(line, "RSN") != NULL) {
11342 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
11343 } else if (strstr(line, "Group cipher") != NULL) {
11344 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
11345 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
11346 strcpy(scan_array[index].ap_EncryptionMode, "AES");
11347 }
11348 }
11349 ret = fgets(line, sizeof(line), f);
11350 }
11351
11352 if (!filter_BSS) {
11353 *output_array_size = index + 1;
11354 } else {
11355 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
11356 *output_array_size = index;
11357 }
11358 *neighbor_ap_array = scan_array;
11359 pclose(f);
11360 free(channels_noise_arr);
11361 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11362 return RETURN_OK;
11363}
11364
11365INT wifi_getApAssociatedDeviceStats(
11366 INT apIndex,
11367 mac_address_t *clientMacAddress,
11368 wifi_associated_dev_stats_t *associated_dev_stats,
11369 u64 *handle)
11370{
11371 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
11372 char interface_name[50] = {0};
11373 char cmd[1024] = {0};
11374 char mac_str[18] = {0};
11375 char *key = NULL;
11376 char *val = NULL;
11377 FILE *f = NULL;
11378 char *line = NULL;
11379 size_t len = 0;
11380
11381 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
11382 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
11383 return RETURN_ERR;
11384 }
11385
11386 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
11387 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
11388 if((f = popen(cmd, "r")) == NULL) {
11389 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
11390 return RETURN_ERR;
11391 }
11392
11393 while ((getline(&line, &len, f)) != -1) {
11394 key = strtok(line,":");
11395 val = strtok(NULL,":");
11396
11397 if(!strncmp(key,"rx bytes",8))
11398 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
11399 if(!strncmp(key,"tx bytes",8))
11400 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
11401 if(!strncmp(key,"rx packets",10))
11402 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
11403 if(!strncmp(key,"tx packets",10))
11404 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
11405 if(!strncmp(key,"tx retries",10))
11406 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
11407 if(!strncmp(key,"tx failed",9))
11408 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
11409 if(!strncmp(key,"rx drop misc",13))
11410 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
11411 if(!strncmp(key,"rx bitrate",10)) {
11412 val = strtok(val, " ");
11413 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
11414 }
11415 if(!strncmp(key,"tx bitrate",10)) {
11416 val = strtok(val, " ");
11417 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
11418 }
11419 }
11420 free(line);
11421 pclose(f);
11422 return RETURN_OK;
11423}
11424
11425INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
11426{
developer7e4a2a62023-04-06 19:56:03 +080011427 char interface_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +080011428 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
11429
developer7e4a2a62023-04-06 19:56:03 +080011430 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
11431
developer72fb0bb2023-01-11 09:46:29 +080011432 if (NULL == output_string)
11433 return RETURN_ERR;
11434
11435 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
11436 return RETURN_ERR;
developer7e4a2a62023-04-06 19:56:03 +080011437
11438 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 +080011439 _syscmd(cmd, buf, sizeof(buf));
11440
11441 //size of SSID name restricted to value less than 32 bytes
11442 snprintf(output_string, 32, "%s", buf);
developer7e4a2a62023-04-06 19:56:03 +080011443 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +080011444
11445 return RETURN_OK;
11446}
11447
11448INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
11449{
developer2edaf012023-05-24 14:24:53 +080011450 char *mac_arry_buf = NULL;
11451 INT policy = -1;
11452 INT buf_size = 1024;
developer72fb0bb2023-01-11 09:46:29 +080011453
developer2edaf012023-05-24 14:24:53 +080011454 mac_arry_buf = malloc(buf_size);
11455 if (!mac_arry_buf) {
11456 wifi_debug(DEBUG_ERROR,"malloc mac_arry_buf fails\n");
developer7e4a2a62023-04-06 19:56:03 +080011457 return RETURN_ERR;
developer2edaf012023-05-24 14:24:53 +080011458 }
11459 memset(mac_arry_buf, 0, buf_size);
11460 if (mtk_wifi_getApAclDevices(apIndex, mac_arry_buf, buf_size) != RETURN_OK) {
11461 wifi_debug(DEBUG_ERROR,"mtk_wifi_getApAclDevices get fails\n");
11462 goto err;
11463 }
11464 /*
11465 mtk format to get policy:
11466 "policy=1
11467 00:11:22:33:44:55
11468 00:11:22:33:44:66
11469 "
11470 */
11471 if (strlen(mac_arry_buf) < strlen("policy=1") || sscanf(mac_arry_buf, "policy=%01d", &policy) != 1) {
11472 wifi_debug(DEBUG_ERROR,"mac_arry_buf(%s) invalid\n", mac_arry_buf);
11473 goto err;
11474 }
11475 if (!(policy >=0 && policy <= 2)){
11476 wifi_debug(DEBUG_ERROR,"policy(%d) is invalid\n", policy);
11477 goto err;
11478 }
11479 *output_filterMode = policy;
11480 wifi_debug(DEBUG_NOTICE, "output_filterMode(%d), success\n", *output_filterMode);
11481 free(mac_arry_buf);
11482 mac_arry_buf = NULL;
11483 return RETURN_OK;
11484err:
11485 free(mac_arry_buf);
11486 mac_arry_buf = NULL;
11487 wifi_debug(DEBUG_NOTICE, "output_filterMode(%d), fails\n", *output_filterMode);
11488 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +080011489}
11490
developer2edaf012023-05-24 14:24:53 +080011491
developer72fb0bb2023-01-11 09:46:29 +080011492INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
11493{
11494 FILE *fp = NULL;
11495 char str[MAX_BUF_SIZE] = {0};
11496 int wificlientindex = 0 ;
11497 int count = 0;
11498 int signalstrength = 0;
11499 int arr[MACADDRESS_SIZE] = {0};
11500 unsigned char mac[MACADDRESS_SIZE] = {0};
11501 UINT wifi_count = 0;
developer72fb0bb2023-01-11 09:46:29 +080011502 char pipeCmd[MAX_CMD_SIZE] = {0};
11503
11504 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11505 *output_array_size = 0;
11506 *associated_dev_array = NULL;
11507 char interface_name[50] = {0};
11508
11509 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
11510 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
11511 return RETURN_ERR;
11512 }
11513
11514 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
11515 fp = popen(pipeCmd, "r");
11516 if (fp == NULL)
11517 {
11518 printf("Failed to run command inside function %s\n",__FUNCTION__ );
11519 return RETURN_ERR;
11520 }
11521
11522 /* Read the output a line at a time - output it. */
11523 fgets(str, sizeof(str)-1, fp);
11524 wifi_count = (unsigned int) atoi ( str );
11525 *output_array_size = wifi_count;
11526 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
11527 pclose(fp);
11528
11529 if(wifi_count == 0)
11530 {
11531 return RETURN_OK;
11532 }
11533 else
11534 {
11535 wifi_associated_dev2_t* temp = NULL;
11536 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
11537 *associated_dev_array = temp;
11538 if(temp == NULL)
11539 {
11540 printf("Error Statement. Insufficient memory \n");
11541 return RETURN_ERR;
11542 }
11543
11544 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
11545 system(pipeCmd);
11546
11547 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
11548 if(fp == NULL)
11549 {
11550 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
11551 return RETURN_ERR;
11552 }
11553 fclose(fp);
11554
11555 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
11556 fp = popen(pipeCmd, "r");
11557 if(fp)
11558 {
11559 for(count =0 ; count < wifi_count; count++)
11560 {
11561 fgets(str, MAX_BUF_SIZE, fp);
11562 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
11563 {
11564 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
11565 {
11566 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
11567
11568 }
11569 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
11570 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]);
11571 }
11572 temp[count].cli_AuthenticationState = 1; //TODO
11573 temp[count].cli_Active = 1; //TODO
11574 }
11575 pclose(fp);
11576 }
11577
11578 //Updating RSSI per client
11579 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt");
11580 fp = popen(pipeCmd, "r");
11581 if(fp)
11582 {
11583 pclose(fp);
11584 }
11585 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
11586 if(fp)
11587 {
11588 for(count =0 ; count < wifi_count ;count++)
11589 {
11590 fgets(str, MAX_BUF_SIZE, fp);
11591 signalstrength = atoi(str);
11592 temp[count].cli_RSSI = signalstrength;
11593 }
11594 pclose(fp);
11595 }
11596
11597
11598 //LastDataDownlinkRate
11599 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt");
11600 fp = popen(pipeCmd, "r");
11601 if (fp)
11602 {
11603 pclose(fp);
11604 }
11605 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
11606 if (fp)
11607 {
11608 for (count = 0; count < wifi_count; count++)
11609 {
11610 fgets(str, MAX_BUF_SIZE, fp);
11611 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
11612 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
11613 }
11614 pclose(fp);
11615 }
11616
11617 //LastDataUplinkRate
11618 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt");
11619 fp = popen(pipeCmd, "r");
11620 if (fp)
11621 {
11622 pclose(fp);
11623 }
11624 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
11625 if (fp)
11626 {
11627 for (count = 0; count < wifi_count; count++)
11628 {
11629 fgets(str, MAX_BUF_SIZE, fp);
11630 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
11631 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
11632 }
11633 pclose(fp);
11634 }
11635 }
11636 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11637 return RETURN_OK;
11638
11639}
11640
11641INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
11642{
11643#if 0
11644 /*char buf[1024] = {0};
11645 sprintf(cmd, "ifconfig %s ", interface_name);
11646 _syscmd(cmd, buf, sizeof(buf));*/
11647
11648 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
11649 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
11650 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
11651 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
11652
11653 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.
11654 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].
11655 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].
11656 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].
11657 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
11658 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
11659
11660 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
11661 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
11662 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
11663 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.
11664 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.
11665 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.
11666 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.
11667 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.
11668 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.
11669 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.
11670 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
11671#endif
11672
11673 FILE *fp = NULL;
11674 char interface_name[50] = {0};
11675 char pipeCmd[128] = {0};
11676 char str[256] = {0};
11677 wifi_ssidTrafficStats2_t *out = output_struct;
11678
11679 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
11680 if (!output_struct)
11681 return RETURN_ERR;
11682
11683 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
11684 if (wifi_GetInterfaceName(ssidIndex, interface_name) != RETURN_OK)
11685 return RETURN_ERR;
11686 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
11687
11688 fp = popen(pipeCmd, "r");
11689 if (fp == NULL) {
11690 fprintf(stderr, "%s: popen failed\n", __func__);
11691 return RETURN_ERR;
11692 }
11693 fgets(str, sizeof(str), fp);
11694 pclose(fp);
11695
11696 if (strlen(str) == 0) // interface not exist
11697 return RETURN_OK;
11698
11699 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
11700 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
11701
11702 memset(str, 0, sizeof(str));
11703 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
11704 fp = popen(pipeCmd, "r");
11705 if (fp == NULL) {
11706 fprintf(stderr, "%s: popen failed\n", __func__);
11707 return RETURN_ERR;
11708 }
11709 fgets(str, sizeof(str), fp);
11710
11711 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
11712 &out->ssid_BroadcastPacketsSent);
11713 pclose(fp);
11714
11715 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
11716 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
11717
11718 // Not supported
11719 output_struct->ssid_RetransCount = 0;
11720 output_struct->ssid_FailedRetransCount = 0;
11721 output_struct->ssid_RetryCount = 0;
11722 output_struct->ssid_MultipleRetryCount = 0;
11723 output_struct->ssid_ACKFailureCount = 0;
11724 output_struct->ssid_AggregatedPacketCount = 0;
11725
11726 return RETURN_OK;
11727}
11728
11729//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).
11730INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
11731{
11732 char output_val[16]={'\0'};
11733 char config_file[MAX_BUF_SIZE] = {0};
11734
11735 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11736 if (!output)
11737 return RETURN_ERR;
11738 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
11739 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
11740
11741 if( strcmp(output_val,"1") == 0 )
11742 *output = TRUE;
11743 else
11744 *output = FALSE;
11745 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11746
11747 return RETURN_OK;
11748}
11749
11750INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
11751{
11752 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +080011753 char string[MAX_BUF_SIZE]={'\0'};
developer72fb0bb2023-01-11 09:46:29 +080011754 char config_file[MAX_BUF_SIZE] = {0};
11755 struct params params;
11756
11757 if(enable == TRUE)
11758 strcpy(string,"1");
11759 else
11760 strcpy(string,"0");
11761
11762 params.name = "ap_isolate";
11763 params.value = string;
11764
11765 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
11766 wifi_hostapdWrite(config_file,&params,1);
11767 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11768
11769 return RETURN_OK;
11770}
11771
11772INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
11773{
developera1255e42023-05-13 17:45:02 +080011774 char mgmtpwr_file[32] = {0};
11775 char cmd[64] = {0};
11776 char buf[32]={0};
11777
developer72fb0bb2023-01-11 09:46:29 +080011778 if (NULL == output_dBm)
11779 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +080011780 snprintf(mgmtpwr_file, sizeof(mgmtpwr_file), "%s%d.txt", MGMT_POWER_CTRL, apIndex);
11781 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mgmtpwr_file);
11782 _syscmd(cmd, buf, sizeof(buf));
11783 if (strlen(buf) > 0)
11784 *output_dBm = strtol(buf, NULL, 10);
11785 else
11786 *output_dBm = 23;
developer72fb0bb2023-01-11 09:46:29 +080011787 return RETURN_OK;
11788}
11789
11790INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
11791{
developera1255e42023-05-13 17:45:02 +080011792 char interface_name[16] = {0};
developera1255e42023-05-13 17:45:02 +080011793 char mgmt_pwr_file[128]={0};
11794 FILE *f = NULL;
developerfead3972023-05-25 20:15:02 +080011795 int if_idx, ret = 0;
11796 struct nl_msg *msg = NULL;
11797 struct nlattr * msg_data = NULL;
11798 struct mtk_nl80211_param param;
11799 struct unl unl_ins;
11800 char power[16] = {0};
developera1255e42023-05-13 17:45:02 +080011801
11802 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11803
11804 if (wifi_GetInterfaceName(wlanIndex, interface_name) != RETURN_OK)
11805 return RETURN_ERR;
developerfead3972023-05-25 20:15:02 +080011806
11807 if_idx = if_nametoindex(interface_name);
11808 /*init mtk nl80211 vendor cmd*/
11809 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_TXPOWER;
11810 param.if_type = NL80211_ATTR_IFINDEX;
11811 param.if_idx = if_idx;
11812
11813 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
11814 if (ret) {
11815 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
11816 return RETURN_ERR;
11817 }
11818
11819 /*add mtk vendor cmd data*/
11820 snprintf(power, sizeof(power), "%d", dBm);
11821 if (nla_put(msg, MTK_NL80211_VENDOR_ATTR_TXPWR_MGMT, strlen(power), power)) {
11822 wifi_debug(DEBUG_ERROR, "Nla put attribute error\n");
11823 nlmsg_free(msg);
11824 goto err;
11825 }
11826
11827 /*send mtk nl80211 vendor msg*/
11828 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
11829 if (ret) {
11830 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
11831 goto err;
11832 }
11833
11834 /*deinit mtk nl80211 vendor msg*/
11835 mtk_nl80211_deint(&unl_ins);
11836 wifi_debug(DEBUG_NOTICE, "set cmd success.\n");
11837
developera1255e42023-05-13 17:45:02 +080011838 snprintf(mgmt_pwr_file, sizeof(mgmt_pwr_file), "%s%d.txt", MGMT_POWER_CTRL, wlanIndex);
11839 f = fopen(mgmt_pwr_file, "w");
11840 if (f == NULL) {
11841 fprintf(stderr, "%s: fopen failed\n", __func__);
11842 return RETURN_ERR;
11843 }
11844 fprintf(f, "%d", dBm);
11845 fclose(f);
developer72fb0bb2023-01-11 09:46:29 +080011846 return RETURN_OK;
developerfead3972023-05-25 20:15:02 +080011847err:
11848 mtk_nl80211_deint(&unl_ins);
11849 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
11850 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +080011851}
11852INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
11853{
11854 return RETURN_OK;
11855}
11856INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
11857{
11858 return RETURN_OK;
11859}
11860INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
11861{
11862 return RETURN_OK;
11863}
11864INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
11865{
11866 return RETURN_OK;
11867}
11868INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
11869{
11870 char config_file[MAX_BUF_SIZE] = {0};
11871 struct params list;
11872
11873 list.name = "bss_transition";
11874 list.value = activate?"1":"0";
11875 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
11876 wifi_hostapdWrite(config_file, &list, 1);
11877
11878 return RETURN_OK;
11879}
11880wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
11881
11882void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
11883{
11884 return;
11885}
11886
11887INT wifi_setApCsaDeauth(INT apIndex, INT mode)
11888{
11889 // TODO Implement me!
11890 return RETURN_OK;
11891}
11892
11893INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
11894{
11895 char file_name[128] = {0};
developer72fb0bb2023-01-11 09:46:29 +080011896 FILE *f = NULL;
11897 int max_num_radios = 0;
11898
11899 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11900
11901 wifi_getMaxRadioNumber(&max_num_radios);
11902 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
11903 for (int index = 0; index < max_num_radios; index++) {
11904 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
11905 f = fopen(file_name, "w");
11906 if (f == NULL)
11907 return RETURN_ERR;
11908 // For mode == 0 is to disable filter, just don't write to the file.
11909 if (mode)
11910 fprintf(f, "%s", essid);
11911
11912 fclose(f);
11913 }
11914 } else { // special case, need to set AP's SSID as filter for each radio.
11915 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
11916 f = fopen(file_name, "w");
11917 if (f == NULL)
11918 return RETURN_ERR;
11919
11920 // For mode == 0 is to disable filter, just don't write to the file.
11921 if (mode)
11922 fprintf(f, "%s", essid);
11923
11924 fclose(f);
11925 }
11926
11927 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11928 return RETURN_OK;
11929}
11930
11931INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
11932{
11933 // TODO Implement me!
11934 //Apply wifi_pushRadioChannel() instantly
11935 return RETURN_ERR;
11936}
11937
11938INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
11939{
11940 // TODO Implement me!
11941 return RETURN_OK;
11942}
11943
11944#ifdef HAL_NETLINK_IMPL
11945static int tidStats_callback(struct nl_msg *msg, void *arg) {
11946 struct nlattr *tb[NL80211_ATTR_MAX + 1];
11947 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
11948 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
11949 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
11950 int rem , tid_index = 0;
11951
11952 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
11953 wifi_associated_dev_tid_entry_t *stats_entry;
11954
11955 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
11956 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
11957 };
11958 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
11959 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
11960 };
11961
11962 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
11963 genlmsg_attrlen(gnlh, 0), NULL);
11964
11965
11966 if (!tb[NL80211_ATTR_STA_INFO]) {
11967 fprintf(stderr, "station stats missing!\n");
11968 return NL_SKIP;
11969 }
11970
11971 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
11972 tb[NL80211_ATTR_STA_INFO],
11973 stats_policy)) {
11974 fprintf(stderr, "failed to parse nested attributes!\n");
11975 return NL_SKIP;
11976 }
11977
developer386281b2023-05-20 15:43:13 +080011978 if (sinfo[NL80211_STA_INFO_TID_STATS]) {
11979 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
11980 {
11981 stats_entry = &out->tid_array[tid_index];
developer72fb0bb2023-01-11 09:46:29 +080011982
developer386281b2023-05-20 15:43:13 +080011983 stats_entry->tid = tid_index;
11984 stats_entry->ac = _tid_ac_index_get[tid_index];
developer72fb0bb2023-01-11 09:46:29 +080011985
developer386281b2023-05-20 15:43:13 +080011986 if(sinfo[NL80211_STA_INFO_TID_STATS])
11987 {
11988 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
11989 printf("failed to parse nested stats attributes!");
11990 return NL_SKIP;
11991 }
developer72fb0bb2023-01-11 09:46:29 +080011992 }
developer386281b2023-05-20 15:43:13 +080011993 if(stats_info[NL80211_TID_STATS_TX_MSDU])
11994 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
developer72fb0bb2023-01-11 09:46:29 +080011995
developer386281b2023-05-20 15:43:13 +080011996 if(tid_index < (PS_MAX_TID - 1))
11997 tid_index++;
11998 }
developer72fb0bb2023-01-11 09:46:29 +080011999 }
12000 //ToDo: sum_time_ms, ewma_time_ms
12001 return NL_SKIP;
12002}
12003#endif
12004
12005INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
12006{
12007#ifdef HAL_NETLINK_IMPL
12008 Netlink nl;
12009 char if_name[10];
12010 char interface_name[16] = {0};
12011
12012 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
12013 return RETURN_ERR;
12014
12015 snprintf(if_name, sizeof(if_name), "%s", interface_name);
12016
12017 nl.id = initSock80211(&nl);
12018
12019 if (nl.id < 0) {
12020 fprintf(stderr, "Error initializing netlink \n");
12021 return -1;
12022 }
12023
12024 struct nl_msg* msg = nlmsg_alloc();
12025
12026 if (!msg) {
12027 fprintf(stderr, "Failed to allocate netlink message.\n");
12028 nlfree(&nl);
12029 return -2;
12030 }
12031
12032 genlmsg_put(msg,
developer8dd72532023-05-17 19:58:35 +080012033 NL_AUTO_PID,
developer72fb0bb2023-01-11 09:46:29 +080012034 NL_AUTO_SEQ,
12035 nl.id,
12036 0,
12037 0,
12038 NL80211_CMD_GET_STATION,
12039 0);
12040
12041 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
12042 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
12043 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
developer8dd72532023-05-17 19:58:35 +080012044 nl_send_auto_complete(nl.socket, msg);
developer72fb0bb2023-01-11 09:46:29 +080012045 nl_recvmsgs(nl.socket, nl.cb);
12046 nlmsg_free(msg);
12047 nlfree(&nl);
12048 return RETURN_OK;
12049#else
12050//iw implementation
12051#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
12052#define TOTAL_MAX_LINES 50
12053
12054 char buf[256] = {'\0'}; /* or other suitable maximum line size */
12055 char if_name[32] = {0};
12056 FILE *fp=NULL;
12057 char pipeCmd[1024]= {'\0'};
12058 int lines,tid_index=0;
12059 char mac_addr[20] = {'\0'};
12060
12061 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
12062 return RETURN_ERR;
12063
12064 wifi_associated_dev_tid_entry_t *stats_entry;
12065
12066 strcpy(mac_addr,clientMacAddress);
12067
12068 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
12069 fp= popen(pipeCmd,"r");
12070 if(fp == NULL)
12071 {
12072 perror("popen for station dump failed\n");
12073 return RETURN_ERR;
12074 }
12075 pclose(fp);
12076
12077 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
12078 fp=popen(pipeCmd,"r");
12079 if(fp == NULL)
12080 {
12081 perror("popen for grep station failed\n");
12082 return RETURN_ERR;
12083 }
12084 else if(fgets(buf,sizeof(buf),fp) != NULL)
12085 lines=atoi(buf);
12086 else
12087 {
12088 pclose(fp);
12089 fprintf(stderr,"No devices are connected \n");
12090 return RETURN_ERR;
12091 }
12092 pclose(fp);
12093
12094 if(lines == 1)
12095 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
12096
12097 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
12098 {
12099 stats_entry = &tid_stats->tid_array[tid_index];
12100 stats_entry->tid = tid_index;
12101
12102 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);
12103
12104 fp=popen(pipeCmd,"r");
12105 if(fp ==NULL)
12106 {
12107 perror("Failed to read from tid file \n");
12108 return RETURN_ERR;
12109 }
12110 else if(fgets(buf,sizeof(buf),fp) != NULL)
12111 stats_entry->num_msdus = atol(buf);
12112
12113 pclose(fp);
12114 stats_entry->ac = _tid_ac_index_get[tid_index];
12115// TODO:
12116// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
12117// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
12118 }
12119 return RETURN_OK;
12120#endif
12121}
12122
12123
12124INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
12125{
12126 char interface_name[16] = {0};
12127 char cmd[128]={0};
12128 char buf[128]={0};
12129 int freq = 0;
12130
12131 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12132
12133 // full mode is used to scan all channels.
12134 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
12135 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
12136 ieee80211_channel_to_frequency(chan_list[0], &freq);
12137
12138 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
12139 return RETURN_ERR;
12140
12141 if (freq)
12142 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d freq %d", interface_name, dwell_time, freq);
12143 else
12144 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d", interface_name, dwell_time);
12145
12146 _syscmd(cmd, buf, sizeof(buf));
12147 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12148
12149 return RETURN_OK;
12150}
12151
12152
12153INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
12154{
12155 // TODO Implement me!
12156 return RETURN_ERR;
12157}
12158
12159INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
12160{
12161 // TODO Implement me!
12162 return RETURN_ERR;
12163}
12164
12165INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
12166{
12167 // TODO Implement me!
12168 return RETURN_ERR;
12169}
12170
12171INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
12172{
12173 // TODO Implement me!
12174 return RETURN_ERR;
12175}
12176
12177INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
12178{
12179 // TODO Implement me!
12180 return RETURN_ERR;
12181}
12182
12183INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
12184{
12185 // TODO Implement me!
12186 return RETURN_ERR;
12187}
12188
12189INT wifi_steering_eventUnregister(void)
12190{
12191 // TODO Implement me!
12192 return RETURN_ERR;
12193}
12194
12195INT wifi_delApAclDevices(INT apIndex)
12196{
developer7e4a2a62023-04-06 19:56:03 +080012197 char inf_name[IF_NAME_SIZE] = {0};
developer2edaf012023-05-24 14:24:53 +080012198 struct unl unl_ins;
12199 int if_idx = 0, ret = 0;
12200 struct nl_msg *msg = NULL;
12201 struct nlattr * msg_data = NULL;
12202 struct mtk_nl80211_param param;
developer72fb0bb2023-01-11 09:46:29 +080012203
developer7e4a2a62023-04-06 19:56:03 +080012204 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
12205 return RETURN_ERR;
developer2edaf012023-05-24 14:24:53 +080012206 if_idx = if_nametoindex(inf_name);
12207 if (!if_idx) {
12208 wifi_debug(DEBUG_ERROR,"can't finde ifname(%s) index,ERROR\n", inf_name);
12209 return RETURN_ERR;
12210 }
12211 /*init mtk nl80211 vendor cmd*/
12212 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_ACL;
12213 param.if_type = NL80211_ATTR_IFINDEX;
12214 param.if_idx = if_idx;
12215 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
12216 if (ret) {
12217 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
12218 return RETURN_ERR;
12219 }
12220 /*add mtk vendor cmd data*/
12221 if (nla_put_flag(msg, MTK_NL80211_VENDOR_ATTR_ACL_CLEAR_ALL)) {
12222 wifi_debug(DEBUG_ERROR, "Nla put attribute error\n");
12223 nlmsg_free(msg);
12224 goto err;
12225 }
12226 /*send mtk nl80211 vendor msg*/
12227 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
12228 if (ret) {
12229 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
12230 goto err;
12231 }
12232 /*deinit mtk nl80211 vendor msg*/
12233 mtk_nl80211_deint(&unl_ins);
12234 wifi_debug(DEBUG_NOTICE, "set cmd success.\n");
12235 return RETURN_OK;
12236err:
12237 mtk_nl80211_deint(&unl_ins);
12238 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
12239 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +080012240
12241 return RETURN_OK;
12242}
12243
12244#ifdef HAL_NETLINK_IMPL
12245static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
12246 struct nlattr *tb[NL80211_ATTR_MAX + 1];
12247 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
12248 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
12249 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
12250 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
12251 char mac_addr[20],dev[20];
12252
12253 nla_parse(tb,
12254 NL80211_ATTR_MAX,
12255 genlmsg_attrdata(gnlh, 0),
12256 genlmsg_attrlen(gnlh, 0),
12257 NULL);
12258
12259 if(!tb[NL80211_ATTR_STA_INFO]) {
12260 fprintf(stderr, "sta stats missing!\n");
12261 return NL_SKIP;
12262 }
12263
12264 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
12265 fprintf(stderr, "failed to parse nested attributes!\n");
12266 return NL_SKIP;
12267 }
12268 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
12269
12270 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
12271
developer386281b2023-05-20 15:43:13 +080012272 if (sinfo[NL80211_STA_INFO_RX_BITRATE]) {
12273 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
12274 fprintf(stderr, "failed to parse nested rate attributes!");
12275 return NL_SKIP;
12276 }
developer72fb0bb2023-01-11 09:46:29 +080012277 }
12278
12279 if(sinfo[NL80211_STA_INFO_TID_STATS])
12280 {
12281 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
12282 printf("failed to parse nested stats attributes!");
12283 return NL_SKIP;
12284 }
12285 }
developer5a1194f2023-05-24 16:00:03 +080012286 if (tb[NL80211_ATTR_VHT_CAPABILITY]) {
developer72fb0bb2023-01-11 09:46:29 +080012287
developereb1ea832023-05-24 14:46:27 +080012288 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
12289 {
12290 printf("Type is VHT\n");
12291 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
12292 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
developer72fb0bb2023-01-11 09:46:29 +080012293
developereb1ea832023-05-24 14:46:27 +080012294 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
12295 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
12296 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
12297 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
12298 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
12299 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
12300 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
12301 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
12302 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
12303 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
12304 }
12305 else
12306 {
12307 printf(" OFDM or CCK \n");
12308 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
12309 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
12310 }
12311 }
developer72fb0bb2023-01-11 09:46:29 +080012312
developereff896f2023-05-29 14:52:55 +080012313 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
12314 if(rinfo[NL80211_RATE_INFO_MCS])
12315 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
12316 }
12317 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
12318 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
12319 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
12320 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
developer72fb0bb2023-01-11 09:46:29 +080012321
developereff896f2023-05-29 14:52:55 +080012322 if(sinfo[NL80211_STA_INFO_TID_STATS]) {
12323 if(stats_info[NL80211_TID_STATS_RX_MSDU])
12324 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
12325 }
developer72fb0bb2023-01-11 09:46:29 +080012326
developereff896f2023-05-29 14:52:55 +080012327 if (sinfo[NL80211_STA_INFO_SIGNAL])
12328 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
12329 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
12330 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
12331 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
12332 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
12333 //rssi_array need to be filled
12334 return NL_SKIP;
developer72fb0bb2023-01-11 09:46:29 +080012335}
12336#endif
12337
12338INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
12339{
12340#ifdef HAL_NETLINK_IMPL
12341 Netlink nl;
12342 char if_name[32];
12343 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
12344 return RETURN_ERR;
12345
12346 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
12347
12348 if (*output_array_size <= 0)
12349 return RETURN_OK;
12350
12351 nl.id = initSock80211(&nl);
12352
12353 if (nl.id < 0) {
12354 fprintf(stderr, "Error initializing netlink \n");
12355 return 0;
12356 }
12357
12358 struct nl_msg* msg = nlmsg_alloc();
12359
12360 if (!msg) {
12361 fprintf(stderr, "Failed to allocate netlink message.\n");
12362 nlfree(&nl);
12363 return 0;
12364 }
12365
12366 genlmsg_put(msg,
developer8dd72532023-05-17 19:58:35 +080012367 NL_AUTO_PID,
developer72fb0bb2023-01-11 09:46:29 +080012368 NL_AUTO_SEQ,
12369 nl.id,
12370 0,
12371 0,
12372 NL80211_CMD_GET_STATION,
12373 0);
12374
12375 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
12376 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
12377 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
developer8dd72532023-05-17 19:58:35 +080012378 nl_send_auto_complete(nl.socket, msg);
developer72fb0bb2023-01-11 09:46:29 +080012379 nl_recvmsgs(nl.socket, nl.cb);
12380 nlmsg_free(msg);
12381 nlfree(&nl);
12382 return RETURN_OK;
12383#else
12384 //TODO Implement me
12385 return RETURN_OK;
12386#endif
12387}
12388
12389#ifdef HAL_NETLINK_IMPL
12390static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
12391 struct nlattr *tb[NL80211_ATTR_MAX + 1];
12392 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
12393 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
12394 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
12395 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
12396 char mac_addr[20],dev[20];
12397
12398 nla_parse(tb,
12399 NL80211_ATTR_MAX,
12400 genlmsg_attrdata(gnlh, 0),
12401 genlmsg_attrlen(gnlh, 0),
12402 NULL);
12403
12404 if(!tb[NL80211_ATTR_STA_INFO]) {
12405 fprintf(stderr, "sta stats missing!\n");
12406 return NL_SKIP;
12407 }
12408
12409 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
12410 fprintf(stderr, "failed to parse nested attributes!\n");
12411 return NL_SKIP;
12412 }
12413
12414 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
12415
12416 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
12417
developer386281b2023-05-20 15:43:13 +080012418 if (sinfo[NL80211_STA_INFO_TX_BITRATE]) {
12419 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
12420 fprintf(stderr, "failed to parse nested rate attributes!");
12421 return NL_SKIP;
12422 }
developer72fb0bb2023-01-11 09:46:29 +080012423 }
12424
12425 if(sinfo[NL80211_STA_INFO_TID_STATS])
12426 {
12427 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
12428 printf("failed to parse nested stats attributes!");
12429 return NL_SKIP;
12430 }
12431 }
developera6beea42023-05-24 16:44:05 +080012432 if (tb[NL80211_ATTR_VHT_CAPABILITY]) {
developereb1ea832023-05-24 14:46:27 +080012433 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
12434 {
12435 printf("Type is VHT\n");
12436 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
12437 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
developer72fb0bb2023-01-11 09:46:29 +080012438
developereb1ea832023-05-24 14:46:27 +080012439 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
12440 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
12441 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
12442 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
12443 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
12444 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
12445 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
12446 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
12447 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
12448 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
12449 }
12450 else
12451 {
12452 printf(" OFDM or CCK \n");
developer72fb0bb2023-01-11 09:46:29 +080012453 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
developereb1ea832023-05-24 14:46:27 +080012454 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
12455 }
developer72fb0bb2023-01-11 09:46:29 +080012456 }
12457
12458 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
12459 if(rinfo[NL80211_RATE_INFO_MCS])
12460 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
12461 }
12462
12463 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
12464 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
12465 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
12466 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
12467
12468 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
developereff896f2023-05-29 14:52:55 +080012469 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
12470 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
developer72fb0bb2023-01-11 09:46:29 +080012471
developereff896f2023-05-29 14:52:55 +080012472 if(sinfo[NL80211_STA_INFO_TID_STATS]) {
12473 if(stats_info[NL80211_TID_STATS_TX_MSDU])
12474 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
12475 }
developer72fb0bb2023-01-11 09:46:29 +080012476
12477 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
12478 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
12479
developereff896f2023-05-29 14:52:55 +080012480 if(sinfo[NL80211_STA_INFO_TX_FAILED] && sinfo[NL80211_STA_INFO_TX_PACKETS])
12481 ((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]);
developer72fb0bb2023-01-11 09:46:29 +080012482
12483 return NL_SKIP;
12484}
12485#endif
12486
12487INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
12488{
12489#ifdef HAL_NETLINK_IMPL
12490 Netlink nl;
12491 char if_name[10];
12492 char interface_name[16] = {0};
12493 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
12494 return RETURN_ERR;
12495
12496 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
12497
12498 if (*output_array_size <= 0)
12499 return RETURN_OK;
12500
12501 snprintf(if_name, sizeof(if_name), "%s", interface_name);
12502
12503 nl.id = initSock80211(&nl);
12504
12505 if(nl.id < 0) {
12506 fprintf(stderr, "Error initializing netlink \n");
12507 return 0;
12508 }
12509
12510 struct nl_msg* msg = nlmsg_alloc();
12511
12512 if(!msg) {
12513 fprintf(stderr, "Failed to allocate netlink message.\n");
12514 nlfree(&nl);
12515 return 0;
12516 }
12517
12518 genlmsg_put(msg,
developer8dd72532023-05-17 19:58:35 +080012519 NL_AUTO_PID,
developer72fb0bb2023-01-11 09:46:29 +080012520 NL_AUTO_SEQ,
12521 nl.id,
12522 0,
12523 0,
12524 NL80211_CMD_GET_STATION,
12525 0);
12526
12527 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
12528 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
12529 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
developer8dd72532023-05-17 19:58:35 +080012530 nl_send_auto_complete(nl.socket, msg);
developer72fb0bb2023-01-11 09:46:29 +080012531 nl_recvmsgs(nl.socket, nl.cb);
12532 nlmsg_free(msg);
12533 nlfree(&nl);
12534 return RETURN_OK;
12535#else
12536 //TODO Implement me
12537 return RETURN_OK;
12538#endif
12539}
12540
12541INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
12542{
12543 // TODO Implement me!
12544 char buf[MAX_BUF_SIZE] = {0};
12545 char config_file[MAX_BUF_SIZE] = {0};
12546
12547 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
12548 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
12549 *activate = (strncmp("1",buf,1) == 0);
12550
12551 return RETURN_OK;
12552}
12553
12554INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
12555{
12556 char config_file[MAX_BUF_SIZE] = {0};
12557 struct params list;
12558
12559 list.name = "rrm_neighbor_report";
12560 list.value = activate?"1":"0";
12561 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
12562 wifi_hostapdWrite(config_file, &list, 1);
12563
12564 return RETURN_OK;
12565}
12566
12567INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
12568{
12569 char buf[32] = {0};
12570 char config_file[MAX_BUF_SIZE] = {0};
12571
12572 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
12573 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
12574 *activate = (strncmp("1",buf,1) == 0);
12575
12576 return RETURN_OK;
12577}
12578#undef HAL_NETLINK_IMPL
12579#ifdef HAL_NETLINK_IMPL
12580static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
12581 struct nlattr *tb[NL80211_ATTR_MAX + 1];
12582 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
12583 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
12584 char dev[20];
12585 int freq =0 ;
12586 static int i=0;
12587
12588 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
12589
12590 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
12591 };
12592
12593 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
12594
12595 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
12596
12597 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
12598 fprintf(stderr, "survey data missing!\n");
12599 return NL_SKIP;
12600 }
12601
12602 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
12603 {
12604 fprintf(stderr, "failed to parse nested attributes!\n");
12605 return NL_SKIP;
12606 }
12607
12608
12609 if(out[0].array_size == 1 )
12610 {
12611 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
12612 {
12613 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
12614 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
12615 out[0].ch_number = ieee80211_frequency_to_channel(freq);
12616
12617 if (sinfo[NL80211_SURVEY_INFO_NOISE])
12618 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
12619 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
12620 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
12621 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
12622 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
12623 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
12624 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
12625 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
12626 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
12627 if (sinfo[NL80211_SURVEY_INFO_TIME])
12628 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
12629 return NL_STOP;
12630 }
12631 }
12632 else
12633 {
12634 if ( i <= out[0].array_size )
12635 {
12636 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
12637 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
12638 out[i].ch_number = ieee80211_frequency_to_channel(freq);
12639
12640 if (sinfo[NL80211_SURVEY_INFO_NOISE])
12641 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
12642 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
12643 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
12644 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
12645 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
12646 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
12647 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
12648 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
12649 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
12650 if (sinfo[NL80211_SURVEY_INFO_TIME])
12651 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
12652 }
12653 }
12654
12655 i++;
12656 return NL_SKIP;
12657}
12658#endif
12659
12660static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
12661{
12662 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
12663 FILE *fp;
12664
12665 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
12666 {
12667 printf("Creating Frequency-Channel Map\n");
12668 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
12669 }
12670 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
12671 if((fp = popen(command, "r")))
12672 {
12673 fgets(output, sizeof(output), fp);
12674 *freqMHz = atoi(output);
12675 pclose(fp);
12676 }
12677
12678 return 0;
12679}
12680
developer2f79c922023-06-02 17:33:42 +080012681static int get_survey_dump_buf(INT radioIndex, int channel, char *buf, size_t bufsz)
developer72fb0bb2023-01-11 09:46:29 +080012682{
12683 int freqMHz = -1;
12684 char cmd[MAX_CMD_SIZE] = {'\0'};
12685 char interface_name[16] = {0};
12686
12687 ieee80211_channel_to_frequency(channel, &freqMHz);
12688 if (freqMHz == -1) {
12689 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
12690 return -1;
12691 }
12692
12693 wifi_GetInterfaceName(radioIndex, interface_name);
12694 if (sprintf(cmd,"iw dev %s survey dump | grep -A5 %d | tr -d '\\t'", interface_name, freqMHz) < 0) {
12695 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
12696 radioIndex, freqMHz);
12697 return -1;
12698 }
12699
12700 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
12701 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
12702 return -1;
12703 }
12704
12705 return 0;
12706}
12707
12708static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
12709{
12710 const char *ptr = buf;
12711 char *key = NULL;
12712 char *val = NULL;
12713 char line[256] = { '\0' };
12714
developerdaf24792023-06-06 11:40:04 +080012715 while ((ptr = get_line_from_str_buf(ptr, line))) {
developer72fb0bb2023-01-11 09:46:29 +080012716 if (strstr(line, "Frequency")) continue;
12717
12718 key = strtok(line, ":");
12719 val = strtok(NULL, " ");
12720 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
12721
12722 if (!strcmp(key, "noise")) {
12723 sscanf(val, "%d", &stats->ch_noise);
12724 if (stats->ch_noise == 0) {
12725 // Workaround for missing noise information.
12726 // Assume -95 for 2.4G and -103 for 5G
12727 if (radioIndex == 0) stats->ch_noise = -95;
12728 if (radioIndex == 1) stats->ch_noise = -103;
12729 }
12730 }
12731 else if (!strcmp(key, "channel active time")) {
12732 sscanf(val, "%llu", &stats->ch_utilization_total);
12733 }
12734 else if (!strcmp(key, "channel busy time")) {
12735 sscanf(val, "%llu", &stats->ch_utilization_busy);
12736 }
12737 else if (!strcmp(key, "channel receive time")) {
12738 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
12739 }
12740 else if (!strcmp(key, "channel transmit time")) {
12741 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
12742 }
12743 };
12744
12745 return 0;
12746}
12747
12748INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
12749{
12750 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12751#ifdef HAL_NETLINK_IMPL
12752 Netlink nl;
12753 wifi_channelStats_t_loc local[array_size];
12754 char if_name[32];
12755
12756 local[0].array_size = array_size;
12757
12758 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
12759 return RETURN_ERR;
12760
12761 nl.id = initSock80211(&nl);
12762
12763 if (nl.id < 0) {
12764 fprintf(stderr, "Error initializing netlink \n");
12765 return -1;
12766 }
12767
12768 struct nl_msg* msg = nlmsg_alloc();
12769
12770 if (!msg) {
12771 fprintf(stderr, "Failed to allocate netlink message.\n");
12772 nlfree(&nl);
12773 return -2;
12774 }
12775
12776 genlmsg_put(msg,
developer8dd72532023-05-17 19:58:35 +080012777 NL_AUTO_PID,
developer72fb0bb2023-01-11 09:46:29 +080012778 NL_AUTO_SEQ,
12779 nl.id,
12780 0,
12781 NLM_F_DUMP,
12782 NL80211_CMD_GET_SURVEY,
12783 0);
12784
12785 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
developer8dd72532023-05-17 19:58:35 +080012786 nl_send_auto_complete(nl.socket, msg);
developer72fb0bb2023-01-11 09:46:29 +080012787 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
12788 nl_recvmsgs(nl.socket, nl.cb);
12789 nlmsg_free(msg);
12790 nlfree(&nl);
12791 //Copying the Values
12792 for(int i=0;i<array_size;i++)
12793 {
12794 input_output_channelStats_array[i].ch_number = local[i].ch_number;
12795 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
12796 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
12797 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
12798 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
12799 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
12800 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
12801 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
12802 }
12803#else
12804 ULONG channel = 0;
12805 int i;
12806 int number_of_channels = array_size;
12807 char buf[512];
developer72fb0bb2023-01-11 09:46:29 +080012808
12809 if (number_of_channels == 0) {
12810 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
12811 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
12812 return RETURN_ERR;
12813 }
12814 number_of_channels = 1;
12815 input_output_channelStats_array[0].ch_number = channel;
12816 }
12817
12818 for (i = 0; i < number_of_channels; i++) {
12819
12820 input_output_channelStats_array[i].ch_noise = 0;
12821 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
12822 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
12823 input_output_channelStats_array[i].ch_utilization_busy = 0;
12824 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
12825 input_output_channelStats_array[i].ch_utilization_total = 0;
12826
12827 memset(buf, 0, sizeof(buf));
12828 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
12829 return RETURN_ERR;
12830 }
12831 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
12832 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
12833 return RETURN_ERR;
12834 }
12835
12836 // XXX: fake missing 'self' counter which is not available in iw survey output
12837 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
12838 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
12839
12840 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
12841 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
12842 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
12843 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
12844 input_output_channelStats_array[i].ch_utilization_total *= 1000;
12845
12846 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",
12847 __func__,
12848 input_output_channelStats_array[i].ch_number,
12849 input_output_channelStats_array[i].ch_noise,
12850 input_output_channelStats_array[i].ch_utilization_total,
12851 input_output_channelStats_array[i].ch_utilization_busy,
12852 input_output_channelStats_array[i].ch_utilization_busy_rx,
12853 input_output_channelStats_array[i].ch_utilization_busy_tx,
12854 input_output_channelStats_array[i].ch_utilization_busy_self,
12855 input_output_channelStats_array[i].ch_utilization_busy_ext);
12856 }
12857#endif
12858 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12859 return RETURN_OK;
12860}
12861#define HAL_NETLINK_IMPL
12862
12863/* Hostapd events */
12864
12865#ifndef container_of
12866#define offset_of(st, m) ((size_t)&(((st *)0)->m))
12867#define container_of(ptr, type, member) \
12868 ((type *)((char *)ptr - offset_of(type, member)))
12869#endif /* container_of */
12870
12871struct ctrl {
12872 char sockpath[128];
12873 char sockdir[128];
12874 char bss[IFNAMSIZ];
12875 char reply[4096];
12876 int ssid_index;
12877 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
12878 void (*overrun)(struct ctrl *ctrl);
12879 struct wpa_ctrl *wpa;
12880 unsigned int ovfl;
12881 size_t reply_len;
12882 int initialized;
12883 ev_timer retry;
12884 ev_timer watchdog;
12885 ev_stat stat;
12886 ev_io io;
12887};
12888static wifi_newApAssociatedDevice_callback clients_connect_cb;
12889static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
12890static struct ctrl wpa_ctrl[MAX_APS];
12891static int initialized;
12892
12893static unsigned int ctrl_get_drops(struct ctrl *ctrl)
12894{
12895 char cbuf[256] = {};
12896 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
12897 struct cmsghdr *cmsg;
12898 unsigned int ovfl = ctrl->ovfl;
12899 unsigned int drop;
12900
12901 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
12902 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
12903 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
12904 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
12905
12906 drop = ovfl - ctrl->ovfl;
12907 ctrl->ovfl = ovfl;
12908
12909 return drop;
12910}
12911
12912static void ctrl_close(struct ctrl *ctrl)
12913{
12914 if (ctrl->io.cb)
12915 ev_io_stop(EV_DEFAULT_ &ctrl->io);
12916 if (ctrl->retry.cb)
12917 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
12918 if (!ctrl->wpa)
12919 return;
12920
12921 wpa_ctrl_detach(ctrl->wpa);
12922 wpa_ctrl_close(ctrl->wpa);
12923 ctrl->wpa = NULL;
12924 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
12925}
12926
12927static void ctrl_process(struct ctrl *ctrl)
12928{
12929 const char *str;
12930 int drops;
12931 int level;
developer72fb0bb2023-01-11 09:46:29 +080012932
12933 /* Example events:
12934 *
12935 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
12936 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
12937 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
12938 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
12939 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
12940 */
12941 if (!(str = index(ctrl->reply, '>')))
12942 return;
12943 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
12944 return;
12945
12946 str++;
12947
12948 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
12949 if (!(str = index(ctrl->reply, ' ')))
12950 return;
12951 wifi_associated_dev_t sta;
12952 memset(&sta, 0, sizeof(sta));
12953
12954 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
12955 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
12956 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
12957
12958 sta.cli_Active=true;
12959
12960 (clients_connect_cb)(ctrl->ssid_index, &sta);
12961 goto handled;
12962 }
12963
12964 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
12965 if (!(str = index(ctrl->reply, ' ')))
12966 return;
12967
12968 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
12969 goto handled;
12970 }
12971
12972 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
12973 printf("CTRL_WPA: handle TERMINATING event\n");
12974 goto retry;
12975 }
12976
12977 if (strncmp("AP-DISABLED", str, 11) == 0) {
12978 printf("CTRL_WPA: handle AP-DISABLED\n");
12979 goto retry;
12980 }
12981
12982 printf("Event not supported!!\n");
12983
12984handled:
12985
12986 if ((drops = ctrl_get_drops(ctrl))) {
12987 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
12988 if (ctrl->overrun)
12989 ctrl->overrun(ctrl);
12990 }
12991
12992 return;
12993
12994retry:
12995 printf("WPA_CTRL: closing\n");
12996 ctrl_close(ctrl);
12997 printf("WPA_CTRL: retrying from ctrl prcoess\n");
12998 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
12999}
13000
13001static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
13002{
13003 struct ctrl *ctrl = container_of(io, struct ctrl, io);
13004 int err;
13005
13006 memset(ctrl->reply, 0, sizeof(ctrl->reply));
13007 ctrl->reply_len = sizeof(ctrl->reply) - 1;
13008 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
13009 ctrl->reply[ctrl->reply_len] = 0;
13010 if (err < 0) {
13011 if (errno == EAGAIN || errno == EWOULDBLOCK)
13012 return;
13013 ctrl_close(ctrl);
13014 ev_timer_again(EV_A_ &ctrl->retry);
13015 return;
13016 }
13017
13018 ctrl_process(ctrl);
13019}
13020
13021static int ctrl_open(struct ctrl *ctrl)
13022{
13023 int fd;
13024
13025 if (ctrl->wpa)
13026 return 0;
13027
13028 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
13029 if (!ctrl->wpa)
13030 goto err;
13031
13032 if (wpa_ctrl_attach(ctrl->wpa) < 0)
13033 goto err_close;
13034
13035 fd = wpa_ctrl_get_fd(ctrl->wpa);
13036 if (fd < 0)
13037 goto err_detach;
13038
13039 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
13040 goto err_detach;
13041
13042 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
13043 ev_io_start(EV_DEFAULT_ &ctrl->io);
13044
13045 return 0;
13046
13047err_detach:
13048 wpa_ctrl_detach(ctrl->wpa);
13049err_close:
13050 wpa_ctrl_close(ctrl->wpa);
13051err:
13052 ctrl->wpa = NULL;
13053 return -1;
13054}
13055
13056static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
13057{
13058 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
13059
13060 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
13061 ctrl_open(ctrl);
13062}
13063
13064static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
13065{
13066 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
13067
13068 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
13069 if (ctrl_open(ctrl) == 0) {
13070 printf("WPA_CTRL: retry successful\n");
13071 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
13072 }
13073}
13074
13075int ctrl_enable(struct ctrl *ctrl)
13076{
13077 if (ctrl->wpa)
13078 return 0;
13079
13080 if (!ctrl->stat.cb) {
13081 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
13082 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
13083 }
13084
13085 if (!ctrl->retry.cb) {
13086 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
13087 }
13088
13089 return ctrl_open(ctrl);
13090}
13091
13092static void
13093ctrl_msg_cb(char *buf, size_t len)
13094{
13095 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
13096
13097 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
13098 ctrl_process(ctrl);
13099}
13100
13101static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
13102{
13103 int err;
13104
13105 if (!ctrl->wpa)
13106 return -1;
13107 if (*reply_len < 2)
13108 return -1;
13109
13110 (*reply_len)--;
13111 ctrl->reply_len = sizeof(ctrl->reply);
13112 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
13113 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
13114 if (err < 0)
13115 return err;
13116
13117 if (ctrl->reply_len > *reply_len)
13118 ctrl->reply_len = *reply_len;
13119
13120 *reply_len = ctrl->reply_len;
13121 memcpy(reply, ctrl->reply, *reply_len);
13122 reply[*reply_len - 1] = 0;
13123 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
13124 return 0;
13125}
13126
13127static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
13128{
13129 const char *pong = "PONG";
13130 const char *ping = "PING";
13131 char reply[1024];
13132 size_t len = sizeof(reply);
13133 int err;
13134 ULONG s, snum;
13135 INT ret;
13136 BOOL status;
13137
13138 printf("WPA_CTRL: watchdog cb\n");
13139
13140 ret = wifi_getSSIDNumberOfEntries(&snum);
13141 if (ret != RETURN_OK) {
13142 printf("%s: failed to get SSID count", __func__);
13143 return;
13144 }
13145
13146 if (snum > MAX_APS) {
13147 printf("more ssid than supported! %lu\n", snum);
13148 return;
13149 }
13150
13151 for (s = 0; s < snum; s++) {
13152 if (wifi_getApEnable(s, &status) != RETURN_OK) {
13153 printf("%s: failed to get AP Enable for index: %lu\n", __func__, s);
13154 continue;
13155 }
13156 if (status == false) continue;
13157
13158 memset(reply, 0, sizeof(reply));
13159 len = sizeof(reply);
13160 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
13161 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
13162 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
13163 continue;
13164
13165 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
13166 ctrl_close(&wpa_ctrl[s]);
13167 printf("WPA_CTRL: ev_timer_again %lu\n", s);
13168 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
13169 }
13170}
13171
13172static int init_wpa()
13173{
developer2f79c922023-06-02 17:33:42 +080013174 int ret = 0;
developer72fb0bb2023-01-11 09:46:29 +080013175 ULONG s, snum;
13176
13177 ret = wifi_getSSIDNumberOfEntries(&snum);
13178 if (ret != RETURN_OK) {
13179 printf("%s: failed to get SSID count", __func__);
13180 return RETURN_ERR;
13181 }
13182
13183 if (snum > MAX_APS) {
13184 printf("more ssid than supported! %lu\n", snum);
13185 return RETURN_ERR;
13186 }
13187
13188 for (s = 0; s < snum; s++) {
13189 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
13190 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
13191 wpa_ctrl[s].ssid_index = s;
13192 ctrl_enable(&wpa_ctrl[s]);
13193 }
13194
13195 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
13196 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
13197
13198 initialized = 1;
13199 printf("WPA_CTRL: initialized\n");
13200
13201 return RETURN_OK;
13202}
13203
13204void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
13205{
13206 clients_connect_cb = callback_proc;
13207 if (!initialized)
13208 init_wpa();
13209}
13210
13211void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
13212{
13213 clients_disconnect_cb = callback_proc;
13214 if (!initialized)
13215 init_wpa();
13216}
13217
13218INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
13219{
13220 // TODO Implement me!
13221 return RETURN_ERR;
13222}
13223
13224INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
13225{
13226 // TODO Implement me!
13227 return RETURN_ERR;
13228}
13229
13230INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
13231{
13232 int i;
developerd1824452023-05-18 12:30:04 +080013233 int phyId = -1;
13234 char cmd[256] = {0};
13235 char channel_numbers_buf[256] = {0};
13236 char dfs_state_buf[256] = {0};
13237 char line[256] = {0};
developer72fb0bb2023-01-11 09:46:29 +080013238 const char *ptr;
developerd1824452023-05-18 12:30:04 +080013239 BOOL dfs_enable = false;
developer72fb0bb2023-01-11 09:46:29 +080013240
developerd1824452023-05-18 12:30:04 +080013241 memset(outputMap, 0, outputMapSize*sizeof(wifi_channelMap_t)); // all unused entries should be zero
developer72fb0bb2023-01-11 09:46:29 +080013242
developerd1824452023-05-18 12:30:04 +080013243 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
13244 phyId = radio_index_to_phy(radioIndex);
developer72fb0bb2023-01-11 09:46:29 +080013245
developerd1824452023-05-18 12:30:04 +080013246 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 +080013247
developerd1824452023-05-18 12:30:04 +080013248 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
13249 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
13250 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +080013251 }
13252
developerd1824452023-05-18 12:30:04 +080013253 ptr = channel_numbers_buf;
13254 i = 0;
developerdaf24792023-06-06 11:40:04 +080013255 while ((ptr = get_line_from_str_buf(ptr, line))) {
developerd1824452023-05-18 12:30:04 +080013256 if (i >= outputMapSize) {
13257 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
13258 return RETURN_ERR;
13259 }
13260 sscanf(line, "%d", &outputMap[i].ch_number);
13261
13262 memset(cmd, 0, sizeof(cmd));
13263 // Below command should fetch string for DFS state (usable, available or unavailable)
13264 // Example line: "DFS state: usable (for 78930 sec)"
13265 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) {
13266 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
developer72fb0bb2023-01-11 09:46:29 +080013267 return RETURN_ERR;
13268 }
13269
developerd1824452023-05-18 12:30:04 +080013270 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
13271 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
developer72fb0bb2023-01-11 09:46:29 +080013272 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
13273 return RETURN_ERR;
13274 }
13275
developerd1824452023-05-18 12:30:04 +080013276 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
developer59fda4f2023-05-16 15:47:38 +080013277
developerd1824452023-05-18 12:30:04 +080013278 if (!strcmp(dfs_state_buf, "usable")) {
13279 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
13280 } else if (!strcmp(dfs_state_buf, "available")) {
13281 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
13282 } else if (!strcmp(dfs_state_buf, "unavailable")) {
13283 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
13284 } else {
13285 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
developer72fb0bb2023-01-11 09:46:29 +080013286 }
developerd1824452023-05-18 12:30:04 +080013287 i++;
developer59fda4f2023-05-16 15:47:38 +080013288 }
developer40ba1762023-05-13 11:03:49 +080013289
developerd1824452023-05-18 12:30:04 +080013290 return RETURN_OK;
13291
developer72fb0bb2023-01-11 09:46:29 +080013292 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
13293 return RETURN_ERR;
13294}
13295
13296INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
13297{
13298 // TODO Implement me!
13299 return RETURN_ERR;
13300}
13301
13302INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
13303{
13304 return RETURN_OK;
13305}
13306
13307INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
13308{
13309 // TODO Implement me!
13310 return RETURN_ERR;
13311}
13312
13313INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
13314{
13315 // TODO API refrence Implementaion is present on RPI hal
13316 return RETURN_ERR;
13317}
13318
13319INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
13320{
developera1255e42023-05-13 17:45:02 +080013321/*
developer72fb0bb2023-01-11 09:46:29 +080013322 char interface_name[16] = {0};
13323 char cmd[128]={'\0'};
13324 char buf[128]={'\0'};
13325 char *support;
13326 int maximum_tx = 0, current_tx = 0;
developera1255e42023-05-13 17:45:02 +080013327*/ ULONG pwr_percentage = 0;
developer72fb0bb2023-01-11 09:46:29 +080013328
13329 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13330 if(txpwr_pcntg == NULL)
developerdaf24792023-06-06 11:40:04 +080013331 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +080013332
developera1255e42023-05-13 17:45:02 +080013333 wifi_getRadioTransmitPower(apIndex, &pwr_percentage);
13334 *txpwr_pcntg = pwr_percentage;
13335/* if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72fb0bb2023-01-11 09:46:29 +080013336 return RETURN_ERR;
13337
13338 // Get the maximum tx power of the device
13339 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", interface_name);
13340 _syscmd(cmd, buf, sizeof(buf));
13341 maximum_tx = strtol(buf, NULL, 10);
13342
13343 // Get the current tx power
13344 memset(cmd, 0, sizeof(cmd));
13345 memset(buf, 0, sizeof(buf));
13346 snprintf(cmd, sizeof(cmd), "iw %s info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", interface_name);
13347 _syscmd(cmd, buf, sizeof(buf));
13348 current_tx = strtol(buf, NULL, 10);
13349
13350 // Get the power supported list and find the current power percentage in supported list
13351 memset(buf, 0, sizeof(buf));
13352 wifi_getRadioTransmitPowerSupported(apIndex, buf);
13353 support = strtok(buf, ",");
13354 while(true)
13355 {
13356 if(support == NULL) { // current power is not in supported list, this should not happen if the power is set by hal.
13357 *txpwr_pcntg = 100;
13358 wifi_dbg_printf("current power is not in supported list\n");
13359 return RETURN_OK;
13360 }
13361 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
13362 if (tmp == current_tx) {
13363 *txpwr_pcntg = strtol(support, NULL, 10);
13364 break;
13365 }
13366 support = strtok(NULL, ",");
13367 }
developera1255e42023-05-13 17:45:02 +080013368*/
developer72fb0bb2023-01-11 09:46:29 +080013369 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13370 return RETURN_OK;
13371}
13372
13373INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
13374{
13375 // TODO precac feature.
developerd1824452023-05-18 12:30:04 +080013376 struct params params[2] = {0};
developer72fb0bb2023-01-11 09:46:29 +080013377 char config_file[128] = {0};
developerd1824452023-05-18 12:30:04 +080013378 BOOL dfs_enable = false;
13379 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +080013380
13381 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developerd1824452023-05-18 12:30:04 +080013382 band = wifi_index_to_band(radioIndex);
13383 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
developer72fb0bb2023-01-11 09:46:29 +080013384
developerd1824452023-05-18 12:30:04 +080013385 if (dfs_enable == false) {
13386 WIFI_ENTRY_EXIT_DEBUG("Please enable DFS firstly!: %s\n", __func__);
13387 return RETURN_ERR;
13388 }
13389 params[0].name = "DfsZeroWaitDefault";
13390 params[0].value = enable?"1":"0";
13391 params[1].name = "DfsDedicatedZeroWait";
13392 params[1].value = enable?"1":"0";
13393 snprintf(config_file, sizeof(config_file), "%s%d.dat", LOGAN_DAT_FILE, band);
13394 wifi_datfileWrite(config_file, params, 2);
developerc0772e62023-05-18 15:10:48 +080013395 wifi_reloadAp(radioIndex);
developer72fb0bb2023-01-11 09:46:29 +080013396 /* TODO precac feature */
13397
13398 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13399 return RETURN_OK;
13400}
13401
13402INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
13403{
13404 char config_file[128] = {0};
developerd1824452023-05-18 12:30:04 +080013405 char buf1[32] = {0};
13406 char buf2[32] = {0};
13407 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +080013408
13409 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13410 if (NULL == enable || NULL == precac)
13411 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +080013412 band = wifi_index_to_band(radioIndex);
13413 snprintf(config_file, sizeof(config_file), "%s%d.dat", LOGAN_DAT_FILE, band);
13414 wifi_datfileRead(config_file, "DfsZeroWaitDefault", buf1, sizeof(buf1));
13415 wifi_datfileRead(config_file, "DfsDedicatedZeroWait", buf2, sizeof(buf2));
13416 if ((strncmp(buf1, "1", 1) == 0) && (strncmp(buf2, "1", 1) == 0))
developer72fb0bb2023-01-11 09:46:29 +080013417 *enable = true;
13418 else
13419 *enable = false;
13420
13421 /* TODO precac feature */
13422
13423 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13424 return RETURN_OK;
13425}
13426
13427INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
13428{
13429 *supported = TRUE;
13430 return RETURN_OK;
13431}
13432
13433INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
13434{
developera1255e42023-05-13 17:45:02 +080013435 UCHAR dat_file[64] = {0};
13436 wifi_band band = band_invalid;
developera1255e42023-05-13 17:45:02 +080013437 char ofdmabuf[32] = {'\0'};
13438 char mimobuf[32] = {'\0'};
13439 char new_ofdmabuf[32] = {'\0'};
13440 char new_mimobuf[32] = {'\0'};
13441 struct params params[2];
13442 char *str_zero = "0;0;0;0;0;0;0;0;0;0;0;0;0;0;0";/*default 15bss per band.*/
13443 char *str_one = "1;1;1;1;1;1;1;1;1;1;1;1;1;1;1";
13444 UCHAR bss_cnt = 0;
13445 UCHAR val_cnt = 0;
developer72fb0bb2023-01-11 09:46:29 +080013446
developera1255e42023-05-13 17:45:02 +080013447 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13448 if ((mu_type < WIFI_DL_MU_TYPE_NONE)
13449 || (mu_type > WIFI_DL_MU_TYPE_OFDMA_MIMO)) {
13450 printf("%s:mu_type input Error", __func__);
13451 return RETURN_ERR;
13452 }
13453 band = wifi_index_to_band(radio_index);
13454 if (band == band_invalid) {
13455 printf("%s:Band Error\n", __func__);
13456 return RETURN_ERR;
13457 }
13458 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
13459 /*get current value in dat file*/
13460 wifi_datfileRead(dat_file, "MuOfdmaDlEnable", ofdmabuf, sizeof(ofdmabuf));
13461 wifi_datfileRead(dat_file, "MuMimoDlEnable", mimobuf, sizeof(mimobuf));
13462 WIFI_ENTRY_EXIT_DEBUG("%s:ofdma-%s, mimo-%s\n", __func__, ofdmabuf, mimobuf);
13463 get_bssnum_byindex(radio_index, &bss_cnt);
13464 val_cnt = 2*bss_cnt - 1;
13465 WIFI_ENTRY_EXIT_DEBUG("bss number: %d\n", bss_cnt);
13466 if ((val_cnt >= sizeof(new_ofdmabuf))
13467 || (val_cnt >= sizeof(new_mimobuf))) {
13468 printf("%s:bss cnt Error", __func__, bss_cnt);
13469 return RETURN_ERR;
13470 }
13471 /*translate set value*/
13472 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
13473 strncpy(new_ofdmabuf, str_zero, val_cnt);
13474 strncpy(new_mimobuf, str_zero, val_cnt);
developer72fb0bb2023-01-11 09:46:29 +080013475 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
developera1255e42023-05-13 17:45:02 +080013476 strncpy(new_ofdmabuf, str_one, val_cnt);
13477 strncpy(new_mimobuf, str_zero, val_cnt);
developer72fb0bb2023-01-11 09:46:29 +080013478 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
developera1255e42023-05-13 17:45:02 +080013479 strncpy(new_ofdmabuf, str_zero, val_cnt);
13480 strncpy(new_mimobuf, str_one, val_cnt);
13481 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO) {
13482 strncpy(new_ofdmabuf, str_one, val_cnt);
13483 strncpy(new_mimobuf, str_one, val_cnt);
developer72fb0bb2023-01-11 09:46:29 +080013484 }
developera1255e42023-05-13 17:45:02 +080013485 WIFI_ENTRY_EXIT_DEBUG("%s:new_ofdmabuf-%s, new_mimobuf-%s\n", __func__, new_ofdmabuf, new_mimobuf);
13486 /*same value, not operation*/
13487 if ((strncmp(new_mimobuf, mimobuf, 1) ==0)
13488 && (strncmp(new_ofdmabuf, ofdmabuf, 1) ==0)) {
13489 printf("%s:Reduntant value\n", __func__);
13490 return RETURN_OK;
13491 }
13492 /*modify dat file to new file*/
13493 params[0].name="MuOfdmaDlEnable";
13494 params[0].value=new_ofdmabuf;
13495 params[1].name="MuMimoDlEnable";
13496 params[1].value=new_mimobuf;
13497 wifi_datfileWrite(dat_file, params, 2);
13498 /*hostapd control restarp ap to take effect on these new value*/
13499 wifi_reloadAp(radio_index);
developer72fb0bb2023-01-11 09:46:29 +080013500 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13501 return RETURN_OK;
13502}
13503
13504INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
13505{
developera1255e42023-05-13 17:45:02 +080013506 UCHAR dat_file[64] = {0};
13507 wifi_band band = band_invalid;
13508 char ofdmabuf[32] = {'\0'};
13509 char mimobuf[32] = {'\0'};
13510 char *token = NULL;
13511 UCHAR ofdma = 0;
13512 UCHAR mimo = 0;
developer72fb0bb2023-01-11 09:46:29 +080013513
13514 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13515
13516 if (mu_type == NULL)
13517 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +080013518 band = wifi_index_to_band(radio_index);
13519 if (band == band_invalid) {
13520 printf("%s:Band Error\n", __func__);
13521 return RETURN_ERR;
13522 }
13523 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
13524 /*get current value in dat file*/
13525 wifi_datfileRead(dat_file, "MuOfdmaDlEnable", ofdmabuf, sizeof(ofdmabuf));
13526 wifi_datfileRead(dat_file, "MuMimoDlEnable", mimobuf, sizeof(mimobuf));
developer72fb0bb2023-01-11 09:46:29 +080013527
developera1255e42023-05-13 17:45:02 +080013528 token = strtok(ofdmabuf, ";");
13529 ofdma = strtol(token, NULL, 10);
13530 token = strtok(mimobuf, ";");
13531 mimo = strtol(token, NULL, 10);
13532 WIFI_ENTRY_EXIT_DEBUG("%s:ofdma=%d,mimo=%d\n", __func__, ofdma, mimo);
13533 if ((ofdma == 1) && (mimo == 1))
13534 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
13535 else if ((ofdma == 0) && (mimo == 1))
13536 *mu_type = WIFI_DL_MU_TYPE_MIMO;
13537 else if ((ofdma == 1) && (mimo == 0))
13538 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
13539 else
13540 *mu_type = WIFI_DL_MU_TYPE_NONE;
developer72fb0bb2023-01-11 09:46:29 +080013541 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13542 return RETURN_OK;
13543}
13544
13545INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
13546{
13547 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
developera1255e42023-05-13 17:45:02 +080013548 UCHAR dat_file[64] = {0};
13549 wifi_band band = band_invalid;
developera1255e42023-05-13 17:45:02 +080013550 char ofdmabuf[32] = {'\0'};
13551 char mimobuf[32] = {'\0'};
13552 char new_ofdmabuf[32] = {'\0'};
13553 char new_mimobuf[32] = {'\0'};
13554 struct params params[2];
13555 char *str_zero = "0;0;0;0;0;0;0;0;0;0;0;0;0;0;0";/*default 15bss per band.*/
13556 char *str_one = "1;1;1;1;1;1;1;1;1;1;1;1;1;1;1";
13557 UCHAR bss_cnt = 0;
13558 UCHAR val_cnt = 0;
developer72fb0bb2023-01-11 09:46:29 +080013559
developera1255e42023-05-13 17:45:02 +080013560 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13561 band = wifi_index_to_band(radio_index);
13562 if (band == band_invalid) {
13563 printf("%s:Band Error\n", __func__);
13564 return RETURN_ERR;
13565 }
13566 if ((mu_type < WIFI_UL_MU_TYPE_NONE)
13567 || (mu_type > WIFI_UL_MU_TYPE_OFDMA)) {
13568 printf("%s:mu_type input Error\n", __func__);
13569 return RETURN_ERR;
13570 }
13571 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
13572 /*get current value in dat file*/
13573 wifi_datfileRead(dat_file, "MuOfdmaUlEnable", ofdmabuf, sizeof(ofdmabuf));
13574 wifi_datfileRead(dat_file, "MuMimoUlEnable", mimobuf, sizeof(mimobuf));
13575 WIFI_ENTRY_EXIT_DEBUG("%s:ofdma-%s, mimo-%s\n", __func__, ofdmabuf, mimobuf);
13576 get_bssnum_byindex(radio_index, &bss_cnt);
13577 val_cnt = 2*bss_cnt - 1;
13578 printf("bssNumber:%d,ValCnt:%d\n", bss_cnt, val_cnt);
13579 if ((val_cnt >= sizeof(new_ofdmabuf))
13580 || (val_cnt >= sizeof(new_mimobuf))) {
13581 printf("%s:bss cnt Error\n", __func__, val_cnt);
13582 return RETURN_ERR;
13583 }
13584 /*translate set value*/
13585 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
13586 strncpy(new_ofdmabuf, str_zero, val_cnt);
13587 strncpy(new_mimobuf, str_zero, val_cnt);
developer72fb0bb2023-01-11 09:46:29 +080013588 }
developera1255e42023-05-13 17:45:02 +080013589 if (mu_type == WIFI_UL_MU_TYPE_OFDMA) {
13590 strncpy(new_ofdmabuf, str_one, val_cnt);
13591 strncpy(new_mimobuf, str_zero, val_cnt);
13592 }
13593 printf("%s:new_ofdmabuf-%s, new_mimobuf-%s\n", __func__, new_ofdmabuf, new_mimobuf);
13594 /*same value, not operation*/
13595 if ((strncmp(new_mimobuf, mimobuf, 1) ==0)
13596 && (strncmp(new_ofdmabuf, ofdmabuf, 1) ==0)) {
13597 printf("%s:Reduntant value\n", __func__);
13598 return RETURN_OK;
13599 }
13600 /*modify dat file to new file*/
13601 params[0].name="MuOfdmaUlEnable";
13602 params[0].value=new_ofdmabuf;
13603 params[1].name="MuMimoUlEnable";
13604 params[1].value=new_mimobuf;
13605 wifi_datfileWrite(dat_file, params, 2);
13606 wifi_reloadAp(radio_index);
developer72fb0bb2023-01-11 09:46:29 +080013607 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13608 return RETURN_OK;
13609}
13610
13611INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
13612{
developera1255e42023-05-13 17:45:02 +080013613 UCHAR dat_file[64] = {0};
13614 wifi_band band = band_invalid;
13615 char ofdmabuf[32] = {'\0'};
13616 char mimobuf[32] = {'\0'};
13617 char *token = NULL;
13618 UCHAR ofdma = 0;
13619 UCHAR mimo = 0;
developer72fb0bb2023-01-11 09:46:29 +080013620
13621 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13622
13623 if (mu_type == NULL)
13624 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +080013625 band = wifi_index_to_band(radio_index);
13626 if (band == band_invalid) {
13627 printf("%s:Band Error", __func__);
13628 return RETURN_ERR;
13629 }
13630 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
13631 /*get current value in dat file*/
13632 wifi_datfileRead(dat_file, "MuOfdmaUlEnable", ofdmabuf, sizeof(ofdmabuf));
13633 wifi_datfileRead(dat_file, "MuMimoUlEnable", mimobuf, sizeof(mimobuf));
developer72fb0bb2023-01-11 09:46:29 +080013634
developera1255e42023-05-13 17:45:02 +080013635 token = strtok(ofdmabuf, ";");
13636 ofdma = strtol(token, NULL, 10);
13637 token = strtok(mimobuf, ";");
13638 mimo = strtol(token, NULL, 10);
13639 WIFI_ENTRY_EXIT_DEBUG("%s:ofdma=%d, mimo=%d\n", __func__, ofdma, mimo);
13640 if ((ofdma == 1) && (mimo == 0))
13641 *mu_type = WIFI_UL_MU_TYPE_OFDMA;
13642 else
13643 *mu_type = WIFI_UL_MU_TYPE_NONE;
developer72fb0bb2023-01-11 09:46:29 +080013644 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13645 return RETURN_OK;
13646}
13647
13648
13649INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
13650{
13651 char cmd[128] = {0};
13652 char buf[256] = {0};
13653 char config_file[64] = {0};
13654 char GI[8] = {0};
13655 int mode_map = 0;
13656 FILE *f = NULL;
13657 wifi_band band = band_invalid;
developera1255e42023-05-13 17:45:02 +080013658 char dat_file[64] = {'\0'};
13659 struct params params[3];
developer72fb0bb2023-01-11 09:46:29 +080013660
13661 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13662
13663 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
13664 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
13665 return RETURN_ERR;
13666 }
developera1255e42023-05-13 17:45:02 +080013667 /*sanity check*/
13668 if (((guard_interval == wifi_guard_interval_1600)
13669 || (guard_interval == wifi_guard_interval_3200))
developerdaf24792023-06-06 11:40:04 +080013670 && ((mode_map & (WIFI_MODE_BE | WIFI_MODE_AX)) == 0)) {
developera1255e42023-05-13 17:45:02 +080013671 wifi_dbg_printf("%s: N/AC Mode not support 1600/3200ns GI\n", __func__);
13672 return RETURN_ERR;
13673 }
developer72fb0bb2023-01-11 09:46:29 +080013674 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
13675 band = wifi_index_to_band(radio_index);
13676
13677 // Hostapd are not supported HE mode GI 1600, 3200 ns.
13678 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
13679 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
13680 _syscmd(cmd, buf, sizeof(buf));
13681 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
13682 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
13683 if (strstr(buf, "[SHORT-GI-") == NULL) {
13684 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[SHORT-GI-20][SHORT-GI-40]/' %s", config_file);
13685 _syscmd(cmd, buf, sizeof(buf));
13686 }
13687 if (band == band_5) {
13688 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
13689 if (strstr(buf, "[SHORT-GI-") == NULL) {
13690 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SHORT-GI-80][SHORT-GI-160]/' %s", config_file);
13691 _syscmd(cmd, buf, sizeof(buf));
13692 }
13693 }
13694 }
developera1255e42023-05-13 17:45:02 +080013695 /*wifi_reloadAp(radio_index);
13696 caller "wifi_setRadioOperatingParameters" have done this step.
13697 */
13698 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
13699 if (guard_interval == wifi_guard_interval_400) {
13700 params[0].name = "HT_GI";
13701 params[0].value = "1";
13702 params[1].name = "VHT_SGI";
13703 params[1].value = "1";
13704 wifi_datfileWrite(dat_file, params, 2);
developer72fb0bb2023-01-11 09:46:29 +080013705 strcpy(GI, "0.4");
developera1255e42023-05-13 17:45:02 +080013706 } else {
13707 params[0].name = "HT_GI";
13708 params[0].value = "0";
13709 params[1].name = "VHT_SGI";
13710 params[1].value = "0";
13711 /*should enable FIXED_HE_GI_SUPPORT in driver*/
13712 params[2].name = "FgiFltf";
13713 if (guard_interval == wifi_guard_interval_800) {
13714 params[2].value = "800";
13715 strcpy(GI, "0.8");
13716 } else if (guard_interval == wifi_guard_interval_1600) {
13717 params[2].value = "1600";
13718 strcpy(GI, "1.6");
13719 } else if (guard_interval == wifi_guard_interval_3200) {
13720 params[2].value = "3200";
13721 strcpy(GI, "3.2");
13722 } else if (guard_interval == wifi_guard_interval_auto) {
13723 params[2].value = "0";
13724 strcpy(GI, "auto");
13725 }
13726 wifi_datfileWrite(dat_file, params, 3);
13727 }
developer72fb0bb2023-01-11 09:46:29 +080013728 // Record GI for get GI function
13729 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
13730 f = fopen(buf, "w");
13731 if (f == NULL)
13732 return RETURN_ERR;
13733 fprintf(f, "%s", GI);
13734 fclose(f);
13735 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13736 return RETURN_OK;
13737}
13738
13739INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
13740{
13741 char buf[32] = {0};
13742 char cmd[64] = {0};
13743
13744 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13745
13746 if (guard_interval == NULL)
13747 return RETURN_ERR;
13748
developera1255e42023-05-13 17:45:02 +080013749 snprintf(cmd, sizeof(cmd), "cat %s%d.txt 2> /dev/null", GUARD_INTERVAL_FILE, radio_index);
developer72fb0bb2023-01-11 09:46:29 +080013750 _syscmd(cmd, buf, sizeof(buf));
13751
13752 if (strncmp(buf, "0.4", 3) == 0)
13753 *guard_interval = wifi_guard_interval_400;
13754 else if (strncmp(buf, "0.8", 3) == 0)
13755 *guard_interval = wifi_guard_interval_800;
13756 else if (strncmp(buf, "1.6", 3) == 0)
13757 *guard_interval = wifi_guard_interval_1600;
13758 else if (strncmp(buf, "3.2", 3) == 0)
13759 *guard_interval = wifi_guard_interval_3200;
13760 else
13761 *guard_interval = wifi_guard_interval_auto;
13762
13763 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13764 return RETURN_OK;
13765}
13766
13767INT wifi_setBSSColor(INT radio_index, UCHAR color)
13768{
13769 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13770 struct params params = {0};
13771 char config_file[128] = {0};
13772 char bss_color[4] ={0};
13773
developera1255e42023-05-13 17:45:02 +080013774 if (color < 1 || color > 63) {
13775 wifi_dbg_printf("color value is err:%d.\n", color);
13776 return RETURN_ERR;
13777 }
developer72fb0bb2023-01-11 09:46:29 +080013778 params.name = "he_bss_color";
13779 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
13780 params.value = bss_color;
13781 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
13782 wifi_hostapdWrite(config_file, &params, 1);
developera1255e42023-05-13 17:45:02 +080013783 //wifi_hostapdProcessUpdate(radio_index, &params, 1);
13784 wifi_reloadAp(radio_index);
developer69b61b02023-03-07 17:17:44 +080013785
developer72fb0bb2023-01-11 09:46:29 +080013786 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13787 return RETURN_OK;
13788}
13789
13790INT wifi_getBSSColor(INT radio_index, UCHAR *color)
13791{
13792 char config_file[128] = {0};
13793 char buf[64] = {0};
13794 char temp_output[128] = {'\0'};
13795
13796 wifi_dbg_printf("\nFunc=%s\n", __func__);
13797 if (NULL == color)
13798 return RETURN_ERR;
13799
13800 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
13801 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
13802
13803 if(strlen(buf) > 0) {
13804 snprintf(temp_output, sizeof(temp_output), "%s", buf);
13805 } else {
13806 snprintf(temp_output, sizeof(temp_output), "1"); // default value
13807 }
13808
13809 *color = (UCHAR)strtoul(temp_output, NULL, 10);
13810 wifi_dbg_printf("\noutput_string=%s\n", color);
13811
13812 return RETURN_OK;
13813}
13814
13815/* multi-psk support */
13816INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
13817{
13818 char cmd[256];
13819 char interface_name[16] = {0};
13820
13821 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
13822 return RETURN_ERR;
13823
13824 sprintf(cmd, "hostapd_cli -i %s sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
13825 interface_name,
13826 mac[0],
13827 mac[1],
13828 mac[2],
13829 mac[3],
13830 mac[4],
13831 mac[5]
13832 );
13833 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
13834 _syscmd(cmd, key->wifi_keyId, 64);
13835
13836
13837 return RETURN_OK;
13838}
13839
13840INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
13841{
13842 char interface_name[16] = {0};
13843 FILE *fd = NULL;
13844 char fname[100];
13845 char cmd[128] = {0};
13846 char out[64] = {0};
13847 wifi_key_multi_psk_t * key = NULL;
13848 if(keysNumber < 0)
13849 return RETURN_ERR;
13850
13851 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
13852 fd = fopen(fname, "w");
13853 if (!fd) {
13854 return RETURN_ERR;
13855 }
13856 key= (wifi_key_multi_psk_t *) keys;
13857 for(int i=0; i<keysNumber; ++i, key++) {
13858 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
13859 }
13860 fclose(fd);
13861
13862 //reload file
13863 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
13864 return RETURN_ERR;
13865 sprintf(cmd, "hostapd_cli -i%s raw RELOAD_WPA_PSK", interface_name);
13866 _syscmd(cmd, out, 64);
13867 return RETURN_OK;
13868}
13869
13870INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
13871{
13872 FILE *fd = NULL;
13873 char fname[100];
13874 char * line = NULL;
13875 char * pos = NULL;
13876 size_t len = 0;
13877 ssize_t read = 0;
13878 INT ret = RETURN_OK;
13879 wifi_key_multi_psk_t *keys_it = NULL;
13880
13881 if (keysNumber < 1) {
13882 return RETURN_ERR;
13883 }
13884
13885 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
13886 fd = fopen(fname, "r");
13887 if (!fd) {
13888 return RETURN_ERR;
13889 }
13890
13891 if (keys == NULL) {
13892 ret = RETURN_ERR;
13893 goto close;
13894 }
13895
13896 keys_it = keys;
13897 while ((read = getline(&line, &len, fd)) != -1) {
13898 //Strip trailing new line if present
13899 if (read > 0 && line[read-1] == '\n') {
13900 line[read-1] = '\0';
13901 }
13902
13903 if(strcmp(line,"keyid=")) {
developerdaf24792023-06-06 11:40:04 +080013904 sscanf(line, "keyid=%s", keys_it->wifi_keyId);
developer72fb0bb2023-01-11 09:46:29 +080013905 if (!(pos = index(line, ' '))) {
13906 ret = RETURN_ERR;
13907 goto close;
13908 }
13909 pos++;
13910 //Here should be 00:00:00:00:00:00
13911 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
13912 printf("Not supported MAC: %s\n", pos);
13913 }
13914 if (!(pos = index(pos, ' '))) {
13915 ret = RETURN_ERR;
13916 goto close;
13917 }
13918 pos++;
13919
13920 //The rest is PSK
13921 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
13922 keys_it++;
13923
13924 if(--keysNumber <= 0)
13925 break;
13926 }
13927 }
13928
13929close:
13930 free(line);
13931 fclose(fd);
13932 return ret;
13933}
13934/* end of multi-psk support */
13935
13936INT wifi_setNeighborReports(UINT apIndex,
13937 UINT numNeighborReports,
13938 wifi_NeighborReport_t *neighborReports)
13939{
13940 char cmd[256] = { 0 };
13941 char hex_bssid[13] = { 0 };
13942 char bssid[18] = { 0 };
13943 char nr[256] = { 0 };
13944 char ssid[256];
13945 char hex_ssid[256];
13946 char interface_name[16] = {0};
13947 INT ret;
13948
13949 /*rmeove all neighbors*/
13950 wifi_dbg_printf("\n[%s]: removing all neighbors from %s\n", __func__, interface_name);
13951 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
13952 return RETURN_ERR;
13953 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);
13954 system(cmd);
13955
13956 for(unsigned int i = 0; i < numNeighborReports; i++)
13957 {
13958 memset(ssid, 0, sizeof(ssid));
13959 ret = wifi_getSSIDName(apIndex, ssid);
13960 if (ret != RETURN_OK)
13961 return RETURN_ERR;
13962
13963 memset(hex_ssid, 0, sizeof(hex_ssid));
13964 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
13965 sprintf(hex_ssid + k,"%02x", ssid[j]);
13966
13967 snprintf(hex_bssid, sizeof(hex_bssid),
13968 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
13969 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
13970 snprintf(bssid, sizeof(bssid),
13971 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
13972 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
13973
13974 snprintf(nr, sizeof(nr),
13975 "%s" // bssid
13976 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
13977 "%02hhx" // operclass
13978 "%02hhx" // channel
13979 "%02hhx", // phy_mode
13980 hex_bssid,
13981 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
13982 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
13983 neighborReports[i].opClass,
13984 neighborReports[i].channel,
13985 neighborReports[i].phyTable);
13986
13987 snprintf(cmd, sizeof(cmd),
13988 "hostapd_cli set_neighbor "
13989 "%s " // bssid
13990 "ssid=%s " // ssid
13991 "nr=%s " // nr
13992 "-i %s",
13993 bssid,hex_ssid,nr, interface_name);
13994
13995 if (WEXITSTATUS(system(cmd)) != 0)
13996 {
13997 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
13998 }
13999 }
14000
14001 return RETURN_OK;
14002}
14003
14004INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
14005{
14006 return RETURN_OK;
14007}
14008
14009#ifdef _WIFI_HAL_TEST_
14010int main(int argc,char **argv)
14011{
14012 int index;
14013 INT ret=0;
14014 char buf[1024]="";
14015
14016 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
14017 if(argc<3)
14018 {
14019 if(argc==2)
14020 {
14021 if(!strcmp(argv[1], "init"))
14022 return wifi_init();
14023 if(!strcmp(argv[1], "reset"))
14024 return wifi_reset();
14025 if(!strcmp(argv[1], "wifi_getHalVersion"))
14026 {
14027 char buffer[64];
14028 if(wifi_getHalVersion(buffer)==RETURN_OK)
14029 printf("Version: %s\n", buffer);
14030 else
14031 printf("Error in wifi_getHalVersion\n");
14032 return RETURN_OK;
14033 }
14034 }
14035 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
14036 exit(-1);
14037 }
14038
14039 index = atoi(argv[2]);
14040 if(strstr(argv[1], "wifi_getApName")!=NULL)
14041 {
14042 wifi_getApName(index,buf);
14043 printf("Ap name is %s \n",buf);
14044 return 0;
14045 }
developerfead3972023-05-25 20:15:02 +080014046 if(strstr(argv[1], "wifi_setRadioMode")!=NULL)
14047 {
14048 UINT pureMode = atoi(argv[3]);
14049
14050 wifi_setRadioMode(index, NULL, pureMode);
14051 printf("Ap SET Radio mode 0x%x\n", pureMode);
14052 return 0;
14053 }
14054 if(strstr(argv[1], "wifi_setRadioTransmitPower")!=NULL)
14055 {
14056 ULONG TransmitPower = atoi(argv[3]);
14057
14058 wifi_setRadioTransmitPower(index, TransmitPower);
14059 printf("Ap SET TransmitPower %lu\n", TransmitPower);
14060 return 0;
14061 }
14062 if(strstr(argv[1], "wifi_setApManagementFramePowerControl")!=NULL)
14063 {
14064 INT TransmitPower = atoi(argv[3]);
14065
14066 wifi_setApManagementFramePowerControl(index, TransmitPower);
14067 printf("Ap SET Mgnt TransmitPower %d\n", TransmitPower);
14068 return 0;
14069 }
14070 if(strstr(argv[1], "wifi_setRadioBW")!=NULL)
14071 {
14072 CHAR *bandwith = argv[3];
14073
14074 wifi_setRadioOperatingChannelBandwidth(index, bandwith);
14075 printf("Ap SET bw %s\n", bandwith);
14076 return 0;
14077 }
14078 if(strstr(argv[1], "wifi_factoryResetRadio")!=NULL)
14079 {
14080 wifi_factoryResetRadio(index);
14081 printf("wifi_factoryResetRadio ok!\n");
14082 return 0;
14083 }
14084 if(strstr(argv[1], "wifi_getRadioResetCount")!=NULL)
14085 {
14086 ULONG rst_cnt;
14087 wifi_getRadioResetCount(index, &rst_cnt);
14088 printf("wifi_factoryResetRadio rst_cnt = %lu\n", rst_cnt);
14089 return 0;
14090 }
developer2edaf012023-05-24 14:24:53 +080014091 if (strncmp(argv[1], "wifi_addApAclDevice", strlen(argv[1])) == 0) {
developer49b17232023-05-19 16:35:19 +080014092 if(argc <= 3 )
14093 {
developer2edaf012023-05-24 14:24:53 +080014094 wifi_debug(DEBUG_ERROR, "Insufficient arguments \n");
developer49b17232023-05-19 16:35:19 +080014095 exit(-1);
14096 }
14097 wifi_addApAclDevice(index, argv[3]);
14098 return 0;
14099 }
developer2edaf012023-05-24 14:24:53 +080014100 if (strncmp(argv[1], "wifi_getApAclDevices", strlen(argv[1])) == 0) {
14101 wifi_getApAclDevices(index, buf, 1024);
14102 wifi_debug(DEBUG_NOTICE, "Ap acl Devices: %s\n", buf);
developer121a8e72023-05-22 09:19:39 +080014103 return 0;
14104 }
developer2edaf012023-05-24 14:24:53 +080014105 if (strncmp(argv[1], "wifi_delApAclDevice", strlen(argv[1])) == 0) {
14106 if(argc <= 3 )
14107 {
14108 wifi_debug(DEBUG_ERROR, "Insufficient arguments \n");
14109 exit(-1);
14110 }
14111 wifi_delApAclDevice(index, argv[3]);
14112 return 0;
14113 }
14114 if (strncmp(argv[1], "wifi_delApAclDevices", strlen(argv[1])) == 0) {
14115 wifi_delApAclDevices(index);
14116 return 0;
14117 }
14118 if (strncmp(argv[1], "wifi_getApAclDeviceNum", strlen(argv[1])) == 0) {
14119 int acl_num = 0;
14120 wifi_getApAclDeviceNum(index, &acl_num);
14121 wifi_debug(DEBUG_NOTICE, "Ap acl numbers: %d\n", acl_num);
14122 return 0;
14123 }
14124 if (strncmp(argv[1], "wifi_getApDenyAclDevices", strlen(argv[1])) == 0) {
14125 wifi_getApDenyAclDevices(index, buf, 1024);
14126 wifi_debug(DEBUG_NOTICE, "Ap Deny Acl Devices: %s\n", buf);
14127 return 0;
14128 }
14129 if (strncmp(argv[1], "wifi_setApMacAddressControlMode", strlen(argv[1])) == 0) {
14130 int filter_mode = 0;
14131 if(argc <= 3 )
14132 {
14133 wifi_debug(DEBUG_ERROR, "Insufficient arguments \n");
14134 exit(-1);
14135 }
14136 filter_mode = atoi(argv[3]);
14137 wifi_setApMacAddressControlMode(index,filter_mode);
14138 return 0;
14139 }
developer5cd4c862023-05-26 09:34:42 +080014140 if (strncmp(argv[1], "wifi_getRadioDeclineBARequestEnable", strlen(argv[1])) == 0) {
14141 BOOL output_bool = 0;
14142 wifi_getRadioDeclineBARequestEnable(index, &output_bool);
14143 wifi_debug(DEBUG_NOTICE, "Ap get radio ba decline enable: %d\n", output_bool);
14144 return 0;
14145 }
14146 if (strncmp(argv[1], "wifi_getRadioAutoBlockAckEnable", strlen(argv[1])) == 0) {
14147 BOOL output_bool = 0;
14148 wifi_getRadioAutoBlockAckEnable(index, &output_bool);
14149 wifi_debug(DEBUG_NOTICE, "Ap get radio auto_ba enable: %d\n", output_bool);
14150 return 0;
14151 }
14152
14153 if (strncmp(argv[1], "wifi_getApMacAddressControlMode", strlen(argv[1])) == 0) {
14154 int filter_mode = 0;
14155 wifi_getApMacAddressControlMode(index, &filter_mode);
14156 wifi_debug(DEBUG_NOTICE, "Ap MacAddress Control Mode: %d\n", filter_mode);
14157 return 0;
14158 }
14159 if (strncmp(argv[1], "wifi_setRadioIGMPSnoopingEnable", strlen(argv[1])) == 0) {
14160 int enable = 0;
14161 if(argc <= 3 )
14162 {
14163 wifi_debug(DEBUG_ERROR, "Insufficient arguments \n");
14164 exit(-1);
14165 }
14166 enable = (BOOL)atoi(argv[3]);
14167 wifi_setRadioIGMPSnoopingEnable(index, enable);
14168 wifi_debug(DEBUG_NOTICE, "Ap set IGMP Snooping Enable: %d\n", enable);
14169 return 0;
14170 }
14171
14172 if (strncmp(argv[1], "wifi_getRadioIGMPSnoopingEnable", strlen(argv[1])) == 0) {
14173 BOOL out_status = 0;
14174 wifi_getRadioIGMPSnoopingEnable(index, &out_status);
14175 wifi_debug(DEBUG_NOTICE, "Ap get IGMP Snooping Enable: %d\n", out_status);
14176 return 0;
14177 }
developer121a8e72023-05-22 09:19:39 +080014178
developer95c045d2023-05-24 19:26:28 +080014179 if (strncmp(argv[1], "wifi_setApWmmEnable", strlen(argv[1])) == 0) {
14180 int enable = 0;
14181 if(argc <= 3)
14182 {
14183 wifi_debug(DEBUG_ERROR, "Insufficient arguments \n");
14184 exit(-1);
14185 }
14186 enable = atoi(argv[3]);
14187 wifi_setApWmmEnable(index,enable);
14188 return 0;
14189 }
developer56fbedb2023-05-30 16:47:05 +080014190 if (strncmp(argv[1], "wifi_down", strlen(argv[1])) == 0) {
14191 wifi_down();
14192 return 0;
14193 }
developer95c045d2023-05-24 19:26:28 +080014194
developer56fbedb2023-05-30 16:47:05 +080014195 if (strncmp(argv[1], "wifi_getRadioStatus", strlen(argv[1])) == 0) {
14196 BOOL enable = 0;
14197
14198 wifi_getRadioStatus(index, &enable);
14199 wifi_debug(DEBUG_NOTICE, "wifi_getRadioStatus enable: %d\n", (int)enable);
14200 return 0;
14201 }
developer333c1eb2023-05-31 14:59:39 +080014202
developer95c045d2023-05-24 19:26:28 +080014203 if (strncmp(argv[1], "wifi_getApWMMCapability", strlen(argv[1])) == 0) {
14204 BOOL enable = 0;
14205
14206 wifi_getApWMMCapability(index, &enable);
14207 wifi_debug(DEBUG_NOTICE, "wifi_getApWMMCapability enable: %d\n", (int)enable);
14208 return 0;
14209 }
14210
14211 if (strncmp(argv[1], "wifi_getApWmmEnable", strlen(argv[1])) == 0) {
14212 BOOL enable = 0;
14213
14214 wifi_getApWmmEnable(index, &enable);
14215 wifi_debug(DEBUG_NOTICE, "wifi_getApWmmEnable enable: %d\n", (int)enable);
14216 return 0;
14217 }
14218
developer2edaf012023-05-24 14:24:53 +080014219 if (strncmp(argv[1], "wifi_getApMacAddressControlMode", strlen(argv[1])) == 0) {
14220 int filter_mode = 0;
14221 wifi_getApMacAddressControlMode(index, &filter_mode);
14222 wifi_debug(DEBUG_NOTICE, "Ap MacAddress Control Mode: %d\n", filter_mode);
14223 return 0;
14224 }
developer0f10c772023-05-16 21:43:39 +080014225 if(strstr(argv[1], "wifi_getRadioMode")!=NULL)
14226 {
14227 int mode = 0;
14228
14229 wifi_getRadioMode(index, buf, &mode);
14230 printf("Ap Radio mode is %s , mode = 0x%x\n", buf, mode);
14231 return 0;
14232 }
developer72fb0bb2023-01-11 09:46:29 +080014233 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
14234 {
14235 BOOL b = FALSE;
14236 BOOL *output_bool = &b;
14237 wifi_getRadioAutoChannelEnable(index,output_bool);
14238 printf("Channel enabled = %d \n",b);
14239 return 0;
14240 }
14241 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
14242 {
14243 wifi_getApWpaEncryptionMode(index,buf);
14244 printf("encryption enabled = %s\n",buf);
14245 return 0;
14246 }
14247 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
14248 {
14249 BOOL b = FALSE;
14250 BOOL *output_bool = &b;
14251 wifi_getApSsidAdvertisementEnable(index,output_bool);
14252 printf("advertisment enabled = %d\n",b);
14253 return 0;
14254 }
14255 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
14256 {
14257 if(argc <= 3 )
14258 {
14259 printf("Insufficient arguments \n");
14260 exit(-1);
14261 }
14262
14263 char sta[20] = {'\0'};
14264 ULLONG handle= 0;
14265 strcpy(sta,argv[3]);
14266 mac_address_t st;
14267 mac_addr_aton(st,sta);
14268
14269 wifi_associated_dev_tid_stats_t tid_stats;
14270 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
14271 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
14272 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);
14273 }
14274
14275 if(strstr(argv[1], "getApEnable")!=NULL) {
14276 BOOL enable;
14277 ret=wifi_getApEnable(index, &enable);
14278 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
14279 }
14280 else if(strstr(argv[1], "setApEnable")!=NULL) {
14281 BOOL enable = atoi(argv[3]);
14282 ret=wifi_setApEnable(index, enable);
14283 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
14284 }
14285 else if(strstr(argv[1], "getApStatus")!=NULL) {
developer69b61b02023-03-07 17:17:44 +080014286 char status[64];
developer72fb0bb2023-01-11 09:46:29 +080014287 ret=wifi_getApStatus(index, status);
14288 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
14289 }
14290 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
14291 {
14292 wifi_getSSIDNameStatus(index,buf);
14293 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
14294 return 0;
developer2202b332023-05-24 16:23:22 +080014295 } else if(strstr(argv[1], "wifi_resetApVlanCfg")!=NULL) {
14296 wifi_resetApVlanCfg(index);
14297 printf("%s %d: wifi_resetApVlanCfg : %s\n",argv[1], index,buf);
14298 return 0;
developer72fb0bb2023-01-11 09:46:29 +080014299 }
14300 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
14301 wifi_ssidTrafficStats2_t stats={0};
14302 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
14303 printf("%s %d: returns %d\n", argv[1], index, ret);
14304 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
14305 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
14306 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
14307 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
14308 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
14309 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
14310 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
14311 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
14312 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
14313 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
14314 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
14315 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
14316 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
14317 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
14318 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
14319 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
14320 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
14321 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
14322 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
14323 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
14324 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
14325 }
14326 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
14327 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
14328 UINT array_size=0;
14329 UINT i=0;
14330 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
14331 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
developer69b61b02023-03-07 17:17:44 +080014332 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
developer72fb0bb2023-01-11 09:46:29 +080014333 printf(" neighbor %d:\n", i);
14334 printf(" ap_SSID =%s\n", pt->ap_SSID);
14335 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
14336 printf(" ap_Mode =%s\n", pt->ap_Mode);
14337 printf(" ap_Channel =%d\n", pt->ap_Channel);
14338 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
14339 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
14340 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
14341 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
14342 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
14343 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
14344 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
14345 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
14346 printf(" ap_Noise =%d\n", pt->ap_Noise);
14347 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
14348 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
14349 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
developer69b61b02023-03-07 17:17:44 +080014350 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
developer72fb0bb2023-01-11 09:46:29 +080014351 }
14352 if(neighbor_ap_array)
14353 free(neighbor_ap_array); //make sure to free the list
14354 }
14355 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
14356 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
14357 UINT array_size=0;
14358 UINT i=0;
14359 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
14360 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
developer69b61b02023-03-07 17:17:44 +080014361 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
developer72fb0bb2023-01-11 09:46:29 +080014362 printf(" associated_dev %d:\n", i);
14363 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
14364 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
14365 printf(" cli_SNR =%d\n", pt->cli_SNR);
14366 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
14367 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
14368 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
14369 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
14370 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
14371 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
14372 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
14373 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
14374 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
14375 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
14376 }
14377 if(associated_dev_array)
14378 free(associated_dev_array); //make sure to free the list
14379 }
14380
14381 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
14382 {
14383#define MAX_ARRAY_SIZE 64
14384 int i, array_size;
14385 char *p, *ch_str;
14386 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
14387
14388 if(argc != 5)
14389 {
14390 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
14391 exit(-1);
14392 }
14393 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
14394
14395 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
14396 {
14397 strtok_r(ch_str, ",", &p);
14398 input_output_channelStats_array[i].ch_number = atoi(ch_str);
14399 }
14400 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
14401 if(!array_size)
14402 array_size=1;//Need to print current channel statistics
14403 for(i=0; i<array_size; i++)
14404 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
14405 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
14406 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
14407 input_output_channelStats_array[i].ch_number,\
14408 input_output_channelStats_array[i].ch_noise,\
14409 input_output_channelStats_array[i].ch_utilization_busy_rx,\
14410 input_output_channelStats_array[i].ch_utilization_busy_tx,\
14411 input_output_channelStats_array[i].ch_utilization_busy,\
14412 input_output_channelStats_array[i].ch_utilization_busy_ext,\
14413 input_output_channelStats_array[i].ch_utilization_total);
14414 }
14415
14416 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
14417 {
14418 if(argc <= 3 )
14419 {
14420 printf("Insufficient arguments \n");
14421 exit(-1);
14422 }
14423 char mac_addr[20] = {'\0'};
14424 wifi_device_t output_struct;
14425 int dev_index = atoi(argv[3]);
14426
14427 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
14428 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
14429 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);
14430 }
14431
14432 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
14433 {
14434 if (argc <= 3)
14435 {
14436 printf("Insufficient arguments\n");
14437 exit(-1);
14438 }
14439 char args[256];
14440 wifi_NeighborReport_t *neighborReports;
14441
14442 neighborReports = calloc(argc - 2, sizeof(neighborReports));
14443 if (!neighborReports)
14444 {
14445 printf("Failed to allocate memory");
14446 exit(-1);
14447 }
14448
14449 for (int i = 3; i < argc; ++i)
14450 {
14451 char *val;
14452 int j = 0;
14453 memset(args, 0, sizeof(args));
14454 strncpy(args, argv[i], sizeof(args));
14455 val = strtok(args, ";");
14456 while (val != NULL)
14457 {
14458 if (j == 0)
14459 {
14460 mac_addr_aton(neighborReports[i - 3].bssid, val);
14461 } else if (j == 1)
14462 {
14463 neighborReports[i - 3].info = strtol(val, NULL, 16);
14464 } else if (j == 2)
14465 {
14466 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
14467 } else if (j == 3)
14468 {
14469 neighborReports[i - 3].channel = strtol(val, NULL, 16);
14470 } else if (j == 4)
14471 {
14472 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
14473 } else {
14474 printf("Insufficient arguments]n\n");
14475 exit(-1);
14476 }
14477 val = strtok(NULL, ";");
14478 j++;
14479 }
14480 }
14481
14482 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
14483 if (ret != RETURN_OK)
14484 {
14485 printf("wifi_setNeighborReports ret = %d", ret);
14486 exit(-1);
14487 }
14488 }
14489 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
14490 {
14491 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
14492 printf("%s.\n", buf);
14493 else
14494 printf("Error returned\n");
14495 }
14496 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
14497 {
14498 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
14499 printf("%s.\n", buf);
14500 else
14501 printf("Error returned\n");
14502 }
14503 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
14504 {
14505 if (argc <= 2)
14506 {
14507 printf("Insufficient arguments\n");
14508 exit(-1);
14509 }
14510 char buf[64]= {'\0'};
14511 wifi_getRadioOperatingChannelBandwidth(index,buf);
14512 printf("Current bandwidth is %s \n",buf);
14513 return 0;
14514 }
14515 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
14516 {
14517 if (argc <= 5)
14518 {
14519 printf("Insufficient arguments\n");
14520 exit(-1);
14521 }
14522 UINT channel = atoi(argv[3]);
14523 UINT width = atoi(argv[4]);
14524 UINT beacon = atoi(argv[5]);
14525 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
14526 printf("Result = %d", ret);
14527 }
14528
14529 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
14530 return 0;
14531}
14532
14533#endif
14534
14535#ifdef WIFI_HAL_VERSION_3
14536
14537INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
14538{
14539 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
14540 if (bitMap & WIFI_BITRATE_1MBPS)
14541 strcat(BasicRate, "1,");
14542 if (bitMap & WIFI_BITRATE_2MBPS)
14543 strcat(BasicRate, "2,");
14544 if (bitMap & WIFI_BITRATE_5_5MBPS)
14545 strcat(BasicRate, "5.5,");
14546 if (bitMap & WIFI_BITRATE_6MBPS)
14547 strcat(BasicRate, "6,");
14548 if (bitMap & WIFI_BITRATE_9MBPS)
14549 strcat(BasicRate, "9,");
14550 if (bitMap & WIFI_BITRATE_11MBPS)
14551 strcat(BasicRate, "11,");
14552 if (bitMap & WIFI_BITRATE_12MBPS)
14553 strcat(BasicRate, "12,");
14554 if (bitMap & WIFI_BITRATE_18MBPS)
14555 strcat(BasicRate, "18,");
14556 if (bitMap & WIFI_BITRATE_24MBPS)
14557 strcat(BasicRate, "24,");
14558 if (bitMap & WIFI_BITRATE_36MBPS)
14559 strcat(BasicRate, "36,");
14560 if (bitMap & WIFI_BITRATE_48MBPS)
14561 strcat(BasicRate, "48,");
14562 if (bitMap & WIFI_BITRATE_54MBPS)
14563 strcat(BasicRate, "54,");
14564 if (strlen(BasicRate) != 0) // remove last comma
14565 BasicRate[strlen(BasicRate) - 1] = '\0';
14566 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
14567 return RETURN_OK;
14568}
14569
14570INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
14571{
14572 UINT BitMap = 0;
14573 char *rate;
14574
14575 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
14576 rate = strtok(BasicRatesList, ",");
14577 while(rate != NULL)
14578 {
14579 if (strcmp(rate, "1") == 0)
14580 BitMap |= WIFI_BITRATE_1MBPS;
14581 else if (strcmp(rate, "2") == 0)
14582 BitMap |= WIFI_BITRATE_2MBPS;
14583 else if (strcmp(rate, "5.5") == 0)
14584 BitMap |= WIFI_BITRATE_5_5MBPS;
14585 else if (strcmp(rate, "6") == 0)
14586 BitMap |= WIFI_BITRATE_6MBPS;
14587 else if (strcmp(rate, "9") == 0)
14588 BitMap |= WIFI_BITRATE_9MBPS;
14589 else if (strcmp(rate, "11") == 0)
14590 BitMap |= WIFI_BITRATE_11MBPS;
14591 else if (strcmp(rate, "12") == 0)
14592 BitMap |= WIFI_BITRATE_12MBPS;
14593 else if (strcmp(rate, "18") == 0)
14594 BitMap |= WIFI_BITRATE_18MBPS;
14595 else if (strcmp(rate, "24") == 0)
14596 BitMap |= WIFI_BITRATE_24MBPS;
14597 else if (strcmp(rate, "36") == 0)
14598 BitMap |= WIFI_BITRATE_36MBPS;
14599 else if (strcmp(rate, "48") == 0)
14600 BitMap |= WIFI_BITRATE_48MBPS;
14601 else if (strcmp(rate, "54") == 0)
14602 BitMap |= WIFI_BITRATE_54MBPS;
14603 rate = strtok(NULL, ",");
14604 }
14605 *basicRateBitMap = BitMap;
14606 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
14607 return RETURN_OK;
14608}
14609
14610// This API is used to configured all radio operation parameter in a single set. it includes channel number, channelWidth, mode and auto chammel configuration.
14611INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
14612{
14613 char buf[128] = {0};
developerdaf24792023-06-06 11:40:04 +080014614 int bandwidth = 20;
developer72fb0bb2023-01-11 09:46:29 +080014615 int set_mode = 0;
developer56fbedb2023-05-30 16:47:05 +080014616 BOOL drv_dat_change = 0, hapd_conf_change = 0;
developer72fb0bb2023-01-11 09:46:29 +080014617 wifi_radio_operationParam_t current_param;
14618
14619 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
14620
14621 multiple_set = TRUE;
14622 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
14623 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
14624 return RETURN_ERR;
14625 }
14626 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
14627 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
14628 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
14629 return RETURN_ERR;
14630 }
developer333c1eb2023-05-31 14:59:39 +080014631 drv_dat_change = TRUE;
developer72fb0bb2023-01-11 09:46:29 +080014632 }
developer333c1eb2023-05-31 14:59:39 +080014633 if (current_param.channelWidth != operationParam->channelWidth ||
14634 current_param.channel != operationParam->channel ||
14635 current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
14636 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
14637 bandwidth = 20;
14638 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
14639 bandwidth = 40;
14640 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
14641 bandwidth = 80;
14642 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
14643 bandwidth = 160;
developer72fb0bb2023-01-11 09:46:29 +080014644
developer333c1eb2023-05-31 14:59:39 +080014645 if (operationParam->autoChannelEnabled) {
14646 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
14647 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
14648 return RETURN_ERR;
14649 }
14650 } else {
14651 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
14652 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
14653 return RETURN_ERR;
14654 }
developer72fb0bb2023-01-11 09:46:29 +080014655 }
developer333c1eb2023-05-31 14:59:39 +080014656 drv_dat_change = TRUE;
developer72fb0bb2023-01-11 09:46:29 +080014657 }
developer72fb0bb2023-01-11 09:46:29 +080014658 if (current_param.variant != operationParam->variant) {
14659 // Two different definition bit map, so need to check every bit.
14660 if (operationParam->variant & WIFI_80211_VARIANT_A)
14661 set_mode |= WIFI_MODE_A;
14662 if (operationParam->variant & WIFI_80211_VARIANT_B)
14663 set_mode |= WIFI_MODE_B;
14664 if (operationParam->variant & WIFI_80211_VARIANT_G)
14665 set_mode |= WIFI_MODE_G;
14666 if (operationParam->variant & WIFI_80211_VARIANT_N)
14667 set_mode |= WIFI_MODE_N;
14668 if (operationParam->variant & WIFI_80211_VARIANT_AC)
14669 set_mode |= WIFI_MODE_AC;
14670 if (operationParam->variant & WIFI_80211_VARIANT_AX)
14671 set_mode |= WIFI_MODE_AX;
14672 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
14673 memset(buf, 0, sizeof(buf));
developer56fbedb2023-05-30 16:47:05 +080014674 drv_dat_change = TRUE;
developer0f10c772023-05-16 21:43:39 +080014675 if (wifi_setRadioMode_by_dat(index, set_mode) != RETURN_OK) {
developer72fb0bb2023-01-11 09:46:29 +080014676 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
14677 return RETURN_ERR;
14678 }
14679 }
14680 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
developer56fbedb2023-05-30 16:47:05 +080014681 hapd_conf_change = TRUE;
developer72fb0bb2023-01-11 09:46:29 +080014682 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
14683 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
14684 return RETURN_ERR;
14685 }
14686 }
14687 if (current_param.beaconInterval != operationParam->beaconInterval) {
developer56fbedb2023-05-30 16:47:05 +080014688 hapd_conf_change = TRUE;
developer72fb0bb2023-01-11 09:46:29 +080014689 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
14690 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
14691 return RETURN_ERR;
14692 }
14693 }
14694 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
developer56fbedb2023-05-30 16:47:05 +080014695 hapd_conf_change = TRUE;
developer72fb0bb2023-01-11 09:46:29 +080014696 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
14697 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
14698 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
14699 return RETURN_ERR;
14700 }
14701 }
14702 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
developer56fbedb2023-05-30 16:47:05 +080014703 hapd_conf_change = TRUE;
developer72fb0bb2023-01-11 09:46:29 +080014704 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
14705 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
14706 return RETURN_ERR;
14707 }
14708 }
14709 if (current_param.guardInterval != operationParam->guardInterval) {
developer56fbedb2023-05-30 16:47:05 +080014710 hapd_conf_change = TRUE;
14711 drv_dat_change = TRUE;
14712 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
developer72fb0bb2023-01-11 09:46:29 +080014713 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
14714 return RETURN_ERR;
14715 }
14716 }
14717 if (current_param.transmitPower != operationParam->transmitPower) {
developer56fbedb2023-05-30 16:47:05 +080014718 drv_dat_change = TRUE;
developer72fb0bb2023-01-11 09:46:29 +080014719 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
14720 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
14721 return RETURN_ERR;
14722 }
14723 }
14724 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
developer56fbedb2023-05-30 16:47:05 +080014725 hapd_conf_change = TRUE;
developer72fb0bb2023-01-11 09:46:29 +080014726 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
14727 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
14728 return RETURN_ERR;
14729 }
14730 }
14731 if (current_param.obssCoex != operationParam->obssCoex) {
developer56fbedb2023-05-30 16:47:05 +080014732 hapd_conf_change = TRUE;
developer72fb0bb2023-01-11 09:46:29 +080014733 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
14734 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
14735 return RETURN_ERR;
14736 }
14737 }
14738 if (current_param.stbcEnable != operationParam->stbcEnable) {
developer56fbedb2023-05-30 16:47:05 +080014739 hapd_conf_change = TRUE;
14740 drv_dat_change = TRUE;
developer72fb0bb2023-01-11 09:46:29 +080014741 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
14742 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
14743 return RETURN_ERR;
14744 }
14745 }
14746 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
14747 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
14748 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
14749 return RETURN_ERR;
14750 }
14751 }
14752
developer56fbedb2023-05-30 16:47:05 +080014753 /* only down/up interface when dat file has been changed,
14754 * if enable is true, then restart the radio.
14755 */
14756 if (drv_dat_change == TRUE) {
14757 wifi_setRadioEnable(index, FALSE);
14758 if (operationParam->enable == TRUE)
14759 wifi_setRadioEnable(index, TRUE);
14760 } else if (hapd_conf_change == TRUE) {
14761 hostapd_raw_remove_bss(index);
14762 if (operationParam->enable == TRUE)
14763 hostapd_raw_add_bss(index);
14764 }
14765
developer72fb0bb2023-01-11 09:46:29 +080014766 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
14767
14768 return RETURN_OK;
14769}
14770
14771INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
14772{
14773 char band[64] = {0};
14774 char buf[256] = {0};
14775 char config_file[64] = {0};
14776 char cmd[128] = {0};
developer72fb0bb2023-01-11 09:46:29 +080014777 int mode = 0;
developer72fb0bb2023-01-11 09:46:29 +080014778 BOOL enabled = FALSE;
developer2f79c922023-06-02 17:33:42 +080014779 UINT dtimPeriod;
14780 UINT beaconInterval;
14781 UINT basicDataTransmitRates;
14782 UINT operationalDataTransmitRates;
14783 wifi_guard_interval_t guardInterval;
14784 UINT transmitPower;
developer72fb0bb2023-01-11 09:46:29 +080014785
14786 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
14787 printf("Entering %s index = %d\n", __func__, (int)index);
14788
14789 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
14790 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
14791 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
14792 {
14793 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
14794 return RETURN_ERR;
14795 }
14796 operationParam->enable = enabled;
14797
14798 memset(band, 0, sizeof(band));
14799 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
14800 {
14801 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
14802 return RETURN_ERR;
14803 }
14804
14805 if (!strcmp(band, "2.4GHz"))
14806 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
14807 else if (!strcmp(band, "5GHz"))
14808 operationParam->band = WIFI_FREQUENCY_5_BAND;
14809 else if (!strcmp(band, "6GHz"))
14810 operationParam->band = WIFI_FREQUENCY_6_BAND;
14811 else
14812 {
14813 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
14814 band);
14815 }
14816
14817 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
14818 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
14819 operationParam->channel = 0;
14820 operationParam->autoChannelEnabled = TRUE;
14821 } else {
14822 operationParam->channel = strtol(buf, NULL, 10);
14823 operationParam->autoChannelEnabled = FALSE;
14824 }
14825
14826 memset(buf, 0, sizeof(buf));
14827 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
14828 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
14829 return RETURN_ERR;
14830 }
14831 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
14832 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
14833 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
14834 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
14835 else
14836 {
14837 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
14838 return false;
14839 }
14840
14841 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
14842 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
14843 return RETURN_ERR;
14844 }
14845 // Two different definition bit map, so need to check every bit.
14846 if (mode & WIFI_MODE_A)
14847 operationParam->variant |= WIFI_80211_VARIANT_A;
14848 if (mode & WIFI_MODE_B)
14849 operationParam->variant |= WIFI_80211_VARIANT_B;
14850 if (mode & WIFI_MODE_G)
14851 operationParam->variant |= WIFI_80211_VARIANT_G;
14852 if (mode & WIFI_MODE_N)
14853 operationParam->variant |= WIFI_80211_VARIANT_N;
14854 if (mode & WIFI_MODE_AC)
14855 operationParam->variant |= WIFI_80211_VARIANT_AC;
14856 if (mode & WIFI_MODE_AX)
14857 operationParam->variant |= WIFI_80211_VARIANT_AX;
14858 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
14859 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
14860 return RETURN_ERR;
14861 }
developer2f79c922023-06-02 17:33:42 +080014862 if (wifi_getApDTIMInterval(index, &dtimPeriod) != RETURN_OK) {
developer72fb0bb2023-01-11 09:46:29 +080014863 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
14864 return RETURN_ERR;
14865 }
developer2f79c922023-06-02 17:33:42 +080014866 operationParam->dtimPeriod = dtimPeriod;
14867 if (wifi_getRadioBeaconPeriod(index, &beaconInterval) != RETURN_OK) {
developer72fb0bb2023-01-11 09:46:29 +080014868 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
14869 return RETURN_ERR;
14870 }
developer2f79c922023-06-02 17:33:42 +080014871 operationParam->beaconInterval = beaconInterval;
developer72fb0bb2023-01-11 09:46:29 +080014872
14873 memset(buf, 0, sizeof(buf));
14874 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
14875 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
14876 return RETURN_ERR;
14877 }
developer2f79c922023-06-02 17:33:42 +080014878 TransmitRatesToBitMap(buf, &basicDataTransmitRates);
14879 operationParam->basicDataTransmitRates = basicDataTransmitRates;
developer72fb0bb2023-01-11 09:46:29 +080014880
14881 memset(buf, 0, sizeof(buf));
14882 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
14883 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
14884 return RETURN_ERR;
14885 }
developer2f79c922023-06-02 17:33:42 +080014886 TransmitRatesToBitMap(buf, &operationalDataTransmitRates);
14887 operationParam->operationalDataTransmitRates = operationalDataTransmitRates;
developer72fb0bb2023-01-11 09:46:29 +080014888
14889 memset(buf, 0, sizeof(buf));
14890 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
14891 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
14892
developer2f79c922023-06-02 17:33:42 +080014893 if (wifi_getGuardInterval(index, &guardInterval) != RETURN_OK) {
developer72fb0bb2023-01-11 09:46:29 +080014894 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
14895 return RETURN_ERR;
14896 }
developer2f79c922023-06-02 17:33:42 +080014897 operationParam->guardInterval = guardInterval;
14898
14899 if (wifi_getRadioPercentageTransmitPower(index, (ULONG *)&transmitPower) != RETURN_OK) {
developer72fb0bb2023-01-11 09:46:29 +080014900 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
14901 return RETURN_ERR;
14902 }
developer2f79c922023-06-02 17:33:42 +080014903 operationParam->transmitPower = transmitPower;
developer72fb0bb2023-01-11 09:46:29 +080014904
14905 memset(buf, 0, sizeof(buf));
14906 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
14907 if (strcmp(buf, "-1") == 0) {
14908 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
14909 operationParam->ctsProtection = FALSE;
14910 } else {
14911 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
14912 operationParam->ctsProtection = TRUE;
14913 }
14914
14915 memset(buf, 0, sizeof(buf));
14916 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
14917 if (strcmp(buf, "0") == 0)
14918 operationParam->obssCoex = FALSE;
14919 else
14920 operationParam->obssCoex = TRUE;
14921
14922 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
14923 _syscmd(cmd, buf, sizeof(buf));
14924 if (strlen(buf) != 0)
14925 operationParam->stbcEnable = TRUE;
14926 else
14927 operationParam->stbcEnable = FALSE;
14928
14929 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
14930 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
14931 return RETURN_ERR;
14932 }
14933
14934 // Below value is hardcoded
14935
14936 operationParam->numSecondaryChannels = 0;
14937 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
14938 operationParam->channelSecondary[i] = 0;
14939 }
14940 operationParam->csa_beacon_count = 15;
14941 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
14942
14943 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
14944 return RETURN_OK;
14945}
14946
14947static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
14948{
14949 int max_radio_num = 0;
14950
14951 wifi_getMaxRadioNumber(&max_radio_num);
14952 if (radioIndex >= max_radio_num) {
14953 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
14954 return RETURN_ERR;
14955 }
14956
14957 return (arrayIndex * max_radio_num) + radioIndex;
14958}
14959
developer96b38512023-02-22 11:17:45 +080014960static int vap_index_to_array_index(int vapIndex, int *radioIndex, int *arrayIndex)
14961{
14962 int max_radio_num = 0;
14963
14964 if ((vapIndex < 0) || (vapIndex > MAX_NUM_VAP_PER_RADIO*MAX_NUM_RADIOS))
14965 return -1;
14966
14967 wifi_getMaxRadioNumber(&max_radio_num);
14968
14969 (*radioIndex) = vapIndex % max_radio_num;
14970 (*arrayIndex) = vapIndex / max_radio_num;
14971
14972 return 0;
14973}
14974
14975
developer72fb0bb2023-01-11 09:46:29 +080014976wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
14977 if (strncmp(beaconRate, "1Mbps", 5) == 0)
14978 return WIFI_BITRATE_1MBPS;
14979 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
14980 return WIFI_BITRATE_2MBPS;
14981 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
14982 return WIFI_BITRATE_5_5MBPS;
14983 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
14984 return WIFI_BITRATE_6MBPS;
14985 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
14986 return WIFI_BITRATE_9MBPS;
14987 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
14988 return WIFI_BITRATE_11MBPS;
14989 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
14990 return WIFI_BITRATE_12MBPS;
14991 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
14992 return WIFI_BITRATE_18MBPS;
14993 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
14994 return WIFI_BITRATE_24MBPS;
14995 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
14996 return WIFI_BITRATE_36MBPS;
14997 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
14998 return WIFI_BITRATE_48MBPS;
14999 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
15000 return WIFI_BITRATE_54MBPS;
15001 return WIFI_BITRATE_DEFAULT;
15002}
15003
15004INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
15005{
15006 if (beacon == WIFI_BITRATE_1MBPS)
15007 strcpy(beacon_str, "1Mbps");
15008 else if (beacon == WIFI_BITRATE_2MBPS)
15009 strcpy(beacon_str, "2Mbps");
15010 else if (beacon == WIFI_BITRATE_5_5MBPS)
15011 strcpy(beacon_str, "5.5Mbps");
15012 else if (beacon == WIFI_BITRATE_6MBPS)
15013 strcpy(beacon_str, "6Mbps");
15014 else if (beacon == WIFI_BITRATE_9MBPS)
15015 strcpy(beacon_str, "9Mbps");
15016 else if (beacon == WIFI_BITRATE_11MBPS)
15017 strcpy(beacon_str, "11Mbps");
15018 else if (beacon == WIFI_BITRATE_12MBPS)
15019 strcpy(beacon_str, "12Mbps");
15020 else if (beacon == WIFI_BITRATE_18MBPS)
15021 strcpy(beacon_str, "18Mbps");
15022 else if (beacon == WIFI_BITRATE_24MBPS)
15023 strcpy(beacon_str, "24Mbps");
15024 else if (beacon == WIFI_BITRATE_36MBPS)
15025 strcpy(beacon_str, "36Mbps");
15026 else if (beacon == WIFI_BITRATE_48MBPS)
15027 strcpy(beacon_str, "48Mbps");
15028 else if (beacon == WIFI_BITRATE_54MBPS)
15029 strcpy(beacon_str, "54Mbps");
15030 return RETURN_OK;
15031}
15032
15033INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
15034{
15035 INT mode = 0;
15036 INT ret = -1;
15037 INT output = 0;
15038 int i = 0;
15039 int vap_index = 0;
15040 BOOL enabled = FALSE;
15041 char buf[256] = {0};
15042 wifi_vap_security_t security = {0};
developer72fb0bb2023-01-11 09:46:29 +080015043
15044 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
15045 printf("Entering %s index = %d\n", __func__, (int)index);
15046
developerfde01262023-05-22 15:15:24 +080015047 ret = wifi_BandProfileRead(0, index, "BssidNum", buf, sizeof(buf), "0");
15048 if (ret != 0) {
15049 fprintf(stderr, "%s: wifi_BandProfileRead BssidNum failed\n", __func__);
15050 return RETURN_ERR;
15051 }
15052
15053 map->num_vaps = atoi(buf);
15054 if (map->num_vaps <= 0) {
15055 fprintf(stderr, "%s: invalid BssidNum %s\n", __func__, buf);
15056 return RETURN_ERR;
15057 }
15058
15059 for (i = 0; i < map->num_vaps; i++)
developer72fb0bb2023-01-11 09:46:29 +080015060 {
15061 map->vap_array[i].radio_index = index;
15062
15063 vap_index = array_index_to_vap_index(index, i);
15064 if (vap_index < 0)
15065 return RETURN_ERR;
15066
15067 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
15068
15069 map->vap_array[i].vap_index = vap_index;
15070
15071 memset(buf, 0, sizeof(buf));
15072 ret = wifi_getApName(vap_index, buf);
15073 if (ret != RETURN_OK) {
15074 printf("%s: wifi_getApName return error\n", __func__);
15075 return RETURN_ERR;
15076 }
15077 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
15078
15079 memset(buf, 0, sizeof(buf));
15080 ret = wifi_getSSIDName(vap_index, buf);
15081 if (ret != RETURN_OK) {
15082 printf("%s: wifi_getSSIDName return error\n", __func__);
15083 return RETURN_ERR;
15084 }
15085 snprintf(map->vap_array[i].u.bss_info.ssid, sizeof(map->vap_array[i].u.bss_info.ssid), "%s", buf);
15086
developere740c2a2023-05-23 18:34:32 +080015087#if 0
developer72fb0bb2023-01-11 09:46:29 +080015088 ret = wifi_getSSIDEnable(vap_index, &enabled);
15089 if (ret != RETURN_OK) {
15090 printf("%s: wifi_getSSIDEnable return error\n", __func__);
15091 return RETURN_ERR;
15092 }
developere740c2a2023-05-23 18:34:32 +080015093#endif
15094 map->vap_array[i].u.bss_info.enabled = true;
developer72fb0bb2023-01-11 09:46:29 +080015095
15096 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
15097 if (ret != RETURN_OK) {
15098 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
15099 return RETURN_ERR;
15100 }
15101 map->vap_array[i].u.bss_info.showSsid = enabled;
developer69b61b02023-03-07 17:17:44 +080015102
developer72fb0bb2023-01-11 09:46:29 +080015103 ret = wifi_getApIsolationEnable(vap_index, &enabled);
15104 if (ret != RETURN_OK) {
15105 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
15106 return RETURN_ERR;
15107 }
15108 map->vap_array[i].u.bss_info.isolation = enabled;
15109
15110 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
15111 if (ret != RETURN_OK) {
15112 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
15113 return RETURN_ERR;
15114 }
15115 map->vap_array[i].u.bss_info.bssMaxSta = output;
15116
15117 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
15118 if (ret != RETURN_OK) {
15119 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
15120 return RETURN_ERR;
15121 }
15122 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
15123
15124 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
15125 if (ret != RETURN_OK) {
15126 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
15127 return RETURN_ERR;
15128 }
15129 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
15130
15131 ret = wifi_getApSecurity(vap_index, &security);
15132 if (ret != RETURN_OK) {
15133 printf("%s: wifi_getApSecurity return error\n", __func__);
15134 return RETURN_ERR;
15135 }
15136 map->vap_array[i].u.bss_info.security = security;
15137
15138 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
15139 if (ret != RETURN_OK) {
15140 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
15141 return RETURN_ERR;
15142 }
developer69b61b02023-03-07 17:17:44 +080015143 if (mode == 0)
developer72fb0bb2023-01-11 09:46:29 +080015144 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
developer69b61b02023-03-07 17:17:44 +080015145 else
developer72fb0bb2023-01-11 09:46:29 +080015146 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
developer69b61b02023-03-07 17:17:44 +080015147 if (mode == 1)
developer72fb0bb2023-01-11 09:46:29 +080015148 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
developer69b61b02023-03-07 17:17:44 +080015149 else if (mode == 2)
developer72fb0bb2023-01-11 09:46:29 +080015150 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
15151
15152 ret = wifi_getApWmmEnable(vap_index, &enabled);
15153 if (ret != RETURN_OK) {
15154 printf("%s: wifi_getApWmmEnable return error\n", __func__);
15155 return RETURN_ERR;
15156 }
15157 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
15158
15159 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
15160 if (ret != RETURN_OK) {
15161 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
15162 return RETURN_ERR;
15163 }
15164 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
15165
15166 memset(buf, 0, sizeof(buf));
15167 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
15168 if (ret != RETURN_OK) {
15169 printf("%s: wifi_getApBeaconRate return error\n", __func__);
15170 return RETURN_ERR;
15171 }
15172 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
15173
15174 memset(buf, 0, sizeof(buf));
15175 ret = wifi_getBaseBSSID(vap_index, buf);
15176 if (ret != RETURN_OK) {
15177 printf("%s: wifi_getBaseBSSID return error\n", __func__);
15178 return RETURN_ERR;
15179 }
developer5b2f10c2023-05-25 17:02:21 +080015180 if (hwaddr_aton2(buf, map->vap_array[i].u.bss_info.bssid) < 0) {
15181 printf("%s: hwaddr_aton2 fail\n", __func__);
15182 return RETURN_ERR;
15183 }
developer72fb0bb2023-01-11 09:46:29 +080015184
15185 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
15186 if (ret != RETURN_OK) {
15187 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
15188 return RETURN_ERR;
15189 }
15190 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
15191
15192 // TODO: wps, noack
15193 }
15194 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
15195 return RETURN_OK;
15196}
15197
developer47cc27a2023-05-17 23:09:58 +080015198void checkVapStatus(int apIndex, BOOL *enable)
developer72fb0bb2023-01-11 09:46:29 +080015199{
15200 char if_name[16] = {0};
15201 char cmd[128] = {0};
15202 char buf[128] = {0};
15203
15204 *enable = FALSE;
15205 if (wifi_GetInterfaceName(apIndex, if_name) != RETURN_OK)
15206 return;
15207
15208 snprintf(cmd, sizeof(cmd), "cat %s | grep ^%s=1", VAP_STATUS_FILE, if_name);
15209 _syscmd(cmd, buf, sizeof(buf));
15210 if (strlen(buf) > 0)
15211 *enable = TRUE;
15212 return;
15213}
15214
15215static int prepareInterface(UINT apIndex, char *new_interface)
15216{
15217 char cur_interface[16] = {0};
15218 char config_file[128] = {0};
developer8a3bbbf2023-03-15 17:47:23 +080015219 char cmd[MAX_CMD_SIZE] = {0};
15220 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +080015221 int max_radio_num = 0;
15222 int radioIndex = -1;
15223 int phyIndex = -1;
developer8a3bbbf2023-03-15 17:47:23 +080015224 struct params params;
developer72fb0bb2023-01-11 09:46:29 +080015225
15226 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
15227 wifi_hostapdRead(config_file, "interface", cur_interface, sizeof(cur_interface));
15228
15229 if (strncmp(cur_interface, new_interface, sizeof(cur_interface)) != 0) {
developer8a3bbbf2023-03-15 17:47:23 +080015230 wifi_getMaxRadioNumber(&max_radio_num);
developer72fb0bb2023-01-11 09:46:29 +080015231 radioIndex = apIndex % max_radio_num;
15232 phyIndex = radio_index_to_phy(radioIndex);
15233 // disable and del old interface, then add new interface
15234 wifi_setApEnable(apIndex, FALSE);
developer8a3bbbf2023-03-15 17:47:23 +080015235
15236 params.name = "interface";
15237 params.value = new_interface;
15238 wifi_hostapdWrite(config_file, &params, 1);
15239
15240 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyIndex, config_file);
15241 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +080015242 }
developer8a3bbbf2023-03-15 17:47:23 +080015243
developer72fb0bb2023-01-11 09:46:29 +080015244 // update the vap status file
15245 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=1' %s", cur_interface, new_interface, VAP_STATUS_FILE);
15246 _syscmd(cmd, buf, sizeof(buf));
15247 return RETURN_OK;
15248}
15249
developer56fbedb2023-05-30 16:47:05 +080015250int hostapd_manage_bss(INT apIndex, BOOL enable)
15251{
15252 char interface_name[16] = {0};
15253 char config_file[MAX_BUF_SIZE] = {0};
15254 char cmd[MAX_CMD_SIZE] = {0};
15255 char buf[MAX_BUF_SIZE] = {0};
15256 BOOL status = FALSE;
15257 int max_radio_num = 0;
15258 int phyId = 0;
15259
15260 wifi_getApEnable(apIndex, &status);
15261
15262 wifi_getMaxRadioNumber(&max_radio_num);
15263 if (enable == status)
15264 return RETURN_OK;
15265
15266 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
15267 return RETURN_ERR;
15268
15269 if (enable == TRUE) {
15270 int radioIndex = apIndex % max_radio_num;
15271 phyId = radio_index_to_phy(radioIndex);
15272 fprintf(stderr, "%s %d\n", __func__, __LINE__);
15273 snprintf(config_file, MAX_BUF_SIZE, "%s%d.conf", CONFIG_PREFIX, apIndex);
15274 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyId, config_file);
15275 _syscmd(cmd, buf, sizeof(buf));
15276 } else {
15277 fprintf(stderr, "%s %d\n", __func__, __LINE__);
15278 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw REMOVE %s", interface_name);
15279 _syscmd(cmd, buf, sizeof(buf));
15280 }
15281 snprintf(cmd, MAX_CMD_SIZE, "sed -i -n -e '/^%s=/!p' -e '$a%s=%d' %s",
15282 interface_name, interface_name, enable, VAP_STATUS_FILE);
15283 _syscmd(cmd, buf, sizeof(buf));
15284 //Wait for wifi up/down to apply
15285 return RETURN_OK;
15286}
15287
15288int hostapd_raw_add_bss(int apIndex)
15289{
15290 return hostapd_manage_bss(apIndex, TRUE);
15291}
15292
15293int hostapd_raw_remove_bss(int apIndex)
15294{
15295 return hostapd_manage_bss(apIndex, FALSE);
15296}
15297
15298int hostapd_raw_restart_bss(int apIndex)
developer333c1eb2023-05-31 14:59:39 +080015299{
developerdaf24792023-06-06 11:40:04 +080015300 int ret = 0;
15301
15302 ret = hostapd_raw_remove_bss(apIndex);
15303 if(ret != RETURN_OK)
15304 return RETURN_ERR;
15305
15306 ret = hostapd_raw_add_bss(apIndex);
15307 if(ret != RETURN_OK)
15308 return RETURN_ERR;
15309
15310 return RETURN_OK;
developer56fbedb2023-05-30 16:47:05 +080015311}
15312
developer72fb0bb2023-01-11 09:46:29 +080015313INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
15314{
developer72fb0bb2023-01-11 09:46:29 +080015315 unsigned int i;
15316 wifi_vap_info_t *vap_info = NULL;
15317 int acl_mode;
15318 int ret = 0;
developer72fb0bb2023-01-11 09:46:29 +080015319 char buf[256] = {0};
15320 char cmd[128] = {0};
15321 char config_file[64] = {0};
developer72fb0bb2023-01-11 09:46:29 +080015322 char psk_file[64] = {0};
developer47cc27a2023-05-17 23:09:58 +080015323 BOOL enable = FALSE;
developere740c2a2023-05-23 18:34:32 +080015324 int band_idx;
15325
developer72fb0bb2023-01-11 09:46:29 +080015326
15327 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
15328 printf("Entering %s index = %d\n", __func__, (int)index);
15329 for (i = 0; i < map->num_vaps; i++)
15330 {
15331 multiple_set = TRUE;
15332 vap_info = &map->vap_array[i];
15333
15334 // Check vap status file to enable multiple ap if the system boot.
15335 checkVapStatus(vap_info->vap_index, &enable);
15336 if (vap_info->u.bss_info.enabled == FALSE && enable == FALSE)
15337 continue;
15338
15339 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
15340
developere740c2a2023-05-23 18:34:32 +080015341 band_idx = radio_index_to_band(index);
15342 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
15343 snprintf(cmd, sizeof(cmd), "cp /etc/hostapd-%s.conf %s", wifi_band_str[band_idx], config_file);
15344 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +080015345
developer56fbedb2023-05-30 16:47:05 +080015346 struct params params[3];
developer72fb0bb2023-01-11 09:46:29 +080015347 params[0].name = "interface";
15348 params[0].value = vap_info->vap_name;
developer72fb0bb2023-01-11 09:46:29 +080015349 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", vap_info->vap_index);
developer56fbedb2023-05-30 16:47:05 +080015350 params[1].name = "wpa_psk_file";
15351 params[1].value = psk_file;
15352 params[2].name = "ssid";
15353 params[2].value = vap_info->u.bss_info.ssid;
developer72fb0bb2023-01-11 09:46:29 +080015354
15355 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
developer56fbedb2023-05-30 16:47:05 +080015356 wifi_hostapdWrite(config_file, params, 3);
developer72fb0bb2023-01-11 09:46:29 +080015357
15358 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
15359 _syscmd(cmd, buf, sizeof(buf));
15360
15361 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
15362 if (ret != RETURN_OK) {
15363 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
15364 return RETURN_ERR;
15365 }
15366
15367 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
15368 if (ret != RETURN_OK) {
15369 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
15370 return RETURN_ERR;
15371 }
15372
15373 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
15374 if (ret != RETURN_OK) {
15375 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
15376 return RETURN_ERR;
15377 }
15378
15379 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
15380 if (ret != RETURN_OK) {
15381 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
15382 return RETURN_ERR;
15383 }
15384
15385 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
15386 if (ret != RETURN_OK) {
15387 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
15388 return RETURN_ERR;
15389 }
15390
15391 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
15392 if (ret != RETURN_OK) {
15393 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
15394 return RETURN_ERR;
15395 }
15396
15397 if (vap_info->u.bss_info.mac_filter_enable == false){
15398 acl_mode = 0;
15399 }else {
15400 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
15401 acl_mode = 2;
15402 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
15403 _syscmd(cmd, buf, sizeof(buf));
15404 }else{
15405 acl_mode = 1;
15406 }
15407 }
15408
15409 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
15410 if (ret != RETURN_OK) {
15411 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
15412 return RETURN_ERR;
15413 }
15414
15415 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
15416 if (ret != RETURN_OK) {
15417 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
15418 return RETURN_ERR;
15419 }
15420
developer0f10c772023-05-16 21:43:39 +080015421 memset(buf, 0, sizeof(buf));
15422 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
15423 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
15424 if (ret != RETURN_OK) {
15425 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
15426 return RETURN_ERR;
15427 }
developer72fb0bb2023-01-11 09:46:29 +080015428
15429 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
15430 if (ret != RETURN_OK) {
15431 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable\n", __func__);
15432 return RETURN_ERR;
15433 }
15434
developer72fb0bb2023-01-11 09:46:29 +080015435 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
15436 if (ret != RETURN_OK) {
15437 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
15438 return RETURN_ERR;
15439 }
developer333c1eb2023-05-31 14:59:39 +080015440
developer56fbedb2023-05-30 16:47:05 +080015441 hostapd_raw_restart_bss(vap_info->vap_index);
developer72fb0bb2023-01-11 09:46:29 +080015442
developer23e71282023-01-18 10:25:19 +080015443 multiple_set = FALSE;
15444
15445 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
developer72fb0bb2023-01-11 09:46:29 +080015446 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
15447 if (ret != RETURN_OK) {
15448 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
15449 return RETURN_ERR;
15450 }
15451
15452 // TODO mgmtPowerControl, interworking, wps
15453 }
15454 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
15455 return RETURN_OK;
15456}
15457
15458int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
15459{
15460 char *token, *next;
15461 const char s[2] = ",";
15462 int count =0;
15463
15464 /* get the first token */
15465 token = strtok_r(pchannels, s, &next);
15466
15467 /* walk through other tokens */
15468 while( token != NULL && count < MAX_CHANNELS) {
15469 chlistptr->channels_list[count++] = atoi(token);
15470 token = strtok_r(NULL, s, &next);
15471 }
15472
15473 return count;
15474}
15475
15476static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
15477{
15478 INT status;
15479 wifi_channels_list_t *chlistp;
15480 CHAR output_string[64];
15481 CHAR pchannels[128];
15482 CHAR interface_name[16] = {0};
15483 wifi_band band;
15484
15485 if(rcap == NULL)
15486 {
15487 return RETURN_ERR;
15488 }
15489
15490 rcap->numSupportedFreqBand = 1;
15491 band = wifi_index_to_band(radioIndex);
15492
15493 if (band == band_2_4)
15494 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
15495 else if (band == band_5)
15496 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
15497 else if (band == band_6)
15498 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
15499
15500 chlistp = &(rcap->channel_list[0]);
15501 memset(pchannels, 0, sizeof(pchannels));
15502
15503 /* possible number of radio channels */
15504 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
15505 {
15506 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
15507 }
15508 /* Number of channels and list*/
15509 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
15510
15511 /* autoChannelSupported */
15512 /* always ON with wifi_getRadioAutoChannelSupported */
15513 rcap->autoChannelSupported = TRUE;
15514
15515 /* DCSSupported */
15516 /* always ON with wifi_getRadioDCSSupported */
15517 rcap->DCSSupported = TRUE;
15518
15519 /* zeroDFSSupported - TBD */
15520 rcap->zeroDFSSupported = FALSE;
15521
15522 /* Supported Country List*/
15523 memset(output_string, 0, sizeof(output_string));
15524 status = wifi_getRadioCountryCode(radioIndex, output_string);
15525 if( status != 0 ) {
15526 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
15527 return RETURN_ERR;
15528 } else {
15529 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
15530 }
15531 if(!strcmp(output_string,"US")){
15532 rcap->countrySupported[0] = wifi_countrycode_US;
15533 rcap->countrySupported[1] = wifi_countrycode_CA;
15534 } else if (!strcmp(output_string,"CA")) {
15535 rcap->countrySupported[0] = wifi_countrycode_CA;
15536 rcap->countrySupported[1] = wifi_countrycode_US;
15537 } else {
15538 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
15539 }
15540
15541 rcap->numcountrySupported = 2;
15542
15543 /* csi */
15544 rcap->csi.maxDevices = 8;
15545 rcap->csi.soudingFrameSupported = TRUE;
15546
15547 wifi_GetInterfaceName(radioIndex, interface_name);
15548 snprintf(rcap->ifaceName, sizeof(interface_name), "%s",interface_name);
15549
15550 /* channelWidth - all supported bandwidths */
15551 int i=0;
15552 rcap->channelWidth[i] = 0;
15553 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
15554 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
15555 WIFI_CHANNELBANDWIDTH_40MHZ);
15556
15557 }
15558 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
15559 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
15560 WIFI_CHANNELBANDWIDTH_40MHZ |
15561 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
15562 }
15563
15564
15565 /* mode - all supported variants */
15566 // rcap->mode[i] = WIFI_80211_VARIANT_H;
15567 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
15568 rcap->mode[i] = ( WIFI_80211_VARIANT_B | WIFI_80211_VARIANT_G | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AX );
15569 }
15570 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
15571 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
15572 }
15573 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
15574 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
15575 }
15576 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
15577 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
15578
15579 /* supportedBitRate - all supported bitrates */
15580 rcap->supportedBitRate[i] = 0;
15581 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
15582 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
15583 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
15584 }
developerdaf24792023-06-06 11:40:04 +080015585 else if ((rcap->band[i] & (WIFI_FREQUENCY_5_BAND )) || (rcap->band[i] & (WIFI_FREQUENCY_6_BAND))) {
developer72fb0bb2023-01-11 09:46:29 +080015586 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
15587 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
15588 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
15589 }
15590
15591
15592 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
15593 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
15594 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
15595 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
15596 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
15597 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
15598 rcap->cipherSupported = 0;
15599 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
15600 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
15601
15602 return RETURN_OK;
15603}
15604
15605INT wifi_getHalCapability(wifi_hal_capability_t *cap)
15606{
15607 INT status = 0, radioIndex = 0;
developer2f79c922023-06-02 17:33:42 +080015608 char output[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +080015609 int iter = 0;
15610 unsigned int j = 0;
15611 int max_num_radios;
15612 wifi_interface_name_idex_map_t *iface_info = NULL;
15613
15614 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
15615
15616 memset(cap, 0, sizeof(wifi_hal_capability_t));
15617
15618 /* version */
15619 cap->version.major = WIFI_HAL_MAJOR_VERSION;
15620 cap->version.minor = WIFI_HAL_MINOR_VERSION;
15621
15622 /* number of radios platform property */
15623 wifi_getMaxRadioNumber(&max_num_radios);
15624 cap->wifi_prop.numRadios = max_num_radios;
15625
15626 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
15627 {
15628 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
15629 if (status != 0) {
15630 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
15631 return RETURN_ERR;
15632 }
15633
15634 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
15635 {
15636 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
15637 {
15638 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
15639 return RETURN_ERR;
15640 }
15641 iface_info = &cap->wifi_prop.interface_map[iter];
15642 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
15643 iface_info->rdk_radio_index = radioIndex;
15644 memset(output, 0, sizeof(output));
15645 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
15646 {
15647 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
15648 }
15649 // TODO: bridge name
15650 // TODO: vlan id
15651 // TODO: primary
15652 iface_info->index = array_index_to_vap_index(radioIndex, j);
15653 memset(output, 0, sizeof(output));
15654 if (wifi_getApName(iface_info->index, output) == RETURN_OK)
15655 {
15656 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
15657 }
15658 iter++;
15659 }
15660 }
15661
15662 cap->BandSteeringSupported = FALSE;
15663 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
15664 return RETURN_OK;
15665}
15666
15667INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
15668{
15669 struct params h_config={0};
15670 char config_file[64] = {0};
15671
15672 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
15673
15674 h_config.name = "okc";
15675 h_config.value = okc_enable?"1":"0";
15676
15677 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
15678 wifi_hostapdWrite(config_file, &h_config, 1);
15679 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
15680
15681 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
15682 return RETURN_OK;
15683}
15684
15685INT wifi_setSAEMFP(int ap_index, BOOL enable)
15686{
15687 struct params h_config={0};
15688 char config_file[64] = {0};
developer72fb0bb2023-01-11 09:46:29 +080015689
15690 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
15691
15692 h_config.name = "sae_require_mfp";
15693 h_config.value = enable?"1":"0";
15694
15695 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
15696 wifi_hostapdWrite(config_file, &h_config, 1);
15697 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
15698
15699 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
15700 return RETURN_OK;
15701}
15702
15703INT wifi_setSAEpwe(int ap_index, int sae_pwe)
15704{
15705 struct params h_config={0};
15706 char config_file[64] = {0};
15707 char buf[128] = {0};
15708
15709 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
15710
15711 h_config.name = "sae_pwe";
15712 snprintf(buf, sizeof(buf), "%d", sae_pwe);
15713 h_config.value = buf;
15714
15715 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
15716 wifi_hostapdWrite(config_file, &h_config, 1);
15717 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
15718
15719 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
15720 return RETURN_OK;
15721}
15722
15723INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
15724{
15725 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
15726 struct params h_config={0};
15727 char config_file[64] = {0};
15728
15729 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
15730
15731 h_config.name = "wpa_disable_eapol_key_retries";
15732 h_config.value = disable_EAPOL_retries?"1":"0";
15733
15734 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
15735 wifi_hostapdWrite(config_file, &h_config, 1);
15736 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
15737
15738 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
15739 return RETURN_OK;
15740}
15741
15742INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
15743{
15744 char buf[128] = {0};
15745 char config_file[128] = {0};
developere5750452023-05-15 16:46:42 +080015746 char cmd[128] = {0};
developer72fb0bb2023-01-11 09:46:29 +080015747 char password[64] = {0};
15748 char mfp[32] = {0};
15749 char wpa_mode[32] = {0};
15750 BOOL okc_enable = FALSE;
15751 BOOL sae_MFP = FALSE;
15752 BOOL disable_EAPOL_retries = TRUE;
15753 int sae_pwe = 0;
15754 struct params params = {0};
15755 wifi_band band = band_invalid;
15756
15757 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
15758
15759 multiple_set = TRUE;
15760 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
15761 if (security->mode == wifi_security_mode_none) {
15762 strcpy(wpa_mode, "None");
15763 } else if (security->mode == wifi_security_mode_wpa_personal)
15764 strcpy(wpa_mode, "WPA-Personal");
15765 else if (security->mode == wifi_security_mode_wpa2_personal)
15766 strcpy(wpa_mode, "WPA2-Personal");
15767 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
15768 strcpy(wpa_mode, "WPA-WPA2-Personal");
15769 else if (security->mode == wifi_security_mode_wpa_enterprise)
15770 strcpy(wpa_mode, "WPA-Enterprise");
15771 else if (security->mode == wifi_security_mode_wpa2_enterprise)
15772 strcpy(wpa_mode, "WPA2-Enterprise");
15773 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
15774 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
15775 else if (security->mode == wifi_security_mode_wpa3_personal) {
15776 strcpy(wpa_mode, "WPA3-Personal");
15777 okc_enable = TRUE;
15778 sae_MFP = TRUE;
15779 sae_pwe = 2;
15780 disable_EAPOL_retries = FALSE;
15781 } else if (security->mode == wifi_security_mode_wpa3_transition) {
15782 strcpy(wpa_mode, "WPA3-Personal-Transition");
15783 okc_enable = TRUE;
15784 sae_MFP = TRUE;
15785 sae_pwe = 2;
15786 disable_EAPOL_retries = FALSE;
15787 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
15788 strcpy(wpa_mode, "WPA3-Enterprise");
15789 sae_MFP = TRUE;
15790 sae_pwe = 2;
15791 disable_EAPOL_retries = FALSE;
developerd01e3e82023-04-26 19:10:38 +080015792 } else if (security->mode == wifi_security_mode_enhanced_open) {
developer3086e2f2023-01-17 09:40:01 +080015793 strcpy(wpa_mode, "OWE");
15794 sae_MFP = TRUE;
15795 sae_pwe = 2;
15796 disable_EAPOL_retries = FALSE;
developer72fb0bb2023-01-11 09:46:29 +080015797 }
15798
15799 band = wifi_index_to_band(ap_index);
15800 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
15801 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
15802 return RETURN_ERR;
15803 }
15804
15805 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
15806 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
15807 wifi_setSAEMFP(ap_index, sae_MFP);
15808 wifi_setSAEpwe(ap_index, sae_pwe);
15809 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
15810
developerd01e3e82023-04-26 19:10:38 +080015811 if (security->mode != wifi_security_mode_none && security->mode != wifi_security_mode_enhanced_open) {
developere5750452023-05-15 16:46:42 +080015812 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) {
15813 int key_len = strlen(security->u.key.key);
15814 // wpa_psk and wpa_passphrase cann;t use at the same time, the command replace one with the other.
15815 if (key_len == 64) { // set wpa_psk
15816 strncpy(password, security->u.key.key, 64); // 64 characters
15817 password[64] = '\0';
15818 wifi_setApSecurityPreSharedKey(ap_index, password);
15819 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_passphrase=/!p' %s", config_file);
15820 } else if (key_len >= 8 && key_len < 64) { // set wpa_passphrase
15821 strncpy(password, security->u.key.key, 63);
15822 password[63] = '\0';
15823 wifi_setApSecurityKeyPassphrase(ap_index, password);
15824 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_psk=/!p' %s", config_file);
15825 } else
15826 return RETURN_ERR;
15827 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +080015828 }
15829 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
15830 params.name = "sae_password";
15831 params.value = security->u.key.key;
15832 wifi_hostapdWrite(config_file, &params, 1);
developere5750452023-05-15 16:46:42 +080015833 } else { // remove sae_password
15834 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^sae_password=/!p' %s", config_file);
15835 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +080015836 }
15837 }
15838
15839 if (security->mode != wifi_security_mode_none) {
15840 memset(&params, 0, sizeof(params));
15841 params.name = "wpa_pairwise";
15842 if (security->encr == wifi_encryption_tkip)
15843 params.value = "TKIP";
15844 else if (security->encr == wifi_encryption_aes)
15845 params.value = "CCMP";
15846 else if (security->encr == wifi_encryption_aes_tkip)
15847 params.value = "TKIP CCMP";
15848 wifi_hostapdWrite(config_file, &params, 1);
15849 }
15850
15851 if (security->mfp == wifi_mfp_cfg_disabled)
15852 strcpy(mfp, "Disabled");
15853 else if (security->mfp == wifi_mfp_cfg_optional)
15854 strcpy(mfp, "Optional");
15855 else if (security->mfp == wifi_mfp_cfg_required)
15856 strcpy(mfp, "Required");
15857 wifi_setApSecurityMFPConfig(ap_index, mfp);
15858
15859 memset(&params, 0, sizeof(params));
15860 params.name = "transition_disable";
15861 if (security->wpa3_transition_disable == TRUE)
15862 params.value = "0x01";
15863 else
15864 params.value = "0x00";
15865 wifi_hostapdWrite(config_file, &params, 1);
15866
15867 memset(&params, 0, sizeof(params));
15868 params.name = "wpa_group_rekey";
15869 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
15870 params.value = buf;
15871 wifi_hostapdWrite(config_file, &params, 1);
15872
15873 memset(&params, 0, sizeof(params));
15874 params.name = "wpa_strict_rekey";
15875 params.value = security->strict_rekey?"1":"0";
15876 wifi_hostapdWrite(config_file, &params, 1);
15877
15878 memset(&params, 0, sizeof(params));
15879 params.name = "wpa_pairwise_update_count";
developere5750452023-05-15 16:46:42 +080015880 if (security->eapol_key_retries == 0)
15881 security->eapol_key_retries = 4; // 0 is invalid, set to default value.
developer72fb0bb2023-01-11 09:46:29 +080015882 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
15883 params.value = buf;
15884 wifi_hostapdWrite(config_file, &params, 1);
15885
15886 memset(&params, 0, sizeof(params));
15887 params.name = "disable_pmksa_caching";
15888 params.value = security->disable_pmksa_caching?"1":"0";
15889 wifi_hostapdWrite(config_file, &params, 1);
15890
developer23e71282023-01-18 10:25:19 +080015891 if (multiple_set == FALSE) {
15892 wifi_setApEnable(ap_index, FALSE);
15893 wifi_setApEnable(ap_index, TRUE);
15894 }
developer72fb0bb2023-01-11 09:46:29 +080015895
15896 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
15897
15898 return RETURN_OK;
15899}
15900
15901INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
15902{
15903 char buf[256] = {0};
15904 char config_file[128] = {0};
15905 int disable = 0;
developere5750452023-05-15 16:46:42 +080015906 bool set_sae = FALSE;
developer72fb0bb2023-01-11 09:46:29 +080015907
15908 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
15909 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
15910 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
15911 security->mode = wifi_security_mode_none;
15912 if (strlen(buf) != 0) {
15913 if (!strcmp(buf, "WPA-Personal"))
15914 security->mode = wifi_security_mode_wpa_personal;
15915 else if (!strcmp(buf, "WPA2-Personal"))
15916 security->mode = wifi_security_mode_wpa2_personal;
15917 else if (!strcmp(buf, "WPA-WPA2-Personal"))
15918 security->mode = wifi_security_mode_wpa_wpa2_personal;
15919 else if (!strcmp(buf, "WPA-Enterprise"))
15920 security->mode = wifi_security_mode_wpa_enterprise;
15921 else if (!strcmp(buf, "WPA2-Enterprise"))
15922 security->mode = wifi_security_mode_wpa2_enterprise;
15923 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
15924 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
15925 else if (!strcmp(buf, "WPA3-Personal"))
15926 security->mode = wifi_security_mode_wpa3_personal;
15927 else if (!strcmp(buf, "WPA3-Personal-Transition"))
15928 security->mode = wifi_security_mode_wpa3_transition;
15929 else if (!strcmp(buf, "WPA3-Enterprise"))
15930 security->mode = wifi_security_mode_wpa3_enterprise;
developer3086e2f2023-01-17 09:40:01 +080015931 else if (!strcmp(buf, "OWE"))
developerd01e3e82023-04-26 19:10:38 +080015932 security->mode = wifi_security_mode_enhanced_open;
developer72fb0bb2023-01-11 09:46:29 +080015933 }
15934
15935 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
15936 if (security->mode == wifi_security_mode_none)
15937 security->encr = wifi_encryption_none;
15938 else {
15939 if (strcmp(buf, "TKIP") == 0)
15940 security->encr = wifi_encryption_tkip;
15941 else if (strcmp(buf, "CCMP") == 0)
15942 security->encr = wifi_encryption_aes;
15943 else
15944 security->encr = wifi_encryption_aes_tkip;
15945 }
15946
developerdaf24792023-06-06 11:40:04 +080015947 if (security->mode != wifi_security_mode_none) {
developer72fb0bb2023-01-11 09:46:29 +080015948 memset(buf, 0, sizeof(buf));
15949 // wpa3 can use one or both configs as password, so we check sae_password first.
15950 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
developere5750452023-05-15 16:46:42 +080015951 if (strlen(buf) != 0) {
15952 if (security->mode == wifi_security_mode_wpa3_personal || security->mode == wifi_security_mode_wpa3_transition)
15953 security->u.key.type = wifi_security_key_type_sae;
15954 set_sae = TRUE;
15955 strncpy(security->u.key.key, buf, sizeof(buf));
15956 }
15957 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
15958 if (strlen(buf) != 0){
15959 if (set_sae == TRUE)
15960 security->u.key.type = wifi_security_key_type_psk_sae;
15961 else if (strlen(buf) == 64)
15962 security->u.key.type = wifi_security_key_type_psk;
15963 else
15964 security->u.key.type = wifi_security_key_type_pass;
15965 strncpy(security->u.key.key, buf, sizeof(security->u.key.key));
developer72fb0bb2023-01-11 09:46:29 +080015966 }
developer72fb0bb2023-01-11 09:46:29 +080015967 security->u.key.key[255] = '\0';
15968 }
15969
15970 memset(buf, 0, sizeof(buf));
15971 wifi_getApSecurityMFPConfig(ap_index, buf);
15972 if (strcmp(buf, "Disabled") == 0)
15973 security->mfp = wifi_mfp_cfg_disabled;
15974 else if (strcmp(buf, "Optional") == 0)
15975 security->mfp = wifi_mfp_cfg_optional;
15976 else if (strcmp(buf, "Required") == 0)
15977 security->mfp = wifi_mfp_cfg_required;
15978
15979 memset(buf, 0, sizeof(buf));
15980 security->wpa3_transition_disable = FALSE;
15981 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
15982 disable = strtol(buf, NULL, 16);
15983 if (disable != 0)
15984 security->wpa3_transition_disable = TRUE;
15985
15986 memset(buf, 0, sizeof(buf));
15987 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
15988 if (strlen(buf) == 0)
15989 security->rekey_interval = 86400;
15990 else
15991 security->rekey_interval = strtol(buf, NULL, 10);
15992
15993 memset(buf, 0, sizeof(buf));
15994 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
15995 if (strlen(buf) == 0)
15996 security->strict_rekey = 1;
15997 else
15998 security->strict_rekey = strtol(buf, NULL, 10);
15999
16000 memset(buf, 0, sizeof(buf));
16001 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
16002 if (strlen(buf) == 0)
16003 security->eapol_key_retries = 4;
16004 else
16005 security->eapol_key_retries = strtol(buf, NULL, 10);
16006
16007 memset(buf, 0, sizeof(buf));
16008 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
16009 if (strlen(buf) == 0)
16010 security->disable_pmksa_caching = FALSE;
16011 else
16012 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
16013
16014 /* TODO
16015 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
16016 */
16017 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
16018 security->eap_identity_req_timeout = 0;
16019 security->eap_identity_req_retries = 0;
16020 security->eap_req_timeout = 0;
16021 security->eap_req_retries = 0;
16022 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
16023 return RETURN_OK;
16024}
16025
16026#endif /* WIFI_HAL_VERSION_3 */
16027
16028#ifdef WIFI_HAL_VERSION_3_PHASE2
16029INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
16030{
16031 char interface_name[16] = {0};
16032 char cmd[128] = {0};
16033 char buf[128] = {0};
16034 char *mac_addr = NULL;
16035 BOOL status = FALSE;
16036 size_t len = 0;
16037
16038 if(ap_index > MAX_APS)
16039 return RETURN_ERR;
16040
16041 *output_numDevices = 0;
16042 wifi_getApEnable(ap_index, &status);
16043 if (status == FALSE)
16044 return RETURN_OK;
16045
16046 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
16047 return RETURN_ERR;
16048 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
16049 _syscmd(cmd, buf, sizeof(buf));
16050
16051 mac_addr = strtok(buf, "\n");
16052 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
16053 *output_numDevices = i + 1;
16054 fprintf(stderr, "mac_addr: %s\n", mac_addr);
16055 addr_ptr = output_deviceMacAddressArray[i];
16056 mac_addr_aton(addr_ptr, mac_addr);
16057 mac_addr = strtok(NULL, "\n");
16058 }
16059
16060 return RETURN_OK;
16061}
16062#else
16063INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
16064{
16065 char interface_name[16] = {0};
16066 char cmd[128];
16067 BOOL status = false;
16068
16069 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
16070 return RETURN_ERR;
16071
16072 output_buf[0] = '\0';
16073
16074 wifi_getApEnable(ap_index,&status);
16075 if (!status)
16076 return RETURN_OK;
16077
16078 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
16079 return RETURN_ERR;
16080 sprintf(cmd, "hostapd_cli -i %s list_sta | tr '\\n' ',' | sed 's/.$//'", interface_name);
16081 _syscmd(cmd, output_buf, output_buf_size);
developer69b61b02023-03-07 17:17:44 +080016082
developer72fb0bb2023-01-11 09:46:29 +080016083 return RETURN_OK;
16084}
16085#endif
16086
16087INT wifi_getProxyArp(INT apIndex, BOOL *enable)
16088{
16089 char output[16]={'\0'};
16090 char config_file[MAX_BUF_SIZE] = {0};
16091
16092 if (!enable)
16093 return RETURN_ERR;
16094
16095 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
16096 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
16097
16098 if (strlen(output) == 0)
16099 *enable = FALSE;
16100 else if (strncmp(output, "1", 1) == 0)
16101 *enable = TRUE;
16102 else
16103 *enable = FALSE;
16104
16105 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
16106 return RETURN_OK;
16107}
16108
16109INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
16110{
16111 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
16112 return RETURN_ERR;
16113 *output_enable=TRUE;
16114 return RETURN_OK;
16115}
16116
16117INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
16118{
16119 char cmd[128] = {0};
16120 char buf[128] = {0};
16121 char line[128] = {0};
developer72fb0bb2023-01-11 09:46:29 +080016122 FILE *f = NULL;
16123 int index = 0;
16124 int exp = 0;
16125 int mantissa = 0;
16126 int duration = 0;
16127 int radio_index = 0;
16128 int max_radio_num = 0;
16129 uint twt_wake_interval = 0;
16130 int phyId = 0;
16131 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
16132
16133 wifi_getMaxRadioNumber(&max_radio_num);
16134
16135 radio_index = ap_index % max_radio_num;
16136
16137 phyId = radio_index_to_phy(radio_index);
16138 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", phyId);
16139 _syscmd(cmd, buf, sizeof(buf));
16140 *numSessionReturned = strtol(buf, NULL, 10) - 1;
16141 if (*numSessionReturned > maxNumberSessions)
16142 *numSessionReturned = maxNumberSessions;
16143 else if (*numSessionReturned < 1) {
16144 *numSessionReturned = 0;
16145 return RETURN_OK;
16146 }
16147
16148 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | tail -n %d | tr '|' ' ' | tr -s ' '", phyId, *numSessionReturned);
16149 if ((f = popen(cmd, "r")) == NULL) {
16150 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
16151 return RETURN_ERR;
16152 }
16153
16154 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
16155 while((fgets(line, sizeof(line), f)) != NULL) {
16156 char *tmp = NULL;
16157 strcpy(buf, line);
16158 tmp = strtok(buf, " ");
16159 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
16160 tmp = strtok(NULL, " ");
16161 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
16162 tmp = strtok(NULL, " ");
16163 if (strstr(tmp, "t")) {
16164 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
16165 }
16166 if (strstr(tmp, "a")) {
16167 twtSessions[index].twtParameters.operation.announced = TRUE;
16168 }
16169 tmp = strtok(NULL, " ");
16170 exp = strtol(tmp, NULL, 10);
16171 tmp = strtok(NULL, " ");
16172 mantissa = strtol(tmp, NULL, 10);
16173 tmp = strtok(NULL, " ");
16174 duration = strtol(tmp, NULL, 10);
16175
16176 // only implicit supported
16177 twtSessions[index].twtParameters.operation.implicit = TRUE;
16178 // only individual agreement supported
16179 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
16180
16181 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
16182 twt_wake_interval = mantissa * (1 << exp);
16183 if (mantissa == 0 || twt_wake_interval/mantissa != (1 << exp)) {
16184 // Overflow handling
16185 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
16186 } else {
16187 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
16188 }
16189 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
16190 index++;
16191 }
16192
16193 pclose(f);
16194 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
16195 return RETURN_OK;
16196}