blob: 15f2b138c412c602ce1dc553ba4ff2d582ebf2fb [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
146#define wifi_dbg_printf(format, args...) printf("")
147#define WIFI_ENTRY_EXIT_DEBUG(format, args...) printf("")
148#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
developerd1824452023-05-18 12:30:04 +0800215typedef enum ht_config_bw{
216 HT_BW_20,
217 HT_BW_40,
218};
219
220typedef enum vht_config_bw{
221 VHT_BW_2040,
222 VHT_BW_80,
223 VHT_BW_160,
224 VHT_BW_8080,
225};
226
227typedef enum eht_config_bw{
228 EHT_BW_20,
229 EHT_BW_40,
230 EHT_BW_80,
231 EHT_BW_160,
232 EHT_BW_320,
233};
234
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);
developer47cc27a2023-05-17 23:09:58 +0800267
developer49b17232023-05-19 16:35:19 +0800268/*type define the nl80211 call back func*/
269typedef int (*mtk_nl80211_cb) (struct nl_msg *, void *);
270
271/**
272*struct mtk_nl80211_param
273* init mtk nl80211 using parameters
274* @sub_cmd: the cmd define in the mtk_vendor_nl80211.h.
275* @if_type: now only support the NL80211_ATTR_IFINDEX/NL80211_ATTR_WIPHY.
276* @if_idx: the index should match the interface or wiphy.
277* Note: NA
278**/
279struct mtk_nl80211_param {
280 unsigned int sub_cmd;
281 int if_type;
282 int if_idx;
283};
284
285/**
developer121a8e72023-05-22 09:19:39 +0800286*struct mtk_nl80211_cb_data
287* init mtk nl80211 call back parameters
288* @out_buf: store the mtk vendor output msg for wifi hal buffer.
289* @out_len: the output buffer length.
290* Note: NA
291**/
292struct mtk_nl80211_cb_data {
293 char * out_buf;
294 unsigned int out_len;
295};
296
297/**
developer49b17232023-05-19 16:35:19 +0800298*mtk_nl80211_init
299* init mtk nl80211 netlink and init the vendor msg common part.
300* @nl: netlink, just init it.
301* @msg: netlink message will alloc it.
302* the msg send success/fails is not free by app
303* only the nla_put etc api fails should use nlmsg_free.
304* @msg_data: vendor data msg attr pointer.
305* @param: init using interface and sub_cmd parameter.
306*
307*init the netlink context and mtk netlink vendor msg.
308*
309*return:
310* 0: success
311* other: fail
312**/
313
314int mtk_nl80211_init(struct unl *nl, struct nl_msg **msg,
315 struct nlattr **msg_data, struct mtk_nl80211_param *param) {
316 /*sanity check here*/
317 if (!nl || !param) {
318 (void)fprintf(stderr,
319 "[%s][%d]:nl(0x%lx) or param(0x%lx) is null, error!\n",
320 __func__, __LINE__, nl, param);
321 return -1;
322 }
323 /*if_type check*/
324 if ( param->if_type != NL80211_ATTR_IFINDEX && param->if_type != NL80211_ATTR_WIPHY) {
325 (void)fprintf(stderr,
326 "[%s][%d]:if_type(0x%x) is not supported, only 0x%x and 0x%x supported.\n",
327 __func__, __LINE__, param->if_type, NL80211_ATTR_IFINDEX, NL80211_ATTR_WIPHY);
328 return -1;
329 }
330 /*init the nl*/
331 if (unl_genl_init(nl, "nl80211") < 0) {
332 (void)fprintf(stderr, "[%s][%d]::Failed to connect to nl80211\n",
333 __func__, __LINE__);
334 return -1;
335 }
336 /*init the msg*/
337 *msg = unl_genl_msg(nl, NL80211_CMD_VENDOR, false);
338
339 if (nla_put_u32(*msg, param->if_type, param->if_idx) ||
340 nla_put_u32(*msg, NL80211_ATTR_VENDOR_ID, MTK_NL80211_VENDOR_ID) ||
341 nla_put_u32(*msg, NL80211_ATTR_VENDOR_SUBCMD, param->sub_cmd)) {
342 (void)fprintf(stderr,
343 "[%s][%d]:Nla put error: if_type: 0x%x, if_idx: 0x%x, sub_cmd: 0x%x\n",
344 __func__, __LINE__, param->if_type, param->if_idx, param->sub_cmd);
345 goto err;
346 }
347
348 *msg_data = nla_nest_start(*msg, NL80211_ATTR_VENDOR_DATA);
349 if (!*msg_data) {
350 (void)fprintf(stderr, "[%s][%d]:Nla put NL80211_ATTR_VENDOR_DATA start error\n",
351 __func__, __LINE__);
352 goto err;
353 }
354
355 return 0;
356err:
developer49b17232023-05-19 16:35:19 +0800357 nlmsg_free(*msg);
358 unl_free(nl);
359 return -1;
360}
361
362/**
363*mtk_nl80211_send
364* set the vendor cmd call back and sent the vendor msg.
365* @nl: netlink.
366* @msg: netlink message.
367* @msg_data: vendor data msg attr pointer.
368* @handler: if the msg have call back shoud add the call back func
369* the event msg will handle by the call back func(exp:get cmd)
370* other set it as NULL(exp:set cmd).
371* @arg:call back func arg parameter.
372*add end of the netlink msg, set the call back and send msg
373*
374*return:
375* 0: success
376* other: fail
377**/
378int mtk_nl80211_send(struct unl *nl, struct nl_msg *msg,
379 struct nlattr *msg_data, mtk_nl80211_cb handler, void *arg) {
380 int ret = 0;
381 /*sanity check*/
382 if (!nl || !msg || !msg_data) {
383 (void)fprintf(stderr,
384 "[%s][%d]:nl(0x%lx),msg(0x%lx) or msg_data(0x%lx) is null, error!\n",
385 __func__, __LINE__, nl, msg, msg_data);
386 return -1;
387 }
388 /*end the msg attr of vendor data*/
389 nla_nest_end(msg, msg_data);
390 /*send the msg and set call back */
391 ret = unl_genl_request(nl, msg, handler, arg);
392 if (ret)
393 (void)fprintf(stderr, "send nl80211 cmd fails\n");
394 return ret;
395}
396
397/**
398*mtk_nl80211_deint
developer2edaf012023-05-24 14:24:53 +0800399* deinit the netlink.
developer49b17232023-05-19 16:35:19 +0800400* @nl: netlink.
401*
developer2edaf012023-05-24 14:24:53 +0800402*free deinit the netlink.
developer49b17232023-05-19 16:35:19 +0800403*
404*return:
405* 0: success
406**/
407
408int mtk_nl80211_deint(struct unl *nl) {
409 unl_free(nl);
410 return 0;
411}
412
developer72fb0bb2023-01-11 09:46:29 +0800413
414static wifi_secur_list map_security[] =
415{
416 WIFI_ITEM_STR(wifi_security_mode_none, "None"),
417 WIFI_ITEM_STR(wifi_security_mode_wep_64, "WEP-64"),
418 WIFI_ITEM_STR(wifi_security_mode_wep_128, "WEP-128"),
419 WIFI_ITEM_STR(wifi_security_mode_wpa_personal, "WPA-Personal"),
420 WIFI_ITEM_STR(wifi_security_mode_wpa_enterprise, "WPA-Enterprise"),
421 WIFI_ITEM_STR(wifi_security_mode_wpa2_personal, "WPA2-Personal"),
422 WIFI_ITEM_STR(wifi_security_mode_wpa2_enterprise, "WPA2-Enterprise"),
423 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_personal, "WPA-WPA2-Personal"),
424 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_enterprise, "WPA-WPA2-Enterprise"),
425 WIFI_ITEM_STR(wifi_security_mode_wpa3_personal, "WPA3-Personal"),
426 WIFI_ITEM_STR(wifi_security_mode_wpa3_transition, "WPA3-Personal-Transition"),
427 WIFI_ITEM_STR(wifi_security_mode_wpa3_enterprise, "WPA3-Enterprise")
428};
429
430wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key)
431{
432 wifi_secur_list *item;
433 int i;
434
435 for (item = list,i = 0;i < list_sz; item++, i++) {
436 if ((int)(item->key) == key) {
437 return item;
438 }
439 }
440
441 return NULL;
442}
443
444char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key)
445{
446 wifi_secur_list *item = wifi_get_item_by_key(list, list_sz, key);
447
448 if (!item) {
449 return "";
450 }
451
452 return (char *)(item->data);
453}
454
455wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str)
456{
457 wifi_secur_list *item;
458 int i;
459
460 for (item = list,i = 0;i < list_sz; item++, i++) {
461 if (strcmp((char *)(item->data), str) == 0) {
462 return item;
463 }
464 }
465
466 return NULL;
467}
468#endif /* WIFI_HAL_VERSION_3 */
469
developer96b38512023-02-22 11:17:45 +0800470
471static char l1profile[32] = "/etc/wireless/l1profile.dat";
developer17038e62023-03-02 14:43:43 +0800472char main_prefix[MAX_NUM_RADIOS][IFNAMSIZ];
473char ext_prefix[MAX_NUM_RADIOS][IFNAMSIZ];
474#define MAX_SSID_LEN 64
475char default_ssid[MAX_NUM_RADIOS][MAX_SSID_LEN];;
developer745f0bd2023-03-06 14:32:53 +0800476int radio_band[MAX_NUM_RADIOS];
developer17038e62023-03-02 14:43:43 +0800477
478static int array_index_to_vap_index(UINT radioIndex, int arrayIndex);
479static int vap_index_to_array_index(int vapIndex, int *radioIndex, int *arrayIndex);
480
developer96b38512023-02-22 11:17:45 +0800481
482static int
483get_value(const char *conf_file, const char *param, char *value, int len)
484{
485 FILE *fp;
486 int ret = -1;
487 int param_len = strlen(param);
488 int buf_len;
489 char buf[256];
490
491 fp = fopen(conf_file, "r");
492 if (!fp) {
493 return -1;
494 }
495
496 while (fgets(buf, sizeof(buf), fp)) {
497 buf_len = strlen(buf);
498 if (buf[buf_len - 1] == '\n') {
499 buf_len--;
500 buf[buf_len] = '\0';
501 }
502 if ((buf_len > param_len) &&
503 (strncmp(buf, param, param_len) == 0) &&
504 (buf[param_len] == '=')) {
505
506 if (buf_len == (param_len + 1)) {
507 value[0] = '\0';
508 ret = 0;
509 } else {
510 ret = snprintf(value, len, "%s", buf + (param_len + 1));
511 }
512 fclose(fp);
513 return ret;
514 }
515 }
516 fclose(fp);
517 return -1;
518}
519
520static int
521get_value_by_idx(const char *conf_file, const char *param, int idx, char *value, int len)
522{
523 char buf[256];
524 int ret;
525 char *save_ptr = NULL;
526 char *tok = NULL;
527
528 ret = get_value(conf_file, param, buf, sizeof(buf));
529 if (ret < 0)
530 return ret;
531
532 tok = strtok_r(buf, ";", &save_ptr);
533 do {
534 if (idx == 0 || tok == NULL)
535 break;
536 else
537 idx--;
538
539 tok = strtok_r(NULL, ";", &save_ptr);
540 } while (tok != NULL);
541
542 if (tok) {
543 ret = snprintf(value, len, "%s", tok);
544 } else {
545 ret = 0;
546 value[0] = '\0';
547 }
548
549 return ret;
550}
551
552
developer72fb0bb2023-01-11 09:46:29 +0800553#ifdef HAL_NETLINK_IMPL
554typedef struct {
555 int id;
556 struct nl_sock* socket;
557 struct nl_cb* cb;
558} Netlink;
559
560static int mac_addr_aton(unsigned char *mac_addr, char *arg)
561{
562 unsigned int mac_addr_int[6]={};
563 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);
564 mac_addr[0] = mac_addr_int[0];
565 mac_addr[1] = mac_addr_int[1];
566 mac_addr[2] = mac_addr_int[2];
567 mac_addr[3] = mac_addr_int[3];
568 mac_addr[4] = mac_addr_int[4];
569 mac_addr[5] = mac_addr_int[5];
570 return 0;
571}
572
573static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
574{
575 unsigned int mac_addr_int[6]={};
576 mac_addr_int[0] = arg[0];
577 mac_addr_int[1] = arg[1];
578 mac_addr_int[2] = arg[2];
579 mac_addr_int[3] = arg[3];
580 mac_addr_int[4] = arg[4];
581 mac_addr_int[5] = arg[5];
582 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]);
583 return;
584}
585
586static int ieee80211_frequency_to_channel(int freq)
587{
588 /* see 802.11-2007 17.3.8.3.2 and Annex J */
589 if (freq == 2484)
590 return 14;
591 /* see 802.11ax D6.1 27.3.23.2 and Annex E */
592 else if (freq == 5935)
593 return 2;
594 else if (freq < 2484)
595 return (freq - 2407) / 5;
596 else if (freq >= 4910 && freq <= 4980)
597 return (freq - 4000) / 5;
598 else if (freq < 5950)
599 return (freq - 5000) / 5;
600 else if (freq <= 45000) /* DMG band lower limit */
601 /* see 802.11ax D6.1 27.3.23.2 */
602 return (freq - 5950) / 5;
603 else if (freq >= 58320 && freq <= 70200)
604 return (freq - 56160) / 2160;
605 else
606 return 0;
607}
608
609static int initSock80211(Netlink* nl) {
610 nl->socket = nl_socket_alloc();
611 if (!nl->socket) {
612 fprintf(stderr, "Failing to allocate the sock\n");
613 return -ENOMEM;
614 }
615
616 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
617
618 if (genl_connect(nl->socket)) {
619 fprintf(stderr, "Failed to connect\n");
620 nl_close(nl->socket);
621 nl_socket_free(nl->socket);
622 return -ENOLINK;
623 }
624
625 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
626 if (nl->id< 0) {
627 fprintf(stderr, "interface not found.\n");
628 nl_close(nl->socket);
629 nl_socket_free(nl->socket);
630 return -ENOENT;
631 }
632
633 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
634 if ((!nl->cb)) {
635 fprintf(stderr, "Failed to allocate netlink callback.\n");
636 nl_close(nl->socket);
637 nl_socket_free(nl->socket);
638 return ENOMEM;
639 }
640
641 return nl->id;
642}
643
644static int nlfree(Netlink *nl)
645{
646 nl_cb_put(nl->cb);
647 nl_close(nl->socket);
648 nl_socket_free(nl->socket);
649 return 0;
650}
651
652static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
653 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
654 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
655 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
656};
657
658static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
659};
660
661static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
662};
663
664typedef struct _wifi_channelStats_loc {
665 INT array_size;
666 INT ch_number;
667 BOOL ch_in_pool;
668 INT ch_noise;
669 BOOL ch_radar_noise;
670 INT ch_max_80211_rssi;
671 INT ch_non_80211_noise;
672 INT ch_utilization;
673 ULLONG ch_utilization_total;
674 ULLONG ch_utilization_busy;
675 ULLONG ch_utilization_busy_tx;
676 ULLONG ch_utilization_busy_rx;
677 ULLONG ch_utilization_busy_self;
678 ULLONG ch_utilization_busy_ext;
679} wifi_channelStats_t_loc;
680
681typedef struct wifi_device_info {
682 INT wifi_devIndex;
683 UCHAR wifi_devMacAddress[6];
684 CHAR wifi_devIPAddress[64];
685 BOOL wifi_devAssociatedDeviceAuthentiationState;
686 INT wifi_devSignalStrength;
687 INT wifi_devTxRate;
688 INT wifi_devRxRate;
689} wifi_device_info_t;
690
691#endif
692
693//For 5g Alias Interfaces
694static BOOL priv_flag = TRUE;
695static BOOL pub_flag = TRUE;
696static BOOL Radio_flag = TRUE;
697//wifi_setApBeaconRate(1, beaconRate);
698
699BOOL multiple_set = FALSE;
700
701struct params
702{
703 char * name;
704 char * value;
705};
706
707static int _syscmd(char *cmd, char *retBuf, int retBufSize)
708{
709 FILE *f;
710 char *ptr = retBuf;
711 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
712
713 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
714 if((f = popen(cmd, "r")) == NULL) {
715 fprintf(stderr,"\npopen %s error\n", cmd);
716 return RETURN_ERR;
717 }
718
719 while(!feof(f))
720 {
721 *ptr = 0;
722 if(bufSize>=128) {
723 bufbytes=128;
724 } else {
725 bufbytes=bufSize-1;
726 }
727
728 fgets(ptr,bufbytes,f);
729 readbytes=strlen(ptr);
730
731 if(!readbytes)
732 break;
733
734 bufSize-=readbytes;
735 ptr += readbytes;
736 }
737 cmd_ret = pclose(f);
738 retBuf[retBufSize-1]=0;
739 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
740
741 return cmd_ret >> 8;
742}
743
744INT radio_index_to_phy(int radioIndex)
745{
developer17038e62023-03-02 14:43:43 +0800746 /* TODO */
747 return radioIndex;
developer72fb0bb2023-01-11 09:46:29 +0800748}
749
750INT wifi_getMaxRadioNumber(INT *max_radio_num)
751{
752 char cmd[64] = {0};
753 char buf[4] = {0};
754
755 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
756
757 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
758 _syscmd(cmd, buf, sizeof(buf));
759 *max_radio_num = strtoul(buf, NULL, 10) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS:strtoul(buf, NULL, 10);
760
761 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
762
763 return RETURN_OK;
764}
765
developer17038e62023-03-02 14:43:43 +0800766wifi_band radio_index_to_band(int radioIndex)
767{
developer745f0bd2023-03-06 14:32:53 +0800768 return radio_band[radioIndex];
developer17038e62023-03-02 14:43:43 +0800769}
770
developer72fb0bb2023-01-11 09:46:29 +0800771wifi_band wifi_index_to_band(int apIndex)
772{
773 char cmd[128] = {0};
774 char buf[64] = {0};
775 int nl80211_band = 0;
776 int i = 0;
777 int phyIndex = 0;
778 int radioIndex = 0;
779 int max_radio_num = 0;
780 wifi_band band = band_invalid;
781
782 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
783
784 wifi_getMaxRadioNumber(&max_radio_num);
785 radioIndex = apIndex % max_radio_num;
786 phyIndex = radio_index_to_phy(radioIndex);
787 while(i < 10){
788 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Band .:' | tail -n 1 | tr -d ':\\n' | awk '{print $2}'", phyIndex);
789 _syscmd(cmd, buf, sizeof(buf));
790 nl80211_band = strtol(buf, NULL, 10);
791 if (nl80211_band == 1)
792 band = band_2_4;
793 else if (nl80211_band == 2)
794 band = band_5;
795 else if (nl80211_band == 4) // band == 3 is 60GHz
796 band = band_6;
797
798 if(band != band_invalid)
799 break;
developer69b61b02023-03-07 17:17:44 +0800800
developer72fb0bb2023-01-11 09:46:29 +0800801 i++;
802 sleep(1);
803 }
804
805 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
806 return band;
807}
808
809static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
810{
developer7e4a2a62023-04-06 19:56:03 +0800811 char cmd[MAX_CMD_SIZE] = {0};
812 char buf[MAX_BUF_SIZE] = {0};
813 int ret = 0;
developer72fb0bb2023-01-11 09:46:29 +0800814
developer7e4a2a62023-04-06 19:56:03 +0800815 ret = snprintf(cmd, MAX_CMD_SIZE, "cat %s 2> /dev/null | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"",
816 conf_file, param);
developer72fb0bb2023-01-11 09:46:29 +0800817
developer7e4a2a62023-04-06 19:56:03 +0800818 if (ret < 0) {
819 printf("%s: snprintf error!", __func__);
820 return -1;
821 }
822
823 ret = _syscmd(cmd, buf, sizeof(buf));
824 if ((ret != 0) && (strlen(buf) == 0)) {
825 printf("%s: _syscmd error!", __func__);
826 return -1;
827 }
828
829 snprintf(output, output_size, "%s", buf);
830
831 return 0;
developer72fb0bb2023-01-11 09:46:29 +0800832}
833
834static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
835{
developer7e4a2a62023-04-06 19:56:03 +0800836 char cmd[MAX_CMD_SIZE] = {0};
837 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +0800838
developer7e4a2a62023-04-06 19:56:03 +0800839 for (int i = 0; i < item_count; i++) {
developer72fb0bb2023-01-11 09:46:29 +0800840 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
developer7e4a2a62023-04-06 19:56:03 +0800841 if (strlen(buf) == 0) /*no such item, insert it*/
developera1255e42023-05-13 17:45:02 +0800842 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 +0800843 else /*find the item, update it*/
developer72fb0bb2023-01-11 09:46:29 +0800844 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 +0800845
developer72fb0bb2023-01-11 09:46:29 +0800846 if(_syscmd(cmd, buf, sizeof(buf)))
847 return -1;
848 }
849
developera1255e42023-05-13 17:45:02 +0800850 return 0;
851}
developerfde01262023-05-22 15:15:24 +0800852
developera1255e42023-05-13 17:45:02 +0800853static int wifi_datfileRead(char *conf_file, char *param, char *output, int output_size)
854{
855 char cmd[MAX_CMD_SIZE] = {0};
developera1255e42023-05-13 17:45:02 +0800856 int ret = 0;
developerfde01262023-05-22 15:15:24 +0800857 int len;
858
859 ret = snprintf(cmd, sizeof(cmd), "datconf -f %s get %s", conf_file, param);
860 if (ret < 0) {
861 printf("%s: snprintf error!", __func__);
862 return -1;
863 }
864
865 ret = _syscmd(cmd, output, output_size);
866 if ((ret != 0) && (strlen(output) == 0)) {
867 printf("%s: _syscmd error!", __func__);
868 return -1;
869 }
developera1255e42023-05-13 17:45:02 +0800870
developerfde01262023-05-22 15:15:24 +0800871 len = strlen(output);
872 if ((len > 0) && (output[len - 1] == '\n')) {
873 output[len - 1] = '\0';
874 }
875
876 return 0;
877}
developera1255e42023-05-13 17:45:02 +0800878
developer3a85ab82023-05-25 11:59:38 +0800879static int wifi_datfileRead2(char *conf_file, int idx, char *param, char *output, int output_size)
developerfde01262023-05-22 15:15:24 +0800880{
881 char cmd[MAX_CMD_SIZE] = {0};
882 int ret = 0;
883 int len;
884
developer3a85ab82023-05-25 11:59:38 +0800885 ret = snprintf(cmd, sizeof(cmd), "datconf -f %s get %s %d", conf_file, param, idx);
developera1255e42023-05-13 17:45:02 +0800886 if (ret < 0) {
887 printf("%s: snprintf error!", __func__);
888 return -1;
889 }
890
developerfde01262023-05-22 15:15:24 +0800891 ret = _syscmd(cmd, output, output_size);
892 if ((ret != 0) && (strlen(output) == 0)) {
developera1255e42023-05-13 17:45:02 +0800893 printf("%s: _syscmd error!", __func__);
894 return -1;
895 }
896
developerfde01262023-05-22 15:15:24 +0800897 len = strlen(output);
898 if ((len > 0) && (output[len - 1] == '\n')) {
899 output[len - 1] = '\0';
900 }
developera1255e42023-05-13 17:45:02 +0800901
developer72fb0bb2023-01-11 09:46:29 +0800902 return 0;
903}
904
developera1255e42023-05-13 17:45:02 +0800905static int wifi_datfileWrite(char *conf_file, struct params *list, int item_count)
906{
developerfde01262023-05-22 15:15:24 +0800907 int ret;
developera1255e42023-05-13 17:45:02 +0800908 char cmd[MAX_CMD_SIZE] = {0};
909 char buf[MAX_BUF_SIZE] = {0};
910
911 for (int i = 0; i < item_count; i++) {
developerfde01262023-05-22 15:15:24 +0800912 ret = snprintf(cmd, sizeof(cmd), "datconf -f %s set %s \"%s\"", conf_file, list[i].name, list[i].value);
913 if (ret < 0) {
914 printf("%s: snprintf error!", __func__);
915 return -1;
916 }
developera1255e42023-05-13 17:45:02 +0800917
918 if(_syscmd(cmd, buf, sizeof(buf)))
919 return -1;
920 }
921
922 return 0;
923}
924
developer3a85ab82023-05-25 11:59:38 +0800925static int wifi_datfileWrite2(char *conf_file, int idx, struct params *list, int item_count)
developerfde01262023-05-22 15:15:24 +0800926{
927 int ret;
928 char cmd[MAX_CMD_SIZE] = {0};
929 char buf[MAX_BUF_SIZE] = {0};
930
931 for (int i = 0; i < item_count; i++) {
developer3a85ab82023-05-25 11:59:38 +0800932 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 +0800933 if (ret < 0) {
934 printf("%s: snprintf error!", __func__);
935 return -1;
936 }
937
938 if(_syscmd(cmd, buf, sizeof(buf)))
939 return -1;
940 }
941
942 return 0;
943}
944
945static int wifi_l1ProfileRead(char *param, char *output, int output_size)
946{
947 char buf[MAX_BUF_SIZE] = {0};
948 int ret;
949
950 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
951 if (!param || !output || (output_size <= 0)) {
952 fprintf(stderr, "%s: invalid parameters", __func__);
953 return RETURN_ERR;
954 }
955
956 ret = wifi_datfileRead(l1profile, param, output, output_size);
957 if (ret != 0) {
958 fprintf(stderr, "%s: wifi_datfileRead %s from %s failed, ret:%d", __func__, param, l1profile, ret);
959 return RETURN_ERR;
960 }
961
962 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
963 return RETURN_OK;
964}
965
developer3a85ab82023-05-25 11:59:38 +0800966static int wifi_l1ProfileRead2(char *param, int idx, char *output, int output_size)
967{
968 char buf[MAX_BUF_SIZE] = {0};
969 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) {
1038 fprintf(stderr, "%s: wifi_CardProfileRead %s failed, ret:%d", __func__, option);
1039 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) {
1076 fprintf(stderr, "%s: wifi_CardProfileRead %s failed, ret:%d", __func__, option);
1077 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) {
1105 fprintf(stderr, "%s: wifi_CardProfileRead %s failed, ret:%d", __func__, option);
1106 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) {
1113 fprintf(stderr, "%s: wifi_datfileWrite failed, ret:%d", __func__);
1114 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];
1130 char buf[64];
1131 char buf2[MAX_BUF_SIZE];
1132 int ret;
1133
1134 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1135
1136 snprintf(option, sizeof(option), "BN%d_profile_path", radio_idx);
1137 ret = wifi_CardProfileRead(card_idx, option, band_profile_path, sizeof(band_profile_path));
1138 if (ret != 0) {
1139 fprintf(stderr, "%s: wifi_CardProfileRead %s failed, ret:%d", __func__, option);
1140 return RETURN_ERR;
1141 }
1142
developer3a85ab82023-05-25 11:59:38 +08001143 ret = wifi_datfileWrite2(band_profile_path, idx, list, item_count);
developerfde01262023-05-22 15:15:24 +08001144 if (ret != 0) {
1145 fprintf(stderr, "%s: wifi_datfileWrite failed, ret:%d", __func__);
1146 return RETURN_ERR;
1147 }
1148
1149 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1150 return RETURN_OK;
1151
1152}
1153
1154
1155
developer72fb0bb2023-01-11 09:46:29 +08001156//For Getting Current Interface Name from corresponding hostapd configuration
1157static int wifi_GetInterfaceName(int apIndex, char *interface_name)
1158{
1159 char config_file[128] = {0};
1160
1161 if (interface_name == NULL)
1162 return RETURN_ERR;
1163
1164 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1165
1166 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
1167 wifi_hostapdRead(config_file, "interface", interface_name, 16);
1168 if (strlen(interface_name) == 0)
1169 return RETURN_ERR;
1170
1171 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1172 return RETURN_OK;
1173}
1174
developera1255e42023-05-13 17:45:02 +08001175static UCHAR get_bssnum_byindex(INT radio_index, UCHAR *bss_cnt)
1176{
1177 char interface_name[IF_NAME_SIZE] = {0};
1178 char cmd[MAX_BUF_SIZE]={'\0'};
1179 char buf[MAX_CMD_SIZE]={'\0'};
1180 UCHAR channel = 0;
1181
1182 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
1183 return RETURN_ERR;
1184 /*interface name to channel number*/
1185 snprintf(cmd, sizeof(cmd), "iw dev %s info | grep -i 'channel' | cut -d ' ' -f2", interface_name);
1186 _syscmd(cmd, buf, sizeof(buf));
1187 channel = atoi(buf);
1188 WIFI_ENTRY_EXIT_DEBUG("%s:channel=%d\n", __func__, channel);
1189 /*count dev number with the same channel*/
1190 snprintf(cmd, sizeof(cmd), "iw dev | grep -i 'channel %d' | wc -l", channel);
1191 _syscmd(cmd, buf, sizeof(buf));
1192 *bss_cnt = atoi(buf) - 1;/*1 for apcli interface*/
1193 WIFI_ENTRY_EXIT_DEBUG("%s:bss_cnt=%d\n", __func__, *bss_cnt);
1194 return RETURN_OK;
1195}
developer72fb0bb2023-01-11 09:46:29 +08001196
1197static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
1198{
1199 char interface_name[16] = {0};
1200 if (multiple_set == TRUE)
1201 return RETURN_OK;
1202 char cmd[MAX_CMD_SIZE]="", output[32]="";
1203 FILE *fp;
1204 int i;
1205 //NOTE RELOAD should be done in ApplySSIDSettings
1206 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
1207 return RETURN_ERR;
1208 for(i=0; i<item_count; i++, list++)
1209 {
developerf6a87542023-05-16 15:47:28 +08001210 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s SET %s %s", interface_name, list->name, list->value);
developer72fb0bb2023-01-11 09:46:29 +08001211 if((fp = popen(cmd, "r"))==NULL)
1212 {
1213 perror("popen failed");
1214 return -1;
1215 }
1216 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
1217 {
1218 pclose(fp);
1219 perror("fgets failed");
1220 return -1;
1221 }
1222 pclose(fp);
1223 }
1224 return 0;
1225}
1226
developer7e4a2a62023-04-06 19:56:03 +08001227static int wifi_quick_reload_ap(int apIndex)
1228{
1229 char interface_name[IF_NAME_SIZE] = {0};
1230 char cmd[MAX_CMD_SIZE] = {0};
1231 char buf[MAX_BUF_SIZE] = {0};
1232
1233 if (multiple_set == TRUE)
1234 return RETURN_OK;
1235
1236 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
1237 return RETURN_ERR;
1238
1239 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s reload", interface_name);
1240 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
1241 return RETURN_ERR;
1242
1243 return RETURN_OK;
1244}
1245
developer72fb0bb2023-01-11 09:46:29 +08001246static int wifi_reloadAp(int apIndex)
1247{
1248 char interface_name[16] = {0};
1249 if (multiple_set == TRUE)
1250 return RETURN_OK;
1251 char cmd[MAX_CMD_SIZE]="";
1252 char buf[MAX_BUF_SIZE]="";
1253
1254 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
1255 return RETURN_ERR;
1256 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s reload", interface_name);
1257 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
1258 return RETURN_ERR;
1259
1260 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s disable", interface_name);
1261 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
1262 return RETURN_ERR;
1263
1264 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s enable", interface_name);
1265 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
1266 return RETURN_ERR;
1267
1268 return RETURN_OK;
1269}
1270
1271INT File_Reading(CHAR *file, char *Value)
1272{
1273 FILE *fp = NULL;
1274 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
1275 int count = 0;
1276
1277 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1278 fp = popen(file,"r");
1279 if(fp == NULL)
1280 return RETURN_ERR;
1281
1282 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
1283 {
1284 for(count=0;buf[count]!='\n';count++)
1285 copy_buf[count]=buf[count];
1286 copy_buf[count]='\0';
1287 }
1288 strcpy(Value,copy_buf);
1289 pclose(fp);
1290 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1291
1292 return RETURN_OK;
1293}
1294
1295void wifi_RestartHostapd_2G()
1296{
1297 int Public2GApIndex = 4;
1298
1299 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1300 wifi_setApEnable(Public2GApIndex, FALSE);
1301 wifi_setApEnable(Public2GApIndex, TRUE);
1302 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1303}
1304
1305void wifi_RestartHostapd_5G()
1306{
1307 int Public5GApIndex = 5;
1308
1309 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1310 wifi_setApEnable(Public5GApIndex, FALSE);
1311 wifi_setApEnable(Public5GApIndex, TRUE);
1312 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1313}
1314
1315void wifi_RestartPrivateWifi_2G()
1316{
1317 int PrivateApIndex = 0;
1318
1319 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1320 wifi_setApEnable(PrivateApIndex, FALSE);
1321 wifi_setApEnable(PrivateApIndex, TRUE);
1322 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1323}
1324
1325void wifi_RestartPrivateWifi_5G()
1326{
1327 int Private5GApIndex = 1;
1328
1329 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1330 wifi_setApEnable(Private5GApIndex, FALSE);
1331 wifi_setApEnable(Private5GApIndex, TRUE);
1332 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1333}
1334
1335static int writeBandWidth(int radioIndex,char *bw_value)
1336{
1337 char buf[MAX_BUF_SIZE];
1338 char cmd[MAX_CMD_SIZE];
1339
1340 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
1341 if(_syscmd(cmd, buf, sizeof(buf)))
1342 {
1343 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
1344 _syscmd(cmd, buf, sizeof(buf));
1345 return RETURN_OK;
1346 }
1347
1348 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
1349 _syscmd(cmd,buf,sizeof(buf));
1350 return RETURN_OK;
1351}
1352
1353static int readBandWidth(int radioIndex,char *bw_value)
1354{
1355 char buf[MAX_BUF_SIZE] = {0};
1356 char cmd[MAX_CMD_SIZE] = {0};
1357 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
1358 _syscmd(cmd,buf,sizeof(buf));
1359 if(NULL!=strstr(buf,"20MHz"))
developer72fb0bb2023-01-11 09:46:29 +08001360 strcpy(bw_value,"20MHz");
developer72fb0bb2023-01-11 09:46:29 +08001361 else if(NULL!=strstr(buf,"40MHz"))
developer72fb0bb2023-01-11 09:46:29 +08001362 strcpy(bw_value,"40MHz");
developer72fb0bb2023-01-11 09:46:29 +08001363 else if(NULL!=strstr(buf,"80MHz"))
developer72fb0bb2023-01-11 09:46:29 +08001364 strcpy(bw_value,"80MHz");
developerd1824452023-05-18 12:30:04 +08001365 else if(NULL!=strstr(buf,"160MHz"))
1366 strcpy(bw_value,"160MHz");
1367 else if(NULL!=strstr(buf,"320MHz"))
1368 strcpy(bw_value,"320MHz");
developer72fb0bb2023-01-11 09:46:29 +08001369 else
developer72fb0bb2023-01-11 09:46:29 +08001370 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08001371 return RETURN_OK;
1372}
1373
1374// Input could be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
1375INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
1376{
1377 struct params params={'\0'};
1378 char config_file[MAX_BUF_SIZE] = {0};
1379 char buf[MAX_BUF_SIZE] = {'\0'};
1380
1381 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1382 // Copy the numeric value
1383 if (strlen (beaconRate) >= 5) {
1384 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
1385 buf[strlen(beaconRate) - 4] = '\0';
1386 } else if (strlen(beaconRate) > 0)
1387 strcpy(buf, beaconRate);
1388 else
1389 return RETURN_ERR;
1390
1391 params.name = "beacon_rate";
1392 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
1393 if (strncmp(buf, "5.5", 3) == 0) {
1394 snprintf(buf, sizeof(buf), "55");
1395 params.value = buf;
1396 } else {
1397 strcat(buf, "0");
1398 params.value = buf;
1399 }
1400
1401 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1402 wifi_hostapdWrite(config_file, &params, 1);
1403 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1404 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1405
1406 return RETURN_OK;
1407}
1408
1409INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
1410{
1411 char config_file[128] = {'\0'};
1412 char temp_output[128] = {'\0'};
1413 char buf[128] = {'\0'};
1414 char cmd[128] = {'\0'};
1415 int rate = 0;
1416 int phyId = 0;
1417
1418 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1419 if (NULL == beaconRate)
1420 return RETURN_ERR;
1421
1422 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1423 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
1424 phyId = radio_index_to_phy(radioIndex);
1425 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
1426 if(strlen(buf) > 0) {
1427 if (strncmp(buf, "55", 2) == 0)
1428 snprintf(temp_output, sizeof(temp_output), "5.5Mbps");
1429 else {
1430 rate = strtol(buf, NULL, 10)/10;
1431 snprintf(temp_output, sizeof(temp_output), "%dMbps", rate);
1432 }
1433 } else {
1434 // config not set, so we would use lowest rate as default
1435 sprintf(cmd, "iw phy%d info | grep Bitrates -A1 | tail -n 1 | awk '{print $2}' | tr -d '.0\\n'", phyId);
1436 _syscmd(cmd, buf, sizeof(buf));
1437 snprintf(temp_output, sizeof(temp_output), "%sMbps", buf);
1438 }
1439 strncpy(beaconRate, temp_output, sizeof(temp_output));
1440 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1441
1442 return RETURN_OK;
1443}
1444
1445INT wifi_setLED(INT radioIndex, BOOL enable)
1446{
1447 return 0;
1448}
1449INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
1450{
1451 return RETURN_OK;
1452}
1453/**********************************************************************************
1454 *
developer69b61b02023-03-07 17:17:44 +08001455 * Wifi Subsystem level function prototypes
developer72fb0bb2023-01-11 09:46:29 +08001456 *
1457**********************************************************************************/
1458//---------------------------------------------------------------------------------------------------
1459//Wifi system api
1460//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 +08001461INT wifi_getHalVersion(CHAR *output_string) //RDKB
developer72fb0bb2023-01-11 09:46:29 +08001462{
1463 if(!output_string)
1464 return RETURN_ERR;
1465 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
1466
1467 return RETURN_OK;
1468}
1469
1470
1471/* wifi_factoryReset() function */
1472/**
developer69b61b02023-03-07 17:17:44 +08001473* @description Clears internal variables to implement a factory reset of the Wi-Fi
developer72fb0bb2023-01-11 09:46:29 +08001474* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
1475*
1476* @param None
1477*
1478* @return The status of the operation.
1479* @retval RETURN_OK if successful.
1480* @retval RETURN_ERR if any error is detected
1481*
1482* @execution Synchronous
1483* @sideeffect None
1484*
1485* @note This function must not suspend and must not invoke any blocking system
1486* calls. It should probably just send a message to a driver event handler task.
1487*
1488*/
1489INT wifi_factoryReset()
1490{
developer47cc27a2023-05-17 23:09:58 +08001491 char cmd[MAX_CMD_SIZE] = {0};
1492 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08001493
developer47cc27a2023-05-17 23:09:58 +08001494 /*delete running hostapd conf files*/
1495 wifi_dbg_printf("\n[%s]: deleting hostapd conf file.", __func__);
1496 snprintf(cmd, MAX_CMD_SIZE, "rm -rf /nvram/*.conf");
1497 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08001498
developer47cc27a2023-05-17 23:09:58 +08001499 wifi_PrepareDefaultHostapdConfigs();
1500 wifi_psk_file_reset();
1501
1502 memset(cmd, 0, MAX_CMD_SIZE);
1503 memset(buf, 0, MAX_BUF_SIZE);
1504
1505 snprintf(cmd, MAX_CMD_SIZE, "systemctl restart hostapd.service");
1506 _syscmd(cmd, buf, sizeof(buf));
1507
1508 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08001509}
1510
1511/* wifi_factoryResetRadios() function */
1512/**
1513* @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.
1514*
1515* @param None
1516* @return The status of the operation
1517* @retval RETURN_OK if successful
1518* @retval RETURN_ERR if any error is detected
1519*
1520* @execution Synchronous
1521*
1522* @sideeffect None
1523*
1524* @note This function must not suspend and must not invoke any blocking system
1525* calls. It should probably just send a message to a driver event handler task.
1526*
1527*/
1528INT wifi_factoryResetRadios()
1529{
1530 if((RETURN_OK == wifi_factoryResetRadio(0)) && (RETURN_OK == wifi_factoryResetRadio(1)))
1531 return RETURN_OK;
1532
1533 return RETURN_ERR;
1534}
1535
developerfead3972023-05-25 20:15:02 +08001536ULONG get_radio_reset_cnt(int radioIndex)
1537{
1538 char cmd[MAX_CMD_SIZE] = {0};
1539 char buf[MAX_BUF_SIZE] = {0};
1540 ULONG reset_count = 0;
1541
1542 snprintf(cmd, MAX_CMD_SIZE, "cat %s 2> /dev/null | grep \"^reset%d=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"",
1543 RADIO_RESET_FILE, radioIndex);
1544 _syscmd(cmd, buf, sizeof(buf));
1545
1546 if (strlen(buf) == 0)
1547 return 0;
1548 else {
1549 reset_count = atol(buf);
1550 return reset_count;
1551 }
1552}
1553void update_radio_reset_cnt(int radioIndex)
1554{
1555 char cmd[MAX_CMD_SIZE] = {0};
1556 char buf[MAX_BUF_SIZE] = {0};
1557 ULONG reset_count = 0;
1558
1559 snprintf(cmd, MAX_CMD_SIZE, "cat %s 2> /dev/null | grep \"^reset%d=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"",
1560 RADIO_RESET_FILE, radioIndex);
1561 _syscmd(cmd, buf, sizeof(buf));
1562
1563 if (strlen(buf) == 0)
1564 snprintf(cmd, sizeof(cmd), "sed -i -e '$a reset%d=1' %s", radioIndex, RADIO_RESET_FILE);
1565 else {
1566 reset_count = atol(buf);
1567 reset_count++;
1568 snprintf(cmd, sizeof(cmd), "sed -i \"s/^reset%d=.*/reset%d=%lu/\" %s", radioIndex, radioIndex, reset_count, RADIO_RESET_FILE);
1569 }
1570 _syscmd(cmd, buf, sizeof(buf));
1571}
developer72fb0bb2023-01-11 09:46:29 +08001572
1573/* wifi_factoryResetRadio() function */
1574/**
1575* @description Restore selected radio parameters without touching access point parameters
1576*
1577* @param radioIndex - Index of Wi-Fi Radio channel
1578*
1579* @return The status of the operation.
1580* @retval RETURN_OK if successful.
1581* @retval RETURN_ERR if any error is detected
1582*
1583* @execution Synchronous.
1584* @sideeffect None.
1585*
1586* @note This function must not suspend and must not invoke any blocking system
1587* calls. It should probably just send a message to a driver event handler task.
1588*
1589*/
1590INT wifi_factoryResetRadio(int radioIndex) //RDKB
1591{
developer47cc27a2023-05-17 23:09:58 +08001592 char cmd[MAX_CMD_SIZE] = {0};
1593 char buf[MAX_BUF_SIZE] = {0};
1594 char vap_idx = 0;
developer72fb0bb2023-01-11 09:46:29 +08001595
developer47cc27a2023-05-17 23:09:58 +08001596 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08001597
developerb2977562023-05-24 17:54:12 +08001598 wifi_dat_file_reset_by_radio(radioIndex);
developer47cc27a2023-05-17 23:09:58 +08001599
developerb2977562023-05-24 17:54:12 +08001600 /*reset gi setting*/
1601 snprintf(cmd, sizeof(cmd), "echo 'Auto' > %s%d.txt", GUARD_INTERVAL_FILE, radioIndex);
developer47cc27a2023-05-17 23:09:58 +08001602 _syscmd(cmd, buf, sizeof(buf));
1603
developerb2977562023-05-24 17:54:12 +08001604 /*TBD: check mbss issue*/
1605 wifi_factoryResetAP(radioIndex);
developerfead3972023-05-25 20:15:02 +08001606 update_radio_reset_cnt(radioIndex);
developerb2977562023-05-24 17:54:12 +08001607
developer47cc27a2023-05-17 23:09:58 +08001608 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
1609 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08001610}
1611
1612/* wifi_initRadio() function */
1613/**
1614* Description: This function call initializes the specified radio.
developer69b61b02023-03-07 17:17:44 +08001615* Implementation specifics may dictate the functionality since
developer72fb0bb2023-01-11 09:46:29 +08001616* different hardware implementations may have different initilization requirements.
1617* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
1618*
1619* @return The status of the operation.
1620* @retval RETURN_OK if successful.
1621* @retval RETURN_ERR if any error is detected
1622*
1623* @execution Synchronous.
1624* @sideeffect None.
1625*
1626* @note This function must not suspend and must not invoke any blocking system
1627* calls. It should probably just send a message to a driver event handler task.
1628*
1629*/
1630INT wifi_initRadio(INT radioIndex)
1631{
1632 //TODO: Initializes the wifi subsystem (for specified radio)
1633 return RETURN_OK;
1634}
1635void macfilter_init()
1636{
1637 char count[4]={'\0'};
1638 char buf[253]={'\0'};
1639 char tmp[19]={'\0'};
1640 int dev_count,block,mac_entry=0;
1641 char res[4]={'\0'};
1642 char acl_file_path[64] = {'\0'};
1643 FILE *fp = NULL;
1644 int index=0;
1645 char iface[10]={'\0'};
1646 char config_file[MAX_BUF_SIZE] = {0};
1647
1648
1649 sprintf(acl_file_path,"/tmp/mac_filter.sh");
1650
1651 fp=fopen(acl_file_path,"w+");
1652 if (fp == NULL) {
1653 fprintf(stderr, "%s: failed to open file %s.\n", __func__, acl_file_path);
developer17038e62023-03-02 14:43:43 +08001654 return;
developer72fb0bb2023-01-11 09:46:29 +08001655 }
1656 sprintf(buf,"#!/bin/sh \n");
1657 fprintf(fp,"%s\n",buf);
1658
1659 system("chmod 0777 /tmp/mac_filter.sh");
1660
1661 for(index=0;index<=1;index++)
1662 {
1663 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
1664 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
1665 sprintf(buf,"syscfg get %dcountfilter",index);
1666 _syscmd(buf,count,sizeof(count));
1667 mac_entry=atoi(count);
1668
1669 sprintf(buf,"syscfg get %dblockall",index);
1670 _syscmd(buf,res,sizeof(res));
1671 block = atoi(res);
1672
1673 //Allow only those macs mentioned in ACL
1674 if(block==1)
1675 {
1676 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1677 fprintf(fp,"%s\n",buf);
1678 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1679 {
1680 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1681 _syscmd(buf,tmp,sizeof(tmp));
1682 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
1683 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
1684 fprintf(fp,"%s\n",buf);
1685 }
1686 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
1687 fprintf(fp,"%s\n",buf);
1688 }
1689
1690 //Block all the macs mentioned in ACL
1691 else if(block==2)
1692 {
1693 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1694 fprintf(fp,"%s\n",buf);
1695
1696 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1697 {
1698 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1699 _syscmd(buf,tmp,sizeof(tmp));
1700 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
1701 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
1702 fprintf(fp,"%s\n",buf);
1703 }
1704 }
1705 }
1706 fclose(fp);
1707}
1708
developer17038e62023-03-02 14:43:43 +08001709
1710static void
1711wifi_ParseProfile(void)
1712{
1713 int i;
1714 int max_radio_num = 0;
1715 int card_idx;
1716 int band_idx;
1717 int phy_idx = 0;
developer745f0bd2023-03-06 14:32:53 +08001718 int wireless_mode = 0;
developer17038e62023-03-02 14:43:43 +08001719 char buf[MAX_BUF_SIZE] = {0};
1720 char chip_name[12];
1721 char card_profile[MAX_BUF_SIZE] = {0};
1722 char band_profile[MAX_BUF_SIZE] = {0};
1723 FILE* fp;
1724
1725 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1726
1727 memset(main_prefix, 0, sizeof(main_prefix));
1728 memset(ext_prefix, 0, sizeof(ext_prefix));
1729 memset(default_ssid, 0, sizeof(default_ssid));
developer745f0bd2023-03-06 14:32:53 +08001730 for (i = 0; i < MAX_NUM_RADIOS; i++)
1731 radio_band[i] = band_invalid;
developer17038e62023-03-02 14:43:43 +08001732
1733 if (wifi_getMaxRadioNumber(&max_radio_num) != RETURN_OK) {
1734 /* LOG */
1735 return;
1736 }
1737
1738 for (card_idx = 0; card_idx < 3; card_idx++) {
1739 snprintf(buf, sizeof(buf), "INDEX%d", card_idx);
1740 if (get_value(l1profile, buf, chip_name, sizeof(chip_name)) < 0) {
1741 break;
1742 }
1743 snprintf(buf, sizeof(buf), "INDEX%d_profile_path", card_idx);
1744 if (get_value(l1profile, buf, card_profile, sizeof(card_profile)) < 0) {
1745 break;
1746 }
1747 for (band_idx = 0; band_idx < 3; band_idx++) {
1748 snprintf(buf, sizeof(buf), "BN%d_profile_path", band_idx);
1749 if (get_value(card_profile, buf, band_profile, sizeof(band_profile)) < 0) {
1750 /* LOG */
1751 break;
1752 }
1753
1754 snprintf(buf, sizeof(buf), "INDEX%d_main_ifname", card_idx);
1755 if (get_value_by_idx(l1profile, buf, band_idx, main_prefix[phy_idx], IFNAMSIZ) < 0) {
1756 /* LOG */
1757 }
1758
1759 snprintf(buf, sizeof(buf), "INDEX%d_ext_ifname", card_idx);
1760 if (get_value_by_idx(l1profile, buf, band_idx, ext_prefix[phy_idx], IFNAMSIZ) < 0) {
1761 /* LOG */
1762 }
1763
1764 if (get_value(band_profile, "SSID1", default_ssid[phy_idx], sizeof(default_ssid[phy_idx])) < 0) {
1765 /* LOG */
1766 }
developer745f0bd2023-03-06 14:32:53 +08001767 if (get_value(band_profile, "WirelessMode", buf, sizeof(buf)) < 0) {
1768 /* LOG */
1769 }
1770
1771 wireless_mode = atoi(buf);
1772 switch (wireless_mode) {
1773 case 22:
1774 case 16:
1775 case 6:
1776 case 4:
1777 case 1:
1778 radio_band[phy_idx] = band_2_4;
1779 break;
1780 case 23:
1781 case 17:
1782 case 14:
1783 case 11:
1784 case 2:
1785 radio_band[phy_idx] = band_5;
1786 break;
1787 case 24:
1788 case 18:
1789 radio_band[phy_idx] = band_6;
1790 break;
1791 }
developer17038e62023-03-02 14:43:43 +08001792 phy_idx++;
1793 }
1794 }
1795
1796 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1797}
1798
1799static void
1800wifi_PrepareDefaultHostapdConfigs(void)
1801{
developer0132ed92023-03-21 13:48:53 +08001802 int radio_idx;
1803 int bss_idx;
1804 int ap_idx;
developer0132ed92023-03-21 13:48:53 +08001805 char buf[MAX_BUF_SIZE] = {0};
1806 char config_file[MAX_BUF_SIZE] = {0};
1807 char ssid[MAX_BUF_SIZE] = {0};
1808 char interface[32] = {0};
1809 char ret_buf[MAX_BUF_SIZE] = {0};
1810 char psk_file[64] = {0};
1811 struct params params[3];
developer47cc27a2023-05-17 23:09:58 +08001812 char *band_str[3] = {"2G", "5G", "6G"};
developer17038e62023-03-02 14:43:43 +08001813
developer0132ed92023-03-21 13:48:53 +08001814 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1815 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++) {
developer47cc27a2023-05-17 23:09:58 +08001816
developer0132ed92023-03-21 13:48:53 +08001817 for (bss_idx = 0; bss_idx < 5; bss_idx++) {
developer47cc27a2023-05-17 23:09:58 +08001818 ap_idx = array_index_to_vap_index(radio_idx, bss_idx);
developer0132ed92023-03-21 13:48:53 +08001819
developer47cc27a2023-05-17 23:09:58 +08001820 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_idx);
developere740c2a2023-05-23 18:34:32 +08001821 snprintf(buf, sizeof(buf), "cp /etc/hostapd-%s.conf %s", wifi_band_str[radio_idx], config_file);
developer47cc27a2023-05-17 23:09:58 +08001822 _syscmd(buf, ret_buf, sizeof(ret_buf));
developer17038e62023-03-02 14:43:43 +08001823
developer47cc27a2023-05-17 23:09:58 +08001824 if (radio_idx == band_2_4) {
1825 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_2G, bss_idx);
1826 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI2G, bss_idx);
1827 } else if (radio_idx == band_5) {
1828 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_5G, bss_idx);
1829 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI5G, bss_idx);
1830 } else if (radio_idx == band_6) {
1831 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_6G, bss_idx);
1832 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI6G, bss_idx);
1833 }
developer17038e62023-03-02 14:43:43 +08001834
developer47cc27a2023-05-17 23:09:58 +08001835 /* fix wpa_psk_file path */
1836 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", ap_idx);
developer17038e62023-03-02 14:43:43 +08001837
developer47cc27a2023-05-17 23:09:58 +08001838 params[0].name = "ssid";
1839 params[0].value = ssid;
1840 params[1].name = "interface";
1841 params[1].value = interface;
1842 params[2].name = "wpa_psk_file";
1843 params[2].value = psk_file;
developer17038e62023-03-02 14:43:43 +08001844
developer47cc27a2023-05-17 23:09:58 +08001845 wifi_hostapdWrite(config_file, params, 3);
developer0132ed92023-03-21 13:48:53 +08001846 }
1847 }
1848 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer17038e62023-03-02 14:43:43 +08001849}
1850
1851static void
1852wifiBringUpInterfacesForRadio(int radio_idx)
1853{
developer0132ed92023-03-21 13:48:53 +08001854 int bss_idx;
1855 int ap_idx;
1856 int band_idx;
1857 char cmd[MAX_CMD_SIZE] = {0};
1858 char config_file[MAX_BUF_SIZE] = {0};
1859 char ret_buf[MAX_BUF_SIZE] = {0};
developer8a3bbbf2023-03-15 17:47:23 +08001860 char inf_name[IF_NAME_SIZE] = {0};
developer17038e62023-03-02 14:43:43 +08001861
1862 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer8a3bbbf2023-03-15 17:47:23 +08001863
developered997d32023-04-18 22:45:39 +08001864 bss_idx = 0;
1865 /*TBD: we need refine setup flow and mbss flow*/
1866// for (bss_idx = 0; bss_idx < 5; bss_idx++) {
developer0132ed92023-03-21 13:48:53 +08001867 ap_idx = array_index_to_vap_index(radio_idx, bss_idx);
1868
1869 snprintf(cmd, sizeof(cmd), "touch %s%d.psk", PSK_FILE, ap_idx);
1870 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1871
1872 memset(cmd, 0, MAX_CMD_SIZE);
1873 memset(ret_buf, 0, MAX_BUF_SIZE);
developer17038e62023-03-02 14:43:43 +08001874
developer0132ed92023-03-21 13:48:53 +08001875 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_idx);
1876 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:%s", radio_idx, config_file);
1877 _syscmd(cmd, ret_buf, sizeof(ret_buf));
developer8a3bbbf2023-03-15 17:47:23 +08001878
1879 wifi_GetInterfaceName(ap_idx, inf_name);
1880
1881 memset(cmd, 0, MAX_CMD_SIZE);
1882 memset(ret_buf, 0, MAX_BUF_SIZE);
1883
1884 /* fix vap-status file */
1885 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=1/\" %s", inf_name, inf_name, VAP_STATUS_FILE);
1886 _syscmd(cmd, ret_buf, sizeof(ret_buf));
developered997d32023-04-18 22:45:39 +08001887// }
1888
1889 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer17038e62023-03-02 14:43:43 +08001890}
1891
1892static void
1893wifi_BringUpInterfaces(void)
1894{
1895 int radio_idx;
1896 int bss_idx;
1897 int ap_idx;
1898 int band_idx;
1899 char cmd[MAX_BUF_SIZE] = {0};
1900 char config_file[MAX_BUF_SIZE] = {0};
1901 char ret_buf[MAX_BUF_SIZE]={'\0'};
1902
1903 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1904 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++) {
1905 band_idx = radio_index_to_band(radio_idx);
1906 if (band_idx < 0) {
1907 break;
1908 }
1909 wifiBringUpInterfacesForRadio(radio_idx);
1910 }
1911 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1912}
1913
1914static void
1915wifi_BringDownInterfacesForRadio(int radio_idx)
1916{
1917 int bss_idx;
1918 int ap_idx;
1919 int band_idx;
1920 char cmd[MAX_BUF_SIZE] = {0};
1921 char config_file[MAX_BUF_SIZE] = {0};
1922 char ret_buf[MAX_BUF_SIZE]={'\0'};
1923
1924 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer17038e62023-03-02 14:43:43 +08001925
developer8a3bbbf2023-03-15 17:47:23 +08001926 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s", main_prefix[radio_idx]);
1927 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1928
1929
developer17038e62023-03-02 14:43:43 +08001930 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1931}
1932
1933
1934static void
1935wifi_BringDownInterfaces(void)
1936{
1937 int radio_idx;
1938 int bss_idx;
1939 int ap_idx;
1940 int band_idx;
1941 char cmd[MAX_BUF_SIZE] = {0};
1942 char config_file[MAX_BUF_SIZE] = {0};
1943 char ret_buf[MAX_BUF_SIZE]={'\0'};
1944
1945 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1946 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++) {
1947 band_idx = radio_index_to_band(radio_idx);
1948 if (band_idx < 0) {
1949 break;
1950 }
1951 wifi_BringDownInterfacesForRadio(radio_idx);
1952 }
1953 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1954}
1955
developerb2977562023-05-24 17:54:12 +08001956static void wifi_dat_file_reset()
1957{
1958 char radio_idx = 0;
1959
1960 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++)
1961 wifi_dat_file_reset_by_radio(radio_idx);
1962}
1963
1964static void wifi_dat_file_reset_by_radio(char radio_idx)
1965{
1966 char cmd[MAX_CMD_SIZE] = {0};
1967 char ret_buf[MAX_BUF_SIZE] = {0};
1968 char rom_dat_file[MAX_CMD_SIZE]= {0};
1969 char dat_file[MAX_CMD_SIZE]= {0};
1970
1971 snprintf(rom_dat_file, sizeof(rom_dat_file), "%s%d.dat", ROM_LOGAN_DAT_FILE, radio_idx);
1972 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, radio_idx);
1973 snprintf(cmd, MAX_CMD_SIZE, "cp -rf %s %s", rom_dat_file, dat_file);
1974 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1975
1976}
1977
developer47cc27a2023-05-17 23:09:58 +08001978static void wifi_psk_file_reset()
1979{
1980 char cmd[MAX_CMD_SIZE] = {0};
1981 char ret_buf[MAX_BUF_SIZE] = {0};
1982 char psk_file[MAX_CMD_SIZE]= {0};
1983 char vap_idx = 0;
1984
1985 for (vap_idx = 0; vap_idx < MAX_APS; vap_idx++) {
1986 snprintf(psk_file, sizeof(psk_file), "%s%d.psk", PSK_FILE, vap_idx);
1987
1988 if (access(psk_file, F_OK) != 0) {
1989 snprintf(cmd, MAX_CMD_SIZE, "touch %s", psk_file);
1990 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1991 } else {
1992 snprintf(cmd, MAX_CMD_SIZE, "echo '' > %s", psk_file);
1993 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1994 }
1995 }
1996}
1997
developerb2977562023-05-24 17:54:12 +08001998static void wifi_psk_file_reset_by_radio(char radio_idx)
1999{
2000 char cmd[MAX_CMD_SIZE] = {0};
2001 char ret_buf[MAX_BUF_SIZE] = {0};
2002 char psk_file[MAX_CMD_SIZE]= {0};
2003 char vap_idx = 0;
2004
2005 for (vap_idx = radio_idx; vap_idx < MAX_APS; vap_idx += MAX_NUM_RADIOS) {
2006 snprintf(psk_file, sizeof(psk_file), "%s%d.psk", PSK_FILE, vap_idx);
2007
2008 if (access(psk_file, F_OK) != 0) {
2009 snprintf(cmd, MAX_CMD_SIZE, "touch %s", psk_file);
2010 _syscmd(cmd, ret_buf, sizeof(ret_buf));
2011 } else {
2012 snprintf(cmd, MAX_CMD_SIZE, "echo '' > %s", psk_file);
2013 _syscmd(cmd, ret_buf, sizeof(ret_buf));
2014 }
2015 }
2016
2017}
2018
2019
developer8a3bbbf2023-03-15 17:47:23 +08002020static void wifi_vap_status_reset()
2021{
2022 char cmd[MAX_CMD_SIZE] = {0};
2023 char ret_buf[MAX_BUF_SIZE] = {0};
2024 char radio_idx = 0;
2025 char bss_idx = 0;
developer8666b312023-03-24 14:05:31 +08002026
developer8a3bbbf2023-03-15 17:47:23 +08002027 if (access(VAP_STATUS_FILE, F_OK) != 0) {
2028 snprintf(cmd, MAX_CMD_SIZE, "touch %s", VAP_STATUS_FILE);
2029 _syscmd(cmd, ret_buf, sizeof(ret_buf));
2030 } else {
2031 snprintf(cmd, MAX_CMD_SIZE, "echo '' > %s", VAP_STATUS_FILE);
2032 _syscmd(cmd, ret_buf, sizeof(ret_buf));
2033 }
2034
2035 memset(cmd, 0, MAX_CMD_SIZE);
2036 memset(ret_buf, 0, MAX_BUF_SIZE);
2037
2038 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++)
2039 for (bss_idx = 0; bss_idx < 5; bss_idx++) {
2040 snprintf(cmd, MAX_CMD_SIZE, "echo %s%d=0 >> %s", ext_prefix[radio_idx], bss_idx, VAP_STATUS_FILE);
2041 _syscmd(cmd, ret_buf, sizeof(ret_buf));
2042 }
2043
developerfead3972023-05-25 20:15:02 +08002044}
2045
2046static void wifi_radio_reset_count_reset()
2047{
2048 char cmd[MAX_CMD_SIZE] = {0};
2049 char ret_buf[MAX_BUF_SIZE] = {0};
2050
2051 if (access(VAP_STATUS_FILE, F_OK) != 0) {
2052 snprintf(cmd, MAX_CMD_SIZE, "touch %s", RADIO_RESET_FILE);
2053 _syscmd(cmd, ret_buf, sizeof(ret_buf));
2054 } else {
2055 snprintf(cmd, MAX_CMD_SIZE, "echo '' > %s", RADIO_RESET_FILE);
2056 _syscmd(cmd, ret_buf, sizeof(ret_buf));
2057 }
developer8a3bbbf2023-03-15 17:47:23 +08002058}
developer17038e62023-03-02 14:43:43 +08002059
developer72fb0bb2023-01-11 09:46:29 +08002060// Initializes the wifi subsystem (all radios)
2061INT wifi_init() //RDKB
2062{
developer96b38512023-02-22 11:17:45 +08002063 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developercc9a4f32023-05-30 17:40:02 +08002064 static int CallOnce = 1;
developer96b38512023-02-22 11:17:45 +08002065 //Not intitializing macfilter for Turris-Omnia Platform for now
2066 //macfilter_init();
developercc9a4f32023-05-30 17:40:02 +08002067 if (CallOnce) {
2068 wifi_ParseProfile();
2069 wifi_PrepareDefaultHostapdConfigs();
2070 wifi_psk_file_reset();
2071 //system("/usr/sbin/iw reg set US");
2072 system("systemctl start hostapd.service");
2073 sleep(2);
developer8a3bbbf2023-03-15 17:47:23 +08002074
developercc9a4f32023-05-30 17:40:02 +08002075 wifi_vap_status_reset();
2076 wifi_radio_reset_count_reset();
2077 CallOnce = 0;
2078 }
developer96b38512023-02-22 11:17:45 +08002079
2080 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08002081
2082 return RETURN_OK;
2083}
2084
2085/* wifi_reset() function */
2086/**
2087* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
developer69b61b02023-03-07 17:17:44 +08002088* Implementation specifics may dictate what is actualy reset since
developer72fb0bb2023-01-11 09:46:29 +08002089* different hardware implementations may have different requirements.
2090* Parameters : None
2091*
2092* @return The status of the operation.
2093* @retval RETURN_OK if successful.
2094* @retval RETURN_ERR if any error is detected
2095*
2096* @execution Synchronous.
2097* @sideeffect None.
2098*
2099* @note This function must not suspend and must not invoke any blocking system
2100* calls. It should probably just send a message to a driver event handler task.
2101*
2102*/
2103INT wifi_reset()
2104{
developer17038e62023-03-02 14:43:43 +08002105
2106 wifi_BringDownInterfaces();
2107 sleep(2);
2108
developer96b38512023-02-22 11:17:45 +08002109 //TODO: resets the wifi subsystem, deletes all APs
2110 system("systemctl stop hostapd.service");
2111 sleep(2);
developer17038e62023-03-02 14:43:43 +08002112
developer96b38512023-02-22 11:17:45 +08002113 system("systemctl start hostapd.service");
2114 sleep(5);
developer17038e62023-03-02 14:43:43 +08002115
2116 wifi_PrepareDefaultHostapdConfigs();
developer47cc27a2023-05-17 23:09:58 +08002117 wifi_psk_file_reset();
developer17038e62023-03-02 14:43:43 +08002118 sleep(2);
developer8a3bbbf2023-03-15 17:47:23 +08002119
2120 wifi_vap_status_reset();
2121
developer72fb0bb2023-01-11 09:46:29 +08002122 return RETURN_OK;
2123}
2124
2125/* wifi_down() function */
2126/**
2127* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
developer69b61b02023-03-07 17:17:44 +08002128* Implementation specifics may dictate some functionality since
developer72fb0bb2023-01-11 09:46:29 +08002129* different hardware implementations may have different requirements.
2130*
2131* @param None
2132*
2133* @return The status of the operation
2134* @retval RETURN_OK if successful
2135* @retval RETURN_ERR if any error is detected
2136*
2137* @execution Synchronous
2138* @sideeffect None
2139*
2140* @note This function must not suspend and must not invoke any blocking system
2141* calls. It should probably just send a message to a driver event handler task.
2142*
2143*/
2144INT wifi_down()
2145{
developer96b38512023-02-22 11:17:45 +08002146 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developerb2977562023-05-24 17:54:12 +08002147 int max_num_radios = 0;
2148 wifi_getMaxRadioNumber(&max_num_radios);
developer17038e62023-03-02 14:43:43 +08002149
developerb2977562023-05-24 17:54:12 +08002150 for (int radioIndex = 0; radioIndex < max_num_radios; radioIndex++)
2151 wifi_setRadioEnable(radioIndex, FALSE);
2152
developer72fb0bb2023-01-11 09:46:29 +08002153 return RETURN_OK;
2154}
2155
2156
2157/* wifi_createInitialConfigFiles() function */
2158/**
2159* @description This function creates wifi configuration files. The format
developer69b61b02023-03-07 17:17:44 +08002160* and content of these files are implementation dependent. This function call is
2161* used to trigger this task if necessary. Some implementations may not need this
2162* function. If an implementation does not need to create config files the function call can
developer72fb0bb2023-01-11 09:46:29 +08002163* do nothing and return RETURN_OK.
2164*
2165* @param None
2166*
2167* @return The status of the operation
2168* @retval RETURN_OK if successful
2169* @retval RETURN_ERR if any error is detected
2170*
2171* @execution Synchronous
2172* @sideeffect None
2173*
2174* @note This function must not suspend and must not invoke any blocking system
2175* calls. It should probably just send a message to a driver event handler task.
2176*
2177*/
2178INT wifi_createInitialConfigFiles()
2179{
2180 //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)
2181 return RETURN_OK;
2182}
2183
developer7e4a2a62023-04-06 19:56:03 +08002184/* outputs the country code to a max 64 character string */
developer72fb0bb2023-01-11 09:46:29 +08002185INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
2186{
developerfde01262023-05-22 15:15:24 +08002187 int ret;
developer72fb0bb2023-01-11 09:46:29 +08002188
developerfde01262023-05-22 15:15:24 +08002189 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer7e4a2a62023-04-06 19:56:03 +08002190
developerfde01262023-05-22 15:15:24 +08002191 ret = wifi_BandProfileRead(0, radioIndex, "CountryCode", output_string, 64, NULL);
2192 if (ret != 0) {
2193 fprintf(stderr, "%s: wifi_BandProfileRead CountryCode failed\n", __func__);
2194 return RETURN_ERR;
2195 }
developer7e4a2a62023-04-06 19:56:03 +08002196
developerfde01262023-05-22 15:15:24 +08002197 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer7e4a2a62023-04-06 19:56:03 +08002198
developerfde01262023-05-22 15:15:24 +08002199 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08002200}
2201
2202INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
2203{
developer7e4a2a62023-04-06 19:56:03 +08002204 /*Set wifi config. Wait for wifi reset to apply*/
2205 char str[MAX_BUF_SIZE] = {0};
2206 char cmd[MAX_CMD_SIZE] = {0};
2207 struct params params;
2208 char config_file[MAX_BUF_SIZE] = {0};
2209 int ret = 0;
developer72fb0bb2023-01-11 09:46:29 +08002210
developer7e4a2a62023-04-06 19:56:03 +08002211 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08002212
developer7e4a2a62023-04-06 19:56:03 +08002213 if(NULL == CountryCode || strlen(CountryCode) >= 32 ) {
2214 printf("%s: input para error!!!\n", __func__);
2215 return RETURN_ERR;
2216 }
developer72fb0bb2023-01-11 09:46:29 +08002217
developer7e4a2a62023-04-06 19:56:03 +08002218 if (!strlen(CountryCode))
2219 strncpy(CountryCode, "US", sizeof("US")); /*default set the code to US*/
developer72fb0bb2023-01-11 09:46:29 +08002220
developer7e4a2a62023-04-06 19:56:03 +08002221 params.name = "country_code";
2222 params.value = CountryCode;
developer72fb0bb2023-01-11 09:46:29 +08002223
developer7e4a2a62023-04-06 19:56:03 +08002224 snprintf(config_file, MAX_BUF_SIZE, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2225 ret = wifi_hostapdWrite(config_file, &params, 1);
2226
2227 if (ret) {
2228 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n",
2229 __func__, ret);
2230 }
2231
2232 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2233
2234 if (ret) {
2235 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n",
2236 __func__, ret);
2237 }
2238
2239 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
2240
2241 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08002242}
2243
2244INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
2245{
2246 char interface_name[16] = {0};
2247 char channel_util_file[64] = {0};
2248 char cmd[128] = {0};
2249 char buf[128] = {0};
2250 char line[128] = {0};
2251 char *param = NULL, *value = NULL;
2252 int read = 0;
2253 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
2254 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
2255 size_t len = 0;
2256 FILE *f = NULL;
2257
2258 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2259
2260 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
2261 return RETURN_ERR;
2262 snprintf(cmd, sizeof(cmd), "iw %s scan | grep signal | awk '{print $2}' | sort -n | tail -n1", interface_name);
2263 _syscmd(cmd, buf, sizeof(buf));
2264 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
2265
2266 memset(cmd, 0, sizeof(cmd));
2267 memset(buf, 0, sizeof(buf));
2268 snprintf(cmd, sizeof(cmd), "iw %s survey dump | grep 'in use' -A6", interface_name);
2269 if ((f = popen(cmd, "r")) == NULL) {
2270 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
2271 return RETURN_ERR;
2272 }
2273
2274 read = getline(&line, &len, f);
2275 while (read != -1) {
2276 param = strtok(line, ":\t");
2277 value = strtok(NULL, " ");
2278 if(strstr(param, "frequency") != NULL) {
2279 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
2280 }
2281 if(strstr(param, "noise") != NULL) {
2282 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
2283 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
2284 }
2285 if(strstr(param, "channel active time") != NULL) {
2286 ActiveTime = strtol(value, NULL, 10);
2287 }
2288 if(strstr(param, "channel busy time") != NULL) {
2289 BusyTime = strtol(value, NULL, 10);
2290 }
2291 if(strstr(param, "channel transmit time") != NULL) {
2292 TransmitTime = strtol(value, NULL, 10);
2293 }
2294 read = getline(&line, &len, f);
2295 }
2296 pclose(f);
2297
2298 // The file should store the last active, busy and transmit time
2299 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
2300 f = fopen(channel_util_file, "r");
2301 if (f != NULL) {
2302 read = getline(&line, &len, f);
2303 preActiveTime = strtol(line, NULL, 10);
2304 read = getline(&line, &len, f);
2305 preBusyTime = strtol(line, NULL, 10);
2306 read = getline(&line, &len, f);
2307 preTransmitTime = strtol(line, NULL, 10);
2308 fclose(f);
2309 }
2310
2311 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
2312 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
2313
2314 f = fopen(channel_util_file, "w");
2315 if (f != NULL) {
2316 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
2317 fclose(f);
2318 }
2319 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2320 return RETURN_OK;
2321}
2322
2323/**********************************************************************************
2324 *
2325 * Wifi radio level function prototypes
2326 *
2327**********************************************************************************/
2328
2329//Get the total number of radios in this wifi subsystem
2330INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
2331{
2332 if (NULL == output)
2333 return RETURN_ERR;
2334 *output = MAX_NUM_RADIOS;
2335
2336 return RETURN_OK;
2337}
2338
developer69b61b02023-03-07 17:17:44 +08002339//Get the total number of SSID entries in this wifi subsystem
developer72fb0bb2023-01-11 09:46:29 +08002340INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
2341{
2342 if (NULL == output)
2343 return RETURN_ERR;
2344 *output = MAX_APS;
2345
2346 return RETURN_OK;
2347}
2348
2349//Get the Radio enable config parameter
2350INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
2351{
developer56fbedb2023-05-30 16:47:05 +08002352 char interface_name[16] = {0};
2353 char buf[128] = {0}, cmd[128] = {0};
2354 int apIndex;
2355 int max_radio_num = 0;
developer3a85ab82023-05-25 11:59:38 +08002356
developer56fbedb2023-05-30 16:47:05 +08002357 if (NULL == output_bool)
2358 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08002359
developer56fbedb2023-05-30 16:47:05 +08002360 *output_bool = FALSE;
developer72fb0bb2023-01-11 09:46:29 +08002361
developer56fbedb2023-05-30 16:47:05 +08002362 wifi_getMaxRadioNumber(&max_radio_num);
developer72fb0bb2023-01-11 09:46:29 +08002363
developer56fbedb2023-05-30 16:47:05 +08002364 if (radioIndex >= max_radio_num)
2365 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08002366
developer56fbedb2023-05-30 16:47:05 +08002367 /* loop all interface in radio, if any is enable, reture true, else return false */
2368 for(apIndex = radioIndex; apIndex < MAX_APS; apIndex += max_radio_num)
2369 {
2370 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
2371 continue;
2372 memset(cmd, 0, sizeof(cmd));
2373 sprintf(cmd, "ifconfig %s 2> /dev/null | grep UP", interface_name);
2374 *output_bool = _syscmd(cmd, buf, sizeof(buf)) ? FALSE : TRUE;
2375 if (*output_bool == TRUE)
2376 break;
2377 }
2378
2379 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08002380}
2381
developere82c0ca2023-05-10 16:25:35 +08002382typedef long time_t;
2383static time_t radio_up_time[MAX_NUM_RADIOS];
2384
developer72fb0bb2023-01-11 09:46:29 +08002385INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
2386{
2387 char interface_name[16] = {0};
2388 char cmd[MAX_CMD_SIZE] = {0};
developer8a3bbbf2023-03-15 17:47:23 +08002389 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08002390 int apIndex, ret;
developer69b61b02023-03-07 17:17:44 +08002391 int max_radio_num = 0;
developer72fb0bb2023-01-11 09:46:29 +08002392 int phyId = 0;
2393
2394 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2395
2396 phyId = radio_index_to_phy(radioIndex);
2397
2398 wifi_getMaxRadioNumber(&max_radio_num);
2399
developer8a3bbbf2023-03-15 17:47:23 +08002400 if(enable == FALSE) {
developer47cc27a2023-05-17 23:09:58 +08002401
2402 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
2403 return RETURN_ERR;
2404
2405 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s", interface_name);
developer8a3bbbf2023-03-15 17:47:23 +08002406 _syscmd(cmd, buf, sizeof(buf));
developer56fbedb2023-05-30 16:47:05 +08002407 memset(cmd, 0, sizeof(cmd));
2408 snprintf(cmd, MAX_CMD_SIZE, "ifconfig %s down", interface_name);
2409 _syscmd(cmd, buf, sizeof(buf));
developere82c0ca2023-05-10 16:25:35 +08002410 if(strncmp(buf, "OK", 2))
2411 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
developer8a3bbbf2023-03-15 17:47:23 +08002412 } else {
developere82c0ca2023-05-10 16:25:35 +08002413 for (apIndex = radioIndex; apIndex < MAX_APS; apIndex += max_radio_num) {
developer72fb0bb2023-01-11 09:46:29 +08002414 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
2415 return RETURN_ERR;
2416
developer8a3bbbf2023-03-15 17:47:23 +08002417 memset(cmd, 0, MAX_CMD_SIZE);
2418 memset(buf, 0, MAX_BUF_SIZE);
2419
developer72fb0bb2023-01-11 09:46:29 +08002420 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
2421 _syscmd(cmd, buf, sizeof(buf));
developer8a3bbbf2023-03-15 17:47:23 +08002422
2423 if(*buf == '1') {
developer56fbedb2023-05-30 16:47:05 +08002424 snprintf(cmd, MAX_CMD_SIZE, "ifconfig %s up", interface_name);
2425 _syscmd(cmd, buf, sizeof(buf));
developer8a3bbbf2023-03-15 17:47:23 +08002426
2427 memset(cmd, 0, MAX_CMD_SIZE);
2428 memset(buf, 0, MAX_BUF_SIZE);
2429
developer72fb0bb2023-01-11 09:46:29 +08002430 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
2431 phyId, apIndex);
2432 _syscmd(cmd, buf, sizeof(buf));
developer8a3bbbf2023-03-15 17:47:23 +08002433
developer72fb0bb2023-01-11 09:46:29 +08002434 }
2435 }
developere82c0ca2023-05-10 16:25:35 +08002436 time(&radio_up_time[radioIndex]);
developer72fb0bb2023-01-11 09:46:29 +08002437 }
2438
2439 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2440 return RETURN_OK;
2441}
2442
2443//Get the Radio enable status
2444INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
2445{
2446 if (NULL == output_bool)
2447 return RETURN_ERR;
2448
2449 return wifi_getRadioEnable(radioIndex, output_bool);
2450}
2451
2452//Get the Radio Interface name from platform, eg "wlan0"
2453INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
2454{
2455 if (NULL == output_string || radioIndex>=MAX_NUM_RADIOS || radioIndex<0)
2456 return RETURN_ERR;
2457 return wifi_GetInterfaceName(radioIndex, output_string);
2458}
2459
2460//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
2461//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.
2462INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
2463{
2464 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
2465 // For max bit rate, we should always choose the best MCS
2466 char mode[64] = {0};
2467 char channel_bandwidth_str[64] = {0};
2468 char *tmp = NULL;
2469 UINT mode_map = 0;
2470 UINT num_subcarrier = 0;
2471 UINT code_bits = 0;
2472 float code_rate = 0; // use max code rate
2473 int NSS = 0;
2474 UINT Symbol_duration = 0;
developer69b61b02023-03-07 17:17:44 +08002475 UINT GI_duration = 0;
developer72fb0bb2023-01-11 09:46:29 +08002476 wifi_band band = band_invalid;
2477 wifi_guard_interval_t gi = wifi_guard_interval_auto;
2478 BOOL enable = FALSE;
2479 float bit_rate = 0;
developera1255e42023-05-13 17:45:02 +08002480 int ant_bitmap = 0;
developer72fb0bb2023-01-11 09:46:29 +08002481
2482 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2483 if (NULL == output_string)
2484 return RETURN_ERR;
2485
2486 wifi_getRadioEnable(radioIndex, &enable);
2487 if (enable == FALSE) {
2488 snprintf(output_string, 64, "0 Mb/s");
2489 return RETURN_OK;
2490 }
2491
2492 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
2493 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
2494 return RETURN_ERR;
2495 }
2496
2497 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
2498 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
2499 return RETURN_ERR;
2500 }
2501
2502 if (gi == wifi_guard_interval_3200)
2503 GI_duration = 32;
2504 else if (gi == wifi_guard_interval_1600)
2505 GI_duration = 16;
2506 else if (gi == wifi_guard_interval_800)
2507 GI_duration = 8;
2508 else // auto, 400
2509 GI_duration = 4;
2510
2511 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
2512 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
2513 return RETURN_ERR;
2514 }
2515
2516 if (strstr(channel_bandwidth_str, "80+80") != NULL)
2517 strcpy(channel_bandwidth_str, "160");
2518
2519 if (mode_map & WIFI_MODE_AX) {
2520 if (strstr(channel_bandwidth_str, "160") != NULL)
2521 num_subcarrier = 1960;
2522 else if (strstr(channel_bandwidth_str, "80") != NULL)
2523 num_subcarrier = 980;
2524 else if (strstr(channel_bandwidth_str, "40") != NULL)
2525 num_subcarrier = 468;
2526 else if (strstr(channel_bandwidth_str, "20") != NULL)
2527 num_subcarrier = 234;
2528 code_bits = 10;
2529 code_rate = (float)5/6;
2530 Symbol_duration = 128;
developera1255e42023-05-13 17:45:02 +08002531 GI_duration = 8;/*HE no GI 400ns*/
developer72fb0bb2023-01-11 09:46:29 +08002532 } else if (mode_map & WIFI_MODE_AC) {
2533 if (strstr(channel_bandwidth_str, "160") != NULL)
2534 num_subcarrier = 468;
2535 else if (strstr(channel_bandwidth_str, "80") != NULL)
2536 num_subcarrier = 234;
2537 else if (strstr(channel_bandwidth_str, "40") != NULL)
2538 num_subcarrier = 108;
2539 else if (strstr(channel_bandwidth_str, "20") != NULL)
2540 num_subcarrier = 52;
2541 code_bits = 8;
2542 code_rate = (float)5/6;
2543 Symbol_duration = 32;
2544 } else if (mode_map & WIFI_MODE_N) {
2545 if (strstr(channel_bandwidth_str, "160") != NULL)
2546 num_subcarrier = 468;
2547 else if (strstr(channel_bandwidth_str, "80") != NULL)
2548 num_subcarrier = 234;
2549 else if (strstr(channel_bandwidth_str, "40") != NULL)
2550 num_subcarrier = 108;
2551 else if (strstr(channel_bandwidth_str, "20") != NULL)
2552 num_subcarrier = 52;
2553 code_bits = 6;
2554 code_rate = (float)3/4;
2555 Symbol_duration = 32;
2556 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
2557 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
2558 snprintf(output_string, 64, "65 Mb/s");
2559 return RETURN_OK;
2560 } else {
2561 snprintf(output_string, 64, "0 Mb/s");
2562 return RETURN_OK;
2563 }
2564
2565 // Spatial streams
developera1255e42023-05-13 17:45:02 +08002566 if (wifi_getRadioTxChainMask(radioIndex, &ant_bitmap) != RETURN_OK) {
developer72fb0bb2023-01-11 09:46:29 +08002567 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
2568 return RETURN_ERR;
2569 }
developera1255e42023-05-13 17:45:02 +08002570 for (; ant_bitmap > 0; ant_bitmap >>= 1)
2571 NSS += ant_bitmap & 1;
developer72fb0bb2023-01-11 09:46:29 +08002572
2573 // multiple 10 is to align duration unit (0.1 us)
2574 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
2575 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
developera1255e42023-05-13 17:45:02 +08002576 WIFI_ENTRY_EXIT_DEBUG("%s:num_subcarrier=%d, code_bits=%d, code_rate=%.3f, nss=%d, symbol time=%u, %.1f Mb/s\n",
2577 __func__, num_subcarrier, code_bits, code_rate, NSS, Symbol_duration + GI_duration, bit_rate);
developer72fb0bb2023-01-11 09:46:29 +08002578 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2579
2580 return RETURN_OK;
2581}
2582#if 0
2583INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
2584{
2585 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2586 char cmd[64];
2587 char buf[1024];
2588 int apIndex;
2589
developer69b61b02023-03-07 17:17:44 +08002590 if (NULL == output_string)
developer72fb0bb2023-01-11 09:46:29 +08002591 return RETURN_ERR;
2592
2593 apIndex=(radioIndex==0)?0:1;
2594
2595 snprintf(cmd, sizeof(cmd), "iwconfig %s | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", interface_name);
2596 _syscmd(cmd,buf, sizeof(buf));
2597
2598 snprintf(output_string, 64, "%s", buf);
2599 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2600 return RETURN_OK;
2601}
2602#endif
2603
2604
2605//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
2606//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.
2607INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
2608{
2609 wifi_band band = band_invalid;
2610
2611 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2612 if (NULL == output_string)
2613 return RETURN_ERR;
2614
2615 band = wifi_index_to_band(radioIndex);
2616
2617 memset(output_string, 0, 10);
2618 if (band == band_2_4)
2619 strcpy(output_string, "2.4GHz");
2620 else if (band == band_5)
2621 strcpy(output_string, "5GHz");
2622 else if (band == band_6)
2623 strcpy(output_string, "6GHz");
2624 else
2625 return RETURN_ERR;
2626 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2627
2628 return RETURN_OK;
2629#if 0
2630 char buf[MAX_BUF_SIZE]={'\0'};
2631 char str[MAX_BUF_SIZE]={'\0'};
2632 char cmd[MAX_CMD_SIZE]={'\0'};
2633 char *ch=NULL;
2634 char *ch2=NULL;
2635
2636 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2637 if (NULL == output_string)
2638 return RETURN_ERR;
2639
2640
2641 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2642
2643 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
2644 {
2645 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2646 return RETURN_ERR;
2647 }
2648 ch=strchr(buf,'\n');
2649 *ch='\0';
2650 ch=strchr(buf,'=');
2651 if(ch==NULL)
2652 return RETURN_ERR;
2653
2654
2655 ch++;
2656
2657 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
2658 strcpy(buf,"0");
2659 if(strlen(ch) == 1)
2660 ch=strcat(buf,ch);
2661
2662
2663 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2664
2665 if(_syscmd(cmd,str,64) == RETURN_ERR)
2666 {
2667 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2668 return RETURN_ERR;
2669 }
2670
2671
2672 ch2=strchr(str,'\n');
2673 //replace \n with \0
2674 *ch2='\0';
2675 ch2=strchr(str,'=');
2676 if(ch2==NULL)
2677 {
2678 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2679 return RETURN_ERR;
2680 }
2681 else
2682 wifi_dbg_printf("%s",ch2+1);
2683
2684
2685 ch2++;
2686
2687
2688 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
2689
2690 memset(buf,'\0',sizeof(buf));
2691 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
2692 {
2693 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2694 return RETURN_ERR;
2695 }
2696 if (strstr(buf,"2.4") != NULL )
2697 strcpy(output_string,"2.4GHz");
2698 else if(strstr(buf,"5.") != NULL )
2699 strcpy(output_string,"5GHz");
2700 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2701
2702 return RETURN_OK;
2703#endif
2704}
2705
2706//Get the frequency band at which the radio is operating, eg: "2.4GHz"
2707//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.
2708INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
2709{
2710 wifi_band band = band_invalid;
2711 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2712 if (NULL == output_string)
2713 return RETURN_ERR;
2714 band = wifi_index_to_band(radioIndex);
2715
developer69b61b02023-03-07 17:17:44 +08002716 if (band == band_2_4)
developer72fb0bb2023-01-11 09:46:29 +08002717 snprintf(output_string, 64, "2.4GHz");
2718 else if (band == band_5)
developer69b61b02023-03-07 17:17:44 +08002719 snprintf(output_string, 64, "5GHz");
developer72fb0bb2023-01-11 09:46:29 +08002720 else if (band == band_6)
2721 snprintf(output_string, 64, "6GHz");
2722
2723 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2724
2725 return RETURN_OK;
2726#if 0
2727 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2728 char buf[MAX_BUF_SIZE]={'\0'};
2729 char str[MAX_BUF_SIZE]={'\0'};
2730 char cmd[MAX_CMD_SIZE]={'\0'};
2731 char *ch=NULL;
2732 char *ch2=NULL;
2733 char ch1[5]="0";
2734
2735 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2736
2737 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
2738 {
2739 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2740 return RETURN_ERR;
2741 }
2742
2743 ch=strchr(buf,'\n');
2744 *ch='\0';
2745 ch=strchr(buf,'=');
2746 if(ch==NULL)
2747 return RETURN_ERR;
2748 ch++;
2749
2750 if(strlen(ch)==1)
2751 {
2752 strcat(ch1,ch);
2753
2754 }
2755 else
2756 {
2757 strcpy(ch1,ch);
2758 }
2759
2760
2761
2762 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2763 if(_syscmd(cmd,str,64) == RETURN_ERR)
2764 {
2765 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2766 return RETURN_ERR;
2767 }
2768
2769
2770 ch2=strchr(str,'\n');
2771 //replace \n with \0
2772 *ch2='\0';
2773 ch2=strchr(str,'=');
2774 if(ch2==NULL)
2775 {
2776 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2777 return RETURN_ERR;
2778 }
2779 else
2780 wifi_dbg_printf("%s",ch2+1);
2781 ch2++;
2782
2783
2784 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
2785 memset(buf,'\0',sizeof(buf));
2786 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
2787 {
2788 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2789 return RETURN_ERR;
2790 }
2791
2792
2793 if(strstr(buf,"2.4")!=NULL)
2794 {
2795 strcpy(output_string,"2.4GHz");
2796 }
2797 if(strstr(buf,"5.")!=NULL)
2798 {
2799 strcpy(output_string,"5GHz");
2800 }
2801 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2802 return RETURN_OK;
2803#endif
2804}
2805
2806//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
2807//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.
2808INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
2809{
2810 char cmd[128]={0};
2811 char buf[128]={0};
2812 char temp_output[128] = {0};
2813 wifi_band band;
2814 int phyId = 0;
2815
2816 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer69b61b02023-03-07 17:17:44 +08002817 if (NULL == output_string)
developer72fb0bb2023-01-11 09:46:29 +08002818 return RETURN_ERR;
2819
2820 band = wifi_index_to_band(radioIndex);
2821 if (band == band_2_4) {
2822 strcat(temp_output, "b,g,");
2823 } else if (band == band_5) {
2824 strcat(temp_output, "a,");
2825 }
2826 phyId = radio_index_to_phy(radioIndex);
2827 // ht capabilities
2828 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);
2829 _syscmd(cmd, buf, sizeof(buf));
2830 if (strlen(buf) >= 4 && strncmp(buf, "0x00", 4) != 0) {
2831 strcat(temp_output, "n,");
2832 }
2833
2834 // vht capabilities
2835 if (band == band_5) {
2836 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'VHT Capabilities' | cut -d '(' -f2 | cut -c1-10 | tr -d '\\n'", phyId);
2837 _syscmd(cmd, buf, sizeof(buf));
2838 if (strlen(buf) >= 10 && strncmp(buf, "0x00000000", 10) != 0) {
2839 strcat(temp_output, "ac,");
2840 }
2841 }
2842
2843 // he capabilities
2844 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);
2845 _syscmd(cmd, buf, sizeof(buf));
2846 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
2847 strcat(temp_output, "ax,");
2848 }
2849
developere82c0ca2023-05-10 16:25:35 +08002850 // eht capabilities
2851 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);
2852 _syscmd(cmd, buf, sizeof(buf));
2853 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
2854 strcat(temp_output, "be,");
2855 }
2856
developer72fb0bb2023-01-11 09:46:29 +08002857 // Remove the last comma
2858 if (strlen(temp_output) != 0)
2859 temp_output[strlen(temp_output)-1] = '\0';
2860 strncpy(output_string, temp_output, strlen(temp_output));
2861 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2862 return RETURN_OK;
2863}
2864
2865//Get the radio operating mode, and pure mode flag. eg: "ac"
2866//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.
2867INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
2868{
2869 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2870 if (NULL == output_string)
2871 return RETURN_ERR;
2872
2873 if (radioIndex == 0) {
2874 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
2875 *gOnly = FALSE;
2876 *nOnly = TRUE;
2877 *acOnly = FALSE;
2878 } else {
2879 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
2880 *gOnly = FALSE;
2881 *nOnly = FALSE;
2882 *acOnly = FALSE;
2883 }
2884 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2885
2886 return RETURN_OK;
2887#if 0
2888 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2889 char buf[64] = {0};
2890 char config_file[MAX_BUF_SIZE] = {0};
2891
developer69b61b02023-03-07 17:17:44 +08002892 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
developer72fb0bb2023-01-11 09:46:29 +08002893 return RETURN_ERR;
2894
2895 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2896 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
2897
2898 wifi_dbg_printf("\nhw_mode=%s\n",buf);
developer69b61b02023-03-07 17:17:44 +08002899 if (strlen(buf) == 0)
developer72fb0bb2023-01-11 09:46:29 +08002900 {
2901 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
2902 return RETURN_ERR;
2903 }
2904 if(strcmp(buf,"g")==0)
2905 {
2906 wifi_dbg_printf("\nG\n");
2907 *gOnly=TRUE;
2908 *nOnly=FALSE;
2909 *acOnly=FALSE;
2910 }
2911 else if(strcmp(buf,"n")==0)
2912 {
2913 wifi_dbg_printf("\nN\n");
2914 *gOnly=FALSE;
2915 *nOnly=TRUE;
2916 *acOnly=FALSE;
2917 }
2918 else if(strcmp(buf,"ac")==0)
2919 {
2920 wifi_dbg_printf("\nac\n");
2921 *gOnly=FALSE;
2922 *nOnly=FALSE;
2923 *acOnly=TRUE;
2924 }
2925 /* hostapd-5G.conf has "a" as hw_mode */
2926 else if(strcmp(buf,"a")==0)
2927 {
2928 wifi_dbg_printf("\na\n");
2929 *gOnly=FALSE;
2930 *nOnly=FALSE;
2931 *acOnly=FALSE;
2932 }
2933 else
2934 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
2935
2936 //for a,n mode
2937 if(radioIndex == 1)
2938 {
2939 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
2940 if(strcmp(buf,"1")==0)
2941 {
2942 strncpy(output_string, "n", 1);
2943 *nOnly=FALSE;
2944 }
2945 }
2946
2947 wifi_dbg_printf("\nReturning from getRadioStandard\n");
2948 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2949 return RETURN_OK;
2950#endif
2951}
2952
developer0f10c772023-05-16 21:43:39 +08002953enum WIFI_MODE {
2954 WMODE_INVALID = 0,
2955 WMODE_A = 1 << 0,
2956 WMODE_B = 1 << 1,
2957 WMODE_G = 1 << 2,
2958 WMODE_GN = 1 << 3,
2959 WMODE_AN = 1 << 4,
2960 WMODE_AC = 1 << 5,
2961 WMODE_AX_24G = 1 << 6,
2962 WMODE_AX_5G = 1 << 7,
2963 WMODE_AX_6G = 1 << 8,
2964 WMODE_BE_24G = 1 << 9,
2965 WMODE_BE_5G = 1 << 10,
2966 WMODE_BE_6G = 1 << 11,
2967 /*
2968 * total types of supported wireless mode,
2969 * add this value once yow add new type
2970 */
2971 WMODE_COMP = 12,
2972};
2973
2974#define RADIO_MODE_LEN 32
developerfead3972023-05-25 20:15:02 +08002975
2976int get_radio_mode_handler(struct nl_msg *msg, void *cb)
developer72fb0bb2023-01-11 09:46:29 +08002977{
developerfead3972023-05-25 20:15:02 +08002978 struct nlattr *tb[NL80211_ATTR_MAX + 1];
2979 struct nlattr *vndr_tb[MTK_NL80211_VENDOR_ATTR_GET_RUNTIME_INFO_MAX + 1];
2980 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
2981 unsigned int *phymode;
2982 int err = 0;
2983 struct mtk_nl80211_cb_data *cb_data = cb;
developer72fb0bb2023-01-11 09:46:29 +08002984
developerfead3972023-05-25 20:15:02 +08002985 if (!msg || !cb_data) {
2986 wifi_debug(DEBUG_ERROR, "msg(0x%lx) or cb_data(0x%lx) is null,error.\n", msg, cb_data);
2987 return NL_SKIP;
2988 }
developer72fb0bb2023-01-11 09:46:29 +08002989
developerfead3972023-05-25 20:15:02 +08002990 err = nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
2991 genlmsg_attrlen(gnlh, 0), NULL);
2992 if (err < 0) {
2993 wifi_debug(DEBUG_ERROR, "nla_parse radio nl80211 msg fails,error.\n");
2994 return NL_SKIP;
2995 }
developer0f10c772023-05-16 21:43:39 +08002996
developerfead3972023-05-25 20:15:02 +08002997 if (tb[NL80211_ATTR_VENDOR_DATA]) {
2998 err = nla_parse_nested(vndr_tb, MTK_NL80211_VENDOR_ATTR_GET_RUNTIME_INFO_MAX,
2999 tb[NL80211_ATTR_VENDOR_DATA], NULL);
3000 if (err < 0)
3001 return NL_SKIP;
developer72fb0bb2023-01-11 09:46:29 +08003002
developerfead3972023-05-25 20:15:02 +08003003 if (vndr_tb[MTK_NL80211_VENDOR_ATTR_GET_RUNTIME_INFO_GET_WMODE]) {
3004 phymode = (unsigned int *)nla_data(vndr_tb[MTK_NL80211_VENDOR_ATTR_GET_RUNTIME_INFO_GET_WMODE]);
3005
3006 memset(cb_data->out_buf, 0, cb_data->out_len);
3007 memmove(cb_data->out_buf, phymode, sizeof(unsigned int));
3008 }
3009 } else
3010 wifi_debug(DEBUG_ERROR, "No Stats from driver.\n");
3011
3012 return NL_OK;
3013}
developer0f10c772023-05-16 21:43:39 +08003014
developerfead3972023-05-25 20:15:02 +08003015void phymode_to_puremode(INT radioIndex, CHAR *output_string, UINT *pureMode, UINT phymode)
3016{
3017 wifi_band band;
3018 unsigned char radio_mode_tem_len;
3019
3020 band = wifi_index_to_band(radioIndex);
developer0f10c772023-05-16 21:43:39 +08003021 // puremode is a bit map
developer72fb0bb2023-01-11 09:46:29 +08003022 *pureMode = 0;
developer0f10c772023-05-16 21:43:39 +08003023 memset(output_string, 0, RADIO_MODE_LEN);
3024
3025 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
3026
3027 switch (band) {
3028 case band_2_4:
3029 if (phymode & WMODE_B) {
3030 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "b,");
3031 *pureMode |= WIFI_MODE_B;
3032 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
3033 }
3034 if (phymode & WMODE_G) {
3035 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "g,");
3036 *pureMode |= WIFI_MODE_G;
3037 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
3038 }
3039 if (phymode & WMODE_GN) {
3040 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "n,");
3041 *pureMode |= WIFI_MODE_N;
3042 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
3043 }
3044 if (phymode & WMODE_AX_24G) {
3045 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "ax,");
3046 *pureMode |= WIFI_MODE_AX;
3047 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
3048 }
3049 if (phymode & WMODE_BE_24G) {
3050 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "be,");
3051 *pureMode |= WIFI_MODE_BE;
3052 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
3053 }
3054 break;
3055 case band_5:
3056 if (phymode & WMODE_A) {
3057 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "a,");
3058 *pureMode |= WIFI_MODE_A;
3059 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
3060 }
3061 if (phymode & WMODE_AN) {
3062 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "n,");
3063 *pureMode |= WIFI_MODE_N;
3064 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
3065 }
3066 if (phymode & WMODE_AC) {
3067 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "ac,");
3068 *pureMode |= WIFI_MODE_AC;
3069 }
3070 if (phymode & WMODE_AX_5G) {
3071 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "ax,");
3072 *pureMode |= WIFI_MODE_AX;
3073 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
3074 }
3075 if (phymode & WMODE_BE_5G) {
3076 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "be,");
3077 *pureMode |= WIFI_MODE_BE;
3078 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
3079 }
3080 break;
3081 case band_6:
3082 if (phymode & WMODE_AX_6G) {
3083 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "ax,");
3084 *pureMode |= WIFI_MODE_AX;
3085 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
3086 }
3087 if (phymode & WMODE_BE_6G) {
3088 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "be,");
3089 *pureMode |= WIFI_MODE_BE;
3090 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
3091 }
3092 break;
3093 default:
3094 fprintf(stderr, "%s band_idx invalid\n", __func__);
3095 break;
3096 }
3097
3098 /* Remove the last comma */
3099 if (strlen(output_string) != 0)
3100 output_string[strlen(output_string)-1] = '\0';
developer72fb0bb2023-01-11 09:46:29 +08003101
developerfead3972023-05-25 20:15:02 +08003102}
3103
3104INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
3105{
3106 unsigned int phymode;
3107 char interface_name[IF_NAME_SIZE] = {0};
3108 struct mtk_nl80211_param params;
3109 int ret = -1;
3110 unsigned int if_idx = 0;
3111 struct unl unl_ins;
3112 struct nl_msg *msg = NULL;
3113 struct nlattr * msg_data = NULL;
3114 struct mtk_nl80211_param param;
3115 struct mtk_nl80211_cb_data cb_data;
3116
3117 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3118 if(NULL == output_string || NULL == pureMode)
3119 return RETURN_ERR;
3120
3121 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3122 return RETURN_ERR;
3123
3124 if_idx = if_nametoindex(interface_name);
3125 if (!if_idx) {
3126 wifi_debug(DEBUG_ERROR, "can't finde ifname(%s) index,ERROR\n", interface_name);
3127 return RETURN_ERR;
3128 }
3129 /*init mtk nl80211 vendor cmd*/
3130 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_GET_RUNTIME_INFO;
3131 param.if_type = NL80211_ATTR_IFINDEX;
3132 param.if_idx = if_idx;
3133
3134 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
3135 if (ret) {
3136 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
3137 return RETURN_ERR;
3138 }
3139
3140 /*add mtk vendor cmd data*/
3141 if (nla_put_u16(msg, MTK_NL80211_VENDOR_ATTR_GET_RUNTIME_INFO_GET_WMODE, 0)) {
3142 wifi_debug(DEBUG_ERROR, "Nla put GET_RUNTIME_INFO_GET_WMODE attribute error\n");
3143 nlmsg_free(msg);
3144 goto err;
3145 }
3146
3147 /*send mtk nl80211 vendor msg*/
3148 cb_data.out_buf = (char *)&phymode;
3149 cb_data.out_len = sizeof(unsigned int);
3150
3151 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, get_radio_mode_handler, &cb_data);
3152
3153 if (ret) {
3154 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
3155 goto err;
3156 }
3157 /*deinit mtk nl80211 vendor msg*/
3158 mtk_nl80211_deint(&unl_ins);
3159
3160 phymode_to_puremode(radioIndex, output_string, pureMode, phymode);
3161 wifi_debug(DEBUG_NOTICE,"send cmd success\n");
3162
developer72fb0bb2023-01-11 09:46:29 +08003163 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3164 return RETURN_OK;
developerfead3972023-05-25 20:15:02 +08003165err:
3166 mtk_nl80211_deint(&unl_ins);
3167 wifi_debug(DEBUG_ERROR,"send cmd fails\n");
3168 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08003169}
3170
3171// Set the radio operating mode, and pure mode flag.
3172INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
3173{
developer69b61b02023-03-07 17:17:44 +08003174 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
developer72fb0bb2023-01-11 09:46:29 +08003175 if (strcmp (channelMode,"11A") == 0)
3176 {
3177 writeBandWidth(radioIndex,"20MHz");
3178 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
3179 printf("\nChannel Mode is 802.11a (5GHz)\n");
3180 }
3181 else if (strcmp (channelMode,"11NAHT20") == 0)
3182 {
3183 writeBandWidth(radioIndex,"20MHz");
3184 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
3185 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
3186 }
3187 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
3188 {
3189 writeBandWidth(radioIndex,"40MHz");
3190 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
3191 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
3192 }
3193 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
3194 {
3195 writeBandWidth(radioIndex,"40MHz");
3196 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
3197 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
3198 }
3199 else if (strcmp (channelMode,"11ACVHT20") == 0)
3200 {
3201 writeBandWidth(radioIndex,"20MHz");
3202 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
3203 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
3204 }
3205 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
3206 {
3207 writeBandWidth(radioIndex,"40MHz");
3208 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
3209 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
3210 }
3211 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
3212 {
3213 writeBandWidth(radioIndex,"40MHz");
3214 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
3215 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
3216 }
3217 else if (strcmp (channelMode,"11ACVHT80") == 0)
3218 {
3219 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
3220 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
3221 }
3222 else if (strcmp (channelMode,"11ACVHT160") == 0)
3223 {
3224 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
3225 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
developer69b61b02023-03-07 17:17:44 +08003226 }
developer72fb0bb2023-01-11 09:46:29 +08003227 else if (strcmp (channelMode,"11B") == 0)
3228 {
3229 writeBandWidth(radioIndex,"20MHz");
3230 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
3231 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
3232 }
3233 else if (strcmp (channelMode,"11G") == 0)
3234 {
3235 writeBandWidth(radioIndex,"20MHz");
3236 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
3237 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
3238 }
3239 else if (strcmp (channelMode,"11NGHT20") == 0)
3240 {
3241 writeBandWidth(radioIndex,"20MHz");
3242 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
3243 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
3244 }
3245 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
3246 {
3247 writeBandWidth(radioIndex,"40MHz");
3248 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
3249 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
3250 }
3251 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
3252 {
3253 writeBandWidth(radioIndex,"40MHz");
3254 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
3255 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
3256 }
developer69b61b02023-03-07 17:17:44 +08003257 else
developer72fb0bb2023-01-11 09:46:29 +08003258 {
3259 return RETURN_ERR;
3260 }
3261 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3262
3263 return RETURN_OK;
3264}
3265
developer0f10c772023-05-16 21:43:39 +08003266typedef enum _RT_802_11_PHY_MODE {
3267 PHY_11BG_MIXED = 0,
3268 PHY_11B = 1,
3269 PHY_11A = 2,
3270 PHY_11ABG_MIXED = 3,
3271 PHY_11G = 4,
3272 PHY_11ABGN_MIXED = 5, /* both band 5 */
3273 PHY_11N_2_4G = 6, /* 11n-only with 2.4G band 6 */
3274 PHY_11GN_MIXED = 7, /* 2.4G band 7 */
3275 PHY_11AN_MIXED = 8, /* 5G band 8 */
3276 PHY_11BGN_MIXED = 9, /* if check 802.11b. 9 */
3277 PHY_11AGN_MIXED = 10, /* if check 802.11b. 10 */
3278 PHY_11N_5G = 11, /* 11n-only with 5G band 11 */
3279 PHY_11VHT_N_ABG_MIXED = 12, /* 12 -> AC/A/AN/B/G/GN mixed */
3280 PHY_11VHT_N_AG_MIXED = 13, /* 13 -> AC/A/AN/G/GN mixed */
3281 PHY_11VHT_N_A_MIXED = 14, /* 14 -> AC/AN/A mixed in 5G band */
3282 PHY_11VHT_N_MIXED = 15, /* 15 -> AC/AN mixed in 5G band */
3283 PHY_11AX_24G = 16,
3284 PHY_11AX_5G = 17,
3285 PHY_11AX_6G = 18,
3286 PHY_11AX_24G_6G = 19,
3287 PHY_11AX_5G_6G = 20,
3288 PHY_11AX_24G_5G_6G = 21,
3289 PHY_11BE_24G = 22,
3290 PHY_11BE_5G = 23,
3291 PHY_11BE_6G = 24,
3292 PHY_11BE_24G_6G = 25,
3293 PHY_11BE_5G_6G = 26,
3294 PHY_11BE_24G_5G_6G = 27,
3295 PHY_MODE_MAX,
3296} RT_802_11_PHY_MODE;
3297
3298unsigned int puremode_to_wireless_mode(INT radioIndex, UINT pureMode)
3299{
3300 int band_idx = 0;
developerfead3972023-05-25 20:15:02 +08003301 unsigned char wireless_mode = PHY_MODE_MAX;
developer0f10c772023-05-16 21:43:39 +08003302
3303 band_idx = radio_index_to_band(radioIndex);
3304
3305 switch (band_idx) {
3306 case band_2_4:
3307 if (pureMode == (WIFI_MODE_G | WIFI_MODE_N))
3308 wireless_mode = PHY_11GN_MIXED;
3309 if (pureMode == (WIFI_MODE_B | WIFI_MODE_G | WIFI_MODE_N))
3310 wireless_mode = PHY_11BGN_MIXED;
3311 if (pureMode & WIFI_MODE_AX)
3312 wireless_mode = PHY_11AX_24G;
3313 if (pureMode & WIFI_MODE_BE)
3314 wireless_mode = PHY_11BE_24G;
3315 break;
3316 case band_5:
3317 if (pureMode == WIFI_MODE_N)
3318 wireless_mode = PHY_11N_5G;
3319 if ((pureMode == WIFI_MODE_AC) || (pureMode == (WIFI_MODE_N | WIFI_MODE_AC)))
3320 wireless_mode = PHY_11VHT_N_MIXED;
3321 if (pureMode == (WIFI_MODE_A | WIFI_MODE_N | WIFI_MODE_AC))
3322 wireless_mode = PHY_11VHT_N_A_MIXED;
3323 if (pureMode & WIFI_MODE_AX)
3324 wireless_mode = PHY_11AX_5G;
3325 if (pureMode & WIFI_MODE_BE)
3326 wireless_mode = PHY_11BE_5G;
3327 break;
3328 case band_6:
3329 if (pureMode & WIFI_MODE_AX)
3330 wireless_mode = PHY_11AX_6G;
3331 if (pureMode & WIFI_MODE_BE)
3332 wireless_mode = PHY_11BE_6G;
3333 break;
3334 default:
3335 fprintf(stderr, "%s band_idx invalid\n", __func__);
3336 break;
3337 }
3338
3339 return wireless_mode;
3340}
3341
developer72fb0bb2023-01-11 09:46:29 +08003342// Set the radio operating mode, and pure mode flag.
3343INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
3344{
developerfead3972023-05-25 20:15:02 +08003345 unsigned char wireless_mode = PHY_MODE_MAX;
developer69b61b02023-03-07 17:17:44 +08003346
developer0f10c772023-05-16 21:43:39 +08003347 char interface_name[IF_NAME_SIZE] = {0};
developerfead3972023-05-25 20:15:02 +08003348 int ret = -1;
3349 unsigned int if_idx = 0;
3350 struct unl unl_ins;
3351 struct nl_msg *msg = NULL;
3352 struct nlattr * msg_data = NULL;
3353 struct mtk_nl80211_param param;
developer72fb0bb2023-01-11 09:46:29 +08003354
developer0f10c772023-05-16 21:43:39 +08003355 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08003356
developer0f10c772023-05-16 21:43:39 +08003357 wireless_mode = puremode_to_wireless_mode(radioIndex, pureMode);
developer72fb0bb2023-01-11 09:46:29 +08003358
developer0f10c772023-05-16 21:43:39 +08003359 if (wireless_mode == PHY_MODE_MAX) {
3360 fprintf(stderr, "%s wireless_mode invalid pureMode = %x\n", __func__, pureMode);
3361 return RETURN_ERR;
3362 }
developer72fb0bb2023-01-11 09:46:29 +08003363
developer0f10c772023-05-16 21:43:39 +08003364 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3365 return RETURN_ERR;
developerfead3972023-05-25 20:15:02 +08003366
3367 if_idx = if_nametoindex(interface_name);
3368 if (!if_idx) {
3369 wifi_debug(DEBUG_ERROR,"can't finde ifname(%s) index,ERROR\n", interface_name);
3370 return RETURN_ERR;
3371 }
3372 /*init mtk nl80211 vendor cmd*/
3373 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_AP_BSS;
3374 param.if_type = NL80211_ATTR_IFINDEX;
3375 param.if_idx = if_idx;
3376
3377 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
3378 if (ret) {
3379 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
3380 return RETURN_ERR;
3381 }
3382
3383 /*add mtk vendor cmd data*/
3384 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_AP_WIRELESS_MODE, wireless_mode)) {
3385 wifi_debug(DEBUG_ERROR, "Nla put AP_WIRELESS_MODE attribute error\n");
3386 nlmsg_free(msg);
3387 goto err;
3388 }
3389 /*send mtk nl80211 vendor msg*/
3390 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
3391 if (ret) {
3392 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
3393 goto err;
3394 }
3395 /*deinit mtk nl80211 vendor msg*/
3396 mtk_nl80211_deint(&unl_ins);
3397 wifi_debug(DEBUG_NOTICE, "set cmd success.\n");
developer72fb0bb2023-01-11 09:46:29 +08003398
developer0f10c772023-05-16 21:43:39 +08003399 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3400
3401 return RETURN_OK;
developerfead3972023-05-25 20:15:02 +08003402err:
3403 mtk_nl80211_deint(&unl_ins);
3404 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
3405 return RETURN_ERR;
developer0f10c772023-05-16 21:43:39 +08003406}
3407
3408INT wifi_setRadioMode_by_dat(INT radioIndex, UINT pureMode)
3409{
developerfead3972023-05-25 20:15:02 +08003410 unsigned char wireless_mode = PHY_MODE_MAX;
developer0f10c772023-05-16 21:43:39 +08003411 char interface_name[IF_NAME_SIZE] = {0};
developer0f10c772023-05-16 21:43:39 +08003412 char buf[MAX_BUF_SIZE] = {0};
developer0f10c772023-05-16 21:43:39 +08003413 char dat_file[MAX_BUF_SIZE] = {0};
3414 struct params params={0};
3415
3416 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, pureMode, __LINE__);
3417
3418 wireless_mode = puremode_to_wireless_mode(radioIndex, pureMode);
3419
3420 if (wireless_mode == PHY_MODE_MAX) {
3421 fprintf(stderr, "%s wireless_mode invalid pureMode = %x\n", __func__, pureMode);
3422 return RETURN_ERR;
3423 }
3424
3425 params.name = "WirelessMode";
3426 snprintf(buf, sizeof(buf), "%d", wireless_mode);
3427 params.value = buf;
3428
3429 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, radioIndex);
3430 wifi_datfileWrite(dat_file, &params, 1);
3431
developer72fb0bb2023-01-11 09:46:29 +08003432 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3433
3434 return RETURN_OK;
3435}
3436
3437INT wifi_setRadioHwMode(INT radioIndex, CHAR *hw_mode) {
3438
3439 char config_file[64] = {0};
3440 char buf[64] = {0};
3441 struct params params = {0};
3442 wifi_band band = band_invalid;
3443
3444 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3445
3446 band = wifi_index_to_band(radioIndex);
3447
3448 if (strncmp(hw_mode, "a", 1) == 0 && (band != band_5 && band != band_6))
3449 return RETURN_ERR;
3450 else if ((strncmp(hw_mode, "b", 1) == 0 || strncmp(hw_mode, "g", 1) == 0) && band != band_2_4)
3451 return RETURN_ERR;
3452 else if ((strncmp(hw_mode, "a", 1) && strncmp(hw_mode, "b", 1) && strncmp(hw_mode, "g", 1)) || band == band_invalid)
3453 return RETURN_ERR;
3454
3455 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3456 params.name = "hw_mode";
3457 params.value = hw_mode;
3458 wifi_hostapdWrite(config_file, &params, 1);
3459 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3460
3461 if (band == band_2_4) {
3462 if (strncmp(hw_mode, "b", 1) == 0) {
3463 wifi_setRadioMode(radioIndex, "20MHz", WIFI_MODE_B);
3464 snprintf(buf, sizeof(buf), "%s", "1,2,5.5,11");
3465 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
3466 snprintf(buf, sizeof(buf), "%s", "1,2");
3467 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
3468 } else {
3469 // We don't set mode here, because we don't know whitch mode should be set (g, n or ax?).
3470
3471 snprintf(buf, sizeof(buf), "%s", "6,9,12,18,24,36,48,54");
3472 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
3473 snprintf(buf, sizeof(buf), "%s", "6,12,24");
3474 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
3475 }
3476 }
3477
3478 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3479 return RETURN_OK;
3480}
3481
3482INT wifi_setNoscan(INT radioIndex, CHAR *noscan)
3483{
3484 char config_file[64] = {0};
3485 struct params params = {0};
3486 wifi_band band = band_invalid;
3487
3488 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3489
3490 band = wifi_index_to_band(radioIndex);
3491 if (band != band_2_4)
3492 return RETURN_OK;
3493
3494 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3495 params.name = "noscan";
3496 params.value = noscan;
3497 wifi_hostapdWrite(config_file, &params, 1);
3498 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3499
3500 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3501 return RETURN_OK;
3502}
3503
3504//Get the list of supported channel. eg: "1-11"
3505//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.
3506INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
3507{
3508 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer69b61b02023-03-07 17:17:44 +08003509 if (NULL == output_string)
developer72fb0bb2023-01-11 09:46:29 +08003510 return RETURN_ERR;
3511 char cmd[256] = {0};
3512 char buf[128] = {0};
3513 BOOL dfs_enable = false;
3514 int phyId = 0;
3515
3516 // Parse possible channel number and separate them with commas.
3517 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
3518 phyId = radio_index_to_phy(radioIndex);
3519 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
3520 if (dfs_enable)
3521 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 +08003522 else
developer72fb0bb2023-01-11 09:46:29 +08003523 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);
3524
3525 _syscmd(cmd,buf,sizeof(buf));
3526 strncpy(output_string, buf, sizeof(buf));
3527
3528 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3529 return RETURN_OK;
3530}
developerd1824452023-05-18 12:30:04 +08003531//Getting current radio extension channel
3532INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
3533{
3534 CHAR buf[150] = {0};
3535 CHAR cmd[150] = {0};
3536
3537 wifi_datfileRead(file, "HT_EXTCHA", buf, sizeof(buf));
developer262f4cb2023-05-24 12:22:04 +08003538 if (strncmp(buf, "Below", 5) == 0) //below
developerd1824452023-05-18 12:30:04 +08003539 strcpy(Value,"BelowControlChannel");
developer262f4cb2023-05-24 12:22:04 +08003540 if(strncmp(buf, "Above", 5) == 0) //above
developerd1824452023-05-18 12:30:04 +08003541 strcpy(Value,"AboveControlChannel");
3542 return RETURN_OK;
3543}
developerf6a87542023-05-16 15:47:28 +08003544
developer72fb0bb2023-01-11 09:46:29 +08003545//Get the list for used channel. eg: "1,6,9,11"
3546//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.
3547INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
3548{
3549 char interface_name[16] = {0};
3550 char cmd[128] = {0};
3551 char buf[128] = {0};
3552 char config_file[64] = {0};
3553 int channel = 0;
3554 int freq = 0;
3555 int bandwidth = 0;
3556 int center_freq = 0;
3557 int center_channel = 0;
3558 int channel_delta = 0;
3559 wifi_band band = band_invalid;
3560
3561 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3562
3563 if (NULL == output_string)
3564 return RETURN_ERR;
3565
3566 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3567 return RETURN_ERR;
3568 sprintf(cmd, "iw %s info | grep channel | sed -e 's/[^0-9 ]//g'", interface_name);
3569 _syscmd(cmd, buf, sizeof(buf));
3570 if (strlen(buf) == 0) {
3571 fprintf(stderr, "%s: failed to get channel information from iw.\n", __func__);
3572 return RETURN_ERR;
3573 }
3574 sscanf(buf, "%d %d %d %*d %d", &channel, &freq, &bandwidth, &center_freq);
3575
3576 if (bandwidth == 20) {
3577 snprintf(output_string, 256, "%d", channel);
3578 return RETURN_OK;
3579 }
3580
3581 center_channel = ieee80211_frequency_to_channel(center_freq);
3582
3583 band = wifi_index_to_band(radioIndex);
3584 if (band == band_2_4 && bandwidth == 40) {
developerd1824452023-05-18 12:30:04 +08003585 sprintf(config_file, "%s%d.dat", LOGAN_DAT_FILE, band);
developer72fb0bb2023-01-11 09:46:29 +08003586 memset(buf, 0, sizeof(buf));
3587 wifi_halgetRadioExtChannel(config_file, buf); // read ht_capab for HT40+ or -
3588
3589 if (strncmp(buf, "AboveControlChannel", strlen("AboveControlChannel")) == 0 && channel < 10) {
3590 snprintf(output_string, 256, "%d,%d", channel, channel+4);
3591 } else if (strncmp(buf, "BelowControlChannel", strlen("BelowControlChannel")) == 0 && channel > 4) {
3592 snprintf(output_string, 256, "%d,%d", channel-4, channel);
3593 } else {
3594 fprintf(stderr, "%s: invalid channel %d set with %s\n.", __func__, channel, buf);
3595 return RETURN_ERR;
3596 }
3597 } else if (band == band_5 || band == band_6){
3598 // 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 +08003599 // 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 +08003600 channel_delta = (bandwidth-20)/10;
developerd1824452023-05-18 12:30:04 +08003601 memset(output_string, 0, 256);
3602 for (int i = center_channel-channel_delta; i <= center_channel+channel_delta; i+=4) {
3603 // If i is not the last channel, we add a comma.
3604 snprintf(buf, sizeof(buf), "%d%s", i, i==center_channel+channel_delta?"":",");
3605 strncat(output_string, buf, strlen(buf));
3606 }
developer72fb0bb2023-01-11 09:46:29 +08003607 } else
3608 return RETURN_ERR;
3609
3610 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3611 return RETURN_OK;
3612}
3613
developer69b61b02023-03-07 17:17:44 +08003614//Get the running channel number
developerd1824452023-05-18 12:30:04 +08003615INT wifi_getRadioChannel(INT radioIndex, ULONG *output_ulong) //RDKB
developer72fb0bb2023-01-11 09:46:29 +08003616{
3617 char channel_str[16] = {0};
3618 char config_file[128] = {0};
developer47a56bf2023-05-30 13:38:57 +08003619 char buf[MAX_BUF_SIZE] = {0};
3620 char cmd[MAX_CMD_SIZE] = {0};
3621 char interface_name[IF_NAME_SIZE] = {0};
developerd1824452023-05-18 12:30:04 +08003622 wifi_band band = band_invalid;
developer47a56bf2023-05-30 13:38:57 +08003623 bool *output_bool = FALSE;
3624 int channel = 0;
3625 ULONG iwChannel = 0;
3626
developer72fb0bb2023-01-11 09:46:29 +08003627
3628 if (output_ulong == NULL)
3629 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08003630 band = wifi_index_to_band(radioIndex);
3631 snprintf(config_file, sizeof(config_file), "%s%d.dat", LOGAN_DAT_FILE, band);
3632 wifi_datfileRead(config_file, "Channel", channel_str, sizeof(channel_str));
developer72fb0bb2023-01-11 09:46:29 +08003633 *output_ulong = strtoul(channel_str, NULL, 10);
developer47a56bf2023-05-30 13:38:57 +08003634 if (*output_ulong == 0) {
3635 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3636 return RETURN_ERR;
3637 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2", interface_name);
3638 _syscmd(cmd,buf,sizeof(buf));
3639 sscanf(buf, "%lu", &iwChannel);
3640 *output_ulong = iwChannel;
3641 }
developer72fb0bb2023-01-11 09:46:29 +08003642
3643 return RETURN_OK;
3644}
3645
developer72fb0bb2023-01-11 09:46:29 +08003646INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
3647{
3648 char cmd[1024] = {0}, buf[5] = {0};
3649 char interface_name[16] = {0};
3650
3651 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3652 if (NULL == output_ulong)
3653 return RETURN_ERR;
3654
developer47a56bf2023-05-30 13:38:57 +08003655 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72fb0bb2023-01-11 09:46:29 +08003656 return RETURN_ERR;
developer47a56bf2023-05-30 13:38:57 +08003657
3658 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2", interface_name);
developer72fb0bb2023-01-11 09:46:29 +08003659 _syscmd(cmd,buf,sizeof(buf));
3660 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
3661 if (*output_ulong == 0) {
3662 return RETURN_ERR;
3663 }
3664
3665 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3666 return RETURN_OK;
3667}
developer72fb0bb2023-01-11 09:46:29 +08003668//Storing the previous channel value
3669INT wifi_storeprevchanval(INT radioIndex)
3670{
3671 char buf[256] = {0};
3672 char output[4]={'\0'};
3673 char config_file[MAX_BUF_SIZE] = {0};
developerd1824452023-05-18 12:30:04 +08003674 wifi_band band = band_invalid;
3675
3676 band = wifi_index_to_band(radioIndex);
3677 if (band == band_invalid) {
3678 return RETURN_ERR;
3679 wifi_dbg_printf("[%s]: Invalid radio index", __func__);
3680 }
3681 snprintf(config_file, sizeof(config_file), "%s%d.dat",LOGAN_DAT_FILE, band);
3682 wifi_datfileRead(config_file, "Channel", output, sizeof(output));
3683
3684 if(band == band_2_4)
developer72fb0bb2023-01-11 09:46:29 +08003685 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
developerd1824452023-05-18 12:30:04 +08003686 else if(band == band_5)
developer72fb0bb2023-01-11 09:46:29 +08003687 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
developerd1824452023-05-18 12:30:04 +08003688 else
3689 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval6G_AutoChannelEnable");
developer72fb0bb2023-01-11 09:46:29 +08003690 system(buf);
3691 Radio_flag = FALSE;
3692 return RETURN_OK;
3693}
3694
3695//Set the running channel number
3696INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
3697{
3698 // We only write hostapd config here
3699 char str_channel[8]={0};
3700 char *list_channel;
3701 char config_file[128] = {0};
3702 char possible_channels[256] = {0};
developerd1824452023-05-18 12:30:04 +08003703 char config_file_dat[128] = {0};
developer72fb0bb2023-01-11 09:46:29 +08003704 int max_radio_num = 0;
3705 struct params list = {0};
developerd1824452023-05-18 12:30:04 +08003706 struct params dat = {0};
3707 struct params acs = {0};
3708 wifi_band band = band_invalid;
3709 bool acs_channel = false;
developer72fb0bb2023-01-11 09:46:29 +08003710
3711 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3712
developerd1824452023-05-18 12:30:04 +08003713 if (channel == 0)
3714 acs_channel = true;
developer72fb0bb2023-01-11 09:46:29 +08003715 // Check valid
3716 sprintf(str_channel, "%lu", channel);
3717
developerd1824452023-05-18 12:30:04 +08003718
developer72fb0bb2023-01-11 09:46:29 +08003719 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
3720 list_channel = strtok(possible_channels, ",");
3721 while(true)
3722 {
3723 if(list_channel == NULL) { // input not in the list
3724 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
3725 return RETURN_ERR;
3726 }
3727 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
3728 break;
3729 list_channel = strtok(NULL, ",");
3730 }
developerd1824452023-05-18 12:30:04 +08003731 /*
developer72fb0bb2023-01-11 09:46:29 +08003732 list.name = "channel";
3733 list.value = str_channel;
3734 wifi_getMaxRadioNumber(&max_radio_num);
3735 for(int i=0; i<=MAX_APS/max_radio_num;i++)
3736 {
3737 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
3738 wifi_hostapdWrite(config_file, &list, 1);
3739 }
developerd1824452023-05-18 12:30:04 +08003740 */
3741 dat.name = "Channel";
3742 dat.value = str_channel;
3743 band = wifi_index_to_band(radioIndex);
3744 snprintf(config_file_dat, sizeof(config_file_dat), "%s%d.dat", LOGAN_DAT_FILE, band);
3745 wifi_datfileWrite(config_file_dat, &dat, 1);
3746 if (acs_channel == true) {
3747 acs.name = "AutoChannelSelect";
3748 acs.value = "3";
3749 } else {
3750 acs.name = "AutoChannelSelect";
3751 acs.value = "0";
3752 }
3753 wifi_datfileWrite(config_file_dat, &acs, 1);
developerc0772e62023-05-18 15:10:48 +08003754 wifi_reloadAp(radioIndex);
developer72fb0bb2023-01-11 09:46:29 +08003755 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3756 return RETURN_OK;
3757}
3758
3759INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
3760{
3761 struct params list[2];
3762 char str_idx[16];
3763 char config_file[64];
3764 int max_num_radios = 0;
3765 wifi_band band = band_invalid;
3766
3767 band = wifi_index_to_band(radioIndex);
3768 if (band == band_2_4)
3769 return RETURN_OK;
3770
3771 snprintf(str_idx, sizeof(str_idx), "%lu", channel);
3772 list[0].name = "vht_oper_centr_freq_seg0_idx";
3773 list[0].value = str_idx;
3774 list[1].name = "he_oper_centr_freq_seg0_idx";
3775 list[1].value = str_idx;
3776
3777 wifi_getMaxRadioNumber(&max_num_radios);
3778 for(int i=0; i<=MAX_APS/max_num_radios; i++)
3779 {
3780 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
3781 if (band == band_6)
3782 wifi_hostapdWrite(config_file, &list[1], 1);
3783 else
3784 wifi_hostapdWrite(config_file, list, 2);
3785 }
3786
3787 return RETURN_OK;
3788}
3789
3790//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
3791//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
3792INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
3793{
3794 //Set to wifi config only. Wait for wifi reset to apply.
3795 char buf[256] = {0};
3796 char str_channel[256] = {0};
3797 int count = 0;
3798 ULONG Value = 0;
3799 FILE *fp = NULL;
developer47a56bf2023-05-30 13:38:57 +08003800 char config_file_dat[128] = {0};
3801 struct params acs = {0};
3802 wifi_band band = band_invalid;
3803
3804 if(enable == TRUE) {
developer72fb0bb2023-01-11 09:46:29 +08003805 wifi_setRadioChannel(radioIndex,Value);
developer47a56bf2023-05-30 13:38:57 +08003806 } else {
3807 acs.name = "AutoChannelSelect";
3808 acs.value = "0";
3809 band = wifi_index_to_band(radioIndex);
3810 snprintf(config_file_dat, sizeof(config_file_dat), "%s%d.dat", LOGAN_DAT_FILE, band);
3811 wifi_datfileWrite(config_file_dat, &acs, 1);
developer72fb0bb2023-01-11 09:46:29 +08003812 }
3813 return RETURN_OK;
3814}
3815
3816INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
3817{
3818 if (output_bool == NULL)
3819 return RETURN_ERR;
3820
3821 *output_bool = TRUE;
3822
3823 return RETURN_OK;
3824}
3825
3826INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
3827{
developer69b61b02023-03-07 17:17:44 +08003828 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08003829 return RETURN_ERR;
3830 *output_bool=FALSE;
3831 return RETURN_OK;
3832}
3833
3834INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
3835{
developer69b61b02023-03-07 17:17:44 +08003836 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08003837 return RETURN_ERR;
3838 *output_bool=FALSE;
3839 return RETURN_OK;
3840}
3841
3842INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
3843{
3844 //Set to wifi config only. Wait for wifi reset to apply.
3845 return RETURN_OK;
3846}
3847
3848INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
3849{
3850 return RETURN_OK;
3851}
3852
3853INT wifi_factoryResetAP(int apIndex)
3854{
developer47cc27a2023-05-17 23:09:58 +08003855 char ap_config_file[MAX_CMD_SIZE] = {0};
3856 char cmd[MAX_CMD_SIZE] = {0};
3857 char ret_buf[MAX_BUF_SIZE] = {0};
3858 int radio_idx = 0;
3859 int bss_idx = 0;
3860 char ssid[32] = {0};
3861 char interface[IF_NAME_SIZE] = {0};
3862 char psk_file[MAX_CMD_SIZE] = {0};
3863 struct params params[3] = {0};
3864 char *band_str[3] = {"2G", "5G", "6G"};
developer72fb0bb2023-01-11 09:46:29 +08003865
3866 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3867
developer47cc27a2023-05-17 23:09:58 +08003868 /*del old config file*/
3869 snprintf(ap_config_file, MAX_CMD_SIZE, "%s%d.conf", CONFIG_PREFIX, apIndex);
3870 snprintf(cmd, MAX_CMD_SIZE, "rm %s", ap_config_file);
3871 _syscmd(cmd, ret_buf, sizeof(ret_buf));
developer72fb0bb2023-01-11 09:46:29 +08003872
developer47cc27a2023-05-17 23:09:58 +08003873 memset(cmd, 0, sizeof(cmd));
3874 memset(ret_buf, 0, sizeof(ret_buf));
developer72fb0bb2023-01-11 09:46:29 +08003875
developer47cc27a2023-05-17 23:09:58 +08003876 vap_index_to_array_index(apIndex, &radio_idx, &bss_idx);
3877
3878 /*prepare new config file*/
developere740c2a2023-05-23 18:34:32 +08003879 snprintf(cmd, sizeof(cmd), "cp /etc/hostapd-%s.conf %s", wifi_band_str[radio_idx], ap_config_file);
developer47cc27a2023-05-17 23:09:58 +08003880 _syscmd(cmd, ret_buf, sizeof(ret_buf));
3881
3882 if (radio_idx == band_2_4) {
3883 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_2G, bss_idx);
3884 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI2G, bss_idx);
3885 } else if (radio_idx == band_5) {
3886 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_5G, bss_idx);
3887 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI5G, bss_idx);
3888 } else if (radio_idx == band_6) {
3889 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_6G, bss_idx);
3890 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI6G, bss_idx);
3891 }
3892
3893 /* fix wpa_psk_file path */
3894 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", apIndex);
3895
3896 params[0].name = "ssid";
3897 params[0].value = ssid;
3898 params[1].name = "interface";
3899 params[1].value = interface;
3900 params[2].name = "wpa_psk_file";
3901 params[2].value = psk_file;
3902
3903 wifi_hostapdWrite(ap_config_file, params, 3);
3904
3905 /*clear psk file*/
3906 memset(cmd, 0, sizeof(cmd));
3907 memset(ret_buf, 0, sizeof(ret_buf));
3908
3909 snprintf(psk_file, sizeof(psk_file), "%s%d.psk", PSK_FILE, apIndex);
3910
3911 if (access(psk_file, F_OK) != 0) {
3912 snprintf(cmd, MAX_CMD_SIZE, "touch %s", psk_file);
3913 _syscmd(cmd, ret_buf, sizeof(ret_buf));
3914 } else {
3915 snprintf(cmd, MAX_CMD_SIZE, "echo '' > %s", psk_file);
3916 _syscmd(cmd, ret_buf, sizeof(ret_buf));
3917 }
3918
developer429ba832023-05-31 11:03:35 +08003919 wifi_setApEnable(apIndex, FALSE);
3920 wifi_setApEnable(apIndex, TRUE);
developer47cc27a2023-05-17 23:09:58 +08003921 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3922
3923 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08003924}
3925
3926//To set Band Steering AP group
3927//To-do
3928INT wifi_setBandSteeringApGroup(char *ApGroup)
3929{
3930 return RETURN_OK;
3931}
3932
3933INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
3934{
3935 char config_file[128] = {'\0'};
3936 char buf[128] = {'\0'};
3937
3938 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3939 if (dtimInterval == NULL)
3940 return RETURN_ERR;
3941
3942 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developer885b56c2023-05-22 15:02:46 +08003943 wifi_hostapdRead(config_file, "dtim_period", buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08003944
3945 if (strlen(buf) == 0) {
3946 *dtimInterval = 2;
3947 } else {
3948 *dtimInterval = strtoul(buf, NULL, 10);
3949 }
3950
3951 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3952 return RETURN_OK;
3953}
3954
3955INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
3956{
3957 struct params params={0};
3958 char config_file[MAX_BUF_SIZE] = {'\0'};
3959 char buf[MAX_BUF_SIZE] = {'\0'};
3960
3961 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3962 if (dtimInterval < 1 || dtimInterval > 255) {
3963 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
3964 return RETURN_ERR;
3965 }
developer69b61b02023-03-07 17:17:44 +08003966
developer72fb0bb2023-01-11 09:46:29 +08003967 params.name = "dtim_period";
3968 snprintf(buf, sizeof(buf), "%d", dtimInterval);
3969 params.value = buf;
3970
3971 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
3972 wifi_hostapdWrite(config_file, &params, 1);
3973 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3974
3975 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3976 return RETURN_OK;
3977}
3978
3979//Check if the driver support the Dfs
3980INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
3981{
3982 wifi_band band = band_invalid;
developer69b61b02023-03-07 17:17:44 +08003983 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08003984 return RETURN_ERR;
3985 *output_bool=FALSE;
3986
3987 band = wifi_index_to_band(radioIndex);
3988 if (band == band_5)
3989 *output_bool = TRUE;
3990 return RETURN_OK;
3991}
3992
3993//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.
3994//The value of this parameter is a comma seperated list of channel number
3995INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
3996{
developer69b61b02023-03-07 17:17:44 +08003997 if (NULL == output_pool)
developer72fb0bb2023-01-11 09:46:29 +08003998 return RETURN_ERR;
3999 if (radioIndex==1)
developer69b61b02023-03-07 17:17:44 +08004000 return RETURN_OK;//TODO need to handle for 5GHz band, i think
developer72fb0bb2023-01-11 09:46:29 +08004001 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
4002
4003 return RETURN_OK;
4004}
4005
4006INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
4007{
4008 //Set to wifi config. And apply instantly.
4009 return RETURN_OK;
4010}
4011
4012INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
4013{
developer69b61b02023-03-07 17:17:44 +08004014 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
developer72fb0bb2023-01-11 09:46:29 +08004015 return RETURN_ERR;
4016 *output_interval_seconds=1800;
4017 *output_dwell_milliseconds=40;
4018
4019 return RETURN_OK;
4020}
4021
4022INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
4023{
4024 //Set to wifi config. And apply instantly.
4025 return RETURN_OK;
4026}
4027
4028INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
4029{
4030 if (output_bool == NULL)
4031 return RETURN_ERR;
developer69b61b02023-03-07 17:17:44 +08004032 *output_bool = true;
4033 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08004034}
4035
4036INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
4037{
4038 return RETURN_OK;
4039}
4040
4041//Get the Dfs enable status
4042INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
4043{
4044 char buf[16] = {0};
4045 FILE *f = NULL;
developerd1824452023-05-18 12:30:04 +08004046 char config_file_dat[128] = {0};
developerd1824452023-05-18 12:30:04 +08004047 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08004048
4049 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4050
4051 if (output_bool == NULL)
4052 return RETURN_ERR;
developerf6a87542023-05-16 15:47:28 +08004053 *output_bool = TRUE; // default
developerd1824452023-05-18 12:30:04 +08004054 band = wifi_index_to_band(radioIndex);
4055 snprintf(config_file_dat, sizeof(config_file_dat), "%s%d.dat", LOGAN_DAT_FILE, band);
4056
developer262f4cb2023-05-24 12:22:04 +08004057 wifi_datfileRead(config_file_dat, "DfsEnable", buf, sizeof(buf));
developerd1824452023-05-18 12:30:04 +08004058
4059 if (strncmp(buf, "0", 1) == 0)
4060 *output_bool = FALSE;
developer72fb0bb2023-01-11 09:46:29 +08004061 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4062 return RETURN_OK;
4063}
4064
4065//Set the Dfs enable status
4066INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
4067{
4068 char config_file[128] = {0};
developerd1824452023-05-18 12:30:04 +08004069 char config_dat_file[128] = {0};
developer72fb0bb2023-01-11 09:46:29 +08004070 FILE *f = NULL;
developerd1824452023-05-18 12:30:04 +08004071 struct params dat = {0};
4072 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08004073
4074 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4075
4076 f = fopen(DFS_ENABLE_FILE, "w");
4077 if (f == NULL)
4078 return RETURN_ERR;
4079 fprintf(f, "%d", enable);
4080 fclose(f);
4081
developer72fb0bb2023-01-11 09:46:29 +08004082 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
4083
developerd1824452023-05-18 12:30:04 +08004084 dat.name = "DfsEnable";
developer262f4cb2023-05-24 12:22:04 +08004085 dat.value = enable?"1":"0";
developerd1824452023-05-18 12:30:04 +08004086 band = wifi_index_to_band(radioIndex);
4087 snprintf(config_dat_file, sizeof(config_dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
4088 wifi_datfileWrite(config_dat_file, &dat, 1);
developer72fb0bb2023-01-11 09:46:29 +08004089 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4090 return RETURN_OK;
4091}
4092
4093//Check if the driver support the AutoChannelRefreshPeriod
4094INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
4095{
developer69b61b02023-03-07 17:17:44 +08004096 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08004097 return RETURN_ERR;
4098 *output_bool=FALSE; //not support
4099
4100 return RETURN_OK;
4101}
4102
4103//Get the ACS refresh period in seconds
4104INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
4105{
developer69b61b02023-03-07 17:17:44 +08004106 if (NULL == output_ulong)
developer72fb0bb2023-01-11 09:46:29 +08004107 return RETURN_ERR;
4108 *output_ulong=300;
4109
4110 return RETURN_OK;
4111}
4112
4113//Set the ACS refresh period in seconds
4114INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
4115{
4116 return RETURN_ERR;
4117}
4118
4119//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
4120//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.
4121INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
4122{
developer8666b312023-03-24 14:05:31 +08004123 char cmd[MAX_CMD_SIZE] = {0}, buf[64] = {0};
developer72fb0bb2023-01-11 09:46:29 +08004124 char extchannel[128] = {0};
developer8666b312023-03-24 14:05:31 +08004125 char interface_name[64] = {0};
4126 int ret = 0, len=0;
developer72fb0bb2023-01-11 09:46:29 +08004127 BOOL radio_enable = FALSE;
4128 wifi_band band;
4129
4130 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4131
developerd1824452023-05-18 12:30:04 +08004132 if (NULL == output_string) {
4133 WIFI_ENTRY_EXIT_DEBUG("output_string is nuill %s: %d \n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08004134 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08004135 }
4136 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR) {
4137 WIFI_ENTRY_EXIT_DEBUG("wifi_getRadioEnable failed %s: %d \n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08004138 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08004139 }
4140 if (radio_enable != TRUE) {
4141 WIFI_ENTRY_EXIT_DEBUG("Radio %d is not enable failed %s: %d \n", radioIndex, __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08004142 return RETURN_OK;
developerd1824452023-05-18 12:30:04 +08004143 }
developer8666b312023-03-24 14:05:31 +08004144 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4145 return RETURN_ERR;
4146 /*IW command get BW320 to do*/
developerd1824452023-05-18 12:30:04 +08004147
developer8666b312023-03-24 14:05:31 +08004148 snprintf(cmd, sizeof(cmd),"iw dev %s info | grep 'width' | cut -d ' ' -f6 | tr -d '\\n'", interface_name);
4149 ret = _syscmd(cmd, buf, sizeof(buf));
4150 len = strlen(buf);
4151 if((ret != 0) || (len == 0))
4152 {
4153 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
4154 return RETURN_ERR;
4155 }
4156
developer72fb0bb2023-01-11 09:46:29 +08004157 band = wifi_index_to_band(radioIndex);
developer8666b312023-03-24 14:05:31 +08004158 if (band == band_2_4 && strncmp(buf, "20", 2) == 0) {
developer72fb0bb2023-01-11 09:46:29 +08004159 wifi_getRadioExtChannel(radioIndex, extchannel);
developer8666b312023-03-24 14:05:31 +08004160 if (strncmp(extchannel, "Auto", 4) != 0) // not auto means we have set HT40+/-
4161 snprintf(buf, sizeof(buf), "40");
developer72fb0bb2023-01-11 09:46:29 +08004162 }
developer8666b312023-03-24 14:05:31 +08004163 snprintf(output_string, 64, "%sMHz", buf);
developer72fb0bb2023-01-11 09:46:29 +08004164 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4165
4166 return RETURN_OK;
developerfead3972023-05-25 20:15:02 +08004167}
4168
4169enum mwctl_chan_width {
4170 MWCTL_CHAN_WIDTH_20,
4171 MWCTL_CHAN_WIDTH_40,
4172 MWCTL_CHAN_WIDTH_80,
4173 MWCTL_CHAN_WIDTH_160,
4174 MWCTL_CHAN_WIDTH_320,
4175};
4176
4177struct bw_option {
4178 unsigned int bandwith;
4179 enum mwctl_chan_width mode;
4180};
4181
4182struct bw_option bw_opt[] = {
4183 {20, MWCTL_CHAN_WIDTH_20},
4184 {40, MWCTL_CHAN_WIDTH_40},
4185 {80, MWCTL_CHAN_WIDTH_80},
4186 {160, MWCTL_CHAN_WIDTH_160},
4187 {320, MWCTL_CHAN_WIDTH_320},
4188};
4189
4190INT wifi_setChannel_netlink(INT radioIndex, UINT* channel, UINT *bandwidth)
4191{
4192 int ret = -1;
4193 int i;
4194 struct unl unl_ins;
4195 struct nl_msg *msg = NULL;
4196 struct nlattr * msg_data = NULL;
4197 struct mtk_nl80211_param param;
4198 bool b_match = FALSE;
4199
4200 /*init mtk nl80211 vendor cmd*/
4201 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_CHANNEL;
4202 param.if_type = NL80211_ATTR_WIPHY;
4203 param.if_idx = radio_index_to_phy(radioIndex);
4204
4205 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
4206 if (ret) {
4207 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
4208 return RETURN_ERR;
4209 }
4210
4211 /*add mtk vendor cmd data*/
4212 if (channel != NULL)
4213 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_CHAN_SET_NUM, *channel)) {
4214 wifi_debug(DEBUG_ERROR, "Nla put CHAN_SET_NUM attribute error\n");
4215 nlmsg_free(msg);
4216 goto err;
4217 }
4218
4219 if (bandwidth != NULL) {
4220 for (i = 0; i < (sizeof(bw_opt)/sizeof(bw_opt[0])); i++) {
4221 if (bw_opt[i].bandwith == *bandwidth) {
4222 b_match = true;
4223 if (nla_put_u32(msg, MTK_NL80211_VENDOR_ATTR_CHAN_SET_BW, bw_opt[i].mode)) {
4224 wifi_debug(DEBUG_ERROR, "Nla put CHAN_SET_BW attribute error\n");
4225 nlmsg_free(msg);
4226 goto err;
4227 }
4228 break;
4229 }
4230 }
4231
4232 if (!b_match) {
4233 wifi_debug(DEBUG_ERROR, "Cannot find bandwith error\n");
4234 nlmsg_free(msg);
4235 goto err;
4236 }
4237 }
4238
4239 /*send mtk nl80211 vendor msg*/
4240 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
4241 if (ret) {
4242 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
4243 goto err;
4244 }
4245 /*deinit mtk nl80211 vendor msg*/
4246 mtk_nl80211_deint(&unl_ins);
4247 wifi_debug(DEBUG_NOTICE, "set cmd success.\n");
4248 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4249
4250 return RETURN_OK;
4251err:
4252 mtk_nl80211_deint(&unl_ins);
4253 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
4254 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08004255}
developerfead3972023-05-25 20:15:02 +08004256
developer72fb0bb2023-01-11 09:46:29 +08004257//Set the Operating Channel Bandwidth.
4258INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
4259{
4260 char config_file[128];
developerd1824452023-05-18 12:30:04 +08004261 char ht_value[16];
4262 char vht_value[16];
4263 char eht_value[16];
4264 struct params dat[3];
4265 wifi_band band = band_invalid;
developerfead3972023-05-25 20:15:02 +08004266 unsigned int bw = 20;
4267 int ret = 0;
developer72fb0bb2023-01-11 09:46:29 +08004268
4269 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4270
4271 if(NULL == bandwidth)
4272 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08004273 band = wifi_index_to_band(radioIndex);
developer72fb0bb2023-01-11 09:46:29 +08004274
developerd1824452023-05-18 12:30:04 +08004275 if(strstr(bandwidth,"320") != NULL) {
4276 snprintf(ht_value, sizeof(ht_value), "%d", HT_BW_40);
4277 snprintf(vht_value, sizeof(vht_value), "%d", VHT_BW_160);
4278 snprintf(eht_value, sizeof(eht_value), "%d", EHT_BW_320);
developer262f4cb2023-05-24 12:22:04 +08004279 bw = 320;
developerd1824452023-05-18 12:30:04 +08004280 } else if(strstr(bandwidth,"160") != NULL) {
4281 snprintf(ht_value, sizeof(ht_value), "%d", HT_BW_40);
4282 snprintf(vht_value, sizeof(vht_value), "%d", VHT_BW_160);
4283 snprintf(eht_value, sizeof(eht_value), "%d", EHT_BW_160);
developer262f4cb2023-05-24 12:22:04 +08004284 bw = 160;
developerd1824452023-05-18 12:30:04 +08004285 } else if(strstr(bandwidth,"80") != NULL) {
4286 snprintf(ht_value, sizeof(ht_value), "%d", HT_BW_40);
4287 snprintf(vht_value, sizeof(vht_value), "%d", VHT_BW_80);
4288 snprintf(eht_value, sizeof(eht_value), "%d", EHT_BW_80);
developer262f4cb2023-05-24 12:22:04 +08004289 bw = 80;
developerd1824452023-05-18 12:30:04 +08004290 } else if(strstr(bandwidth,"40") != NULL) {
4291 snprintf(ht_value, sizeof(ht_value), "%d", HT_BW_40);
4292 snprintf(vht_value, sizeof(vht_value), "%d", VHT_BW_2040);
4293 snprintf(eht_value, sizeof(eht_value), "%d", EHT_BW_40);
developerfead3972023-05-25 20:15:02 +08004294 bw = 40;
developerd1824452023-05-18 12:30:04 +08004295 } else if(strstr(bandwidth,"20") != NULL) {
4296 snprintf(ht_value, sizeof(ht_value), "%d", HT_BW_20);
4297 snprintf(vht_value, sizeof(vht_value), "%d", VHT_BW_2040);
4298 snprintf(eht_value, sizeof(eht_value), "%d", EHT_BW_20);
developer262f4cb2023-05-24 12:22:04 +08004299 bw = 20;
developerd1824452023-05-18 12:30:04 +08004300 } else {
developer72fb0bb2023-01-11 09:46:29 +08004301 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
4302 return RETURN_ERR;
4303 }
4304
developerd1824452023-05-18 12:30:04 +08004305 snprintf(config_file, sizeof(config_file), "%s%d.dat", LOGAN_DAT_FILE, band);
4306 dat[0].name = "HT_BW";
4307 dat[0].value = ht_value;
4308 dat[1].name = "VHT_BW";
4309 dat[1].value = vht_value;
4310 dat[2].name = "EHT_ApBw";
4311 dat[2].value = eht_value;
4312 wifi_datfileWrite(config_file, dat, 3);
developerfead3972023-05-25 20:15:02 +08004313 ret = wifi_setChannel_netlink(radioIndex, NULL, &bw);
4314 if (ret != RETURN_OK) {
4315 fprintf(stderr, "%s: wifi_setChannel return error.\n", __func__);
4316 return RETURN_ERR;
4317 }
developer72fb0bb2023-01-11 09:46:29 +08004318
4319 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4320 return RETURN_OK;
4321}
4322
developer72fb0bb2023-01-11 09:46:29 +08004323//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
4324//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.
4325INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
4326{
4327 char config_file[64] = {0};
developerd1824452023-05-18 12:30:04 +08004328 char config_dat_file[64] = {0};
developer72fb0bb2023-01-11 09:46:29 +08004329 char mode_str[16] = {0};
4330 char buf[64] = {0};
developerd1824452023-05-18 12:30:04 +08004331 char cmd[MAX_CMD_SIZE] = {0};
4332 char interface_name[64] = {0};
4333 int ret = 0, len=0;
developer72fb0bb2023-01-11 09:46:29 +08004334 wifi_band band;
developerd1824452023-05-18 12:30:04 +08004335 ULONG channel = 0;
4336 int centr_channel = 0;
developer72fb0bb2023-01-11 09:46:29 +08004337 UINT mode_map = 0;
developerd1824452023-05-18 12:30:04 +08004338 int freq=0;
developer72fb0bb2023-01-11 09:46:29 +08004339
4340 if (output_string == NULL)
4341 return RETURN_ERR;
4342
4343 wifi_getRadioMode(radioIndex, mode_str, &mode_map);
4344
4345 band = wifi_index_to_band(radioIndex);
4346 if (band == band_invalid)
4347 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08004348 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4349 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08004350
4351 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4352
4353 snprintf(output_string, 64, "Auto");
developer23e71282023-01-18 10:25:19 +08004354 if (band == band_2_4 || (!(mode_map&WIFI_MODE_AC) && !(mode_map&WIFI_MODE_AX))) {
developerd1824452023-05-18 12:30:04 +08004355 // 2G band or ac and ax mode is disable, we will check HT_EXTCHA
4356 snprintf(config_dat_file, sizeof(config_dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
4357 wifi_halgetRadioExtChannel(config_dat_file, output_string);
developer23e71282023-01-18 10:25:19 +08004358 if (!(mode_map&WIFI_MODE_N))
developer72fb0bb2023-01-11 09:46:29 +08004359 snprintf(output_string, 64, "Auto");
4360 } else {
4361 // 5G and 6G band with ac or ax mode.
4362 wifi_getRadioChannel(radioIndex, &channel);
developerd1824452023-05-18 12:30:04 +08004363 snprintf(cmd, sizeof(cmd),"iw dev %s info | grep 'center1' | cut -d ' ' -f9 | tr -d '\\n'", interface_name);
4364
4365 ret = _syscmd(cmd, buf, sizeof(buf));
4366 len = strlen(buf);
4367 if((ret != 0) || (len == 0))
4368 {
4369 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
4370 return RETURN_ERR;
4371 }
4372 sscanf(buf, "%d", &freq);
4373 centr_channel = ieee80211_frequency_to_channel(freq);
4374 if (centr_channel > (int)channel)
developer72fb0bb2023-01-11 09:46:29 +08004375 snprintf(output_string, 64, "AboveControlChannel");
4376 else
4377 snprintf(output_string, 64, "BelowControlChannel");
4378 }
4379
4380 return RETURN_OK;
4381}
4382
4383//Set the extension channel.
4384INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
developer69b61b02023-03-07 17:17:44 +08004385{
developer72fb0bb2023-01-11 09:46:29 +08004386 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4387 struct params params={0};
4388 char config_file[64] = {0};
developerd1824452023-05-18 12:30:04 +08004389 char config_dat_file[64] = {0};
4390 char ext_channel[64] = {0};
developer72fb0bb2023-01-11 09:46:29 +08004391 char buf[128] = {0};
4392 char cmd[128] = {0};
4393 int max_radio_num =0, ret = 0, bandwidth = 0;
4394 unsigned long channel = 0, centr_channel = 0;
4395 bool stbcEnable = FALSE;
4396 params.name = "ht_capab";
4397 wifi_band band;
4398
4399 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
4400 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
4401 _syscmd(cmd, buf, sizeof(buf));
4402 if (strlen(buf) != 0)
4403 stbcEnable = TRUE;
4404 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, buf) != RETURN_OK)
4405 return RETURN_ERR;
4406 bandwidth = strtol(buf, NULL, 10);
4407 // TDK expected to get error with 20MHz
developer262f4cb2023-05-24 12:22:04 +08004408 // we handle 20MHz in function wifi_RemoveRadioExtChannel().
developer72fb0bb2023-01-11 09:46:29 +08004409 if (bandwidth == 20 || strstr(buf, "80+80") != NULL)
4410 return RETURN_ERR;
4411
4412 band = wifi_index_to_band(radioIndex);
4413 if (band == band_invalid)
4414 return RETURN_ERR;
4415
4416 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK)
4417 return RETURN_ERR;
4418
developer262f4cb2023-05-24 12:22:04 +08004419 snprintf(buf, sizeof(buf), "HT%d", bandwidth);
4420 ret = util_get_sec_chan_offset(channel, buf);
4421 if (ret == -EINVAL)
4422 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08004423
4424 if(NULL!= strstr(string,"Above")) {
developer262f4cb2023-05-24 12:22:04 +08004425 if ((band == band_2_4 && channel > 9) || (band == band_5 && ret == -1))
4426 return RETURN_OK;
4427 strcpy(ext_channel, "Above");
developer72fb0bb2023-01-11 09:46:29 +08004428 } else if(NULL!= strstr(string,"Below")) {
developer262f4cb2023-05-24 12:22:04 +08004429 if ((band == band_2_4 && channel < 5) || (band == band_5 && ret == -1))
4430 return RETURN_OK;
4431 strcpy(ext_channel, "Below");
4432 } else {
developerd1824452023-05-18 12:30:04 +08004433 printf("%s: invalid EXT_CHA:%s\n", __func__, string);
developer262f4cb2023-05-24 12:22:04 +08004434 return RETURN_ERR;
4435 }
developerd1824452023-05-18 12:30:04 +08004436 params.name = "HT_EXTCHA";
developer72fb0bb2023-01-11 09:46:29 +08004437 params.value = ext_channel;
4438
developerd1824452023-05-18 12:30:04 +08004439 snprintf (config_dat_file, sizeof(config_dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
4440 wifi_datfileWrite(config_dat_file, &params, 1);
4441
developer72fb0bb2023-01-11 09:46:29 +08004442 wifi_getMaxRadioNumber(&max_radio_num);
4443 for(int i=0; i<=MAX_APS/max_radio_num; i++)
4444 {
4445 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(max_radio_num*i));
developer72fb0bb2023-01-11 09:46:29 +08004446 wifi_setRadioSTBCEnable(radioIndex+(max_radio_num*i), stbcEnable);
4447 }
4448
4449 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
4450 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4451 return RETURN_OK;
4452}
4453
4454//Get the guard interval value. eg "400nsec" or "800nsec"
4455//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.
4456INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
4457{
4458 wifi_guard_interval_t GI;
4459
4460 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4461
4462 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
4463 return RETURN_ERR;
4464
4465 if (GI == wifi_guard_interval_400)
4466 strcpy(output_string, "400nsec");
4467 else if (GI == wifi_guard_interval_800)
4468 strcpy(output_string, "800nsec");
4469 else if (GI == wifi_guard_interval_1600)
4470 strcpy(output_string, "1600nsec");
4471 else if (GI == wifi_guard_interval_3200)
4472 strcpy(output_string, "3200nsec");
4473 else
4474 strcpy(output_string, "Auto");
4475
4476 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4477 return RETURN_OK;
4478}
4479
4480//Set the guard interval value.
4481INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
4482{
4483 wifi_guard_interval_t GI;
4484 int ret = 0;
4485
4486 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4487
4488 if (strcmp(string, "400nsec") == 0)
4489 GI = wifi_guard_interval_400;
4490 else if (strcmp(string , "800nsec") == 0)
4491 GI = wifi_guard_interval_800;
4492 else if (strcmp(string , "1600nsec") == 0)
4493 GI = wifi_guard_interval_1600;
4494 else if (strcmp(string , "3200nsec") == 0)
4495 GI = wifi_guard_interval_3200;
4496 else
4497 GI = wifi_guard_interval_auto;
4498
4499 ret = wifi_setGuardInterval(radioIndex, GI);
4500
4501 if (ret == RETURN_ERR) {
4502 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
4503 return RETURN_ERR;
4504 }
4505
4506 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4507 return RETURN_OK;
4508}
4509
4510//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
4511INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
4512{
4513 char buf[32]={0};
4514 char mcs_file[64] = {0};
4515 char cmd[64] = {0};
4516 int mode_bitmap = 0;
4517
4518 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4519 if(output_int == NULL)
4520 return RETURN_ERR;
4521 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
4522
4523 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
4524 _syscmd(cmd, buf, sizeof(buf));
4525 if (strlen(buf) > 0)
4526 *output_int = strtol(buf, NULL, 10);
4527 else {
4528 // output the max MCS for the current radio mode
4529 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
4530 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
4531 return RETURN_ERR;
4532 }
4533 if (mode_bitmap & WIFI_MODE_AX) {
4534 *output_int = 11;
4535 } else if (mode_bitmap & WIFI_MODE_AC) {
4536 *output_int = 9;
4537 } else if (mode_bitmap & WIFI_MODE_N) {
4538 *output_int = 7;
4539 }
4540 }
4541 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4542
4543 return RETURN_OK;
4544}
4545
4546//Set the Modulation Coding Scheme index
4547INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
4548{
developera1255e42023-05-13 17:45:02 +08004549 /*Only HE mode can specify MCS capability. We don't support MCS in HT mode,
4550 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 +08004551 char config_file[64] = {0};
4552 char set_value[16] = {0};
4553 char mcs_file[32] = {0};
developer72fb0bb2023-01-11 09:46:29 +08004554 struct params set_config = {0};
4555 FILE *f = NULL;
developera1255e42023-05-13 17:45:02 +08004556 INT nss = 0;
4557 int ant_bitmap = 0;
4558 unsigned short cal_value = 0;
4559 UCHAR tval = 0, i = 0;
developer72fb0bb2023-01-11 09:46:29 +08004560
4561 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4562
4563 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4564
4565 // -1 means auto
4566 if (MCS > 15 || MCS < -1) {
4567 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
4568 return RETURN_ERR;
4569 }
developera1255e42023-05-13 17:45:02 +08004570 wifi_getRadioTxChainMask(radioIndex, &ant_bitmap);/*nss is a bit map value,1111*/
4571 for(; ant_bitmap > 0; ant_bitmap >>= 1)
4572 nss += 1;
4573 //printf("%s:nss = %d\n", __func__, nss);
4574 /*16-bit combination of 2-bit values of Max HE-MCS For 1..8 SS;each 2-bit value have following meaning:
4575 0 = HE-MCS 0-7, 1 = HE-MCS 0-9, 2 = HE-MCS 0-11, 3 = not supported*/
developer72fb0bb2023-01-11 09:46:29 +08004576 if (MCS > 9 || MCS == -1)
developera1255e42023-05-13 17:45:02 +08004577 tval = 2;/*one stream value*/
developer72fb0bb2023-01-11 09:46:29 +08004578 else if (MCS > 7)
developera1255e42023-05-13 17:45:02 +08004579 tval = 1;
developer72fb0bb2023-01-11 09:46:29 +08004580 else
developera1255e42023-05-13 17:45:02 +08004581 tval = 0;
4582 for (i = 0; i < nss; i++)
4583 cal_value |= (tval << (2*i));
4584 snprintf(set_value, sizeof(set_value), "%x", cal_value);
4585 WIFI_ENTRY_EXIT_DEBUG("%s:set=%s, cal=%x\n", __func__, set_value, cal_value);
4586 set_config.name = "he_basic_mcs_nss_set";/*He capability in beacon or response*/
developer72fb0bb2023-01-11 09:46:29 +08004587 set_config.value = set_value;
4588
4589 wifi_hostapdWrite(config_file, &set_config, 1);
4590 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
4591
4592 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
4593 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
4594 f = fopen(mcs_file, "w");
4595 if (f == NULL) {
4596 fprintf(stderr, "%s: fopen failed\n", __func__);
4597 return RETURN_ERR;
4598 }
4599 fprintf(f, "%d", MCS);
4600 fclose(f);
4601
4602 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4603 return RETURN_OK;
4604}
4605
4606//Get supported Transmit Power list, eg : "0,25,50,75,100"
4607//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.
4608INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
4609{
4610 if (NULL == output_list)
4611 return RETURN_ERR;
4612 snprintf(output_list, 64,"0,25,50,75,100");
4613 return RETURN_OK;
4614}
4615
4616//Get current Transmit Power in dBm units.
4617//The transmite power level is in units of full power for this radio.
4618INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
4619{
4620 char interface_name[16] = {0};
4621 char cmd[128]={0};
4622 char buf[16]={0};
developera1255e42023-05-13 17:45:02 +08004623 char pwr_file[128]={0};
4624
developer72fb0bb2023-01-11 09:46:29 +08004625 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4626
4627 if(output_ulong == NULL)
4628 return RETURN_ERR;
4629
4630 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4631 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +08004632/*
developer72fb0bb2023-01-11 09:46:29 +08004633 snprintf(cmd, sizeof(cmd), "iw %s info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", interface_name);
4634 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08004635 *output_ulong = strtol(buf, NULL, 10);
developera1255e42023-05-13 17:45:02 +08004636*/
4637 snprintf(pwr_file, sizeof(pwr_file), "%s%d.txt", POWER_PERCENTAGE, radioIndex);
4638 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", pwr_file);
4639 _syscmd(cmd, buf, sizeof(buf));
4640 if (strlen(buf) > 0)
4641 *output_ulong = strtol(buf, NULL, 10);
4642 else
4643 *output_ulong = 100;
developer72fb0bb2023-01-11 09:46:29 +08004644 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4645 return RETURN_OK;
4646}
4647
4648//Set Transmit Power
4649//The transmite power level is in units of full power for this radio.
4650INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
4651{
4652 char interface_name[16] = {0};
4653 char *support;
developer72fb0bb2023-01-11 09:46:29 +08004654 char buf[128]={0};
4655 char txpower_str[64] = {0};
developera1255e42023-05-13 17:45:02 +08004656 char pwr_file[128]={0};
4657 FILE *f = NULL;
developerfead3972023-05-25 20:15:02 +08004658 int if_idx, ret = 0;
4659 struct nl_msg *msg = NULL;
4660 struct nlattr * msg_data = NULL;
4661 struct mtk_nl80211_param param;
4662 struct unl unl_ins;
developer72fb0bb2023-01-11 09:46:29 +08004663
4664 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4665
4666 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4667 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +08004668 // Get the Tx power supported list and check that is the input in the list
4669 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
4670 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
4671 support = strtok(buf, ",");
4672 while(true)
4673 {
4674 if(support == NULL) { // input not in the list
4675 wifi_dbg_printf("Input value is invalid.\n");
4676 return RETURN_ERR;
4677 }
4678 if (strncmp(txpower_str, support, strlen(support)) == 0) {
4679 break;
4680 }
4681 support = strtok(NULL, ",");
4682 }
developerfead3972023-05-25 20:15:02 +08004683
4684 if_idx = if_nametoindex(interface_name);
4685 /*init mtk nl80211 vendor cmd*/
4686 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_TXPOWER;
4687 param.if_type = NL80211_ATTR_IFINDEX;
4688 param.if_idx = if_idx;
4689 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
4690 if (ret) {
4691 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
4692 return RETURN_ERR;
4693 }
4694 /*add mtk vendor cmd data*/
4695 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_TXPWR_PERCENTAGE_EN, 1)) {
4696 wifi_debug(DEBUG_ERROR, "Nla put attribute error\n");
4697 nlmsg_free(msg);
4698 goto err;
4699 }
4700
4701 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_TXPWR_DROP_CTRL, TransmitPower)) {
4702 wifi_debug(DEBUG_ERROR, "Nla put attribute error\n");
4703 nlmsg_free(msg);
4704 goto err;
4705 }
4706
4707 /*send mtk nl80211 vendor msg*/
4708 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
4709 if (ret) {
4710 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
4711 goto err;
4712 }
4713 /*deinit mtk nl80211 vendor msg*/
4714 mtk_nl80211_deint(&unl_ins);
4715 wifi_debug(DEBUG_NOTICE, "set cmd success.\n");
4716
developera1255e42023-05-13 17:45:02 +08004717 snprintf(pwr_file, sizeof(pwr_file), "%s%d.txt", POWER_PERCENTAGE, radioIndex);
4718 f = fopen(pwr_file, "w");
4719 if (f == NULL) {
4720 fprintf(stderr, "%s: fopen failed\n", __func__);
4721 return RETURN_ERR;
4722 }
4723 fprintf(f, "%d", TransmitPower);
4724 fclose(f);
4725/* 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 +08004726 _syscmd(cmd, buf, sizeof(buf));
4727 maximum_tx = strtol(buf, NULL, 10);
4728
4729 // Get the Tx power supported list and check that is the input in the list
4730 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
4731 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
4732 support = strtok(buf, ",");
4733 while(true)
4734 {
4735 if(support == NULL) { // input not in the list
4736 wifi_dbg_printf("Input value is invalid.\n");
4737 return RETURN_ERR;
4738 }
4739 if (strncmp(txpower_str, support, strlen(support)) == 0) {
4740 break;
4741 }
4742 support = strtok(NULL, ",");
4743 }
4744 txpower = TransmitPower*maximum_tx/100;
4745 phyId = radio_index_to_phy(radioIndex);
4746 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", phyId, txpower);
4747 _syscmd(cmd, buf, sizeof(buf));
4748 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera1255e42023-05-13 17:45:02 +08004749*/
4750 return RETURN_OK;
developerfead3972023-05-25 20:15:02 +08004751err:
4752 mtk_nl80211_deint(&unl_ins);
4753 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
4754 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08004755}
4756
4757//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
4758INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
4759{
developer69b61b02023-03-07 17:17:44 +08004760 if (NULL == Supported)
developer72fb0bb2023-01-11 09:46:29 +08004761 return RETURN_ERR;
4762 *Supported = TRUE;
4763
4764 return RETURN_OK;
4765}
4766
4767//Get 80211h feature enable
4768INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
4769{
4770 char buf[64]={'\0'};
4771 char config_file[64] = {'\0'};
4772
4773 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4774 if(enable == NULL)
4775 return RETURN_ERR;
4776
4777 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
developerd1824452023-05-18 12:30:04 +08004778 /* wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf)); */
4779 wifi_datfileRead(config_file, "IEEE80211H", buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08004780
4781 if (strncmp(buf, "1", 1) == 0)
4782 *enable = TRUE;
4783 else
4784 *enable = FALSE;
4785
4786 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4787 return RETURN_OK;
4788}
4789
4790//Set 80211h feature enable
4791INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
4792{
4793 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4794 struct params params={'\0'};
developerd1824452023-05-18 12:30:04 +08004795 struct params dat={0};
developer72fb0bb2023-01-11 09:46:29 +08004796 char config_file[MAX_BUF_SIZE] = {0};
developerd1824452023-05-18 12:30:04 +08004797 char config_dat_file[MAX_BUF_SIZE] = {0};
4798 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08004799
4800 params.name = "ieee80211h";
4801
4802 if (enable) {
4803 params.value = "1";
4804 } else {
4805 params.value = "0";
4806 }
4807
developerd1824452023-05-18 12:30:04 +08004808 dat.name = "IEEE80211H";
4809 dat.value = params.value;
4810
4811 band = wifi_index_to_band(radioIndex);
4812 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4813 snprintf(config_dat_file, sizeof(config_dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
developer69b61b02023-03-07 17:17:44 +08004814
developerd1824452023-05-18 12:30:04 +08004815 wifi_hostapdWrite(config_file, &params, 1);
4816 wifi_datfileWrite(config_dat_file, &dat, 1);
developer72fb0bb2023-01-11 09:46:29 +08004817 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
4818 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4819 return RETURN_OK;
4820}
4821
4822//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.
4823INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
4824{
4825 if (NULL == output)
4826 return RETURN_ERR;
4827 *output=100;
4828
4829 return RETURN_OK;
4830}
4831
4832//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.
4833INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
4834{
4835 if (NULL == output)
4836 return RETURN_ERR;
4837 *output = -99;
4838
4839 return RETURN_OK;
4840}
4841
4842INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
4843{
4844 return RETURN_ERR;
4845}
4846
4847
4848//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
4849INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
4850{
4851 char interface_name[16] = {0};
4852 char cmd[MAX_BUF_SIZE]={'\0'};
4853 char buf[MAX_CMD_SIZE]={'\0'};
4854
4855 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4856 if(output == NULL)
4857 return RETURN_ERR;
4858
4859 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4860 return RETURN_ERR;
4861 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", interface_name);
4862 _syscmd(cmd, buf, sizeof(buf));
4863 *output = atoi(buf);
4864
4865 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4866 return RETURN_OK;
4867}
developer69b61b02023-03-07 17:17:44 +08004868
developer72fb0bb2023-01-11 09:46:29 +08004869INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
4870{
4871 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4872 struct params params={'\0'};
4873 char buf[MAX_BUF_SIZE] = {'\0'};
4874 char config_file[MAX_BUF_SIZE] = {'\0'};
4875
4876 if (BeaconPeriod < 15 || BeaconPeriod > 65535)
4877 return RETURN_ERR;
4878
4879 params.name = "beacon_int";
4880 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
4881 params.value = buf;
4882
4883 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
4884 wifi_hostapdWrite(config_file, &params, 1);
developer69b61b02023-03-07 17:17:44 +08004885
developer72fb0bb2023-01-11 09:46:29 +08004886 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
4887 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4888 return RETURN_OK;
4889}
4890
4891//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.
4892INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
4893{
4894 //TODO: need to revisit below implementation
4895 char *temp;
4896 char temp_output[128] = {0};
4897 char temp_TransmitRates[64] = {0};
4898 char config_file[64] = {0};
4899
4900 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4901 if (NULL == output)
4902 return RETURN_ERR;
4903 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
4904 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
developer69b61b02023-03-07 17:17:44 +08004905
developer72fb0bb2023-01-11 09:46:29 +08004906 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
4907 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
4908 } else {
4909 temp = strtok(temp_TransmitRates," ");
4910 while(temp!=NULL)
4911 {
4912 // Convert 100 kbps to Mbps
4913 temp[strlen(temp)-1]=0;
4914 if((temp[0]=='5') && (temp[1]=='\0'))
4915 {
4916 temp="5.5";
4917 }
4918 strcat(temp_output,temp);
4919 temp = strtok(NULL," ");
4920 if(temp!=NULL)
4921 {
4922 strcat(temp_output,",");
4923 }
4924 }
4925 strcpy(output,temp_output);
4926 }
4927 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4928 return RETURN_OK;
4929}
4930
4931INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
4932{
4933 char *temp;
4934 char temp1[128];
4935 char temp_output[128];
4936 char temp_TransmitRates[128];
4937 char set[128];
4938 char sub_set[128];
4939 int set_count=0,subset_count=0;
4940 int set_index=0,subset_index=0;
4941 char *token;
4942 int flag=0, i=0;
4943 struct params params={'\0'};
4944 char config_file[MAX_BUF_SIZE] = {0};
4945 wifi_band band = wifi_index_to_band(radioIndex);
4946
4947 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4948 if(NULL == TransmitRates)
4949 return RETURN_ERR;
4950 strcpy(sub_set,TransmitRates);
4951
4952 //Allow only supported Data transmit rate to be set
4953 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
4954 token = strtok(sub_set,",");
4955 while( token != NULL ) /* split the basic rate to be set, by comma */
4956 {
4957 sub_set[subset_count]=atoi(token);
4958 subset_count++;
4959 token=strtok(NULL,",");
4960 }
4961 token=strtok(set,",");
4962 while(token!=NULL) /* split the supported rate by comma */
4963 {
4964 set[set_count]=atoi(token);
4965 set_count++;
4966 token=strtok(NULL,",");
4967 }
4968 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
4969 {
4970 for(set_index=0;set_index < set_count;set_index++)
4971 {
4972 flag=0;
4973 if(sub_set[subset_index]==set[set_index])
4974 break;
4975 else
4976 flag=1; /* No match found */
4977 }
4978 if(flag==1)
4979 return RETURN_ERR; //If value not found return Error
4980 }
4981 strcpy(temp_TransmitRates,TransmitRates);
4982
4983 for(i=0;i<strlen(temp_TransmitRates);i++)
4984 {
4985 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
4986 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
4987 {
4988 continue;
4989 }
4990 else
4991 {
4992 return RETURN_ERR;
4993 }
4994 }
4995 strcpy(temp_output,"");
4996 temp = strtok(temp_TransmitRates,",");
4997 while(temp!=NULL)
4998 {
4999 strcpy(temp1,temp);
5000 if(band == band_5)
5001 {
5002 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
5003 {
5004 return RETURN_ERR;
5005 }
5006 }
5007
5008 if(strcmp(temp,"5.5")==0)
5009 {
5010 strcpy(temp1,"55");
5011 }
5012 else
5013 {
5014 strcat(temp1,"0");
5015 }
5016 strcat(temp_output,temp1);
5017 temp = strtok(NULL,",");
5018 if(temp!=NULL)
5019 {
5020 strcat(temp_output," ");
5021 }
5022 }
5023 strcpy(TransmitRates,temp_output);
5024
5025 params.name= "basic_rates";
5026 params.value =TransmitRates;
5027
5028 wifi_dbg_printf("\n%s:",__func__);
5029 wifi_dbg_printf("\nparams.value=%s\n",params.value);
5030 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
5031 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
5032 wifi_hostapdWrite(config_file,&params,1);
5033 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5034 return RETURN_OK;
5035}
5036
5037//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
5038INT wifi_GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
5039{
5040 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5041 FILE *fp = NULL;
5042 char path[256] = {0}, output_string[256] = {0};
5043 int count = 0;
5044 char *interface = NULL;
5045
5046 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
5047 if (fp == NULL)
5048 {
5049 printf("Failed to run command in Function %s\n", __FUNCTION__);
5050 return RETURN_ERR;
5051 }
5052 if (fgets(path, sizeof(path) - 1, fp) != NULL)
5053 {
5054 interface = strchr(path, '=');
5055
5056 if (interface != NULL)
5057 {
5058 strcpy(output_string, interface + 1);
5059 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
5060 interface_name[count] = output_string[count];
5061
5062 interface_name[count] = '\0';
5063 }
5064 }
5065 pclose(fp);
5066 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5067 return RETURN_OK;
5068}
5069
5070INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
5071{
5072 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5073 output_struct->radio_BytesSent = 0;
5074 output_struct->radio_BytesReceived = 0;
5075 output_struct->radio_PacketsSent = 0;
5076 output_struct->radio_PacketsReceived = 0;
5077 output_struct->radio_ErrorsSent = 0;
5078 output_struct->radio_ErrorsReceived = 0;
5079 output_struct->radio_DiscardPacketsSent = 0;
5080 output_struct->radio_DiscardPacketsReceived = 0;
5081 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5082 return RETURN_OK;
5083}
5084
5085
5086INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
5087{
5088 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5089 CHAR buf[MAX_CMD_SIZE] = {0};
5090 CHAR Value[MAX_BUF_SIZE] = {0};
5091 FILE *fp = NULL;
5092
5093 if (ifname == NULL || strlen(ifname) <= 1)
5094 return RETURN_OK;
5095
5096 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
5097 system(buf);
5098
5099 fp = fopen("/tmp/Radio_Stats.txt", "r");
5100 if(fp == NULL)
5101 {
5102 printf("/tmp/Radio_Stats.txt not exists \n");
5103 return RETURN_ERR;
5104 }
5105 fclose(fp);
5106
5107 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
5108 File_Reading(buf, Value);
5109 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
5110
5111 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
5112 File_Reading(buf, Value);
5113 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
5114
5115 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
5116 File_Reading(buf, Value);
5117 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
5118
5119 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
5120 File_Reading(buf, Value);
5121 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
5122
5123 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
5124 File_Reading(buf, Value);
5125 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
5126
5127 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
5128 File_Reading(buf, Value);
5129 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
5130
5131 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
5132 File_Reading(buf, Value);
5133 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
5134
5135 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
5136 File_Reading(buf, Value);
5137 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
5138
5139 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5140 return RETURN_OK;
5141}
5142
5143INT GetIfacestatus(CHAR *interface_name, CHAR *status)
5144{
developer7e4a2a62023-04-06 19:56:03 +08005145 CHAR buf[MAX_CMD_SIZE] = {0};
5146 INT count = 0;
developer72fb0bb2023-01-11 09:46:29 +08005147
developer7e4a2a62023-04-06 19:56:03 +08005148 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5149
5150 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL) {
5151 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
5152 File_Reading(buf, status);
5153 }
5154
5155 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5156 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08005157}
5158
5159//Get detail radio traffic static info
5160INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
5161{
5162
developer69b61b02023-03-07 17:17:44 +08005163#if 0
5164 //ifconfig radio_x
developer72fb0bb2023-01-11 09:46:29 +08005165 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
5166 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
5167 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
5168 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
5169
5170 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
5171 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
5172 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.
5173 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.
5174
developer69b61b02023-03-07 17:17:44 +08005175 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 +08005176 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].
5177 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
5178 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.
5179 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
5180 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
5181 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
5182 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
5183 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
5184
5185 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
5186 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
5187 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
5188 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.
5189
5190 return RETURN_OK;
5191#endif
5192
5193 CHAR interface_name[64] = {0};
5194 BOOL iface_status = FALSE;
5195 wifi_radioTrafficStats2_t radioTrafficStats = {0};
5196
5197 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5198 if (NULL == output_struct)
5199 return RETURN_ERR;
5200
5201 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
5202 return RETURN_ERR;
5203
5204 wifi_getApEnable(radioIndex, &iface_status);
5205
5206 if (iface_status == TRUE)
5207 wifi_halGetIfStats(interface_name, &radioTrafficStats);
5208 else
5209 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
5210
5211 output_struct->radio_BytesSent = radioTrafficStats.radio_BytesSent;
5212 output_struct->radio_BytesReceived = radioTrafficStats.radio_BytesReceived;
5213 output_struct->radio_PacketsSent = radioTrafficStats.radio_PacketsSent;
5214 output_struct->radio_PacketsReceived = radioTrafficStats.radio_PacketsReceived;
5215 output_struct->radio_ErrorsSent = radioTrafficStats.radio_ErrorsSent;
5216 output_struct->radio_ErrorsReceived = radioTrafficStats.radio_ErrorsReceived;
5217 output_struct->radio_DiscardPacketsSent = radioTrafficStats.radio_DiscardPacketsSent;
5218 output_struct->radio_DiscardPacketsReceived = radioTrafficStats.radio_DiscardPacketsReceived;
5219
5220 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
5221 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].
5222 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
5223 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.
5224 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
5225 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
5226 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
5227 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
5228 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
5229
5230 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
5231 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
5232 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
5233 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.
5234
5235 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5236
5237 return RETURN_OK;
5238}
5239
5240//Set radio traffic static Measureing rules
5241INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
5242{
5243 //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
5244 // Else, save the MeasuringRate and MeasuringInterval for future usage
5245
5246 return RETURN_OK;
5247}
5248
5249//To start or stop RadioTrafficStats
5250INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
5251{
5252 //zqiu: If the RadioTrafficStats process running
5253 // if(enable)
5254 // return RETURN_OK.
5255 // else
5256 // Stop RadioTrafficStats process
developer69b61b02023-03-07 17:17:44 +08005257 // Else
developer72fb0bb2023-01-11 09:46:29 +08005258 // if(enable)
5259 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
5260 // else
5261 // return RETURN_OK.
5262
5263 return RETURN_OK;
5264}
5265
5266//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
5267INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
5268{
5269 //zqiu: Please ignor signalIndex.
developer69b61b02023-03-07 17:17:44 +08005270 if (NULL == SignalLevel)
developer72fb0bb2023-01-11 09:46:29 +08005271 return RETURN_ERR;
developer47cc27a2023-05-17 23:09:58 +08005272
developer72fb0bb2023-01-11 09:46:29 +08005273 *SignalLevel=(radioIndex==0)?-19:-19;
5274
5275 return RETURN_OK;
5276}
5277
5278//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
5279INT wifi_applyRadioSettings(INT radioIndex)
5280{
5281 return RETURN_OK;
5282}
5283
5284//Get the radio index assocated with this SSID entry
5285INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
5286{
5287 if(NULL == radioIndex)
5288 return RETURN_ERR;
5289 int max_radio_num = 0;
5290 wifi_getMaxRadioNumber(&max_radio_num);
5291 *radioIndex = ssidIndex%max_radio_num;
5292 return RETURN_OK;
5293}
5294
5295//Device.WiFi.SSID.{i}.Enable
5296//Get SSID enable configuration parameters (not the SSID enable status)
5297INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
5298{
developer69b61b02023-03-07 17:17:44 +08005299 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08005300 return RETURN_ERR;
5301
5302 return wifi_getApEnable(ssidIndex, output_bool);
5303}
5304
5305//Device.WiFi.SSID.{i}.Enable
5306//Set SSID enable configuration parameters
5307INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
5308{
5309 return wifi_setApEnable(ssidIndex, enable);
5310}
5311
5312//Device.WiFi.SSID.{i}.Status
5313//Get the SSID enable status
5314INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
5315{
5316 char cmd[MAX_CMD_SIZE]={0};
5317 char buf[MAX_BUF_SIZE]={0};
5318 BOOL output_bool;
5319
5320 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5321 if (NULL == output_string)
5322 return RETURN_ERR;
developer69b61b02023-03-07 17:17:44 +08005323
developer72fb0bb2023-01-11 09:46:29 +08005324 wifi_getApEnable(ssidIndex,&output_bool);
5325 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
5326
5327 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5328 return RETURN_OK;
5329}
5330
5331// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
5332INT wifi_getSSIDName(INT apIndex, CHAR *output)
5333{
5334 char config_file[MAX_BUF_SIZE] = {0};
5335
developer69b61b02023-03-07 17:17:44 +08005336 if (NULL == output)
developer72fb0bb2023-01-11 09:46:29 +08005337 return RETURN_ERR;
5338
5339 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5340 wifi_hostapdRead(config_file,"ssid",output,32);
5341
5342 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
5343 return RETURN_OK;
5344}
5345
developer69b61b02023-03-07 17:17:44 +08005346// Set a max 32 byte string and sets an internal variable to the SSID name
developer72fb0bb2023-01-11 09:46:29 +08005347INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
5348{
5349 char str[MAX_BUF_SIZE]={'\0'};
5350 char cmd[MAX_CMD_SIZE]={'\0'};
5351 struct params params;
5352 char config_file[MAX_BUF_SIZE] = {0};
5353
5354 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5355 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
5356 return RETURN_ERR;
5357
5358 params.name = "ssid";
5359 params.value = ssid_string;
5360 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5361 wifi_hostapdWrite(config_file, &params, 1);
5362 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5363 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5364
5365 return RETURN_OK;
5366}
5367
5368//Get the BSSID
5369INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
5370{
developer7e4a2a62023-04-06 19:56:03 +08005371 char cmd[MAX_CMD_SIZE] = {0};
5372 char inf_name[IF_NAME_SIZE] = {0};
5373 char conf_file[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08005374
developer7e4a2a62023-04-06 19:56:03 +08005375 if (!output_string)
developer72fb0bb2023-01-11 09:46:29 +08005376 return RETURN_ERR;
5377
developer47cc27a2023-05-17 23:09:58 +08005378 if (wifi_GetInterfaceName(ssidIndex, inf_name) != RETURN_OK)
5379 return RETURN_ERR;
developer7e4a2a62023-04-06 19:56:03 +08005380
developer5b2f10c2023-05-25 17:02:21 +08005381 if (ssidIndex < 0 || ssidIndex > MAX_APS) {
5382 wifi_debug(DEBUG_ERROR, "innvalide ssidIdex(%d)\n", ssidIndex);
5383 strncpy(output_string, "\0", 1);
5384 return RETURN_ERR;
5385 }
5386 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep bssid | cut -d '=' -f2 | tr -d '\\n'", inf_name);
5387 _syscmd(cmd, output_string, 64);
developer7e4a2a62023-04-06 19:56:03 +08005388
developer5b2f10c2023-05-25 17:02:21 +08005389 /* if hostapd does not control interface even if this interface has been brought up,
5390 * try to get its mac address by iw command.
5391 */
5392 if(strlen(output_string) == 0) {
5393 memset(cmd, 0, sizeof(cmd));
5394 snprintf(cmd, sizeof(cmd), "iw dev %s info | grep \"addr\" | awk \'{print $2}\'", inf_name);
5395 _syscmd(cmd, output_string, 64);
5396 }
developer72fb0bb2023-01-11 09:46:29 +08005397
developer5b2f10c2023-05-25 17:02:21 +08005398 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08005399}
5400
5401//Get the MAC address associated with this Wifi SSID
5402INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
5403{
5404 wifi_getBaseBSSID(ssidIndex,output_string);
5405 return RETURN_OK;
5406}
5407
5408//Get the basic SSID traffic static info
5409//Apply SSID and AP (in the case of Acess Point devices) to the hardware
5410//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
5411INT wifi_applySSIDSettings(INT ssidIndex)
5412{
5413 char interface_name[16] = {0};
5414 BOOL status = false;
5415 char cmd[MAX_CMD_SIZE] = {0};
5416 char buf[MAX_CMD_SIZE] = {0};
5417 int apIndex, ret;
5418 int max_radio_num = 0;
5419 int radioIndex = 0;
5420
5421 wifi_getMaxRadioNumber(&max_radio_num);
5422
5423 radioIndex = ssidIndex % max_radio_num;
5424
5425 wifi_getApEnable(ssidIndex,&status);
5426 // Do not apply when ssid index is disabled
5427 if (status == false)
5428 return RETURN_OK;
5429
5430 /* Doing full remove and add for ssid Index
5431 * Not all hostapd options are supported with reload
5432 * for example macaddr_acl
5433 */
5434 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
5435 return RETURN_ERR;
5436
5437 ret = wifi_setApEnable(ssidIndex,true);
5438
5439 /* Workaround for hostapd issue with multiple bss definitions
5440 * when first created interface will be removed
5441 * then all vaps other vaps on same phy are removed
5442 * after calling setApEnable to false readd all enabled vaps */
5443 for(int i=0; i < MAX_APS/max_radio_num; i++) {
5444 apIndex = max_radio_num*i+radioIndex;
5445 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5446 return RETURN_ERR;
5447 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
5448 _syscmd(cmd, buf, sizeof(buf));
5449 if(*buf == '1')
5450 wifi_setApEnable(apIndex, true);
5451 }
5452
5453 return ret;
5454}
5455
5456struct channels_noise {
5457 int channel;
5458 int noise;
5459};
5460
5461// Return noise array for each channel
5462int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
5463{
5464 char interface_name[16] = {0};
5465 FILE *f = NULL;
5466 char cmd[128] = {0};
5467 char line[256] = {0};
5468 size_t len = 0;
5469 ssize_t read = 0;
5470 int tmp = 0, arr_index = -1;
5471
5472 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
5473 return RETURN_ERR;
5474 sprintf(cmd, "iw dev %s survey dump | grep 'frequency\\|noise' | awk '{print $2}'", interface_name);
5475
5476 if ((f = popen(cmd, "r")) == NULL) {
5477 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
5478 return RETURN_ERR;
5479 }
developer69b61b02023-03-07 17:17:44 +08005480
developer72fb0bb2023-01-11 09:46:29 +08005481 while(fgets(line, sizeof(line), f) != NULL) {
5482 if(arr_index < channels_num){
5483 sscanf(line, "%d", &tmp);
5484 if (tmp > 0) { // channel frequency, the first line must be frequency
5485 arr_index++;
5486 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
5487 } else { // noise
5488 channels_noise_arr[arr_index].noise = tmp;
5489 }
5490 }else{
5491 break;
5492 }
5493 }
5494 pclose(f);
5495 return RETURN_OK;
5496}
5497
5498//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
5499//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
developer69b61b02023-03-07 17:17:44 +08005500INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
developer72fb0bb2023-01-11 09:46:29 +08005501{
5502 int index = -1;
5503 wifi_neighbor_ap2_t *scan_array = NULL;
5504 char cmd[256]={0};
5505 char buf[128]={0};
5506 char file_name[32] = {0};
5507 char filter_SSID[32] = {0};
5508 char line[256] = {0};
5509 char interface_name[16] = {0};
5510 char *ret = NULL;
5511 int freq=0;
5512 FILE *f = NULL;
5513 size_t len=0;
5514 int channels_num = 0;
5515 int vht_channel_width = 0;
5516 int get_noise_ret = RETURN_ERR;
5517 bool filter_enable = false;
5518 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
5519 int phyId = 0;
5520
5521 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
5522
5523 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
5524 return RETURN_ERR;
5525
5526 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
5527 f = fopen(file_name, "r");
5528 if (f != NULL) {
developer47a56bf2023-05-30 13:38:57 +08005529 fgets(buf, sizeof(file_name), f);
5530 if ((strncmp(buf, "0", 1)) != 0) {
5531 fgets(filter_SSID, sizeof(file_name), f);
5532 if (strlen(filter_SSID) != 0)
5533 filter_enable = true;
5534 }
developer72fb0bb2023-01-11 09:46:29 +08005535 fclose(f);
5536 }
5537
5538 phyId = radio_index_to_phy(radioIndex);
5539 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
5540 _syscmd(cmd, buf, sizeof(buf));
5541 channels_num = strtol(buf, NULL, 10);
5542
5543
5544
5545 sprintf(cmd, "iw dev %s scan | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
5546 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", interface_name, interface_name);
5547 fprintf(stderr, "cmd: %s\n", cmd);
5548 if ((f = popen(cmd, "r")) == NULL) {
5549 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
5550 return RETURN_ERR;
5551 }
developer69b61b02023-03-07 17:17:44 +08005552
developer72fb0bb2023-01-11 09:46:29 +08005553 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
5554 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
developer69b61b02023-03-07 17:17:44 +08005555
developer72fb0bb2023-01-11 09:46:29 +08005556 ret = fgets(line, sizeof(line), f);
5557 while (ret != NULL) {
5558 if(strstr(line, "BSS") != NULL) { // new neighbor info
developer69b61b02023-03-07 17:17:44 +08005559 // 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 +08005560 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
5561 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
5562
5563 if (!filter_BSS) {
5564 index++;
5565 wifi_neighbor_ap2_t *tmp;
5566 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
5567 if (tmp == NULL) { // no more memory to use
5568 index--;
5569 wifi_dbg_printf("%s: realloc failed\n", __func__);
5570 break;
5571 }
5572 scan_array = tmp;
5573 }
5574 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
5575
5576 filter_BSS = false;
5577 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
5578 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
5579 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
5580 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
5581 } else if (strstr(line, "freq") != NULL) {
5582 sscanf(line," freq: %d", &freq);
5583 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
5584
5585 if (freq >= 2412 && freq <= 2484) {
5586 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
5587 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
5588 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
5589 }
5590 else if (freq >= 5160 && freq <= 5805) {
5591 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
5592 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
5593 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
5594 }
5595
5596 scan_array[index].ap_Noise = 0;
5597 if (get_noise_ret == RETURN_OK) {
5598 for (int i = 0; i < channels_num; i++) {
5599 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
5600 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
5601 break;
5602 }
5603 }
5604 }
5605 } else if (strstr(line, "beacon interval") != NULL) {
5606 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
5607 } else if (strstr(line, "signal") != NULL) {
5608 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
5609 } else if (strstr(line,"SSID") != NULL) {
5610 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
5611 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
5612 filter_BSS = true;
5613 }
5614 } else if (strstr(line, "Supported rates") != NULL) {
5615 char SRate[80] = {0}, *tmp = NULL;
5616 memset(buf, 0, sizeof(buf));
5617 strcpy(SRate, line);
5618 tmp = strtok(SRate, ":");
5619 tmp = strtok(NULL, ":");
5620 strcpy(buf, tmp);
5621 memset(SRate, 0, sizeof(SRate));
5622
5623 tmp = strtok(buf, " \n");
5624 while (tmp != NULL) {
5625 strcat(SRate, tmp);
5626 if (SRate[strlen(SRate) - 1] == '*') {
5627 SRate[strlen(SRate) - 1] = '\0';
5628 }
5629 strcat(SRate, ",");
5630
5631 tmp = strtok(NULL, " \n");
5632 }
5633 SRate[strlen(SRate) - 1] = '\0';
5634 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
5635 } else if (strstr(line, "DTIM") != NULL) {
5636 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
5637 } else if (strstr(line, "VHT capabilities") != NULL) {
5638 strcat(scan_array[index].ap_SupportedStandards, ",ac");
5639 strcpy(scan_array[index].ap_OperatingStandards, "ac");
5640 } else if (strstr(line, "HT capabilities") != NULL) {
5641 strcat(scan_array[index].ap_SupportedStandards, ",n");
5642 strcpy(scan_array[index].ap_OperatingStandards, "n");
5643 } else if (strstr(line, "VHT operation") != NULL) {
5644 ret = fgets(line, sizeof(line), f);
5645 sscanf(line," * channel width: %d", &vht_channel_width);
5646 if(vht_channel_width == 1) {
5647 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
5648 } else {
5649 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
5650 }
5651 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
5652 continue;
5653 } else if (strstr(line, "HT operation") != NULL) {
5654 ret = fgets(line, sizeof(line), f);
5655 sscanf(line," * secondary channel offset: %s", &buf);
5656 if (!strcmp(buf, "above")) {
5657 //40Mhz +
5658 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
5659 }
5660 else if (!strcmp(buf, "below")) {
5661 //40Mhz -
5662 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
5663 } else {
5664 //20Mhz
5665 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
5666 }
5667 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
5668 continue;
5669 } else if (strstr(line, "HE capabilities") != NULL) {
5670 strcat(scan_array[index].ap_SupportedStandards, ",ax");
5671 strcpy(scan_array[index].ap_OperatingStandards, "ax");
5672 ret = fgets(line, sizeof(line), f);
5673 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
5674 if (strstr(line, "HE40/2.4GHz") != NULL)
5675 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
5676 else
5677 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
5678 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
5679 if (strstr(line, "HE80/5GHz") != NULL) {
5680 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
5681 ret = fgets(line, sizeof(line), f);
5682 } else
5683 continue;
5684 if (strstr(line, "HE160/5GHz") != NULL)
5685 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
5686 }
5687 continue;
5688 } else if (strstr(line, "WPA") != NULL) {
5689 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
5690 } else if (strstr(line, "RSN") != NULL) {
5691 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
5692 } else if (strstr(line, "Group cipher") != NULL) {
5693 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
5694 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
5695 strcpy(scan_array[index].ap_EncryptionMode, "AES");
5696 }
5697 }
5698 ret = fgets(line, sizeof(line), f);
5699 }
5700
5701 if (!filter_BSS) {
5702 *output_array_size = index + 1;
5703 } else {
5704 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
5705 *output_array_size = index;
5706 }
5707 *neighbor_ap_array = scan_array;
5708 pclose(f);
5709 free(channels_noise_arr);
5710 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5711 return RETURN_OK;
5712}
5713
5714//>> Deprecated: used for old RDKB code.
5715INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
5716{
5717 INT status = RETURN_ERR;
5718
5719 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5720 output_struct->wifi_PLCPErrorCount = 0;
5721 output_struct->wifi_FCSErrorCount = 0;
5722 output_struct->wifi_InvalidMACCount = 0;
5723 output_struct->wifi_PacketsOtherReceived = 0;
5724 output_struct->wifi_Noise = 0;
5725 status = RETURN_OK;
5726 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5727 return status;
5728}
5729
5730INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
5731{
5732 char interface_name[16] = {0};
5733 char cmd[128] = {0};
5734 char buf[1280] = {0};
5735 char *pos = NULL;
5736
5737 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5738 if (NULL == output_struct)
5739 return RETURN_ERR;
5740
5741 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5742 return RETURN_ERR;
5743
5744 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
5745
5746 snprintf(cmd, sizeof(cmd), "ifconfig %s", interface_name);
5747 _syscmd(cmd, buf, sizeof(buf));
5748
5749 pos = buf;
5750 if ((pos = strstr(pos, "RX packets:")) == NULL)
5751 return RETURN_ERR;
5752 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
5753
5754 if ((pos = strstr(pos, "TX packets:")) == NULL)
5755 return RETURN_ERR;
5756 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
5757
5758 if ((pos = strstr(pos, "RX bytes:")) == NULL)
5759 return RETURN_ERR;
5760 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
5761
5762 if ((pos = strstr(pos, "TX bytes:")) == NULL)
5763 return RETURN_ERR;
5764 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
5765
5766 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l | tr -d '\n'", interface_name);
5767 _syscmd(cmd, buf, sizeof(buf));
5768 sscanf(buf, "%lu", &output_struct->wifi_Associations);
5769
5770#if 0
5771 //TODO: need to revisit below implementation
5772 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5773 char interface_name[MAX_BUF_SIZE] = {0};
5774 char interface_status[MAX_BUF_SIZE] = {0};
5775 char Value[MAX_BUF_SIZE] = {0};
5776 char buf[MAX_CMD_SIZE] = {0};
5777 char cmd[MAX_CMD_SIZE] = {0};
5778 FILE *fp = NULL;
5779
5780 if (NULL == output_struct) {
5781 return RETURN_ERR;
5782 }
5783
5784 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
5785
5786 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
5787 {
5788 if(apIndex == 0) //private_wifi for 2.4G
5789 {
5790 wifi_GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
5791 }
5792 else if(apIndex == 1) //private_wifi for 5G
5793 {
5794 wifi_GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
5795 }
5796 else if(apIndex == 4) //public_wifi for 2.4G
5797 {
5798 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
5799 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
5800 {
5801 return RETURN_ERR;
5802 }
5803 if(buf[0] == '#')//tp-link
5804 wifi_GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
5805 else//tenda
5806 wifi_GetInterfaceName_virtualInterfaceName_2G(interface_name);
5807 }
5808 else if(apIndex == 5) //public_wifi for 5G
5809 {
5810 wifi_GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
5811 }
5812
5813 GetIfacestatus(interface_name, interface_status);
5814
5815 if(0 != strcmp(interface_status, "1"))
5816 return RETURN_ERR;
5817
5818 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
5819 system(cmd);
5820
5821 fp = fopen("/tmp/SSID_Stats.txt", "r");
5822 if(fp == NULL)
5823 {
5824 printf("/tmp/SSID_Stats.txt not exists \n");
5825 return RETURN_ERR;
5826 }
5827 fclose(fp);
5828
5829 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
5830 File_Reading(buf, Value);
5831 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
5832
5833 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
5834 File_Reading(buf, Value);
5835 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
5836
5837 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
5838 File_Reading(buf, Value);
5839 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
5840
5841 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
5842 File_Reading(buf, Value);
5843 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
5844
5845 /* There is no specific parameter from caller to associate the value wifi_Associations */
5846 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
5847 //_syscmd(cmd, buf, sizeof(buf));
5848 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
5849 }
5850#endif
5851 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5852 return RETURN_OK;
5853}
5854
5855INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
5856{
5857 char interface_name[MAX_BUF_SIZE] = {0};
5858 char interface_status[MAX_BUF_SIZE] = {0};
5859 char Value[MAX_BUF_SIZE] = {0};
5860 char buf[MAX_CMD_SIZE] = {0};
5861 char cmd[MAX_CMD_SIZE] = {0};
5862 FILE *fp = NULL;
5863
5864 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5865 if (NULL == output_struct)
5866 return RETURN_ERR;
5867
5868 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
5869
5870 if (wifi_GetInterfaceName(apIndex,interface_name) != RETURN_OK)
5871 return RETURN_ERR;
5872 GetIfacestatus(interface_name, interface_status);
5873
5874 if(0 != strcmp(interface_status, "1"))
5875 return RETURN_ERR;
5876
5877 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
5878 system(cmd);
5879
5880 fp = fopen("/tmp/SSID_Stats.txt", "r");
5881 if(fp == NULL)
5882 {
5883 printf("/tmp/SSID_Stats.txt not exists \n");
5884 return RETURN_ERR;
5885 }
5886 fclose(fp);
5887
5888 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
5889 File_Reading(buf, Value);
5890 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
5891
5892 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
5893 File_Reading(buf, Value);
5894 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
5895
5896 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
5897 File_Reading(buf, Value);
5898 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
5899
5900 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
5901 File_Reading(buf, Value);
5902 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
5903
5904 output_struct->wifi_UnicastPacketsSent = 0;
5905 output_struct->wifi_UnicastPacketsReceived = 0;
5906 output_struct->wifi_MulticastPacketsSent = 0;
5907 output_struct->wifi_MulticastPacketsReceived = 0;
5908 output_struct->wifi_BroadcastPacketsSent = 0;
5909 output_struct->wifi_BroadcastPacketsRecevied = 0;
5910 output_struct->wifi_UnknownPacketsReceived = 0;
5911
5912 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5913 return RETURN_OK;
5914}
5915
5916INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
5917{
5918 INT status = RETURN_ERR;
5919
5920 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5921 //Below values should get updated from hal
5922 output_struct->wifi_RetransCount=0;
5923 output_struct->wifi_FailedRetransCount=0;
5924 output_struct->wifi_RetryCount=0;
5925 output_struct->wifi_MultipleRetryCount=0;
5926 output_struct->wifi_ACKFailureCount=0;
5927 output_struct->wifi_AggregatedPacketCount=0;
5928
5929 status = RETURN_OK;
5930 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5931
5932 return status;
5933}
5934
5935INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
5936{
5937 INT status = RETURN_ERR;
5938 UINT index;
5939 wifi_neighbor_ap_t *pt=NULL;
5940
5941 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5942 *output_array_size=2;
5943 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
5944 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
5945 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
5946 strcpy(pt->ap_Radio,"");
5947 strcpy(pt->ap_SSID,"");
5948 strcpy(pt->ap_BSSID,"");
5949 strcpy(pt->ap_Mode,"");
5950 pt->ap_Channel=1;
5951 pt->ap_SignalStrength=0;
5952 strcpy(pt->ap_SecurityModeEnabled,"");
5953 strcpy(pt->ap_EncryptionMode,"");
5954 strcpy(pt->ap_OperatingFrequencyBand,"");
5955 strcpy(pt->ap_SupportedStandards,"");
5956 strcpy(pt->ap_OperatingStandards,"");
5957 strcpy(pt->ap_OperatingChannelBandwidth,"");
5958 pt->ap_BeaconPeriod=1;
5959 pt->ap_Noise=0;
5960 strcpy(pt->ap_BasicDataTransferRates,"");
5961 strcpy(pt->ap_SupportedDataTransferRates,"");
5962 pt->ap_DTIMPeriod=1;
5963 pt->ap_ChannelUtilization = 1;
5964 }
5965
5966 status = RETURN_OK;
5967 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5968
5969 return status;
5970}
5971
5972//----------------- AP HAL -------------------------------
5973
5974//>> Deprecated: used for old RDKB code.
5975INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
5976{
5977 if (NULL == output_ulong || NULL == output_struct)
5978 return RETURN_ERR;
5979 *output_ulong = 0;
5980 *output_struct = NULL;
5981 return RETURN_OK;
5982}
5983
5984#ifdef HAL_NETLINK_IMPL
5985static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
5986 struct nlattr *tb[NL80211_ATTR_MAX + 1];
5987 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
5988 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
5989 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
5990 char mac_addr[20];
5991 static int count=0;
5992 int rate=0;
5993
5994 wifi_device_info_t *out = (wifi_device_info_t*)arg;
5995
5996 nla_parse(tb,
5997 NL80211_ATTR_MAX,
5998 genlmsg_attrdata(gnlh, 0),
5999 genlmsg_attrlen(gnlh, 0),
6000 NULL);
6001
6002 if(!tb[NL80211_ATTR_STA_INFO]) {
6003 fprintf(stderr, "sta stats missing!\n");
6004 return NL_SKIP;
6005 }
6006
6007
6008 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
6009 fprintf(stderr, "failed to parse nested attributes!\n");
6010 return NL_SKIP;
6011 }
6012
6013 //devIndex starts from 1
6014 if( ++count == out->wifi_devIndex )
6015 {
6016 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
6017 //Getting the mac addrress
6018 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
6019
6020 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
6021 fprintf(stderr, "failed to parse nested rate attributes!");
6022 return NL_SKIP;
6023 }
6024
6025 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
6026 if(rinfo[NL80211_RATE_INFO_BITRATE])
6027 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
6028 out->wifi_devTxRate = rate/10;
6029 }
6030
6031 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
6032 fprintf(stderr, "failed to parse nested rate attributes!");
6033 return NL_SKIP;
6034 }
6035
6036 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
6037 if(rinfo[NL80211_RATE_INFO_BITRATE])
6038 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
6039 out->wifi_devRxRate = rate/10;
6040 }
6041 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
6042 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
6043
6044 out->wifi_devAssociatedDeviceAuthentiationState = 1;
6045 count = 0; //starts the count for next cycle
6046 return NL_STOP;
6047 }
6048
6049 return NL_SKIP;
6050
6051}
6052#endif
6053
6054INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
6055{
6056#ifdef HAL_NETLINK_IMPL
6057 Netlink nl = {0};
6058 char if_name[10] = {0};
6059 char interface_name[16] = {0};
6060
6061 wifi_device_info_t info = {0};
6062 info.wifi_devIndex = devIndex;
6063
6064 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6065 return RETURN_ERR;
6066
6067 snprintf(if_name,sizeof(if_name),"%s", interface_name);
6068
6069 nl.id = initSock80211(&nl);
6070
6071 if (nl.id < 0) {
6072 fprintf(stderr, "Error initializing netlink \n");
6073 return -1;
6074 }
6075
6076 struct nl_msg* msg = nlmsg_alloc();
6077
6078 if (!msg) {
6079 fprintf(stderr, "Failed to allocate netlink message.\n");
6080 nlfree(&nl);
6081 return -2;
6082 }
6083
6084 genlmsg_put(msg,
developer8dd72532023-05-17 19:58:35 +08006085 NL_AUTO_PID,
developer72fb0bb2023-01-11 09:46:29 +08006086 NL_AUTO_SEQ,
6087 nl.id,
6088 0,
6089 NLM_F_DUMP,
6090 NL80211_CMD_GET_STATION,
6091 0);
6092
6093 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
developer8dd72532023-05-17 19:58:35 +08006094 nl_send_auto_complete(nl.socket, msg);
developer72fb0bb2023-01-11 09:46:29 +08006095 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
6096 nl_recvmsgs(nl.socket, nl.cb);
6097 nlmsg_free(msg);
6098 nlfree(&nl);
6099
6100 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
6101 output_struct->wifi_devRxRate = info.wifi_devRxRate;
6102 output_struct->wifi_devTxRate = info.wifi_devTxRate;
6103 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
6104 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
6105 return RETURN_OK;
6106#else
6107 //iw utility to retrieve station information
6108#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
6109#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
6110#define MACFILE "/tmp/wifi_AssoMac.txt"
6111#define TXRATEFILE "/tmp/wifi_txrate.txt"
6112#define RXRATEFILE "/tmp/wifi_rxrate.txt"
6113 FILE *file = NULL;
6114 char if_name[10] = {'\0'};
6115 char pipeCmd[256] = {'\0'};
6116 char line[256] = {0};
6117 char interface_name[16] = {0};
6118 int count = 0, device = 0;
6119
6120 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6121 return RETURN_ERR;
6122
6123 snprintf(if_name,sizeof(if_name),"%s", interface_name);
6124
6125 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
6126 file = popen(pipeCmd, "r");
6127
6128 if(file == NULL)
6129 return RETURN_ERR; //popen failed
6130
6131 fgets(line, sizeof line, file);
6132 device = atoi(line);
6133 pclose(file);
6134
6135 if(device == 0)
6136 return RETURN_ERR; //No devices are connected
6137
6138 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
6139 system(pipeCmd);
6140
6141 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
6142
6143 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
6144
6145 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
6146
6147 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
6148
6149 //devIndex starts from 1, ++count
6150 if((file = fopen(SIGNALFILE, "r")) != NULL )
6151 {
6152 for(count =0;fgets(line, sizeof line, file) != NULL;)
6153 {
6154 if (++count == devIndex)
6155 {
6156 output_struct->wifi_devSignalStrength = atoi(line);
6157 break;
6158 }
6159 }
6160 fclose(file);
6161 }
6162 else
6163 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
6164
6165 if((file = fopen(MACFILE, "r")) != NULL )
6166 {
6167 for(count =0;fgets(line, sizeof line, file) != NULL;)
6168 {
6169 if (++count == devIndex)
6170 {
6171 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]);
6172 break;
6173 }
6174 }
6175 fclose(file);
6176 }
6177 else
6178 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
6179
6180 if((file = fopen(TXRATEFILE, "r")) != NULL )
6181 {
6182 for(count =0;fgets(line, sizeof line, file) != NULL;)
6183 {
6184 if (++count == devIndex)
6185 {
6186 output_struct->wifi_devTxRate = atoi(line);
6187 break;
6188 }
6189 }
6190 fclose(file);
6191 }
6192 else
6193 fprintf(stderr,"fopen wifi_txrate.txt failed");
6194
6195 if((file = fopen(RXRATEFILE, "r")) != NULL)
6196 {
6197 for(count =0;fgets(line, sizeof line, file) != NULL;)
6198 {
6199 if (++count == devIndex)
6200 {
6201 output_struct->wifi_devRxRate = atoi(line);
6202 break;
6203 }
6204 }
6205 fclose(file);
6206 }
6207 else
6208 fprintf(stderr,"fopen wifi_rxrate.txt failed");
6209
6210 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
6211
6212 return RETURN_OK;
6213#endif
6214}
6215
6216INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
6217{
6218 if (NULL == device)
6219 return RETURN_ERR;
6220 return RETURN_OK;
6221}
6222//<<
6223
6224
6225//--------------wifi_ap_hal-----------------------------
6226//enables CTS protection for the radio used by this AP
6227INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
6228{
6229 //save config and Apply instantly
6230 return RETURN_ERR;
6231}
6232
6233// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
6234INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
6235{
6236 char config_file[64] = {'\0'};
developerd1824452023-05-18 12:30:04 +08006237 char config_dat_file[64] = {'\0'};
developer72fb0bb2023-01-11 09:46:29 +08006238 char buf[64] = {'\0'};
developerd1824452023-05-18 12:30:04 +08006239 struct params list = {0};
6240 struct params dat = {0};
6241 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08006242
6243 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6244 list.name = "ht_coex";
6245 snprintf(buf, sizeof(buf), "%d", enable);
6246 list.value = buf;
6247
developerd1824452023-05-18 12:30:04 +08006248 dat.name = "HT_BSSCoexistence";
6249 dat.value = buf;
6250
6251 band = wifi_index_to_band(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08006252 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developerd1824452023-05-18 12:30:04 +08006253 snprintf(config_dat_file, sizeof(config_dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
developer72fb0bb2023-01-11 09:46:29 +08006254 wifi_hostapdWrite(config_file, &list, 1);
developer262f4cb2023-05-24 12:22:04 +08006255 wifi_datfileWrite(config_dat_file, &dat, 1);
developer72fb0bb2023-01-11 09:46:29 +08006256 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6257
6258 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6259
6260 return RETURN_OK;
6261}
6262
6263//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
6264INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
6265{
6266 char config_file[MAX_BUF_SIZE] = {'\0'};
6267 char buf[MAX_BUF_SIZE] = {'\0'};
6268 struct params list;
6269
6270 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6271 if (threshold < 256 || threshold > 2346 )
6272 return RETURN_ERR;
6273 list.name = "fragm_threshold";
6274 snprintf(buf, sizeof(buf), "%d", threshold);
6275 list.value = buf;
6276
6277 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6278 wifi_hostapdWrite(config_file, &list, 1);
6279 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6280
6281 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6282
6283 return RETURN_OK;
6284}
6285
6286// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
6287INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
6288{
6289 char config_file[64] = {'\0'};
6290 char cmd[512] = {'\0'};
6291 char buf[512] = {'\0'};
6292 char stbc_config[16] = {'\0'};
6293 wifi_band band;
6294 int iterator = 0;
6295 BOOL current_stbc = FALSE;
6296 int ant_count = 0;
6297 int ant_bitmap = 0;
6298 struct params list;
developera1255e42023-05-13 17:45:02 +08006299 char dat_file[64] = {'\0'};
developer72fb0bb2023-01-11 09:46:29 +08006300
6301 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6302
6303 band = wifi_index_to_band(radioIndex);
6304 if (band == band_invalid)
6305 return RETURN_ERR;
6306
6307 if (band == band_2_4)
6308 iterator = 1;
developera1255e42023-05-13 17:45:02 +08006309 else if ((band == band_5) || (band == band_6))
developer72fb0bb2023-01-11 09:46:29 +08006310 iterator = 2;
6311 else
6312 return RETURN_OK;
6313
6314 wifi_getRadioTxChainMask(radioIndex, &ant_bitmap);
6315 for (; ant_bitmap > 0; ant_bitmap >>= 1)
6316 ant_count += ant_bitmap & 1;
6317
6318 if (ant_count == 1 && STBC_Enable == TRUE) {
6319 fprintf(stderr, "%s: can not enable STBC when using only one antenna\n", __func__);
6320 return RETURN_OK;
6321 }
6322
6323 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
6324
6325 // set ht and vht config
6326 for (int i = 0; i < iterator; i++) {
6327 memset(stbc_config, 0, sizeof(stbc_config));
6328 memset(cmd, 0, sizeof(cmd));
6329 memset(buf, 0, sizeof(buf));
6330 list.name = (i == 0)?"ht_capab":"vht_capab";
6331 snprintf(stbc_config, sizeof(stbc_config), "%s", list.name);
6332 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
6333 _syscmd(cmd, buf, sizeof(buf));
6334 if (strlen(buf) != 0)
6335 current_stbc = TRUE;
6336 if (current_stbc == STBC_Enable)
6337 continue;
6338
6339 if (STBC_Enable == TRUE) {
6340 // Append the STBC flags in capab config
6341 memset(cmd, 0, sizeof(cmd));
6342 if (i == 0)
6343 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
6344 else
6345 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1][RX-STBC-1]/' %s", config_file);
6346 _syscmd(cmd, buf, sizeof(buf));
6347 } else if (STBC_Enable == FALSE) {
6348 // Remove the STBC flags and remain other flags in capab
6349 memset(cmd, 0, sizeof(cmd));
6350 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
6351 _syscmd(cmd, buf, sizeof(buf));
6352 memset(cmd, 0, sizeof(cmd));
6353 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
6354 _syscmd(cmd, buf, sizeof(buf));
6355 }
6356 wifi_hostapdRead(config_file, list.name, buf, sizeof(buf));
6357 list.value = buf;
6358 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
6359 }
developera1255e42023-05-13 17:45:02 +08006360 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
6361 snprintf(cmd, sizeof(cmd), "sed -r -i 's/^HT_STBC=.*/HT_STBC=%d/g' %s", STBC_Enable, dat_file);
6362 _syscmd(cmd, buf, sizeof(buf));
6363 if ((band == band_5) || (band == band_6)) {
6364 snprintf(cmd, sizeof(cmd), "sed -r -i 's/^VHT_STBC=.*/VHT_STBC=%d/g' %s", STBC_Enable, dat_file);
6365 _syscmd(cmd, buf, sizeof(buf));
6366 }
6367 /*wifi_reloadAp(radioIndex);
6368 the caller do this.*/
developer72fb0bb2023-01-11 09:46:29 +08006369
6370 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6371 return RETURN_OK;
6372}
6373
6374// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
6375INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
6376{
developer2c22d832023-05-18 17:46:26 +08006377 char dat_file[128] = {0};
6378 BOOL enable;
6379 wifi_band band;
6380 char amdus_buff[8] = {'\0'};
developer72fb0bb2023-01-11 09:46:29 +08006381
developer2c22d832023-05-18 17:46:26 +08006382 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08006383
developer2c22d832023-05-18 17:46:26 +08006384 band = wifi_index_to_band(radioIndex);
6385 if (band == band_invalid) {
6386 printf("%s:Band Error\n", __func__);
6387 return RETURN_ERR;
6388 }
6389 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
6390 wifi_datfileRead(dat_file, "HT_AMSDU", amdus_buff, sizeof(amdus_buff));
6391 if (strncmp(amdus_buff, "1", 1) == 0)
developer72fb0bb2023-01-11 09:46:29 +08006392 *output_bool = TRUE;
developer2c22d832023-05-18 17:46:26 +08006393 else
6394 *output_bool = FALSE;
developer72fb0bb2023-01-11 09:46:29 +08006395
developer2c22d832023-05-18 17:46:26 +08006396 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6397
6398 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006399}
6400
6401// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
6402INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
6403{
developer2c22d832023-05-18 17:46:26 +08006404 char dat_file[128] = {0};
6405 BOOL enable;
6406 wifi_band band;
6407 char amdus_buff[8] = {'\0'};
6408 struct params params = {0};
developer72fb0bb2023-01-11 09:46:29 +08006409
developer2c22d832023-05-18 17:46:26 +08006410 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08006411
developer2c22d832023-05-18 17:46:26 +08006412 band = wifi_index_to_band(radioIndex);
6413 if (band == band_invalid) {
6414 printf("%s:Band Error\n", __func__);
6415 return RETURN_ERR;
6416 }
6417 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
6418 wifi_datfileRead(dat_file, "HT_AMSDU", amdus_buff, sizeof(amdus_buff));
6419 if (strncmp(amdus_buff, "1", 1) == 0)
6420 enable = TRUE;
6421 else
6422 enable = FALSE;
6423 if (amsduEnable == enable)
6424 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006425
developer2c22d832023-05-18 17:46:26 +08006426 params.name = "HT_AMSDU";
6427 if (amsduEnable)
6428 params.value = "1";
6429 else
6430 params.value = "0";
6431 wifi_datfileWrite(dat_file, &params, 1);
6432 wifi_reloadAp(radioIndex);
developer72fb0bb2023-01-11 09:46:29 +08006433
developer2c22d832023-05-18 17:46:26 +08006434 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08006435
developer72fb0bb2023-01-11 09:46:29 +08006436 return RETURN_OK;
6437}
6438
6439//P2 // outputs the number of Tx streams
6440INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
6441{
6442 char buf[8] = {0};
6443 char cmd[128] = {0};
6444 int phyId = 0;
6445
6446 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6447
6448 phyId = radio_index_to_phy(radioIndex);
6449 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Configured Antennas' | awk '{print $4}'", phyId);
6450 _syscmd(cmd, buf, sizeof(buf));
6451
6452 *output_int = (INT)strtol(buf, NULL, 16);
6453
6454 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6455
6456 return RETURN_OK;
6457}
6458
6459INT fitChainMask(INT radioIndex, int antcount)
6460{
6461 char buf[128] = {0};
6462 char cmd[128] = {0};
6463 char config_file[64] = {0};
6464 wifi_band band;
6465 struct params list[2] = {0};
6466
6467 band = wifi_index_to_band(radioIndex);
6468 if (band == band_invalid)
6469 return RETURN_ERR;
6470
6471 list[0].name = "he_mu_beamformer";
6472 list[1].name = "he_su_beamformer";
6473
6474 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
6475 if (antcount == 1) {
6476 // remove config about multiple antennas
6477 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
6478 _syscmd(cmd, buf, sizeof(buf));
6479
6480 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SOUNDING-DIMENSION-.\\]//' %s", config_file);
6481 _syscmd(cmd, buf, sizeof(buf));
6482
6483 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SU-BEAMFORMER\\]//' %s", config_file);
6484 _syscmd(cmd, buf, sizeof(buf));
6485
6486 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[MU-BEAMFORMER\\]//' %s", config_file);
6487 _syscmd(cmd, buf, sizeof(buf));
6488
6489 list[0].value = "0";
6490 list[1].value = "0";
6491 } else {
6492 // 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.
6493 if (band == band_2_4 || band == band_5) {
6494 snprintf(cmd, sizeof(cmd), "cat %s | grep '^ht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
6495 _syscmd(cmd, buf, sizeof(buf));
6496 if (strlen(buf) > 0) {
6497 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC]/' %s", config_file);
6498 _syscmd(cmd, buf, sizeof(buf));
6499 }
6500 }
6501 if (band == band_5) {
6502 snprintf(cmd, sizeof(cmd), "cat %s | grep '^vht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
6503 _syscmd(cmd, buf, sizeof(buf));
6504 if (strlen(buf) > 0) {
6505 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1]/' %s", config_file);
6506 _syscmd(cmd, buf, sizeof(buf));
6507 }
6508 }
6509
6510 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SU-BEAMFORMER\\]'", config_file);
6511 _syscmd(cmd, buf, sizeof(buf));
6512 if (strlen(buf) == 0) {
6513 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SU-BEAMFORMER]/' %s", config_file);
6514 _syscmd(cmd, buf, sizeof(buf));
6515 }
6516
6517 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[MU-BEAMFORMER\\]'", config_file);
6518 _syscmd(cmd, buf, sizeof(buf));
6519 if (strlen(buf) == 0) {
6520 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[MU-BEAMFORMER]/' %s", config_file);
6521 _syscmd(cmd, buf, sizeof(buf));
6522 }
6523
6524 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SOUNDING-DIMENSION-.\\]'", config_file);
6525 _syscmd(cmd, buf, sizeof(buf));
6526 if (strlen(buf) == 0) {
6527 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SOUNDING-DIMENSION-%d]/' %s", antcount, config_file);
6528 } else {
6529 snprintf(cmd, sizeof(cmd), "sed -r -i 's/(SOUNDING-DIMENSION-)./\\1%d/' %s", antcount, config_file);
6530 }
6531 _syscmd(cmd, buf, sizeof(buf));
6532
6533 list[0].value = "1";
6534 list[1].value = "1";
6535 }
6536 wifi_hostapdWrite(config_file, list, 2);
6537}
6538
6539//P2 // sets the number of Tx streams to an enviornment variable
6540INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
6541{
6542 char cmd[128] = {0};
6543 char buf[128] = {0};
6544 int phyId = 0;
6545 int cur_mask = 0;
developera1255e42023-05-13 17:45:02 +08006546 int antcountmsk = 0;
6547 INT cur_nss = 0;
6548 UCHAR dat_file[64] = {0};
6549 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08006550
6551 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6552
6553 if (numStreams <= 0) {
6554 fprintf(stderr, "%s: chainmask is not supported %d.\n", __func__, numStreams);
6555 return RETURN_ERR;
6556 }
6557
developera1255e42023-05-13 17:45:02 +08006558 wifi_getRadioTxChainMask(radioIndex, &cur_mask);//this is mask value
6559 for(; cur_mask > 0; cur_mask >>= 1)//convert to number of streams.
6560 cur_nss += 1;
6561 WIFI_ENTRY_EXIT_DEBUG("%s:cur_nss=%d, new_nss=%d\n", __func__, cur_nss, numStreams);
6562 if (cur_nss == numStreams)
developer72fb0bb2023-01-11 09:46:29 +08006563 return RETURN_OK;
6564
6565 wifi_setRadioEnable(radioIndex, FALSE);
6566
6567 phyId = radio_index_to_phy(radioIndex);
developera1255e42023-05-13 17:45:02 +08006568 //iw need mask value.
6569 for (;numStreams > 0; numStreams--)
6570 antcountmsk |= 0x1 << (numStreams - 1);
6571 snprintf(cmd, sizeof(cmd), "iw phy%d set antenna 0x%x 2>&1", phyId, antcountmsk);
developer72fb0bb2023-01-11 09:46:29 +08006572 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006573 if (strlen(buf) > 0) {
6574 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
6575 return RETURN_ERR;
6576 }
developera1255e42023-05-13 17:45:02 +08006577 band = wifi_index_to_band(radioIndex);
6578 if (band == band_invalid) {
6579 printf("%s:Band Error\n", __func__);
6580 return RETURN_ERR;
6581 }
6582 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
6583 snprintf(cmd, sizeof(cmd), "sed -r -i 's/^HT_TxStream=.*/HT_TxStream=%d/g' %s", numStreams, dat_file);
6584 _syscmd(cmd, buf, sizeof(buf));
6585 if (strlen(buf) > 0) {
6586 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
6587 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006588 }
developera1255e42023-05-13 17:45:02 +08006589 snprintf(cmd, sizeof(cmd), "sed -r -i 's/^HT_RxStream=.*/HT_RxStream=%d/g' %s", numStreams, dat_file);
6590 _syscmd(cmd, buf, sizeof(buf));
6591 if (strlen(buf) > 0) {
6592 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
6593 return RETURN_ERR;
6594 }
6595 fitChainMask(radioIndex, numStreams);
developer72fb0bb2023-01-11 09:46:29 +08006596 wifi_setRadioEnable(radioIndex, TRUE);
6597
6598 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6599 return RETURN_OK;
6600}
6601
6602//P2 // outputs the number of Rx streams
6603INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
6604{
6605 char buf[8] = {0};
6606 char cmd[128] = {0};
6607 int phyId = 0;
6608
6609 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6610
6611 phyId = radio_index_to_phy(radioIndex);
6612 sprintf(cmd, "iw phy%d info | grep 'Configured Antennas' | awk '{print $6}'", phyId);
6613 _syscmd(cmd, buf, sizeof(buf));
6614
6615 *output_int = (INT)strtol(buf, NULL, 16);
6616
6617 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6618
6619 return RETURN_OK;
6620}
6621
6622//P2 // sets the number of Rx streams to an enviornment variable
6623INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
6624{
6625 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6626 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
6627 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
6628 return RETURN_ERR;
6629 }
6630 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6631 return RETURN_ERR;
6632}
6633
6634//Get radio RDG enable setting
6635INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
6636{
developer47cc27a2023-05-17 23:09:58 +08006637 if (NULL == output_bool)
6638 return RETURN_ERR;
6639
6640 *output_bool = TRUE;
6641 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006642}
6643
6644//Get radio RDG enable setting
6645INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
6646{
developer47cc27a2023-05-17 23:09:58 +08006647 char cmd[MAX_CMD_SIZE] = {0};
6648 char buf[MAX_BUF_SIZE] = {0};
6649 char rdg_status[2] = {0};
6650 char dat_file[MAX_CMD_SIZE] = {0};
6651 struct params params = {0};
6652
6653 if (NULL == output_bool)
6654 return RETURN_ERR;
6655
6656 /*prepare dat file path*/
6657 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, radioIndex);
6658
6659 wifi_datfileRead(dat_file, "HT_RDG", rdg_status, sizeof(rdg_status));
6660 if (!strncmp(rdg_status, "1", sizeof(rdg_status)))
6661 *output_bool = TRUE;
6662 else
6663 *output_bool = FALSE;
6664
6665 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006666}
6667
6668//Set radio RDG enable setting
6669INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
6670{
developer47cc27a2023-05-17 23:09:58 +08006671 char cmd[MAX_CMD_SIZE] = {0};
6672 char buf[MAX_BUF_SIZE] = {0};
6673 char dat_file[MAX_CMD_SIZE] = {0};
6674 struct params params = {0};
6675
6676 /*prepare dat file path*/
6677 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, radioIndex);
6678
6679 params.name = "HT_RDG";
6680
6681 if (enable) {
6682 params.value = "1";
6683 } else {
6684 params.value = "0";
6685 }
6686
6687 wifi_datfileWrite(dat_file, &params, 1);
6688
6689 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006690}
6691
developer5cd4c862023-05-26 09:34:42 +08006692
6693int mtk_get_ba_auto_status_callback(struct nl_msg *msg, void *data)
developer72fb0bb2023-01-11 09:46:29 +08006694{
developer5cd4c862023-05-26 09:34:42 +08006695 struct nlattr *tb[NL80211_ATTR_MAX + 1];
6696 struct nlattr *vndr_tb[MTK_NL80211_VENDOR_AP_BA_ATTR_MAX + 1];
6697 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
6698 unsigned char status;
6699 unsigned char *out_status = data;
6700 int err = 0;
developer8e6583c2023-05-23 13:36:06 +08006701
developer5cd4c862023-05-26 09:34:42 +08006702 err = nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
6703 genlmsg_attrlen(gnlh, 0), NULL);
6704 if (err < 0){
6705 wifi_debug(DEBUG_ERROR, "get NL80211_ATTR_MAX fails\n");
6706 return err;
6707 }
developer8e6583c2023-05-23 13:36:06 +08006708
developer5cd4c862023-05-26 09:34:42 +08006709 if (tb[NL80211_ATTR_VENDOR_DATA]) {
6710 err = nla_parse_nested(vndr_tb, MTK_NL80211_VENDOR_AP_BA_ATTR_MAX,
6711 tb[NL80211_ATTR_VENDOR_DATA], NULL);
6712 if (err < 0){
6713 wifi_debug(DEBUG_ERROR, "get MTK_NL80211_VENDOR_AP_BA_ATTR_MAX fails\n");
6714 return err;
6715 }
developer8e6583c2023-05-23 13:36:06 +08006716
developer5cd4c862023-05-26 09:34:42 +08006717 if (vndr_tb[MTK_NL80211_VENDOR_ATTR_AP_BA_EN_INFO]) {
6718 status = nla_get_u8(vndr_tb[MTK_NL80211_VENDOR_ATTR_AP_BA_EN_INFO]);
6719 if (status == 0) {
6720 wifi_debug(DEBUG_NOTICE, "disabled\n");
6721 } else {
6722 wifi_debug(DEBUG_NOTICE, "enabled\n");
6723 }
6724 *out_status = status;
6725 }
6726 }
developer8e6583c2023-05-23 13:36:06 +08006727
developer5cd4c862023-05-26 09:34:42 +08006728 return 0;
6729}
developer8e6583c2023-05-23 13:36:06 +08006730
developer5cd4c862023-05-26 09:34:42 +08006731int mtk_get_ba_decline_status_callback(struct nl_msg *msg, void *data)
6732{
6733 struct nlattr *tb[NL80211_ATTR_MAX + 1];
6734 struct nlattr *vndr_tb[MTK_NL80211_VENDOR_AP_BA_ATTR_MAX + 1];
6735 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
6736 unsigned char status;
6737 unsigned char *out_status = data;
6738 int err = 0;
6739
6740 err = nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
6741 genlmsg_attrlen(gnlh, 0), NULL);
6742 if (err < 0) {
6743 wifi_debug(DEBUG_ERROR, "get NL80211_ATTR_MAX fails\n");
6744 return err;
6745 }
6746
6747 if (tb[NL80211_ATTR_VENDOR_DATA]) {
6748 err = nla_parse_nested(vndr_tb, MTK_NL80211_VENDOR_AP_BA_ATTR_MAX,
6749 tb[NL80211_ATTR_VENDOR_DATA], NULL);
6750 if (err < 0) {
6751 wifi_debug(DEBUG_ERROR, "get MTK_NL80211_VENDOR_AP_BA_ATTR_MAX fails\n");
6752 return err;
6753 }
6754
6755 if (vndr_tb[MTK_NL80211_VENDOR_ATTR_AP_BA_DECLINE_INFO]) {
6756 status = nla_get_u8(vndr_tb[MTK_NL80211_VENDOR_ATTR_AP_BA_DECLINE_INFO]);
6757 if (status == 0) {
6758 wifi_debug(DEBUG_NOTICE, "disabled\n");
6759 } else {
6760 wifi_debug(DEBUG_NOTICE, "enabled\n");
6761 }
6762 *out_status = status;
6763 }
6764 }
6765
6766 return NL_OK;
developer72fb0bb2023-01-11 09:46:29 +08006767}
6768
developer5cd4c862023-05-26 09:34:42 +08006769INT mtk_wifi_get_ba_decl_auto_status(
6770 INT apIndex, INT vendor_data_attr, mtk_nl80211_cb call_back, BOOL *output_bool)
6771{
6772 char inf_name[IF_NAME_SIZE] = {0};
6773 struct mtk_nl80211_param params;
6774 unsigned int if_idx = 0;
6775 int ret = -1;
6776 struct unl unl_ins;
6777 struct nl_msg *msg = NULL;
6778 struct nlattr * msg_data = NULL;
6779 struct mtk_nl80211_param param;
6780
6781 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
6782 return RETURN_ERR;
6783 if_idx = if_nametoindex(inf_name);
6784 if (!if_idx) {
6785 wifi_debug(DEBUG_ERROR,"can't finde ifname(%s) index,ERROR\n", inf_name);
6786 return RETURN_ERR;
6787 }
6788 /*init mtk nl80211 vendor cmd*/
6789 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_BA;
6790 param.if_type = NL80211_ATTR_IFINDEX;
6791 param.if_idx = if_idx;
6792
6793 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
6794 if (ret) {
6795 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
6796 return RETURN_ERR;
6797 }
6798 /*add mtk vendor cmd data*/
6799 if (nla_put_u8(msg, vendor_data_attr, 0xf)) {
6800 wifi_debug(DEBUG_ERROR, "Nla put vendor_data_attr(%d) attribute error\n", vendor_data_attr);
6801 nlmsg_free(msg);
6802 goto err;
6803 }
6804
6805 /*send mtk nl80211 vendor msg*/
6806 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, call_back, output_bool);
6807 if (ret) {
6808 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
6809 goto err;
6810 }
6811 /*deinit mtk nl80211 vendor msg*/
6812 mtk_nl80211_deint(&unl_ins);
6813 wifi_debug(DEBUG_NOTICE,"send cmd success, get output_bool:%d\n", *output_bool);
6814 return RETURN_OK;
6815err:
6816 mtk_nl80211_deint(&unl_ins);
6817 wifi_debug(DEBUG_ERROR,"send cmd fails\n");
6818 return RETURN_ERR;
6819}
6820//Get radio ADDBA enable setting
6821INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
6822{
6823 if (output_bool == NULL) {
6824 wifi_debug(DEBUG_ERROR, "invalid: output_bool is null\n");
6825 return RETURN_ERR;
6826 }
6827 if (mtk_wifi_get_ba_decl_auto_status(radioIndex,
6828 MTK_NL80211_VENDOR_ATTR_AP_BA_DECLINE_INFO, mtk_get_ba_decline_status_callback, output_bool) != RETURN_OK) {
6829 wifi_debug(DEBUG_ERROR, "cmd MTK_NL80211_VENDOR_ATTR_AP_BA_DECLINE_INFO(0x%x) fails\n",
6830 MTK_NL80211_VENDOR_ATTR_AP_BA_DECLINE_INFO);
6831 return RETURN_ERR;
6832 }
6833 wifi_debug(DEBUG_NOTICE, "cmd success:output_bool(%d)\n", *output_bool);
6834 return RETURN_OK;
6835}
6836
developer72fb0bb2023-01-11 09:46:29 +08006837//Set radio ADDBA enable setting
6838INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
6839{
6840 return RETURN_ERR;
6841}
6842
6843//Get radio auto block ack enable setting
6844INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
6845{
developer5cd4c862023-05-26 09:34:42 +08006846 if (output_bool == NULL) {
6847 wifi_debug(DEBUG_ERROR, "invalid: output_bool is null\n");
6848 return RETURN_ERR;
6849 }
developer8e6583c2023-05-23 13:36:06 +08006850
developer5cd4c862023-05-26 09:34:42 +08006851 if (mtk_wifi_get_ba_decl_auto_status(radioIndex,
6852 MTK_NL80211_VENDOR_ATTR_AP_BA_EN_INFO,
6853 mtk_get_ba_auto_status_callback, output_bool) != RETURN_OK) {
6854 wifi_debug(DEBUG_ERROR, "cmd MTK_NL80211_VENDOR_ATTR_AP_BA_EN_INFO(0x%x) fails\n",
6855 MTK_NL80211_VENDOR_ATTR_AP_BA_EN_INFO);
6856 return RETURN_ERR;
6857 }
6858 wifi_debug(DEBUG_NOTICE, "cmd success:output_bool(%d)\n", *output_bool);
6859 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006860}
6861
6862//Set radio auto block ack enable setting
6863INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
6864{
6865 return RETURN_ERR;
6866}
6867
6868//Get radio 11n pure mode enable support
6869INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
6870{
6871 if (NULL == output_bool)
6872 return RETURN_ERR;
6873 *output_bool = TRUE;
6874 return RETURN_OK;
6875}
6876
6877//Get radio 11n pure mode enable setting
6878INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
6879{
6880 if (NULL == output_bool)
6881 return RETURN_ERR;
6882 *output_bool = TRUE;
6883 return RETURN_OK;
6884}
6885
6886//Set radio 11n pure mode enable setting
6887INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
6888{
6889 return RETURN_ERR;
6890}
6891
developer5cd4c862023-05-26 09:34:42 +08006892
6893int mtk_get_igmp_status_callback(struct nl_msg *msg, void *data)
developer72fb0bb2023-01-11 09:46:29 +08006894{
developer5cd4c862023-05-26 09:34:42 +08006895 struct nlattr *tb[NL80211_ATTR_MAX + 1];
6896 struct nlattr *vndr_tb[MTK_NL80211_VENDOR_MCAST_SNOOP_ATTR_MAX + 1];
6897 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
6898 unsigned char status = 0, *out_status = data;
6899 int err = 0;
developer72fb0bb2023-01-11 09:46:29 +08006900
developer5cd4c862023-05-26 09:34:42 +08006901 err = nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
6902 genlmsg_attrlen(gnlh, 0), NULL);
6903 if (err < 0) {
6904 wifi_debug(DEBUG_ERROR, "get NL80211_ATTR_MAX fails\n");
6905 return err;
6906 }
developer72fb0bb2023-01-11 09:46:29 +08006907
developer5cd4c862023-05-26 09:34:42 +08006908 if (tb[NL80211_ATTR_VENDOR_DATA]) {
6909 err = nla_parse_nested(vndr_tb, MTK_NL80211_VENDOR_MCAST_SNOOP_ATTR_MAX,
6910 tb[NL80211_ATTR_VENDOR_DATA], NULL);
6911 if (err < 0){
6912 wifi_debug(DEBUG_ERROR, "get MTK_NL80211_VENDOR_MCAST_SNOOP_ATTR_MAX fails\n");
6913 return err;
6914 }
developer72fb0bb2023-01-11 09:46:29 +08006915
developer5cd4c862023-05-26 09:34:42 +08006916 if (vndr_tb[MTK_NL80211_VENDOR_ATTR_MCAST_SNOOP_ENABLE]) {
6917 status = nla_get_u8(vndr_tb[MTK_NL80211_VENDOR_ATTR_MCAST_SNOOP_ENABLE]);
6918 if (status == 0) {
6919 wifi_debug(DEBUG_NOTICE, "disabled\n");
6920 } else {
6921 wifi_debug(DEBUG_NOTICE, "enabled\n");
6922 }
6923 *out_status = status;
6924 wifi_debug(DEBUG_NOTICE, "status: %d\n", *out_status);
6925 }
6926 }
6927
6928 return 0;
6929}
6930
6931INT mtk_wifi_set_igmp_en_status(
6932 INT apIndex, INT vendor_data_attr, mtk_nl80211_cb call_back,
6933 unsigned char in_en_stat, BOOL *output_bool)
6934{
6935 char inf_name[IF_NAME_SIZE] = {0};
6936 struct mtk_nl80211_param params;
6937 unsigned int if_idx = 0;
6938 int ret = -1;
6939 struct unl unl_ins;
6940 struct nl_msg *msg = NULL;
6941 struct nlattr * msg_data = NULL;
6942 struct mtk_nl80211_param param;
6943
6944 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
6945 return RETURN_ERR;
6946 if_idx = if_nametoindex(inf_name);
6947 if (!if_idx) {
6948 wifi_debug(DEBUG_ERROR,"can't finde ifname(%s) index,ERROR\n", inf_name);
6949 return RETURN_ERR;
6950 }
6951 /*init mtk nl80211 vendor cmd*/
6952 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_MULTICAST_SNOOPING;
6953 param.if_type = NL80211_ATTR_IFINDEX;
6954 param.if_idx = if_idx;
6955
6956 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
6957 if (ret) {
6958 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
6959 return RETURN_ERR;
6960 }
6961 /*add mtk vendor cmd data*/
6962 if (nla_put_u8(msg, vendor_data_attr, in_en_stat)) {
6963 wifi_debug(DEBUG_ERROR, "Nla put vendor_data_attr(%d) attribute error\n", vendor_data_attr);
6964 nlmsg_free(msg);
6965 goto err;
6966 }
6967
6968 /*send mtk nl80211 vendor msg*/
6969 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, call_back, output_bool);
6970 if (ret) {
6971 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
6972 goto err;
6973 }
6974 /*deinit mtk nl80211 vendor msg*/
6975 mtk_nl80211_deint(&unl_ins);
6976 if (output_bool) {
6977 wifi_debug(DEBUG_NOTICE, "send cmd success, get output_bool:%d\n", *output_bool);
6978 } else {
6979 wifi_debug(DEBUG_NOTICE, "send cmd success.\n");
6980 }
6981 return RETURN_OK;
6982err:
6983 mtk_nl80211_deint(&unl_ins);
6984 wifi_debug(DEBUG_ERROR,"send cmd fails\n");
6985 return RETURN_ERR;
6986}
6987
6988
6989//Get radio IGMP snooping enable setting
6990INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
6991{
6992 if (output_bool == NULL) {
6993 wifi_debug(DEBUG_ERROR, "invalid: output_bool is null\n");
6994 return RETURN_ERR;
6995 }
6996 if (mtk_wifi_set_igmp_en_status
6997 (radioIndex, MTK_NL80211_VENDOR_ATTR_MCAST_SNOOP_ENABLE,
6998 mtk_get_igmp_status_callback, 0xf, output_bool)!= RETURN_OK) {
6999 wifi_debug(DEBUG_ERROR, "send MTK_NL80211_VENDOR_ATTR_MCAST_SNOOP_ENABLE cmd fails\n");
7000 return RETURN_ERR;
7001 }
7002 wifi_debug(DEBUG_ERROR, "send cmd success: get igmp status:(%d)\n", *output_bool);
developer72fb0bb2023-01-11 09:46:29 +08007003 return RETURN_OK;
7004}
7005
7006//Set radio IGMP snooping enable setting
7007INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
7008{
developer5cd4c862023-05-26 09:34:42 +08007009 if (mtk_wifi_set_igmp_en_status
7010 (radioIndex, MTK_NL80211_VENDOR_ATTR_MCAST_SNOOP_ENABLE,
7011 NULL, enable, NULL) != RETURN_OK) {
7012 wifi_debug(DEBUG_ERROR, "send MTK_NL80211_VENDOR_ATTR_MCAST_SNOOP_ENABLE cmd fails\n");
7013 return RETURN_ERR;
7014 }
7015 wifi_debug(DEBUG_ERROR, "send cmd success: set igmp enable(%d)\n", enable);
developer72fb0bb2023-01-11 09:46:29 +08007016 return RETURN_OK;
7017}
7018
7019//Get the Reset count of radio
developer69b61b02023-03-07 17:17:44 +08007020INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
developer72fb0bb2023-01-11 09:46:29 +08007021{
developer69b61b02023-03-07 17:17:44 +08007022 if (NULL == output_int)
developer72fb0bb2023-01-11 09:46:29 +08007023 return RETURN_ERR;
developerfead3972023-05-25 20:15:02 +08007024 *output_int = get_radio_reset_cnt(radioIndex);
developer72fb0bb2023-01-11 09:46:29 +08007025
7026 return RETURN_OK;
7027}
7028
7029
7030//---------------------------------------------------------------------------------------------------
7031//
7032// Additional Wifi AP level APIs used for Access Point devices
7033//
7034//---------------------------------------------------------------------------------------------------
7035
7036// creates a new ap and pushes these parameters to the hardware
7037INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
7038{
7039 // Deprecated when use hal version 3, use wifi_createVap() instead.
7040 return RETURN_OK;
7041}
7042
7043// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
7044INT wifi_deleteAp(INT apIndex)
7045{
developer7e4a2a62023-04-06 19:56:03 +08007046 char interface_name[16] = {0};
7047 char buf[MAX_BUF_SIZE];
7048 char cmd[MAX_CMD_SIZE];
developer72fb0bb2023-01-11 09:46:29 +08007049
developer7e4a2a62023-04-06 19:56:03 +08007050 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7051 return RETURN_ERR;
developer8a3bbbf2023-03-15 17:47:23 +08007052
developer7e4a2a62023-04-06 19:56:03 +08007053 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw REMOVE %s", interface_name);
7054 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08007055
developer7e4a2a62023-04-06 19:56:03 +08007056 wifi_removeApSecVaribles(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08007057
developer7e4a2a62023-04-06 19:56:03 +08007058 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08007059}
7060
7061// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
7062INT wifi_getApName(INT apIndex, CHAR *output_string)
7063{
developer7e4a2a62023-04-06 19:56:03 +08007064 char interface_name[IF_NAME_SIZE] = {0};
developer47cc27a2023-05-17 23:09:58 +08007065 int radio_idx = 0;
7066 int bss_idx = 0;
developer72fb0bb2023-01-11 09:46:29 +08007067
developer7e4a2a62023-04-06 19:56:03 +08007068 if(!output_string)
7069 return RETURN_ERR;
7070
7071 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
7072 vap_index_to_array_index(apIndex, &radio_idx, &bss_idx);
7073
7074 snprintf(output_string, IF_NAME_SIZE, "%s%d", ext_prefix[radio_idx], bss_idx); // For wifiagent generating data model.
7075 } else
7076 snprintf(output_string, IF_NAME_SIZE, "%s", interface_name);
7077
7078 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08007079}
7080
7081// Outputs the index number in that corresponds to the SSID string
7082INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
7083{
developer7e4a2a62023-04-06 19:56:03 +08007084 char cmd [128] = {0};
7085 char buf[32] = {0};
7086 char ap_idx = 0;
7087 char *apIndex_str = NULL;
7088 char radio_idx = 0;
7089 char bss_idx = 0;
developer72fb0bb2023-01-11 09:46:29 +08007090
developer7e4a2a62023-04-06 19:56:03 +08007091 snprintf(cmd, sizeof(cmd), "grep -rn ^interface=%s$ /nvram/hostapd*.conf | cut -d '.' -f1 | cut -d 'd' -f2 | tr -d '\\n'",
7092 inputSsidString);
7093 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08007094
developer7e4a2a62023-04-06 19:56:03 +08007095 if (strlen(buf)) {
7096 apIndex_str = strtok(buf, "\n");
7097 *output_int = strtoul(apIndex_str, NULL, 10);
7098 return RETURN_OK;
7099 }
developer72fb0bb2023-01-11 09:46:29 +08007100
developer7e4a2a62023-04-06 19:56:03 +08007101 /* If interface name is not in hostapd config, the caller maybe wifi agent to generate data model.*/
7102 if (strstr(inputSsidString, PREFIX_WIFI6G)) {
7103 bss_idx = atoi(inputSsidString + strlen(PREFIX_WIFI6G));
7104 radio_idx = 2;
7105 } else if (strstr(inputSsidString, PREFIX_WIFI5G)) {
7106 bss_idx = atoi(inputSsidString + strlen(PREFIX_WIFI5G));
7107 radio_idx = 1;
7108 } else if (strstr(inputSsidString, PREFIX_WIFI2G)) {
7109 bss_idx = atoi(inputSsidString + strlen(PREFIX_WIFI2G));
7110 radio_idx = 0;
7111 } else {
7112 printf("%s: hostapd conf not find, unknow inf(%s), return ERROR!!!(%d).\n",
7113 __func__, inputSsidString, ap_idx);
7114 *output_int = -1;
7115 return RETURN_ERR;
7116 }
7117
7118 ap_idx = array_index_to_vap_index(radio_idx, bss_idx);
7119
7120 if (ap_idx >= 0 && ap_idx < MAX_VAP) {
7121 printf("%s: hostapd conf not find, inf(%s), use inf idx(%d).\n",
7122 __func__, inputSsidString, ap_idx);
7123 *output_int = ap_idx;
7124 return RETURN_OK;
7125 }
7126
7127 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007128}
7129
7130INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
7131{
7132 return wifi_getIndexFromName(inputSsidString, output_int);
7133}
7134
7135// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
7136INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
7137{
7138 char buf[MAX_BUF_SIZE] = {0};
7139 char cmd[MAX_CMD_SIZE] = {0};
7140 char config_file[MAX_BUF_SIZE] = {0};
7141
7142 if(NULL == output_string)
7143 return RETURN_ERR;
7144
7145 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7146 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
7147 if((strcmp(buf,"3")==0))
7148 snprintf(output_string, 32, "WPAand11i");
7149 else if((strcmp(buf,"2")==0))
7150 snprintf(output_string, 32, "11i");
7151 else if((strcmp(buf,"1")==0))
7152 snprintf(output_string, 32, "WPA");
7153 else
7154 snprintf(output_string, 32, "None");
7155
7156 return RETURN_OK;
7157}
7158
7159// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
7160INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
7161{
7162 char config_file[MAX_BUF_SIZE] = {0};
7163 struct params list;
7164
7165 if (NULL == beaconTypeString)
7166 return RETURN_ERR;
7167 list.name = "wpa";
7168 list.value = "0";
7169
7170 if((strcmp(beaconTypeString,"WPAand11i")==0))
7171 list.value="3";
7172 else if((strcmp(beaconTypeString,"11i")==0))
7173 list.value="2";
7174 else if((strcmp(beaconTypeString,"WPA")==0))
7175 list.value="1";
7176
7177 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7178 wifi_hostapdWrite(config_file, &list, 1);
7179 wifi_hostapdProcessUpdate(apIndex, &list, 1);
7180 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
7181 return RETURN_OK;
7182}
7183
7184// sets the beacon interval on the hardware for this AP
7185INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
7186{
7187 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7188 struct params params={'\0'};
7189 char buf[MAX_BUF_SIZE] = {'\0'};
7190 char config_file[MAX_BUF_SIZE] = {'\0'};
7191
7192 params.name = "beacon_int";
7193 snprintf(buf, sizeof(buf), "%u", beaconInterval);
7194 params.value = buf;
7195
7196 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7197 wifi_hostapdWrite(config_file, &params, 1);
developer69b61b02023-03-07 17:17:44 +08007198
developer72fb0bb2023-01-11 09:46:29 +08007199 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7200 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7201 return RETURN_OK;
7202}
7203
7204INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
7205{
7206 if (wifi_setApDTIMInterval(apIndex, dtimInterval) != RETURN_OK)
7207 return RETURN_ERR;
7208 return RETURN_OK;
7209}
7210
7211// Get the packet size threshold supported.
7212INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
7213{
7214 //save config and apply instantly
7215 if (NULL == output_bool)
7216 return RETURN_ERR;
7217 *output_bool = TRUE;
7218 return RETURN_OK;
7219}
7220
7221// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
7222INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
7223{
developer72fb0bb2023-01-11 09:46:29 +08007224 char buf[16] = {0};
7225 char config_file[128] = {0};
7226 struct params param = {0};
7227
7228 if (threshold > 65535) {
7229 fprintf(stderr, "%s: rts threshold %u is too big.\n", __func__, threshold);
7230 return RETURN_ERR;
7231 }
7232
developer23e71282023-01-18 10:25:19 +08007233 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developer72fb0bb2023-01-11 09:46:29 +08007234 snprintf(buf, sizeof(buf), "%u", threshold);
7235 param.name = "rts_threshold";
7236 param.value = buf;
7237 wifi_hostapdWrite(config_file, &param, 1);
7238 wifi_hostapdProcessUpdate(apIndex, &param, 1);
7239 wifi_reloadAp(apIndex);
7240
7241 return RETURN_OK;
7242}
7243
7244// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
7245INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
7246{
7247 if (NULL == output_string)
7248 return RETURN_ERR;
7249 snprintf(output_string, 32, "TKIPandAESEncryption");
7250 return RETURN_OK;
7251
7252}
7253
7254// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
7255INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
7256{
7257 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7258 char *param_name = NULL;
7259 char buf[32] = {0}, config_file[MAX_BUF_SIZE] = {0};
7260
7261 if(NULL == output_string)
7262 return RETURN_ERR;
7263
7264 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7265 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
7266
7267 if(strcmp(buf,"0")==0)
7268 {
7269 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
7270 snprintf(output_string, 32, "None");
7271 return RETURN_OK;
7272 }
7273 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
7274 param_name = "rsn_pairwise";
7275 else if((strcmp(buf,"1")==0))
7276 param_name = "wpa_pairwise";
7277 else
7278 return RETURN_ERR;
7279 memset(output_string,'\0',32);
7280 wifi_hostapdRead(config_file,param_name,output_string,32);
7281 if (strlen(output_string) == 0) { // rsn_pairwise is optional. When it is empty use wpa_pairwise instead.
7282 param_name = "wpa_pairwise";
7283 memset(output_string, '\0', 32);
7284 wifi_hostapdRead(config_file, param_name, output_string, 32);
7285 }
7286 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
7287
developere5750452023-05-15 16:46:42 +08007288 if(strcmp(output_string,"TKIP CCMP") == 0)
7289 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
7290 else if(strcmp(output_string,"TKIP") == 0)
developer72fb0bb2023-01-11 09:46:29 +08007291 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
7292 else if(strcmp(output_string,"CCMP") == 0)
7293 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
developer72fb0bb2023-01-11 09:46:29 +08007294
7295 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7296 return RETURN_OK;
7297}
7298
7299// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
7300INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
7301{
7302 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7303 struct params params={'\0'};
7304 char output_string[32];
7305 char config_file[MAX_BUF_SIZE] = {0};
7306
7307 memset(output_string,'\0',32);
developere5750452023-05-15 16:46:42 +08007308 wifi_getApBeaconType(apIndex,output_string);
developer72fb0bb2023-01-11 09:46:29 +08007309
7310 if(strcmp(encMode, "TKIPEncryption") == 0)
7311 params.value = "TKIP";
7312 else if(strcmp(encMode,"AESEncryption") == 0)
7313 params.value = "CCMP";
7314 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
7315 params.value = "TKIP CCMP";
7316
7317 if((strcmp(output_string,"WPAand11i")==0))
7318 {
7319 params.name = "wpa_pairwise";
7320 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7321 wifi_hostapdWrite(config_file, &params, 1);
7322 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7323
7324 params.name = "rsn_pairwise";
7325 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7326 wifi_hostapdWrite(config_file, &params, 1);
7327 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7328
7329 return RETURN_OK;
7330 }
7331 else if((strcmp(output_string,"11i")==0))
7332 {
7333 params.name = "rsn_pairwise";
7334 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7335 wifi_hostapdWrite(config_file, &params, 1);
7336 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7337 return RETURN_OK;
7338 }
7339 else if((strcmp(output_string,"WPA")==0))
7340 {
7341 params.name = "wpa_pairwise";
7342 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7343 wifi_hostapdWrite(config_file, &params, 1);
7344 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7345 return RETURN_OK;
7346 }
7347
7348 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7349 return RETURN_OK;
7350}
7351
7352// deletes internal security varable settings for this ap
7353INT wifi_removeApSecVaribles(INT apIndex)
7354{
7355 //TODO: remove the entry in hostapd config file
7356 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s.conf//g' /tmp/conf_filename", interface_name);
7357 //_syscmd(cmd, buf, sizeof(buf));
7358
7359 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s//g' /tmp/conf_filename", interface_name);
7360 //_syscmd(cmd, buf, sizeof(buf));
7361 return RETURN_ERR;
7362}
7363
7364// changes the hardware settings to disable encryption on this ap
7365INT wifi_disableApEncryption(INT apIndex)
7366{
7367 //Apply instantly
7368 return RETURN_ERR;
7369}
7370
7371// set the authorization mode on this ap
7372// mode mapping as: 1: open, 2: shared, 4:auto
7373INT wifi_setApAuthMode(INT apIndex, INT mode)
7374{
7375 struct params params={0};
7376 char config_file[64] = {0};
7377 int ret;
7378
7379 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
7380
7381 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
7382 params.name = "auth_algs";
7383
developere5750452023-05-15 16:46:42 +08007384 if ((mode & 1 && mode & 2) || mode & 4)
developer72fb0bb2023-01-11 09:46:29 +08007385 params.value = "3";
7386 else if (mode & 2)
7387 params.value = "2";
7388 else if (mode & 1)
7389 params.value = "1";
7390 else
7391 params.value = "0";
7392
7393 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7394 wifi_hostapdWrite(config_file, &params, 1);
7395 wifi_hostapdProcessUpdate(apIndex, &params, 1);
developere5750452023-05-15 16:46:42 +08007396 wifi_reloadAp(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08007397 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
7398
7399 return RETURN_OK;
7400}
7401
7402// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
7403INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
7404{
7405 //save to wifi config, and wait for wifi restart to apply
7406 struct params params={'\0'};
7407 char config_file[MAX_BUF_SIZE] = {0};
7408 int ret;
7409
7410 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7411 if(authMode == NULL)
7412 return RETURN_ERR;
7413
7414 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
7415 params.name = "wpa_key_mgmt";
7416
7417 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
7418 params.value = "WPA-PSK";
7419 else if(strcmp(authMode,"EAPAuthentication") == 0)
7420 params.value = "WPA-EAP";
7421 else if (strcmp(authMode, "SAEAuthentication") == 0)
7422 params.value = "SAE";
7423 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
7424 params.value = "WPA-EAP-SUITE-B-192";
7425 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
7426 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer3086e2f2023-01-17 09:40:01 +08007427 else if (strcmp(authMode, "Enhanced_Open") == 0)
7428 params.value = "OWE";
developer72fb0bb2023-01-11 09:46:29 +08007429 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
7430 return RETURN_OK; //This is taken careof in beaconType
7431
7432 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7433 ret=wifi_hostapdWrite(config_file,&params,1);
7434 if(!ret)
7435 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
7436 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7437
7438 return ret;
7439}
7440
7441// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
7442INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
7443{
7444 //save to wifi config, and wait for wifi restart to apply
7445 char BeaconType[50] = {0};
7446 char config_file[MAX_BUF_SIZE] = {0};
7447
7448 *authMode = 0;
7449 wifi_getApBeaconType(apIndex,BeaconType);
7450 printf("%s____%s \n",__FUNCTION__,BeaconType);
7451
7452 if(strcmp(BeaconType,"None") == 0)
7453 strcpy(authMode,"None");
7454 else
7455 {
7456 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7457 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
7458 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
7459 if(strcmp(authMode,"WPA-PSK") == 0)
7460 strcpy(authMode,"SharedAuthentication");
7461 else if(strcmp(authMode,"WPA-EAP") == 0)
7462 strcpy(authMode,"EAPAuthentication");
7463 }
7464
7465 return RETURN_OK;
7466}
7467
7468// Outputs the number of stations associated per AP
7469INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
7470{
7471 char interface_name[16] = {0};
7472 char cmd[128]={0};
7473 char buf[128]={0};
7474 BOOL status = false;
7475
7476 if(apIndex > MAX_APS)
7477 return RETURN_ERR;
7478
7479 wifi_getApEnable(apIndex,&status);
7480 if (!status)
7481 return RETURN_OK;
7482
7483 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);//alternate method
7484 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7485 return RETURN_ERR;
7486 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l", interface_name);
7487 _syscmd(cmd, buf, sizeof(buf));
7488 sscanf(buf,"%lu", output_ulong);
7489
7490 return RETURN_OK;
7491}
7492
7493// manually removes any active wi-fi association with the device specified on this ap
7494INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
7495{
developer7e4a2a62023-04-06 19:56:03 +08007496 char inf_name[16] = {0};
7497 char cmd[MAX_CMD_SIZE] = {0};
7498 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08007499
developer7e4a2a62023-04-06 19:56:03 +08007500 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
developer72fb0bb2023-01-11 09:46:29 +08007501 return RETURN_ERR;
developer7e4a2a62023-04-06 19:56:03 +08007502
7503 snprintf(cmd, sizeof(cmd),"hostapd_cli -i %s disassociate %s", inf_name, client_mac);
7504 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08007505
7506 return RETURN_OK;
7507}
7508
7509// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
7510INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
7511{
developer7e4a2a62023-04-06 19:56:03 +08007512 int max_radio_num = 0;
7513
7514 if(NULL == output_int)
7515 return RETURN_ERR;
7516
7517 wifi_getMaxRadioNumber(&max_radio_num);
7518 *output_int = apIndex % max_radio_num;
7519
7520 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08007521}
7522
7523// sets the radio index for the specific ap
7524INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
7525{
7526 //set to config only and wait for wifi reset to apply settings
7527 return RETURN_ERR;
7528}
7529
developer121a8e72023-05-22 09:19:39 +08007530
7531#define MAX_ACL_DUMP_LEN 4096
7532int mtk_acl_list_dump_callback(struct nl_msg *msg, void *cb)
7533{
7534 struct nlattr *tb[NL80211_ATTR_MAX + 1];
7535 struct nlattr *vndr_tb[MTK_NL80211_VENDOR_AP_ACL_ATTR_MAX + 1];
7536 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
7537 char *show_str = NULL;
developer2edaf012023-05-24 14:24:53 +08007538 int err = 0;
developer121a8e72023-05-22 09:19:39 +08007539 unsigned short acl_result_len = 0;
7540 struct mtk_nl80211_cb_data *cb_data = cb;
developer121a8e72023-05-22 09:19:39 +08007541 if (!msg || !cb_data) {
developer2edaf012023-05-24 14:24:53 +08007542 wifi_debug(DEBUG_ERROR, "msg(0x%lx) or cb_data(0x%lx) is null,error.\n", msg, cb_data);
developer121a8e72023-05-22 09:19:39 +08007543 return NL_SKIP;
7544 }
developer121a8e72023-05-22 09:19:39 +08007545 err = nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
7546 genlmsg_attrlen(gnlh, 0), NULL);
7547 if (err < 0) {
developer2edaf012023-05-24 14:24:53 +08007548 wifi_debug(DEBUG_ERROR, "nla_parse acl list nl80211 msg fails,error.\n");
developer121a8e72023-05-22 09:19:39 +08007549 return NL_SKIP;
7550 }
developer121a8e72023-05-22 09:19:39 +08007551 if (tb[NL80211_ATTR_VENDOR_DATA]) {
7552 err = nla_parse_nested(vndr_tb, MTK_NL80211_VENDOR_AP_ACL_ATTR_MAX,
7553 tb[NL80211_ATTR_VENDOR_DATA], NULL);
7554 if (err < 0)
7555 return NL_SKIP;
7556 if (vndr_tb[MTK_NL80211_VENDOR_ATTR_ACL_LIST_INFO]) {
7557 acl_result_len = nla_len(vndr_tb[MTK_NL80211_VENDOR_ATTR_ACL_LIST_INFO]);
7558 show_str = nla_data(vndr_tb[MTK_NL80211_VENDOR_ATTR_ACL_LIST_INFO]);
7559 if (acl_result_len > MAX_ACL_DUMP_LEN) {
7560 wifi_debug(DEBUG_ERROR,"the scan result len is invalid !!!\n");
7561 return NL_SKIP;
7562 } else if (*(show_str + acl_result_len - 1) != '\0') {
7563 wifi_debug(DEBUG_INFO, "the result string is not ended with right terminator, handle it!!!\n");
7564 *(show_str + acl_result_len - 1) = '\0';
7565 }
7566 wifi_debug(DEBUG_INFO, "driver msg:%s\n", show_str);
developer2edaf012023-05-24 14:24:53 +08007567
7568 if (cb_data->out_len >= acl_result_len) {
7569 memset(cb_data->out_buf, 0, cb_data->out_len);
7570 /*skip the first line: 'policy=1\n' to find the acl mac addrs*/
7571 memmove(cb_data->out_buf, show_str, acl_result_len);
7572 wifi_debug(DEBUG_INFO, "out buff:%s\n", cb_data->out_buf);
7573 } else {
7574 memset(cb_data->out_buf, 0, cb_data->out_len);
developer121a8e72023-05-22 09:19:39 +08007575 }
developer121a8e72023-05-22 09:19:39 +08007576 } else
7577 wifi_debug(DEBUG_ERROR, "no acl result attr\n");
7578 } else
7579 wifi_debug(DEBUG_ERROR, "no any acl result from driver\n");
7580 return NL_OK;
7581}
developer72fb0bb2023-01-11 09:46:29 +08007582// Get the ACL MAC list per AP
developer2edaf012023-05-24 14:24:53 +08007583INT mtk_wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
developer72fb0bb2023-01-11 09:46:29 +08007584{
developer7e4a2a62023-04-06 19:56:03 +08007585 char inf_name[IF_NAME_SIZE] = {0};
developer121a8e72023-05-22 09:19:39 +08007586 struct mtk_nl80211_param params;
7587 unsigned int if_idx = 0;
7588 int ret = -1;
7589 struct unl unl_ins;
7590 struct nl_msg *msg = NULL;
7591 struct nlattr * msg_data = NULL;
7592 struct mtk_nl80211_param param;
7593 struct mtk_nl80211_cb_data cb_data;
developer7e4a2a62023-04-06 19:56:03 +08007594 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
7595 return RETURN_ERR;
developer121a8e72023-05-22 09:19:39 +08007596 if_idx = if_nametoindex(inf_name);
7597 if (!if_idx) {
developer2edaf012023-05-24 14:24:53 +08007598 wifi_debug(DEBUG_ERROR,"can't finde ifname(%s) index,ERROR\n", inf_name);
developer121a8e72023-05-22 09:19:39 +08007599 return RETURN_ERR;
7600 }
7601 /*init mtk nl80211 vendor cmd*/
7602 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_ACL;
7603 param.if_type = NL80211_ATTR_IFINDEX;
7604 param.if_idx = if_idx;
7605
7606 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
7607 if (ret) {
7608 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
7609 return RETURN_ERR;
7610 }
developer121a8e72023-05-22 09:19:39 +08007611 /*add mtk vendor cmd data*/
7612 if (nla_put_flag(msg, MTK_NL80211_VENDOR_ATTR_ACL_SHOW_ALL)) {
developer2edaf012023-05-24 14:24:53 +08007613 wifi_debug(DEBUG_ERROR, "Nla put ACL_SHOW_ALL attribute error\n");
developer121a8e72023-05-22 09:19:39 +08007614 nlmsg_free(msg);
7615 goto err;
7616 }
developer72fb0bb2023-01-11 09:46:29 +08007617
developer121a8e72023-05-22 09:19:39 +08007618 /*send mtk nl80211 vendor msg*/
7619 cb_data.out_buf = macArray;
7620 cb_data.out_len = buf_size;
7621
7622 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, mtk_acl_list_dump_callback, &cb_data);
7623 if (ret) {
7624 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
7625 goto err;
7626 }
7627 /*deinit mtk nl80211 vendor msg*/
7628 mtk_nl80211_deint(&unl_ins);
developer2edaf012023-05-24 14:24:53 +08007629 wifi_debug(DEBUG_NOTICE,"send cmd success, get out_buf:%s\n", macArray);
developer72fb0bb2023-01-11 09:46:29 +08007630 return RETURN_OK;
developer121a8e72023-05-22 09:19:39 +08007631err:
7632 mtk_nl80211_deint(&unl_ins);
developer2edaf012023-05-24 14:24:53 +08007633 wifi_debug(DEBUG_ERROR,"send cmd fails\n");
developer121a8e72023-05-22 09:19:39 +08007634 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007635}
7636
developer2edaf012023-05-24 14:24:53 +08007637INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
7638{
7639 char *mac_arry_buf = NULL;
7640
7641 mac_arry_buf = malloc(buf_size);
7642 if (!mac_arry_buf) {
7643 wifi_debug(DEBUG_ERROR,"malloc mac_arry_buf fails\n");
7644 return RETURN_ERR;
7645 }
7646 memset(mac_arry_buf, 0, buf_size);
7647 if (mtk_wifi_getApAclDevices(apIndex, mac_arry_buf, buf_size) != RETURN_OK) {
7648 wifi_debug(DEBUG_ERROR,"mtk_wifi_getApAclDevices get fails\n");
7649 free(mac_arry_buf);
7650 mac_arry_buf = NULL;
7651 return RETURN_ERR;
7652 }
7653 /*
7654 mtk format to wifi hal format:
7655 "policy=1
7656 00:11:22:33:44:55
7657 00:11:22:33:44:66
7658 "
7659 -->
7660 "00:11:22:33:44:55
7661 00:11:22:33:44:66
7662 "
7663 */
7664 memset(macArray, 0, buf_size);
7665 if (*mac_arry_buf != '\0' && strchr(mac_arry_buf,'\n')) {
7666 memmove(macArray, strchr(mac_arry_buf,'\n')+1, strlen(strchr(mac_arry_buf,'\n')+1)+1);
7667 wifi_debug(DEBUG_NOTICE,"macArray:\n%s\n", macArray);
7668 }
7669 free(mac_arry_buf);
7670 mac_arry_buf = NULL;
7671 return RETURN_OK;
7672}
7673
developer72fb0bb2023-01-11 09:46:29 +08007674INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
7675{
developer72fb0bb2023-01-11 09:46:29 +08007676
developer7e4a2a62023-04-06 19:56:03 +08007677 wifi_getApAclDevices(apIndex, macArray, buf_size);
developer72fb0bb2023-01-11 09:46:29 +08007678
7679 return RETURN_OK;
7680}
7681
7682
7683// Get the list of stations associated per AP
7684INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
7685{
developer7e4a2a62023-04-06 19:56:03 +08007686 char interface_name[IF_NAME_SIZE] = {0};
7687 char cmd[MAX_CMD_SIZE];
developer72fb0bb2023-01-11 09:46:29 +08007688
developer7e4a2a62023-04-06 19:56:03 +08007689 if(apIndex > 3) //Currently supporting apIndex upto 3
7690 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007691
developer7e4a2a62023-04-06 19:56:03 +08007692 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7693 return RETURN_ERR;
7694
7695 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s list_sta", interface_name);
7696 _syscmd(cmd, macArray, buf_size);
7697 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08007698}
7699
developer8dd72532023-05-17 19:58:35 +08007700int hex2num(char c)
7701{
7702 if (c >= '0' && c <= '9')
7703 return c - '0';
7704 if (c >= 'a' && c <= 'f')
7705 return c - 'a' + 10;
7706 if (c >= 'A' && c <= 'F')
7707 return c - 'A' + 10;
7708 return -1;
7709}
7710
7711/**
7712 * hwaddr_aton2 - Convert ASCII string to MAC address (in any known format)
7713 * @txt: MAC address as a string (e.g., 00:11:22:33:44:55 or 0011.2233.4455)
7714 * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
7715 * Returns: Characters used (> 0) on success, -1 on failure
7716 */
7717int hwaddr_aton2(const char *txt, unsigned char *addr)
7718{
7719 int i;
7720 const char *pos = txt;
7721
7722 for (i = 0; i < 6; i++) {
7723 int a, b;
7724
7725 while (*pos == ':' || *pos == '.' || *pos == '-')
7726 pos++;
7727
7728 a = hex2num(*pos++);
7729 if (a < 0)
7730 return -1;
7731 b = hex2num(*pos++);
7732 if (b < 0)
7733 return -1;
7734 *addr++ = (a << 4) | b;
7735 }
7736
7737 return pos - txt;
7738}
7739
developer72fb0bb2023-01-11 09:46:29 +08007740// adds the mac address to the filter list
7741//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
7742INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
7743{
developer7e4a2a62023-04-06 19:56:03 +08007744 char inf_name[IF_NAME_SIZE] = {0};
developer8dd72532023-05-17 19:58:35 +08007745 int if_idx, ret = 0;
developer49b17232023-05-19 16:35:19 +08007746 struct nl_msg *msg = NULL;
7747 struct nlattr * msg_data = NULL;
7748 struct mtk_nl80211_param param;
developer8dd72532023-05-17 19:58:35 +08007749 unsigned char mac[ETH_ALEN] = {0x00, 0x0c, 0x43, 0x11, 0x22, 0x33};
7750 struct unl unl_ins;
developer7e4a2a62023-04-06 19:56:03 +08007751 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
7752 return RETURN_ERR;
developer7e4a2a62023-04-06 19:56:03 +08007753 if (!DeviceMacAddress)
7754 return RETURN_ERR;
developer8dd72532023-05-17 19:58:35 +08007755 if (hwaddr_aton2(DeviceMacAddress, mac) < 0) {
developer2edaf012023-05-24 14:24:53 +08007756 wifi_debug(DEBUG_ERROR, "error device mac address=%s\n", DeviceMacAddress);
developer8dd72532023-05-17 19:58:35 +08007757 return RETURN_ERR;
7758 }
developer8dd72532023-05-17 19:58:35 +08007759 if_idx = if_nametoindex(inf_name);
developer2edaf012023-05-24 14:24:53 +08007760 if (!if_idx) {
7761 wifi_debug(DEBUG_ERROR, "can't finde ifname(%s) index,ERROR\n", inf_name);
7762 return RETURN_ERR;
7763 }
developer49b17232023-05-19 16:35:19 +08007764 /*init mtk nl80211 vendor cmd*/
7765 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_ACL;
7766 param.if_type = NL80211_ATTR_IFINDEX;
7767 param.if_idx = if_idx;
7768 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
7769 if (ret) {
7770 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
developer8dd72532023-05-17 19:58:35 +08007771 return RETURN_ERR;
7772 }
developer49b17232023-05-19 16:35:19 +08007773 /*add mtk vendor cmd data*/
7774 if (nla_put(msg, MTK_NL80211_VENDOR_ATTR_ACL_ADD_MAC, ETH_ALEN, mac)) {
developer2edaf012023-05-24 14:24:53 +08007775 wifi_debug(DEBUG_ERROR, "Nla put attribute error\n");
developer8dd72532023-05-17 19:58:35 +08007776 nlmsg_free(msg);
7777 goto err;
7778 }
developer49b17232023-05-19 16:35:19 +08007779 /*send mtk nl80211 vendor msg*/
7780 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
7781 if (ret) {
7782 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
developer8dd72532023-05-17 19:58:35 +08007783 goto err;
7784 }
developer49b17232023-05-19 16:35:19 +08007785 /*deinit mtk nl80211 vendor msg*/
7786 mtk_nl80211_deint(&unl_ins);
7787 wifi_debug(DEBUG_NOTICE, "set cmd success.\n");
developer8dd72532023-05-17 19:58:35 +08007788 return RETURN_OK;
7789err:
developer49b17232023-05-19 16:35:19 +08007790 mtk_nl80211_deint(&unl_ins);
7791 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
developer8dd72532023-05-17 19:58:35 +08007792 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007793}
7794
7795// deletes the mac address from the filter list
7796//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
7797INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
7798{
developer2edaf012023-05-24 14:24:53 +08007799 struct unl unl_ins;
7800 int if_idx = 0, ret = 0;
7801 struct nl_msg *msg = NULL;
7802 struct nlattr * msg_data = NULL;
7803 struct mtk_nl80211_param param;
developer7e4a2a62023-04-06 19:56:03 +08007804 char inf_name[IF_NAME_SIZE] = {0};
developer2edaf012023-05-24 14:24:53 +08007805 unsigned char mac[ETH_ALEN] = {0};
developer72fb0bb2023-01-11 09:46:29 +08007806
developer7e4a2a62023-04-06 19:56:03 +08007807 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
7808 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007809
developer7e4a2a62023-04-06 19:56:03 +08007810 if (!DeviceMacAddress)
7811 return RETURN_ERR;
7812
developer2edaf012023-05-24 14:24:53 +08007813 if (hwaddr_aton2(DeviceMacAddress, mac) < 0) {
7814 wifi_debug(DEBUG_ERROR, "error device mac address=%s\n", DeviceMacAddress);
7815 return RETURN_ERR;
7816 }
developer72fb0bb2023-01-11 09:46:29 +08007817
developer2edaf012023-05-24 14:24:53 +08007818 if_idx = if_nametoindex(inf_name);
7819 if (!if_idx) {
7820 wifi_debug(DEBUG_ERROR, "can't finde ifname(%s) index,ERROR\n", inf_name);
7821 return RETURN_ERR;
7822 }
7823 /*init mtk nl80211 vendor cmd*/
7824 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_ACL;
7825 param.if_type = NL80211_ATTR_IFINDEX;
7826 param.if_idx = if_idx;
7827 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
7828 if (ret) {
7829 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
7830 return RETURN_ERR;
7831 }
7832 /*add mtk vendor cmd data*/
7833 if (nla_put(msg, MTK_NL80211_VENDOR_ATTR_ACL_DEL_MAC, ETH_ALEN, mac)) {
7834 wifi_debug(DEBUG_ERROR, "Nla put attribute error\n");
7835 nlmsg_free(msg);
7836 goto err;
7837 }
7838 /*send mtk nl80211 vendor msg*/
7839 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
7840 if (ret) {
7841 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
7842 goto err;
7843 }
7844 /*deinit mtk nl80211 vendor msg*/
7845 mtk_nl80211_deint(&unl_ins);
7846 wifi_debug(DEBUG_NOTICE, "set cmd success.\n");
7847 return RETURN_OK;
7848err:
7849 mtk_nl80211_deint(&unl_ins);
7850 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
7851 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007852}
7853
7854// outputs the number of devices in the filter list
7855INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
7856{
developer7e4a2a62023-04-06 19:56:03 +08007857 char inf_name[IF_NAME_SIZE] = {0};
developer2edaf012023-05-24 14:24:53 +08007858 char *mac_arry = NULL, *ptr = NULL, mac_str[18] = {0};
7859 UINT buf_size = 1024;
7860 UINT sta_num = 0;
7861 unsigned char mac[ETH_ALEN] = {0};
developer72fb0bb2023-01-11 09:46:29 +08007862 if(output_uint == NULL)
7863 return RETURN_ERR;
7864
developer2edaf012023-05-24 14:24:53 +08007865 mac_arry = (char *)malloc(buf_size);
7866 if (mac_arry == NULL) {
7867 wifi_debug(DEBUG_ERROR, "malloc mac_arry fails\n");
developer7e4a2a62023-04-06 19:56:03 +08007868 return RETURN_ERR;
developer2edaf012023-05-24 14:24:53 +08007869 }
7870 memset(mac_arry, buf_size, 0);
7871 /*mac_arry str format: 00:11:22:33:44:55\n00:11:22:33:44:66\0*/
7872 if (wifi_getApAclDevices(apIndex, mac_arry, buf_size)!= RETURN_OK) {
7873 wifi_debug(DEBUG_ERROR, "get acl list entries fails\n");
7874 return RETURN_ERR;
7875 }
7876 /*count the acl str nums:*/
7877 wifi_debug(DEBUG_NOTICE, "mac_arry: %s\n", mac_arry);
developer7e4a2a62023-04-06 19:56:03 +08007878
developer2edaf012023-05-24 14:24:53 +08007879 /*mac addr string format:
7880 exp1: 00:11:22:33:44:55\0
7881 exp2: 00:11:22:33:44:55\n00:11:22:33:44:66\0
7882 */
7883 ptr = mac_arry;
7884 while (sscanf(ptr, "%17s", mac_str) == 1) {
7885 if (hwaddr_aton2(mac_str, mac) >= 0)
7886 sta_num++;
7887 ptr = strstr(ptr, mac_str) + strlen(mac_str);
7888 }
7889 *output_uint = sta_num;
7890 wifi_debug(DEBUG_NOTICE, "output_uint: %d\n", *output_uint);
7891 free(mac_arry);
7892 mac_arry = NULL;
developer7e4a2a62023-04-06 19:56:03 +08007893 return RETURN_OK;
developer2edaf012023-05-24 14:24:53 +08007894err:
7895 free(mac_arry);
7896 mac_arry = NULL;
7897 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007898}
7899
7900INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
7901{
7902 char cmd[128]={'\0'};
7903 char buf[128]={'\0'};
7904
7905 if(strcmp(action,"DENY")==0)
7906 {
7907 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
7908 system(buf);
7909 return RETURN_OK;
7910 }
7911
7912 if(strcmp(action,"ALLOW")==0)
7913 {
7914 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
7915 system(buf);
7916 return RETURN_OK;
7917 }
7918
7919 return RETURN_ERR;
7920
7921}
7922
7923// enable kick for devices on acl black list
7924INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
7925{
developer47cc27a2023-05-17 23:09:58 +08007926 char aclArray[MAX_BUF_SIZE] = {0}, *acl = NULL;
7927 char assocArray[MAX_BUF_SIZE] = {0}, *asso = NULL;
developer72fb0bb2023-01-11 09:46:29 +08007928
7929 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
7930 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
7931
developer7e4a2a62023-04-06 19:56:03 +08007932 /* if there are no devices connected there is nothing to do */
developer72fb0bb2023-01-11 09:46:29 +08007933 if (strlen(assocArray) < 17)
7934 return RETURN_OK;
7935
developer7e4a2a62023-04-06 19:56:03 +08007936 if (enable == TRUE) {
7937 /* kick off the MAC which is in ACL array (deny list) */
7938 acl = strtok(aclArray, "\n");
developer72fb0bb2023-01-11 09:46:29 +08007939 while (acl != NULL) {
7940 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
7941 wifi_kickApAssociatedDevice(apIndex, acl);
7942
developer7e4a2a62023-04-06 19:56:03 +08007943 acl = strtok(NULL, "\n");
developer72fb0bb2023-01-11 09:46:29 +08007944 }
7945 wifi_setApMacAddressControlMode(apIndex, 2);
developer7e4a2a62023-04-06 19:56:03 +08007946 } else
developer72fb0bb2023-01-11 09:46:29 +08007947 wifi_setApMacAddressControlMode(apIndex, 0);
developer72fb0bb2023-01-11 09:46:29 +08007948
developer72fb0bb2023-01-11 09:46:29 +08007949 return RETURN_OK;
7950}
7951
7952INT wifi_setPreferPrivateConnection(BOOL enable)
7953{
7954 return RETURN_OK;
7955}
7956
7957// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
7958INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
7959{
developer2edaf012023-05-24 14:24:53 +08007960 int if_idx = 0, ret = 0;
7961 struct unl unl_ins;
7962 struct nl_msg *msg = NULL;
7963 struct nlattr * msg_data = NULL;
7964 struct mtk_nl80211_param param;
7965 int acl_policy = -1;
developer7e4a2a62023-04-06 19:56:03 +08007966 char inf_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08007967
developer7e4a2a62023-04-06 19:56:03 +08007968 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
7969 return RETURN_ERR;
developer2edaf012023-05-24 14:24:53 +08007970 if_idx = if_nametoindex(inf_name);
7971 if (!if_idx) {
7972 wifi_debug(DEBUG_ERROR, "can't finde ifname(%s) index,ERROR\n", inf_name);
7973 return RETURN_ERR;
7974 }
7975 /*init mtk nl80211 vendor cmd*/
7976 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_ACL;
7977 param.if_type = NL80211_ATTR_IFINDEX;
7978 param.if_idx = if_idx;
7979 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
7980 if (ret) {
7981 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
7982 return RETURN_ERR;
7983 }
7984 /*add mtk vendor cmd data*/
7985 if (filterMode == 0) {
7986 acl_policy = MTK_NL80211_VENDOR_ATTR_ACL_DISABLE;
7987 } else if (filterMode == 1) {
7988 acl_policy = MTK_NL80211_VENDOR_ATTR_ACL_ENABLE_WHITE_LIST;
7989 } else if (filterMode == 2) {
7990 acl_policy = MTK_NL80211_VENDOR_ATTR_ACL_ENABLE_BLACK_LIST;
7991 } else {
7992 wifi_debug(DEBUG_ERROR, "filtermode(%d) not support error\n", filterMode);
7993 nlmsg_free(msg);
7994 goto err;
7995 }
7996 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_ACL_POLICY, acl_policy)) {
7997 wifi_debug(DEBUG_ERROR, "Nla put attribute error\n");
7998 nlmsg_free(msg);
7999 goto err;
8000 }
8001 /*send mtk nl80211 vendor msg*/
8002 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
8003 if (ret) {
8004 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
8005 goto err;
8006 }
8007 /*deinit mtk nl80211 vendor msg*/
8008 mtk_nl80211_deint(&unl_ins);
8009 wifi_debug(DEBUG_NOTICE, "set cmd success.\n");
developer7e4a2a62023-04-06 19:56:03 +08008010 return RETURN_OK;
developer2edaf012023-05-24 14:24:53 +08008011err:
8012 mtk_nl80211_deint(&unl_ins);
8013 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
8014 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08008015}
8016
8017// 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.
8018INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
8019{
8020 return RETURN_ERR;
8021}
8022
8023// gets the vlan ID for this ap from an internal enviornment variable
8024INT wifi_getApVlanID(INT apIndex, INT *output_int)
8025{
8026 if(apIndex==0)
8027 {
8028 *output_int=100;
8029 return RETURN_OK;
8030 }
8031
8032 return RETURN_ERR;
8033}
8034
8035// sets the vlan ID for this ap to an internal enviornment variable
8036INT wifi_setApVlanID(INT apIndex, INT vlanId)
8037{
8038 //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)
8039 return RETURN_ERR;
8040}
8041
8042// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
8043INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
8044{
8045 snprintf(bridgeName, 32, "brlan0");
8046 snprintf(IP, 32, "10.0.0.1");
8047 snprintf(subnet, 32, "255.255.255.0");
8048
8049 return RETURN_OK;
8050}
8051
8052//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
8053INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
8054{
8055 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
8056 return RETURN_ERR;
8057}
8058
8059// reset the vlan configuration for this ap
8060INT wifi_resetApVlanCfg(INT apIndex)
8061{
developera1255e42023-05-13 17:45:02 +08008062 char interface_name[16] = {0};
developer2202b332023-05-24 16:23:22 +08008063 int if_idx, ret = 0;
8064 struct nl_msg *msg = NULL;
8065 struct nlattr * msg_data = NULL;
8066 struct mtk_nl80211_param param;
8067 struct unl unl_ins;
8068 struct vlan_policy_param vlan_param;
developer72fb0bb2023-01-11 09:46:29 +08008069
developer2202b332023-05-24 16:23:22 +08008070 if (apIndex > MAX_APS) {
8071 wifi_debug(DEBUG_ERROR, "Invalid apIndex %d\n", apIndex);
8072 return RETURN_ERR;
8073 }
developer72fb0bb2023-01-11 09:46:29 +08008074
developer2202b332023-05-24 16:23:22 +08008075 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8076 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8077 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08008078
developer2202b332023-05-24 16:23:22 +08008079 /*step 1. mwctl dev %s set vlan_tag 0*/
8080 if_idx = if_nametoindex(interface_name);
8081 /*init mtk nl80211 vendor cmd*/
8082 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_VLAN;
8083 param.if_type = NL80211_ATTR_IFINDEX;
8084 param.if_idx = if_idx;
8085 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
developer72fb0bb2023-01-11 09:46:29 +08008086
developer2202b332023-05-24 16:23:22 +08008087 if (ret) {
8088 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
8089 return RETURN_ERR;
8090 }
developer72fb0bb2023-01-11 09:46:29 +08008091
developer2202b332023-05-24 16:23:22 +08008092 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_VLAN_TAG_INFO, 0)) {
8093 printf("Nla put attribute error\n");
8094 nlmsg_free(msg);
8095 goto err;
8096 }
developer72fb0bb2023-01-11 09:46:29 +08008097
developer2202b332023-05-24 16:23:22 +08008098 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
8099 if (ret) {
8100 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vendor msg fails\n");
8101 goto err;
8102 }
8103 mtk_nl80211_deint(&unl_ins);
8104 wifi_debug(DEBUG_NOTICE, "set vlan_tag 0 cmd success.\n");
developer72fb0bb2023-01-11 09:46:29 +08008105
developer2202b332023-05-24 16:23:22 +08008106 /*step 2. mwctl dev %s set vlan_priority 0*/
8107 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
8108 if (ret) {
8109 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
8110 return RETURN_ERR;
8111 }
developer72fb0bb2023-01-11 09:46:29 +08008112
developer2202b332023-05-24 16:23:22 +08008113 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_VLAN_PRIORITY_INFO, 0)) {
8114 printf("Nla put attribute error\n");
8115 nlmsg_free(msg);
8116 goto err;
8117 }
developer72fb0bb2023-01-11 09:46:29 +08008118
developer2202b332023-05-24 16:23:22 +08008119 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
8120 if (ret) {
8121 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vendor msg fails\n");
8122 goto err;
8123 }
8124 mtk_nl80211_deint(&unl_ins);
8125 wifi_debug(DEBUG_NOTICE, "set vlan_priority 0 cmd success.\n");
8126
8127 /*step 3. mwctl dev %s set vlan_id 0*/
8128 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
8129 if (ret) {
8130 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
developera1255e42023-05-13 17:45:02 +08008131 return RETURN_ERR;
developer2202b332023-05-24 16:23:22 +08008132 }
developer72fb0bb2023-01-11 09:46:29 +08008133
developer2202b332023-05-24 16:23:22 +08008134 if (nla_put_u16(msg, MTK_NL80211_VENDOR_ATTR_VLAN_ID_INFO, 0)) {
8135 printf("Nla put attribute error\n");
8136 nlmsg_free(msg);
8137 goto err;
8138 }
8139
8140 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
8141 if (ret) {
8142 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vendor msg fails\n");
8143 goto err;
8144 }
8145 mtk_nl80211_deint(&unl_ins);
8146 wifi_debug(DEBUG_NOTICE, "set vlan_id cmd success.\n");
8147
8148 /*step 4. mwctl dev %s set vlan_en 0*/
8149 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
8150 if (ret) {
8151 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
8152 return RETURN_ERR;
8153 }
8154
8155 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_VLAN_EN_INFO, 0)) {
8156 printf("Nla put attribute error\n");
8157 nlmsg_free(msg);
8158 goto err;
8159 }
8160
8161 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
8162 if (ret) {
8163 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vendor msg fails\n");
8164 goto err;
8165 }
8166 mtk_nl80211_deint(&unl_ins);
8167 wifi_debug(DEBUG_NOTICE, "set vlan_id cmd success.\n");
8168
8169 /*step 5. mwctl dev %s set vlan_policy 0:4*/
8170 vlan_param.direction = 0;
8171 vlan_param.policy = 4;
8172 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
8173 if (ret) {
8174 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
8175 return RETURN_ERR;
8176 }
8177 if (nla_put(msg, MTK_NL80211_VENDOR_ATTR_VLAN_POLICY_INFO, sizeof(vlan_param), &vlan_param)) {
8178 printf("Nla put attribute error\n");
8179 nlmsg_free(msg);
8180 goto err;
8181 }
8182
8183 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
8184 if (ret) {
8185 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vendor msg fails\n");
8186 goto err;
8187 }
8188 mtk_nl80211_deint(&unl_ins);
8189 wifi_debug(DEBUG_NOTICE, "set vlan_policy 0:4 cmd success.\n");
8190
8191 /*step 6. mwctl dev %s set vlan_policy 1:0*/
8192 vlan_param.direction = 1;
8193 vlan_param.policy = 0;
8194 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
8195 if (ret) {
8196 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
8197 return RETURN_ERR;
8198 }
8199
8200 if (nla_put(msg, MTK_NL80211_VENDOR_ATTR_VLAN_POLICY_INFO, sizeof(vlan_param), &vlan_param)) {
8201 printf("Nla put attribute error\n");
8202 nlmsg_free(msg);
8203 goto err;
8204 }
8205
8206 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
8207 if (ret) {
8208 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vendor msg fails\n");
8209 goto err;
8210 }
8211 /*deinit mtk nl80211 vendor msg*/
8212 mtk_nl80211_deint(&unl_ins);
8213 wifi_debug(DEBUG_NOTICE, "set vlan_policy 1:0 cmd success.\n");
8214
8215 /*TODO need to modify VLAN config in dat file*/
8216 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8217
8218 return RETURN_OK;
8219err:
8220 mtk_nl80211_deint(&unl_ins);
8221 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
8222 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08008223}
8224
8225// 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.
8226INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
8227{
8228 return RETURN_ERR;
8229}
8230
8231// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
8232INT wifi_startHostApd()
8233{
8234 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8235 system("systemctl start hostapd.service");
8236 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8237 return RETURN_OK;
8238 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
8239}
8240
8241// stops hostapd
developer69b61b02023-03-07 17:17:44 +08008242INT wifi_stopHostApd()
developer72fb0bb2023-01-11 09:46:29 +08008243{
8244 char cmd[128] = {0};
8245 char buf[128] = {0};
8246
8247 sprintf(cmd,"systemctl stop hostapd");
8248 _syscmd(cmd, buf, sizeof(buf));
8249
8250 return RETURN_OK;
8251}
8252
8253// restart hostapd dummy function
8254INT wifi_restartHostApd()
8255{
8256 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8257 system("systemctl restart hostapd-global");
8258 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8259
8260 return RETURN_OK;
8261}
8262
8263static int align_hostapd_config(int index)
8264{
8265 ULONG lval;
8266 wifi_getRadioChannel(index%2, &lval);
8267 wifi_setRadioChannel(index%2, lval);
8268 return RETURN_OK;
8269}
8270
8271// sets the AP enable status variable for the specified ap.
8272INT wifi_setApEnable(INT apIndex, BOOL enable)
8273{
developer7e4a2a62023-04-06 19:56:03 +08008274 char interface_name[16] = {0};
8275 char config_file[MAX_BUF_SIZE] = {0};
8276 char cmd[MAX_CMD_SIZE] = {0};
8277 char buf[MAX_BUF_SIZE] = {0};
developer47cc27a2023-05-17 23:09:58 +08008278 BOOL status = FALSE;
developer7e4a2a62023-04-06 19:56:03 +08008279 int max_radio_num = 0;
8280 int phyId = 0;
developer72fb0bb2023-01-11 09:46:29 +08008281
developer7e4a2a62023-04-06 19:56:03 +08008282 wifi_getApEnable(apIndex, &status);
developer72fb0bb2023-01-11 09:46:29 +08008283
developer7e4a2a62023-04-06 19:56:03 +08008284 wifi_getMaxRadioNumber(&max_radio_num);
8285 if (enable == status)
8286 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08008287
developer7e4a2a62023-04-06 19:56:03 +08008288 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8289 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08008290
developer7e4a2a62023-04-06 19:56:03 +08008291 if (enable == TRUE) {
8292 int radioIndex = apIndex % max_radio_num;
8293 phyId = radio_index_to_phy(radioIndex);
developerf3c7d292023-05-29 17:57:16 +08008294 snprintf(cmd, MAX_CMD_SIZE, "ifconfig %s up", interface_name);
8295 _syscmd(cmd, buf, sizeof(buf));
developer8a3bbbf2023-03-15 17:47:23 +08008296
developer7e4a2a62023-04-06 19:56:03 +08008297 snprintf(config_file, MAX_BUF_SIZE, "%s%d.conf", CONFIG_PREFIX, apIndex);
8298 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyId, config_file);
8299 _syscmd(cmd, buf, sizeof(buf));
8300 } else {
8301 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw REMOVE %s", interface_name);
8302 _syscmd(cmd, buf, sizeof(buf));
developerf3c7d292023-05-29 17:57:16 +08008303 snprintf(cmd, MAX_CMD_SIZE, "ifconfig %s down", interface_name);
8304 _syscmd(cmd, buf, sizeof(buf));
developer7e4a2a62023-04-06 19:56:03 +08008305 }
8306 snprintf(cmd, MAX_CMD_SIZE, "sed -i -n -e '/^%s=/!p' -e '$a%s=%d' %s",
8307 interface_name, interface_name, enable, VAP_STATUS_FILE);
8308 _syscmd(cmd, buf, sizeof(buf));
8309 //Wait for wifi up/down to apply
8310 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08008311}
8312
8313// Outputs the setting of the internal variable that is set by wifi_setApEnable().
8314INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
8315{
developer7e4a2a62023-04-06 19:56:03 +08008316 char interface_name[IF_NAME_SIZE] = {0};
8317 char cmd[MAX_CMD_SIZE] = {0};
8318 char buf[MAX_BUF_SIZE] = {0};
developere740c2a2023-05-23 18:34:32 +08008319 int ret;
developer72fb0bb2023-01-11 09:46:29 +08008320
developer7e4a2a62023-04-06 19:56:03 +08008321 if ((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
8322 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08008323
developer7e4a2a62023-04-06 19:56:03 +08008324 *output_bool = 0;
developer72fb0bb2023-01-11 09:46:29 +08008325
developer7e4a2a62023-04-06 19:56:03 +08008326 if ((apIndex >= 0) && (apIndex < MAX_APS)) {
8327 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
8328 *output_bool = FALSE;
8329 return RETURN_OK;
8330 }
developere740c2a2023-05-23 18:34:32 +08008331 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status", interface_name);
8332 ret = system(cmd);
8333 if (ret == 0)
8334 *output_bool = 1;
developer7e4a2a62023-04-06 19:56:03 +08008335 }
developer72fb0bb2023-01-11 09:46:29 +08008336
developer7e4a2a62023-04-06 19:56:03 +08008337 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08008338}
8339
developer69b61b02023-03-07 17:17:44 +08008340// Outputs the AP "Enabled" "Disabled" status from driver
8341INT wifi_getApStatus(INT apIndex, CHAR *output_string)
developer72fb0bb2023-01-11 09:46:29 +08008342{
developer7e4a2a62023-04-06 19:56:03 +08008343 char cmd[128] = {0};
8344 char buf[128] = {0};
8345 BOOL output_bool;
developer72fb0bb2023-01-11 09:46:29 +08008346
developer7e4a2a62023-04-06 19:56:03 +08008347 if (!output_string) {
8348 printf("%s: null pointer!", __func__);
8349 return RETURN_ERR;
8350 }
developer72fb0bb2023-01-11 09:46:29 +08008351
developer7e4a2a62023-04-06 19:56:03 +08008352 wifi_getApEnable(apIndex, &output_bool);
developer72fb0bb2023-01-11 09:46:29 +08008353
developer7e4a2a62023-04-06 19:56:03 +08008354 if(output_bool == 1)
8355 snprintf(output_string, 32, "Up");
8356 else
8357 snprintf(output_string, 32, "Disable");
8358
8359 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08008360}
8361
8362//Indicates whether or not beacons include the SSID name.
8363// outputs a 1 if SSID on the AP is enabled, else outputs 0
8364INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
8365{
8366 //get the running status
8367 char config_file[MAX_BUF_SIZE] = {0};
8368 char buf[16] = {0};
8369
8370 if (!output)
8371 return RETURN_ERR;
8372
8373 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8374 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
8375 // default is enable
8376 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
8377 *output = TRUE;
8378
8379 return RETURN_OK;
8380}
8381
8382// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
8383INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
8384{
8385 //store the config, apply instantly
8386 char config_file[MAX_BUF_SIZE] = {0};
8387 struct params list;
8388
8389 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8390 list.name = "ignore_broadcast_ssid";
8391 list.value = enable?"0":"1";
8392
8393 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8394 wifi_hostapdWrite(config_file, &list, 1);
8395 wifi_hostapdProcessUpdate(apIndex, &list, 1);
8396 //TODO: call hostapd_cli for dynamic_config_control
8397 wifi_reloadAp(apIndex);
8398 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8399
8400 return RETURN_OK;
8401}
8402
8403//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
8404INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
8405{
developer47cc27a2023-05-17 23:09:58 +08008406 /* get the running status */
8407 if(!output_uint)
8408 return RETURN_ERR;
8409
8410 *output_uint = 15;
8411 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08008412}
8413
developer47cc27a2023-05-17 23:09:58 +08008414/*Do not support AP retry limit fix*/
developer72fb0bb2023-01-11 09:46:29 +08008415INT wifi_setApRetryLimit(INT apIndex, UINT number)
8416{
developer47cc27a2023-05-17 23:09:58 +08008417 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08008418}
8419
developer95c045d2023-05-24 19:26:28 +08008420int get_wmm_cap_status_callback(struct nl_msg *msg, void *data)
8421{
8422 struct nlattr *tb[NL80211_ATTR_MAX + 1];
8423 struct nlattr *vndr_tb[MTK_NL80211_VENDOR_WMM_ATTR_MAX + 1];
8424 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
8425 unsigned char *status = (unsigned char * *)data;
8426 int err = 0;
8427 //u16 acl_result_len = 0;
8428
8429 err = nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
8430 genlmsg_attrlen(gnlh, 0), NULL);
8431 if (err < 0)
8432 return err;
8433
8434 if (tb[NL80211_ATTR_VENDOR_DATA]) {
8435 err = nla_parse_nested(vndr_tb, MTK_NL80211_VENDOR_WMM_ATTR_MAX,
8436 tb[NL80211_ATTR_VENDOR_DATA], NULL);
8437 if (err < 0)
8438 return err;
8439
8440 if (vndr_tb[MTK_NL80211_VENDOR_ATTR_WMM_AP_CAP_INFO]) {
8441 //acl_result_len = nla_len(vndr_tb[MTK_NL80211_VENDOR_ATTR_MCAST_SNOOP_ENABLE]);
8442 *status = nla_get_u8(vndr_tb[MTK_NL80211_VENDOR_ATTR_WMM_AP_CAP_INFO]);
8443 }
8444 }
8445
8446 return 0;
8447}
8448
developer72fb0bb2023-01-11 09:46:29 +08008449//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
8450INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
8451{
developer95c045d2023-05-24 19:26:28 +08008452 int if_idx, ret = 0;
developer8e6583c2023-05-23 13:36:06 +08008453 char interface_name[16] = {0};
developer95c045d2023-05-24 19:26:28 +08008454 unsigned char status = 0;
8455 struct nl_msg *msg = NULL;
8456 struct nlattr * msg_data = NULL;
8457 struct mtk_nl80211_param param;
8458 struct unl unl_ins;
8459 struct vlan_policy_param vlan_param;
developer8e6583c2023-05-23 13:36:06 +08008460
8461 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08008462 if(!output)
8463 return RETURN_ERR;
developer8e6583c2023-05-23 13:36:06 +08008464
developer95c045d2023-05-24 19:26:28 +08008465 if (apIndex > MAX_APS) {
8466 wifi_debug(DEBUG_ERROR, "Invalid apIndex %d\n", apIndex);
8467 return RETURN_ERR;
8468 }
8469
developer8e6583c2023-05-23 13:36:06 +08008470 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8471 return RETURN_ERR;
developer95c045d2023-05-24 19:26:28 +08008472
8473 if_idx = if_nametoindex(interface_name);
8474 /*init mtk nl80211 vendor cmd*/
8475 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_WMM;
8476 param.if_type = NL80211_ATTR_IFINDEX;
8477 param.if_idx = if_idx;
8478 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
8479
8480 if (ret) {
8481 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
8482 return RETURN_ERR;
8483 }
8484
8485 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_WMM_AP_CAP_INFO, 0xf)) {
8486 wifi_debug(DEBUG_ERROR, "Nla put attribute error\n");
8487 nlmsg_free(msg);
8488 goto err;
8489 }
8490
8491 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, get_wmm_cap_status_callback,
8492 (void *)&status);
8493 if (ret) {
8494 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vendor msg fails\n");
8495 goto err;
8496 }
8497 mtk_nl80211_deint(&unl_ins);
8498
8499 *output = status == 0 ? FALSE : TRUE;
8500 wifi_debug(DEBUG_NOTICE, "wmm cap (%u).\n", (unsigned int)(*output));
developer8e6583c2023-05-23 13:36:06 +08008501
8502 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08008503 return RETURN_OK;
developer95c045d2023-05-24 19:26:28 +08008504err:
8505 mtk_nl80211_deint(&unl_ins);
8506 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
8507 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08008508}
8509
8510//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
8511INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
8512{
8513 //get the running status from driver
8514 char cmd[128] = {0};
8515 char buf[128] = {0};
8516 int max_radio_num = 0, radioIndex = 0;
8517 int phyId = 0;
8518
8519 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8520
8521 wifi_getMaxRadioNumber(&max_radio_num);
8522 radioIndex = apIndex % max_radio_num;
8523 phyId = radio_index_to_phy(radioIndex);
8524 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", phyId);
8525 _syscmd(cmd,buf, sizeof(buf));
8526
8527 if (strlen(buf) > 0)
8528 *output = true;
8529
8530 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8531
8532 return RETURN_OK;
8533}
8534
8535//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
8536INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
8537{
developer95c045d2023-05-24 19:26:28 +08008538 return wifi_getApWMMCapability(apIndex, output);
developer72fb0bb2023-01-11 09:46:29 +08008539}
8540
8541// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
8542INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
8543{
developer95c045d2023-05-24 19:26:28 +08008544 int if_idx, ret = 0;
8545 char interface_name[16] = {0};
8546 unsigned char status = 0;
8547 struct nl_msg *msg = NULL;
8548 struct nlattr * msg_data = NULL;
8549 struct mtk_nl80211_param param;
8550 struct unl unl_ins;
8551 struct vlan_policy_param vlan_param;
developer72fb0bb2023-01-11 09:46:29 +08008552
developer95c045d2023-05-24 19:26:28 +08008553 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08008554
developer95c045d2023-05-24 19:26:28 +08008555 if (apIndex > MAX_APS) {
8556 wifi_debug(DEBUG_ERROR, "Invalid apIndex %d\n", apIndex);
8557 return RETURN_ERR;
8558 }
developer72fb0bb2023-01-11 09:46:29 +08008559
developer95c045d2023-05-24 19:26:28 +08008560 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8561 return RETURN_ERR;
developer8e6583c2023-05-23 13:36:06 +08008562
developer95c045d2023-05-24 19:26:28 +08008563 if_idx = if_nametoindex(interface_name);
8564 /*init mtk nl80211 vendor cmd*/
8565 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_WMM;
8566 param.if_type = NL80211_ATTR_IFINDEX;
8567 param.if_idx = if_idx;
8568 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
8569
8570 if (ret) {
8571 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
8572 return RETURN_ERR;
8573 }
8574
8575 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_WMM_AP_CAP_INFO, enable ? 1 : 0)) {
8576 wifi_debug(DEBUG_ERROR, "Nla put attribute error\n");
8577 nlmsg_free(msg);
8578 goto err;
8579 }
8580
8581 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
8582 if (ret) {
8583 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vendor msg fails\n");
8584 goto err;
8585 }
8586 mtk_nl80211_deint(&unl_ins);
8587
8588 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8589 return RETURN_OK;
8590err:
8591 mtk_nl80211_deint(&unl_ins);
8592 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
8593 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08008594}
8595
developer95c045d2023-05-24 19:26:28 +08008596
developer72fb0bb2023-01-11 09:46:29 +08008597//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.
8598INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
8599{
8600 //get the running status from driver
8601 if(!output)
8602 return RETURN_ERR;
8603
8604 char config_file[128] = {0};
8605 char buf[16] = {0};
8606
8607 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8608 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
8609 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
8610 *output = TRUE;
8611 else
8612 *output = FALSE;
8613
8614 return RETURN_OK;
8615}
8616
8617// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
8618INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
8619{
8620 //save config and apply instantly.
8621 char config_file[MAX_BUF_SIZE] = {0};
8622 struct params list;
8623
8624 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8625 list.name = "uapsd_advertisement_enabled";
8626 list.value = enable?"1":"0";
8627
8628 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8629 wifi_hostapdWrite(config_file, &list, 1);
8630 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developere82c0ca2023-05-10 16:25:35 +08008631 wifi_quick_reload_ap(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08008632 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8633
8634 return RETURN_OK;
8635}
8636
8637// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
8638INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
8639{
8640 char interface_name[16] = {0};
8641 // assume class 0->BE, 1->BK, 2->VI, 3->VO
8642 char cmd[128] = {0};
8643 char buf[128] = {0};
8644 char ack_filepath[128] = {0};
8645 uint16_t bitmap = 0;
8646 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
8647 FILE *f = NULL;
8648
8649 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
8650
8651 // Get current setting
8652 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
8653 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
8654 _syscmd(cmd, buf, sizeof(buf));
8655 if (strlen(buf) > 0)
8656 bitmap = strtoul(buf, NULL, 10);
8657
8658 bitmap = strtoul(buf, NULL, 10);
8659
8660 if (ackPolicy == TRUE) { // True, unset this class
8661 bitmap &= ~class_map[class];
8662 } else { // False, set this class
8663 bitmap |= class_map[class];
8664 }
8665
8666 f = fopen(ack_filepath, "w");
8667 if (f == NULL) {
8668 fprintf(stderr, "%s: fopen failed\n", __func__);
8669 return RETURN_ERR;
8670 }
8671 fprintf(f, "%hu", bitmap);
8672 fclose(f);
8673
8674 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8675 return RETURN_ERR;
8676 snprintf(cmd, sizeof(cmd), "iw dev %s set noack_map 0x%04x\n", interface_name, bitmap);
8677 _syscmd(cmd, buf, sizeof(buf));
8678
8679 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
8680 return RETURN_OK;
8681}
8682
8683//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.
8684INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
8685{
8686 //get the running status from driver
8687 if(!output_uint)
8688 return RETURN_ERR;
8689
8690 char output[16]={'\0'};
8691 char config_file[MAX_BUF_SIZE] = {0};
8692
8693 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8694 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
8695 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
8696 else {
8697 int device_num = atoi(output);
8698 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
8699 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
8700 return RETURN_ERR;
8701 }
8702 else {
8703 *output_uint = device_num;
8704 }
8705 }
8706
8707 return RETURN_OK;
8708}
8709
8710INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
8711{
8712 //store to wifi config, apply instantly
8713 char str[MAX_BUF_SIZE]={'\0'};
8714 char cmd[MAX_CMD_SIZE]={'\0'};
8715 struct params params;
8716 char config_file[MAX_BUF_SIZE] = {0};
8717
8718 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8719 if (number > MAX_ASSOCIATED_STA_NUM) {
8720 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
8721 return RETURN_ERR;
8722 }
8723 sprintf(str, "%d", number);
8724 params.name = "max_num_sta";
8725 params.value = str;
8726
8727 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
8728 int ret = wifi_hostapdWrite(config_file, &params, 1);
8729 if (ret) {
8730 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
8731 ,__func__, ret);
8732 }
8733
8734 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
8735 if (ret) {
8736 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
8737 ,__func__, ret);
8738 }
8739 wifi_reloadAp(apIndex);
8740 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8741
8742 return RETURN_OK;
8743}
8744
8745//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.
8746INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
8747{
8748 //get the current threshold
8749 if(!output_uint)
8750 return RETURN_ERR;
8751 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
8752 if (*output_uint == 0)
8753 *output_uint = 50;
8754 return RETURN_OK;
8755}
8756
8757INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
8758{
8759 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
8760 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
8761 return RETURN_OK;
8762 return RETURN_ERR;
8763}
8764
8765//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.
8766INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
8767{
8768 if(!output_uint)
8769 return RETURN_ERR;
8770 *output_uint = 3;
8771 return RETURN_OK;
8772}
8773
8774//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
8775INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
8776{
8777 if(!output_uint)
8778 return RETURN_ERR;
8779 *output_uint = 3;
8780 return RETURN_OK;
8781}
8782
8783//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.
8784INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
8785{
8786 if(!output_in_seconds)
8787 return RETURN_ERR;
8788 *output_in_seconds = 0;
8789 return RETURN_OK;
8790}
8791
8792//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
8793INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
8794{
8795 if(!output || apIndex>=MAX_APS)
8796 return RETURN_ERR;
8797 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
8798 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
8799 return RETURN_OK;
developer69b61b02023-03-07 17:17:44 +08008800}
developer72fb0bb2023-01-11 09:46:29 +08008801
8802//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
8803INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
8804{
8805 char config_file[128] = {0};
8806 char wpa[16] = {0};
8807 char key_mgmt[64] = {0};
8808 char buf[16] = {0};
8809 if (!output)
8810 return RETURN_ERR;
8811
8812 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8813 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
8814
8815 strcpy(output, "None");//Copying "None" to output string for default case
8816 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
8817 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
8818 if (!strcmp(wpa, "1"))
8819 snprintf(output, 32, "WPA-Personal");
8820 else if (!strcmp(wpa, "2"))
8821 snprintf(output, 32, "WPA2-Personal");
8822 else if (!strcmp(wpa, "3"))
8823 snprintf(output, 32, "WPA-WPA2-Personal");
8824
developere5750452023-05-15 16:46:42 +08008825 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
8826 snprintf(output, 32, "WPA3-Enterprise");
developer72fb0bb2023-01-11 09:46:29 +08008827 } else if (strstr(key_mgmt, "WPA-EAP")) {
8828 if (!strcmp(wpa, "1"))
8829 snprintf(output, 32, "WPA-Enterprise");
8830 else if (!strcmp(wpa, "2"))
8831 snprintf(output, 32, "WPA2-Enterprise");
8832 else if (!strcmp(wpa, "3"))
8833 snprintf(output, 32, "WPA-WPA2-Enterprise");
8834 } else if (strstr(key_mgmt, "SAE")) {
8835 if (strstr(key_mgmt, "WPA-PSK") == NULL)
8836 snprintf(output, 32, "WPA3-Personal");
8837 else
8838 snprintf(output, 32, "WPA3-Personal-Transition");
developer72fb0bb2023-01-11 09:46:29 +08008839 }
8840
8841 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
8842 return RETURN_OK;
8843#if 0
8844 //TODO: need to revisit below implementation
8845 char securityType[32], authMode[32];
8846 int enterpriseMode=0;
8847
8848 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8849 if(!output)
8850 return RETURN_ERR;
8851
8852 wifi_getApBeaconType(apIndex, securityType);
8853 strcpy(output,"None");//By default, copying "None" to output string
8854 if (strncmp(securityType,"None", strlen("None")) == 0)
8855 return RETURN_OK;
8856
8857 wifi_getApBasicAuthenticationMode(apIndex, authMode);
8858 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
8859
8860 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
8861 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
8862 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
8863 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
8864 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
8865 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
8866 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8867
8868 return RETURN_OK;
8869#endif
8870}
developer69b61b02023-03-07 17:17:44 +08008871
developer72fb0bb2023-01-11 09:46:29 +08008872INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
8873{
8874 char securityType[32];
8875 char authMode[32];
8876
8877 //store settings and wait for wifi up to apply
8878 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8879 if(!encMode)
8880 return RETURN_ERR;
8881
8882 if (strcmp(encMode, "None")==0)
8883 {
8884 strcpy(securityType,"None");
8885 strcpy(authMode,"None");
8886 }
8887 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
8888 {
8889 strcpy(securityType,"WPAand11i");
8890 strcpy(authMode,"PSKAuthentication");
8891 }
8892 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
8893 {
8894 strcpy(securityType,"WPAand11i");
8895 strcpy(authMode,"EAPAuthentication");
8896 }
8897 else if (strcmp(encMode, "WPA-Personal")==0)
8898 {
8899 strcpy(securityType,"WPA");
8900 strcpy(authMode,"PSKAuthentication");
8901 }
8902 else if (strcmp(encMode, "WPA-Enterprise")==0)
8903 {
8904 strcpy(securityType,"WPA");
8905 strcpy(authMode,"EAPAuthentication");
8906 }
8907 else if (strcmp(encMode, "WPA2-Personal")==0)
8908 {
8909 strcpy(securityType,"11i");
8910 strcpy(authMode,"PSKAuthentication");
8911 }
8912 else if (strcmp(encMode, "WPA2-Enterprise")==0)
8913 {
8914 strcpy(securityType,"11i");
8915 strcpy(authMode,"EAPAuthentication");
8916 }
8917 else if (strcmp(encMode, "WPA3-Personal") == 0)
8918 {
8919 strcpy(securityType,"11i");
8920 strcpy(authMode,"SAEAuthentication");
8921 }
8922 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
8923 {
8924 strcpy(securityType, "11i");
8925 strcpy(authMode, "PSK-SAEAuthentication");
8926 }
8927 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
8928 {
8929 strcpy(securityType,"11i");
8930 strcpy(authMode,"EAP_192-bit_Authentication");
8931 }
developer3086e2f2023-01-17 09:40:01 +08008932 else if (strcmp(encMode, "OWE") == 0)
8933 {
8934 strcpy(securityType,"11i");
8935 strcpy(authMode,"Enhanced_Open");
8936 }
developer72fb0bb2023-01-11 09:46:29 +08008937 else
8938 {
8939 strcpy(securityType,"None");
8940 strcpy(authMode,"None");
8941 }
8942 wifi_setApBeaconType(apIndex, securityType);
8943 wifi_setApBasicAuthenticationMode(apIndex, authMode);
8944 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8945
8946 return RETURN_OK;
developer69b61b02023-03-07 17:17:44 +08008947}
developer72fb0bb2023-01-11 09:46:29 +08008948
8949
8950//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
8951// output_string must be pre-allocated as 64 character string by caller
8952// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
8953INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
8954{
8955 char buf[16] = {0};
8956 char config_file[MAX_BUF_SIZE] = {0};
8957
8958 if(output_string==NULL)
8959 return RETURN_ERR;
8960
8961 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8962 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
8963
8964 if(strcmp(buf,"0")==0)
8965 {
8966 printf("wpa_mode is %s ......... \n",buf);
8967 return RETURN_ERR;
8968 }
8969
8970 wifi_dbg_printf("\nFunc=%s\n",__func__);
8971 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developere5750452023-05-15 16:46:42 +08008972 wifi_hostapdRead(config_file,"wpa_psk",output_string,65);
developer72fb0bb2023-01-11 09:46:29 +08008973 wifi_dbg_printf("\noutput_string=%s\n",output_string);
8974
8975 return RETURN_OK;
8976}
8977
8978// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
8979// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
8980INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
8981{
8982 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
8983 struct params params={'\0'};
8984 int ret;
8985 char config_file[MAX_BUF_SIZE] = {0};
8986
8987 if(NULL == preSharedKey)
8988 return RETURN_ERR;
8989
developere5750452023-05-15 16:46:42 +08008990 params.name = "wpa_psk";
developer72fb0bb2023-01-11 09:46:29 +08008991
developere5750452023-05-15 16:46:42 +08008992 if(strlen(preSharedKey) != 64)
developer72fb0bb2023-01-11 09:46:29 +08008993 {
developere5750452023-05-15 16:46:42 +08008994 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 64 chars\n");
developer72fb0bb2023-01-11 09:46:29 +08008995 return RETURN_ERR;
8996 }
8997 params.value = preSharedKey;
8998 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8999 ret = wifi_hostapdWrite(config_file, &params, 1);
developere5750452023-05-15 16:46:42 +08009000 if(!ret) {
developer72fb0bb2023-01-11 09:46:29 +08009001 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
developere5750452023-05-15 16:46:42 +08009002 wifi_reloadAp(apIndex);
9003 }
developer72fb0bb2023-01-11 09:46:29 +08009004 return ret;
9005 //TODO: call hostapd_cli for dynamic_config_control
9006}
9007
9008//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
9009// outputs the passphrase, maximum 63 characters
9010INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
9011{
9012 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
9013
9014 wifi_dbg_printf("\nFunc=%s\n",__func__);
9015 if (NULL == output_string)
9016 return RETURN_ERR;
9017
9018 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9019 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
9020 if(strcmp(buf,"0")==0)
9021 {
9022 printf("wpa_mode is %s ......... \n",buf);
9023 return RETURN_ERR;
9024 }
9025
9026 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
9027 wifi_dbg_printf("\noutput_string=%s\n",output_string);
9028
9029 return RETURN_OK;
9030}
9031
9032// sets the passphrase enviornment variable, max 63 characters
9033INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
9034{
9035 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
9036 struct params params={'\0'};
9037 char config_file[MAX_BUF_SIZE] = {0};
9038 int ret;
9039
9040 if(NULL == passPhrase)
9041 return RETURN_ERR;
9042
9043 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
9044 {
9045 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
9046 return RETURN_ERR;
9047 }
9048 params.name = "wpa_passphrase";
9049 params.value = passPhrase;
9050 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9051 ret=wifi_hostapdWrite(config_file,&params,1);
developere5750452023-05-15 16:46:42 +08009052 if(!ret) {
developer72fb0bb2023-01-11 09:46:29 +08009053 wifi_hostapdProcessUpdate(apIndex, &params, 1);
developere5750452023-05-15 16:46:42 +08009054 wifi_reloadAp(apIndex);
9055 }
developer72fb0bb2023-01-11 09:46:29 +08009056
9057 return ret;
9058}
9059
9060//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.
9061INT wifi_setApSecurityReset(INT apIndex)
9062{
9063 char original_config_file[64] = {0};
9064 char current_config_file[64] = {0};
9065 char buf[64] = {0};
9066 char cmd[64] = {0};
9067 char wpa[4] = {0};
9068 char wpa_psk[64] = {0};
9069 char wpa_passphrase[64] = {0};
9070 char wpa_psk_file[128] = {0};
9071 char wpa_key_mgmt[64] = {0};
9072 char wpa_pairwise[32] = {0};
9073 wifi_band band;
9074 struct params list[6];
9075
9076 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9077
9078 band = wifi_index_to_band(apIndex);
9079 if (band == band_2_4)
9080 sprintf(original_config_file, "/etc/hostapd-2G.conf");
9081 else if (band == band_5)
9082 sprintf(original_config_file, "/etc/hostapd-5G.conf");
9083 else if (band == band_6)
9084 sprintf(original_config_file, "/etc/hostapd-6G.conf");
9085 else
9086 return RETURN_ERR;
9087
9088 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
9089 list[0].name = "wpa";
9090 list[0].value = wpa;
developer69b61b02023-03-07 17:17:44 +08009091
developer72fb0bb2023-01-11 09:46:29 +08009092 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
9093 list[1].name = "wpa_psk";
9094 list[1].value = wpa_psk;
9095
9096 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
9097 list[2].name = "wpa_passphrase";
9098 list[2].value = wpa_passphrase;
9099
9100 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
9101
9102 if (strlen(wpa_psk_file) == 0)
9103 strcpy(wpa_psk_file, PSK_FILE);
9104
9105 if (access(wpa_psk_file, F_OK) != 0) {
9106 sprintf(cmd, "touch %s", wpa_psk_file);
9107 _syscmd(cmd, buf, sizeof(buf));
9108 }
9109 list[3].name = "wpa_psk_file";
9110 list[3].value = wpa_psk_file;
9111
9112 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
9113 list[4].name = "wpa_key_mgmt";
9114 list[4].value = wpa_key_mgmt;
9115
9116 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
9117 list[5].name = "wpa_pairwise";
9118 list[5].value = wpa_pairwise;
9119
9120 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
9121 wifi_hostapdWrite(current_config_file, list, 6);
9122
9123 wifi_setApEnable(apIndex, FALSE);
9124 wifi_setApEnable(apIndex, TRUE);
9125
9126 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9127 return RETURN_OK;
9128}
9129
9130//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).
9131INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
9132{
9133 char config_file[64] = {0};
9134 char buf[64] = {0};
9135 char cmd[256] = {0};
9136
9137 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9138
9139 if(!IP_output || !Port_output || !RadiusSecret_output)
9140 return RETURN_ERR;
9141
9142 // Read the first matched config
9143 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9144 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
9145 _syscmd(cmd, buf, sizeof(buf));
9146 strncpy(IP_output, buf, 64);
9147
9148 memset(buf, 0, sizeof(buf));
9149 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
9150 _syscmd(cmd, buf, sizeof(buf));
9151 *Port_output = atoi(buf);
9152
9153 memset(buf, 0, sizeof(buf));
9154 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
9155 _syscmd(cmd, buf, sizeof(buf));
9156 strncpy(RadiusSecret_output, buf, 64);
9157
9158 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9159 return RETURN_OK;
9160}
9161
9162INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
9163{
9164 char config_file[64] = {0};
9165 char port_str[8] = {0};
9166 char cmd[256] = {0};
9167 char buf[128] = {0};
9168
9169 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9170
developere5750452023-05-15 16:46:42 +08009171 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
9172 return RETURN_ERR;
9173
9174 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
9175 return RETURN_ERR;
9176
developer72fb0bb2023-01-11 09:46:29 +08009177 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9178
9179 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
9180 _syscmd(cmd, buf, sizeof(buf));
9181 memset(cmd, 0, sizeof(cmd));
9182
9183 snprintf(port_str, sizeof(port_str), "%d", port);
9184 if (strlen(buf) == 0)
9185 // Append
9186 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
9187 "auth_server_addr=%s\\n"
9188 "auth_server_port=%s\\n"
9189 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
9190 else {
9191 // Delete the three lines setting after the "# radius 1" comment
9192 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
9193 _syscmd(cmd, buf, sizeof(buf));
9194 memset(cmd, 0, sizeof(cmd));
9195 // Use "# radius 1" comment to find the location to insert the radius setting
9196 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
9197 "# radius 1\\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 }
9202 if(_syscmd(cmd, buf, sizeof(buf))) {
9203 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
9204 return RETURN_ERR;
9205 }
9206
9207 wifi_reloadAp(apIndex);
9208 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9209 return RETURN_OK;
9210}
9211
9212INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
9213{
9214 char config_file[64] = {0};
9215 char buf[64] = {0};
9216 char cmd[256] = {0};
9217
9218 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9219
9220 if(!IP_output || !Port_output || !RadiusSecret_output)
9221 return RETURN_ERR;
9222
9223 // Read the second matched config
9224 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9225 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
9226 _syscmd(cmd, buf, sizeof(buf));
9227 strncpy(IP_output, buf, 64);
9228
9229 memset(buf, 0, sizeof(buf));
9230 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
9231 _syscmd(cmd, buf, sizeof(buf));
9232 *Port_output = atoi(buf);
9233
9234 memset(buf, 0, sizeof(buf));
9235 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
9236 _syscmd(cmd, buf, sizeof(buf));
9237 strncpy(RadiusSecret_output, buf, 64);
9238
9239 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9240 return RETURN_OK;
9241}
9242
9243INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
9244{
9245 char config_file[64] = {0};
9246 char port_str[8] = {0};
9247 char cmd[256] = {0};
9248 char buf[128] = {0};
9249
9250 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9251
developere5750452023-05-15 16:46:42 +08009252 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
9253 return RETURN_ERR;
9254
9255 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
9256 return RETURN_ERR;
9257
developer72fb0bb2023-01-11 09:46:29 +08009258 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9259
9260 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
9261 _syscmd(cmd, buf, sizeof(buf));
9262 memset(cmd, 0, sizeof(cmd));
9263
9264 snprintf(port_str, sizeof(port_str), "%d", port);
9265 if (strlen(buf) == 0)
9266 // Append
9267 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
9268 "auth_server_addr=%s\\n"
9269 "auth_server_port=%s\\n"
9270 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
9271 else {
9272 // Delete the three lines setting after the "# radius 2" comment
9273 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
9274 _syscmd(cmd, buf, sizeof(buf));
9275 memset(cmd, 0, sizeof(cmd));
9276 // Use "# radius 2" comment to find the location to insert the radius setting
9277 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
9278 "# radius 2\\n"
9279 "auth_server_addr=%s\\n"
9280 "auth_server_port=%s\\n"
9281 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
9282 }
9283 if(_syscmd(cmd, buf, sizeof(buf))) {
9284 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
9285 return RETURN_ERR;
9286 }
9287
9288 wifi_reloadAp(apIndex);
9289 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9290 return RETURN_OK;
9291}
9292
9293//RadiusSettings
9294INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
9295{
9296 if(!output)
9297 return RETURN_ERR;
9298
9299 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
developer69b61b02023-03-07 17:17:44 +08009300 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
9301 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
9302 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
9303 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 +08009304 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 +08009305 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
9306 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
9307 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 +08009308 //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.
9309
9310 return RETURN_OK;
9311}
9312
9313INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
9314{
9315 //store the paramters, and apply instantly
9316 return RETURN_ERR;
9317}
9318
9319//Device.WiFi.AccessPoint.{i}.WPS.Enable
9320//Enables or disables WPS functionality for this access point.
9321// outputs the WPS enable state of this ap in output_bool
9322INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
9323{
9324 char interface_name[16] = {0};
9325 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
9326 if(!output_bool)
9327 return RETURN_ERR;
9328 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9329 return RETURN_ERR;
9330 sprintf(cmd,"hostapd_cli -i %s get_config | grep wps_state | cut -d '=' -f2", interface_name);
9331 _syscmd(cmd, buf, sizeof(buf));
9332 if(strstr(buf, "configured"))
9333 *output_bool=TRUE;
9334 else
9335 *output_bool=FALSE;
9336
9337 return RETURN_OK;
developer69b61b02023-03-07 17:17:44 +08009338}
developer72fb0bb2023-01-11 09:46:29 +08009339
9340//Device.WiFi.AccessPoint.{i}.WPS.Enable
9341// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
9342INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
9343{
9344 char config_file[MAX_BUF_SIZE] = {0};
developere5750452023-05-15 16:46:42 +08009345 char buf[128] = {0};
developer72fb0bb2023-01-11 09:46:29 +08009346 struct params params;
9347
9348 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9349 //store the paramters, and wait for wifi up to apply
9350 params.name = "wps_state";
developere5750452023-05-15 16:46:42 +08009351 if (enable == TRUE) {
9352 wifi_getApBeaconType(apIndex, buf);
9353 if (strncmp(buf, "None", 4) == 0) // If ap didn't set encryption
9354 params.value = "1";
9355 else // If ap set encryption
9356 params.value = "2";
9357 } else {
9358 params.value = "0";
9359 }
developer72fb0bb2023-01-11 09:46:29 +08009360
9361 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9362 wifi_hostapdWrite(config_file, &params, 1);
9363 wifi_hostapdProcessUpdate(apIndex, &params, 1);
9364 wifi_reloadAp(apIndex);
9365
9366 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9367 return RETURN_OK;
9368}
9369
9370//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
9371INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
9372{
9373 if(!output)
9374 return RETURN_ERR;
9375 snprintf(output, 128, "PushButton,PIN");
9376 return RETURN_OK;
9377}
9378
9379//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
9380//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.
9381// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
9382INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
9383{
9384 if(!output)
9385 return RETURN_ERR;
9386 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
9387
9388 return RETURN_OK;
9389}
9390
9391//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
9392// 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
9393INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
9394{
9395 //apply instantly. No setting need to be stored.
9396 char methods[MAX_BUF_SIZE], *token, *next_token;
9397 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
9398 struct params params;
9399
9400 if(!methodString)
9401 return RETURN_ERR;
9402 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9403 //store the paramters, and wait for wifi up to apply
9404
9405 snprintf(methods, sizeof(methods), "%s", methodString);
9406 for(token=methods; *token; token=next_token)
9407 {
9408 strtok_r(token, ",", &next_token);
9409 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
9410 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
9411 else if(*token=='E')
9412 {
9413 if(!strcmp(methods, "Ethernet"))
9414 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
9415 else if(!strcmp(methods, "ExternalNFCToken"))
9416 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
9417 else
9418 printf("%s: Unknown WpsConfigMethod\n", __func__);
9419 }
9420 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
9421 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
9422 else if(*token=='N' && !strcmp(token, "NFCInterface"))
9423 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
9424 else if(*token=='P' )
9425 {
9426 if(!strcmp(token, "PushButton"))
developere5750452023-05-15 16:46:42 +08009427 snprintf(config_methods, sizeof(config_methods), "%s ", "push_button");
developer72fb0bb2023-01-11 09:46:29 +08009428 else if(!strcmp(token, "PIN"))
9429 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
9430 else
9431 printf("%s: Unknown WpsConfigMethod\n", __func__);
9432 }
9433 else
9434 printf("%s: Unknown WpsConfigMethod\n", __func__);
9435 }
9436 params.name = "config_methods";
9437 params.value = config_methods;
9438 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9439 wifi_hostapdWrite(config_file, &params, 1);
9440 wifi_hostapdProcessUpdate(apIndex, &params, 1);
9441 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9442
9443 return RETURN_OK;
9444}
9445
9446// outputs the pin value, ulong_pin must be allocated by the caller
9447INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
9448{
9449 char buf[MAX_BUF_SIZE] = {0};
9450 char cmd[MAX_CMD_SIZE] = {0};
9451
9452 if(!output_ulong)
9453 return RETURN_ERR;
9454 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
9455 _syscmd(cmd, buf, sizeof(buf));
9456 if(strlen(buf) > 0)
9457 *output_ulong=strtoul(buf, NULL, 10);
9458
9459 return RETURN_OK;
9460}
9461
9462// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
9463INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
9464{
9465 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
9466 char ap_pin[16] = {0};
9467 char buf[MAX_BUF_SIZE] = {0};
9468 char config_file[MAX_BUF_SIZE] = {0};
9469 ULONG prev_pin = 0;
9470 struct params params;
9471
9472 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9473 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
9474 params.name = "ap_pin";
9475 params.value = ap_pin;
9476 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9477 wifi_hostapdWrite(config_file, &params, 1);
9478 wifi_hostapdProcessUpdate(apIndex, &params, 1);
9479 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9480
9481 return RETURN_OK;
9482}
9483
9484// Output string is either Not configured or Configured, max 32 characters
9485INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
9486{
9487 char interface_name[16] = {0};
9488 char cmd[MAX_CMD_SIZE];
9489 char buf[MAX_BUF_SIZE]={0};
9490
9491 if(!output_string)
9492 return RETURN_ERR;
9493 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9494 snprintf(output_string, 32, "Not configured");
9495 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9496 return RETURN_ERR;
9497 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep wps_state | cut -d'=' -f2", interface_name);
9498 _syscmd(cmd, buf, sizeof(buf));
9499
9500 if(!strncmp(buf, "configured", 10))
9501 snprintf(output_string, 32, "Configured");
9502 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9503
9504 return RETURN_OK;
9505}
9506
9507// sets the WPS pin for this AP
9508INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
9509{
9510 char interface_name[16] = {0};
9511 char cmd[MAX_CMD_SIZE];
9512 char buf[MAX_BUF_SIZE]={0};
9513 BOOL enable;
9514
9515 wifi_getApEnable(apIndex, &enable);
9516 if (!enable)
9517 return RETURN_ERR;
9518 wifi_getApWpsEnable(apIndex, &enable);
9519 if (!enable)
9520 return RETURN_ERR;
9521
9522 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9523 return RETURN_ERR;
9524 snprintf(cmd, 64, "hostapd_cli -i%s wps_pin any %s", interface_name, pin);
9525 _syscmd(cmd, buf, sizeof(buf));
9526 if((strstr(buf, "OK"))!=NULL)
9527 return RETURN_OK;
9528
9529 return RETURN_ERR;
9530}
9531
9532// This function is called when the WPS push button has been pressed for this AP
9533INT wifi_setApWpsButtonPush(INT apIndex)
9534{
9535 char cmd[MAX_CMD_SIZE];
9536 char buf[MAX_BUF_SIZE]={0};
9537 char interface_name[16] = {0};
9538 BOOL enable=FALSE;
9539
9540 wifi_getApEnable(apIndex, &enable);
9541 if (!enable)
9542 return RETURN_ERR;
9543
9544 wifi_getApWpsEnable(apIndex, &enable);
9545 if (!enable)
9546 return RETURN_ERR;
9547
9548 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9549 return RETURN_ERR;
9550
9551 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel; hostapd_cli -i%s wps_pbc", interface_name, interface_name);
9552 _syscmd(cmd, buf, sizeof(buf));
9553
9554 if((strstr(buf, "OK"))!=NULL)
9555 return RETURN_OK;
9556 return RETURN_ERR;
9557}
9558
9559// cancels WPS mode for this AP
9560INT wifi_cancelApWPS(INT apIndex)
9561{
9562 char interface_name[16] = {0};
9563 char cmd[MAX_CMD_SIZE];
9564 char buf[MAX_BUF_SIZE]={0};
9565
9566 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9567 return RETURN_ERR;
9568 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel", interface_name);
9569 _syscmd(cmd,buf, sizeof(buf));
9570
9571 if((strstr(buf, "OK"))!=NULL)
9572 return RETURN_OK;
9573 return RETURN_ERR;
9574}
9575
9576//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
9577//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
9578INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
9579{
9580 char interface_name[16] = {0};
9581 FILE *f = NULL;
9582 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
9583 char cmd[256] = {0}, buf[2048] = {0};
9584 char *param = NULL, *value = NULL, *line=NULL;
9585 size_t len = 0;
9586 ssize_t nread = 0;
9587 wifi_associated_dev_t *dev=NULL;
9588
9589 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9590 *associated_dev_array = NULL;
9591 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9592 return RETURN_ERR;
9593 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
9594 _syscmd(cmd,buf,sizeof(buf));
9595 *output_array_size = atoi(buf);
9596
9597 if (*output_array_size <= 0)
9598 return RETURN_OK;
9599
9600 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
9601 *associated_dev_array = dev;
9602 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt" , interface_name);
9603 _syscmd(cmd,buf,sizeof(buf));
9604 f = fopen("/tmp/connected_devices.txt", "r");
9605 if (f==NULL)
9606 {
9607 *output_array_size=0;
9608 return RETURN_ERR;
9609 }
9610 while ((getline(&line, &len, f)) != -1)
9611 {
9612 param = strtok(line,"=");
9613 value = strtok(NULL,"=");
9614
9615 if( strcmp("flags",param) == 0 )
9616 {
9617 value[strlen(value)-1]='\0';
9618 if(strstr (value,"AUTHORIZED") != NULL )
9619 {
9620 dev[auth_temp].cli_AuthenticationState = 1;
9621 dev[auth_temp].cli_Active = 1;
9622 auth_temp++;
9623 read_flag=1;
9624 }
9625 }
9626 if(read_flag==1)
9627 {
9628 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
9629 {
9630 value[strlen(value)-1]='\0';
9631 sscanf(value, "%x:%x:%x:%x:%x:%x",
9632 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
9633 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
9634 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
9635 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
9636 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
9637 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
9638 mac_temp++;
9639 read_flag=0;
9640 }
9641 }
9642 }
9643 *output_array_size = auth_temp;
9644 auth_temp=0;
9645 mac_temp=0;
9646 free(line);
9647 fclose(f);
9648 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9649 return RETURN_OK;
9650}
9651
9652#define MACADDRESS_SIZE 6
9653
9654INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
9655{
9656 FILE *fp = NULL;
9657 char str[MAX_BUF_SIZE] = {0};
9658 int wificlientindex = 0 ;
9659 int count = 0;
9660 int signalstrength = 0;
9661 int arr[MACADDRESS_SIZE] = {0};
9662 unsigned char mac[MACADDRESS_SIZE] = {0};
9663 UINT wifi_count = 0;
9664 char virtual_interface_name[MAX_BUF_SIZE] = {0};
9665 char pipeCmd[MAX_CMD_SIZE] = {0};
9666
9667 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9668 *output_array_size = 0;
9669 *associated_dev_array = NULL;
9670
9671 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
9672 fp = popen(pipeCmd, "r");
developer69b61b02023-03-07 17:17:44 +08009673 if (fp == NULL)
developer72fb0bb2023-01-11 09:46:29 +08009674 {
9675 printf("Failed to run command inside function %s\n",__FUNCTION__ );
9676 return RETURN_ERR;
9677 }
9678
9679 /* Read the output a line at a time - output it. */
9680 fgets(str, sizeof(str)-1, fp);
9681 wifi_count = (unsigned int) atoi ( str );
9682 *output_array_size = wifi_count;
9683 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
9684 pclose(fp);
9685
9686 if(wifi_count == 0)
9687 {
9688 return RETURN_OK;
9689 }
9690 else
9691 {
9692 wifi_associated_dev3_t* temp = NULL;
9693 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
9694 if(temp == NULL)
9695 {
9696 printf("Error Statement. Insufficient memory \n");
9697 return RETURN_ERR;
9698 }
9699
9700 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
9701 system(pipeCmd);
9702 memset(pipeCmd,0,sizeof(pipeCmd));
9703 if(apIndex == 0)
9704 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
9705 else if(apIndex == 1)
9706 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
9707 system(pipeCmd);
9708
9709 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
9710 if(fp == NULL)
9711 {
9712 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
9713 free(temp);
9714 return RETURN_ERR;
9715 }
9716 fclose(fp);
9717
9718 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
9719 fp = popen(pipeCmd, "r");
9720 if(fp)
9721 {
9722 for(count =0 ; count < wifi_count; count++)
9723 {
9724 fgets(str, MAX_BUF_SIZE, fp);
9725 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
9726 {
9727 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
9728 {
9729 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
9730
9731 }
9732 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
9733 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]);
9734 }
9735 temp[count].cli_AuthenticationState = 1; //TODO
9736 temp[count].cli_Active = 1; //TODO
9737 }
9738 pclose(fp);
9739 }
9740
9741 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt");
9742 fp = popen(pipeCmd, "r");
9743 if(fp)
developer69b61b02023-03-07 17:17:44 +08009744 {
developer72fb0bb2023-01-11 09:46:29 +08009745 pclose(fp);
9746 }
9747 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
9748 if(fp)
9749 {
9750 for(count =0 ; count < wifi_count ;count++)
9751 {
9752 fgets(str, MAX_BUF_SIZE, fp);
9753 signalstrength = atoi(str);
9754 temp[count].cli_SignalStrength = signalstrength;
9755 temp[count].cli_RSSI = signalstrength;
9756 temp[count].cli_SNR = signalstrength + 95;
9757 }
9758 pclose(fp);
9759 }
9760
9761
9762 if((apIndex == 0) || (apIndex == 4))
9763 {
9764 for(count =0 ; count < wifi_count ;count++)
developer69b61b02023-03-07 17:17:44 +08009765 {
developer72fb0bb2023-01-11 09:46:29 +08009766 strcpy(temp[count].cli_OperatingStandard,"g");
9767 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
9768 }
9769
9770 //BytesSent
9771 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt");
9772 fp = popen(pipeCmd, "r");
9773 if(fp)
developer69b61b02023-03-07 17:17:44 +08009774 {
developer72fb0bb2023-01-11 09:46:29 +08009775 pclose(fp);
9776 }
9777 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
9778 if(fp)
9779 {
9780 for (count = 0; count < wifi_count; count++)
9781 {
9782 fgets(str, MAX_BUF_SIZE, fp);
9783 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
9784 }
9785 pclose(fp);
9786 }
9787
9788 //BytesReceived
9789 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt");
9790 fp = popen(pipeCmd, "r");
9791 if (fp)
9792 {
9793 pclose(fp);
9794 }
9795 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
9796 if (fp)
9797 {
9798 for (count = 0; count < wifi_count; count++)
9799 {
9800 fgets(str, MAX_BUF_SIZE, fp);
9801 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
9802 }
9803 pclose(fp);
9804 }
9805
9806 //PacketsSent
9807 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt");
9808 fp = popen(pipeCmd, "r");
9809 if (fp)
9810 {
9811 pclose(fp);
9812 }
9813
9814 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
9815 if (fp)
9816 {
9817 for (count = 0; count < wifi_count; count++)
9818 {
9819 fgets(str, MAX_BUF_SIZE, fp);
9820 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
9821 }
9822 pclose(fp);
9823 }
9824
9825 //PacketsReceived
9826 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt");
9827 fp = popen(pipeCmd, "r");
9828 if (fp)
9829 {
9830 pclose(fp);
9831 }
9832 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
9833 if (fp)
9834 {
9835 for (count = 0; count < wifi_count; count++)
9836 {
9837 fgets(str, MAX_BUF_SIZE, fp);
9838 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
9839 }
9840 pclose(fp);
9841 }
9842
9843 //ErrorsSent
9844 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt");
9845 fp = popen(pipeCmd, "r");
9846 if (fp)
9847 {
9848 pclose(fp);
9849 }
9850 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
9851 if (fp)
9852 {
9853 for (count = 0; count < wifi_count; count++)
9854 {
9855 fgets(str, MAX_BUF_SIZE, fp);
9856 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
9857 }
9858 pclose(fp);
9859 }
9860
9861 //ErrorsSent
9862 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt");
9863 fp = popen(pipeCmd, "r");
9864 if (fp)
9865 {
9866 pclose(fp);
9867 }
9868 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
9869 if (fp)
9870 {
9871 for (count = 0; count < wifi_count; count++)
9872 {
9873 fgets(str, MAX_BUF_SIZE, fp);
9874 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
9875 }
9876 pclose(fp);
9877 }
9878
9879 //LastDataDownlinkRate
9880 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt");
9881 fp = popen(pipeCmd, "r");
9882 if (fp)
9883 {
9884 pclose(fp);
9885 }
9886 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
9887 if (fp)
9888 {
9889 for (count = 0; count < wifi_count; count++)
9890 {
9891 fgets(str, MAX_BUF_SIZE, fp);
9892 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
9893 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
9894 }
9895 pclose(fp);
9896 }
9897
9898 //LastDataUplinkRate
9899 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt");
9900 fp = popen(pipeCmd, "r");
9901 if (fp)
9902 {
9903 pclose(fp);
9904 }
9905 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
9906 if (fp)
9907 {
9908 for (count = 0; count < wifi_count; count++)
9909 {
9910 fgets(str, MAX_BUF_SIZE, fp);
9911 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
9912 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
9913 }
9914 pclose(fp);
9915 }
9916
9917 }
9918 else if ((apIndex == 1) || (apIndex == 5))
9919 {
9920 for (count = 0; count < wifi_count; count++)
9921 {
9922 strcpy(temp[count].cli_OperatingStandard, "a");
9923 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
9924 temp[count].cli_BytesSent = 0;
9925 temp[count].cli_BytesReceived = 0;
9926 temp[count].cli_LastDataUplinkRate = 0;
9927 temp[count].cli_LastDataDownlinkRate = 0;
9928 temp[count].cli_PacketsSent = 0;
9929 temp[count].cli_PacketsReceived = 0;
9930 temp[count].cli_ErrorsSent = 0;
9931 }
9932 }
9933
9934 for (count = 0; count < wifi_count; count++)
9935 {
9936 temp[count].cli_Retransmissions = 0;
9937 temp[count].cli_DataFramesSentAck = 0;
9938 temp[count].cli_DataFramesSentNoAck = 0;
9939 temp[count].cli_MinRSSI = 0;
9940 temp[count].cli_MaxRSSI = 0;
9941 strncpy(temp[count].cli_InterferenceSources, "", 64);
9942 memset(temp[count].cli_IPAddress, 0, 64);
9943 temp[count].cli_RetransCount = 0;
9944 temp[count].cli_FailedRetransCount = 0;
9945 temp[count].cli_RetryCount = 0;
9946 temp[count].cli_MultipleRetryCount = 0;
9947 }
9948 *associated_dev_array = temp;
9949 }
9950 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9951 return RETURN_OK;
9952}
9953
developer7e4a2a62023-04-06 19:56:03 +08009954int wifihal_interfacestatus(CHAR *wifi_status, CHAR *interface_name)
developer72fb0bb2023-01-11 09:46:29 +08009955{
developer7e4a2a62023-04-06 19:56:03 +08009956 char cmd[MAX_CMD_SIZE] = {0};
9957 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08009958
developer7e4a2a62023-04-06 19:56:03 +08009959 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
9960
9961 snprintf(cmd, MAX_CMD_SIZE, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4 | tr -d '\\n'",
9962 interface_name);
9963 _syscmd(cmd, buf, MAX_BUF_SIZE);
9964
9965 strcpy(wifi_status, buf); /* TBD: check wifi_status mem lenth and replace with strcpy later */
9966
9967 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08009968 return RETURN_OK;
9969}
9970
9971/* #define HOSTAPD_STA_PARAM_ENTRIES 29
9972struct hostapd_sta_param {
9973 char key[50];
9974 char value[100];
9975}
9976
9977static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
9978 int i = 0;
9979
9980 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
9981 if (strncmp(params[i].key,key,50) == 0){
9982 return &params[i].value;
9983 }
9984 i++;
9985 }
9986 return NULL;
9987
9988} */
9989
9990static unsigned int count_occurences(const char *buf, const char *word)
9991{
9992 unsigned int n = 0;
9993 char *ptr = strstr(buf, word);
9994
9995 while (ptr++) {
9996 n++;
9997 ptr = strstr(ptr, word);
9998 }
9999
10000 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
10001 return n;
10002}
10003
10004static const char *get_line_from_str_buf(const char *buf, char *line)
10005{
10006 int i;
10007 int n = strlen(buf);
10008
10009 for (i = 0; i < n; i++) {
10010 line[i] = buf[i];
10011 if (buf[i] == '\n') {
10012 line[i] = '\0';
10013 return &buf[i + 1];
10014 }
10015 }
10016
10017 return NULL;
10018}
10019
10020INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
10021{
developer0d26f2c2023-05-25 19:46:36 +080010022 char interface_name[16] = {0};
10023 FILE *f = NULL;
10024 int auth_temp= -1;
10025 char cmd[256] = {0}, buf[2048] = {0};
10026 char *param = NULL, *value = NULL, *line=NULL;
10027 size_t len = 0;
10028 wifi_associated_dev3_t *dev=NULL;
developer72fb0bb2023-01-11 09:46:29 +080010029
10030 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer0d26f2c2023-05-25 19:46:36 +080010031 *associated_dev_array = NULL;
10032 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72fb0bb2023-01-11 09:46:29 +080010033 return RETURN_ERR;
developer0d26f2c2023-05-25 19:46:36 +080010034 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
10035 _syscmd(cmd, buf, sizeof(buf));
10036 *output_array_size = atoi(buf);
developer72fb0bb2023-01-11 09:46:29 +080010037
developer0d26f2c2023-05-25 19:46:36 +080010038 if (*output_array_size <= 0)
10039 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +080010040
developer0d26f2c2023-05-25 19:46:36 +080010041 dev=(wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
10042 *associated_dev_array = dev;
10043 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/diagnostic3_devices.txt" , interface_name);
10044 _syscmd(cmd,buf,sizeof(buf));
10045 f = fopen("/tmp/diagnostic3_devices.txt", "r");
10046 if (f == NULL)
10047 {
10048 *output_array_size=0;
developer72fb0bb2023-01-11 09:46:29 +080010049 return RETURN_ERR;
10050 }
developer0d26f2c2023-05-25 19:46:36 +080010051 while ((getline(&line, &len, f)) != -1)
10052 {
10053 param = strtok(line, "=");
10054 value = strtok(NULL, "=");
developer72fb0bb2023-01-11 09:46:29 +080010055
developer0d26f2c2023-05-25 19:46:36 +080010056 if( strcmp("flags",param) == 0 )
10057 {
10058 value[strlen(value)-1]='\0';
10059 if(strstr (value,"AUTHORIZED") != NULL )
10060 {
10061 auth_temp++;
10062 dev[auth_temp].cli_AuthenticationState = 1;
10063 dev[auth_temp].cli_Active = 1;
developer72fb0bb2023-01-11 09:46:29 +080010064 }
developer0d26f2c2023-05-25 19:46:36 +080010065 } else if (auth_temp < 0) {
10066 continue;
10067 } else 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[auth_temp].cli_MACAddress[0],
10072 (unsigned int *)&dev[auth_temp].cli_MACAddress[1],
10073 (unsigned int *)&dev[auth_temp].cli_MACAddress[2],
10074 (unsigned int *)&dev[auth_temp].cli_MACAddress[3],
10075 (unsigned int *)&dev[auth_temp].cli_MACAddress[4],
10076 (unsigned int *)&dev[auth_temp].cli_MACAddress[5]);
10077 } else if (strcmp("signal", param) == 0) {
10078 value[strlen(value)-1]='\0';
10079 sscanf(value, "%d", &dev[auth_temp].cli_RSSI);
10080 dev[auth_temp].cli_SNR = 95 + dev[auth_temp].cli_RSSI;
developer72fb0bb2023-01-11 09:46:29 +080010081 }
developer0d26f2c2023-05-25 19:46:36 +080010082 }
10083 if (line)
10084 free(line);
10085 fclose(f);
developer72fb0bb2023-01-11 09:46:29 +080010086 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +080010087 return RETURN_OK;
10088}
10089
10090#if 0
10091//To-do
10092INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
10093{
10094 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10095
10096 //Using different approach to get required WiFi Parameters from system available commands
developer69b61b02023-03-07 17:17:44 +080010097#if 0
developer72fb0bb2023-01-11 09:46:29 +080010098 FILE *f;
10099 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
10100 char cmd[256], buf[2048];
10101 char *param , *value, *line=NULL;
10102 size_t len = 0;
10103 ssize_t nread;
10104 wifi_associated_dev3_t *dev=NULL;
10105 *associated_dev_array = NULL;
10106 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
10107 _syscmd(cmd,buf,sizeof(buf));
10108 *output_array_size = atoi(buf);
10109
10110 if (*output_array_size <= 0)
10111 return RETURN_OK;
10112
10113 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
10114 *associated_dev_array = dev;
10115 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt", interface_name);
10116 _syscmd(cmd,buf,sizeof(buf));
10117 f = fopen("/tmp/connected_devices.txt", "r");
10118 if (f==NULL)
10119 {
10120 *output_array_size=0;
10121 return RETURN_ERR;
10122 }
10123 while ((nread = getline(&line, &len, f)) != -1)
10124 {
10125 param = strtok(line,"=");
10126 value = strtok(NULL,"=");
10127
10128 if( strcmp("flags",param) == 0 )
10129 {
10130 value[strlen(value)-1]='\0';
10131 if(strstr (value,"AUTHORIZED") != NULL )
10132 {
10133 dev[auth_temp].cli_AuthenticationState = 1;
10134 dev[auth_temp].cli_Active = 1;
10135 auth_temp++;
10136 read_flag=1;
10137 }
10138 }
10139 if(read_flag==1)
10140 {
10141 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
10142 {
10143 value[strlen(value)-1]='\0';
10144 sscanf(value, "%x:%x:%x:%x:%x:%x",
10145 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
10146 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
10147 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
10148 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
10149 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
10150 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
10151
10152 }
10153 else if( strcmp("rx_packets",param) == 0 )
10154 {
10155 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
10156 }
10157
10158 else if( strcmp("tx_packets",param) == 0 )
10159 {
developer69b61b02023-03-07 17:17:44 +080010160 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
developer72fb0bb2023-01-11 09:46:29 +080010161 }
10162
10163 else if( strcmp("rx_bytes",param) == 0 )
10164 {
10165 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
10166 }
10167
10168 else if( strcmp("tx_bytes",param) == 0 )
10169 {
developer69b61b02023-03-07 17:17:44 +080010170 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
developer72fb0bb2023-01-11 09:46:29 +080010171 mac_temp++;
10172 read_flag=0;
developer69b61b02023-03-07 17:17:44 +080010173 }
developer72fb0bb2023-01-11 09:46:29 +080010174 }
10175 }
10176
10177 *output_array_size = auth_temp;
10178 auth_temp=0;
10179 mac_temp=0;
10180 free(line);
10181 fclose(f);
10182#endif
10183 char interface_name[MAX_BUF_SIZE] = {0};
10184 char wifi_status[MAX_BUF_SIZE] = {0};
10185 char hostapdconf[MAX_BUF_SIZE] = {0};
10186
10187 wifi_associated_dev3_t *dev_array = NULL;
10188 ULONG wifi_count = 0;
10189
10190 *associated_dev_array = NULL;
10191 *output_array_size = 0;
10192
10193 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
10194 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
10195 {
10196 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
10197
10198 wifi_GetInterfaceName(interface_name, hostapdconf);
10199
10200 if(strlen(interface_name) > 1)
10201 {
10202 wifihal_interfacestatus(wifi_status,interface_name);
10203 if(strcmp(wifi_status,"RUNNING") == 0)
10204 {
10205 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
10206
10207 *associated_dev_array = dev_array;
developer69b61b02023-03-07 17:17:44 +080010208 *output_array_size = wifi_count;
developer72fb0bb2023-01-11 09:46:29 +080010209 }
10210 else
10211 {
10212 *associated_dev_array = NULL;
10213 }
10214 }
10215 }
10216
10217 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10218 return RETURN_OK;
10219}
10220#endif
10221
10222/* getIPAddress function */
10223/**
10224* @description Returning IpAddress of the Matched String
10225*
developer69b61b02023-03-07 17:17:44 +080010226* @param
developer72fb0bb2023-01-11 09:46:29 +080010227* @str Having MacAddress
developer69b61b02023-03-07 17:17:44 +080010228* @ipaddr Having ipaddr
developer72fb0bb2023-01-11 09:46:29 +080010229* @return The status of the operation
10230* @retval RETURN_OK if successful
10231* @retval RETURN_ERR if any error is detected
10232*
10233*/
10234
10235INT getIPAddress(char *str,char *ipaddr)
10236{
10237 FILE *fp = NULL;
10238 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
10239 int LeaseTime = 0,ret = 0;
10240 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
10241 {
10242 return RETURN_ERR;
10243 }
10244
10245 while ( fgets(buf, sizeof(buf), fp)!= NULL )
10246 {
10247 /*
10248 Sample:sss
10249 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
10250 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
10251 */
10252 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
10253 &(LeaseTime),
10254 phyAddr,
10255 ipAddr,
10256 hostName
10257 );
10258 if(ret != 4)
10259 continue;
10260 if(strcmp(str,phyAddr) == 0)
10261 strcpy(ipaddr,ipAddr);
10262 }
10263 fclose(fp);
10264 return RETURN_OK;
10265}
10266
10267/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
10268/**
10269* @description Returning Inactive wireless connected clients informations
10270*
developer69b61b02023-03-07 17:17:44 +080010271* @param
developer72fb0bb2023-01-11 09:46:29 +080010272* @filename Holding private_wifi 2g/5g content files
10273* @associated_dev_array Having inactiv wireless clients informations
10274* @output_array_size Returning Inactive wireless counts
10275* @return The status of the operation
10276* @retval RETURN_OK if successful
10277* @retval RETURN_ERR if any error is detected
10278*
10279*/
10280
10281INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
10282{
10283 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10284 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
10285 FILE *fp = NULL;
10286 int arr[MACADDRESS_SIZE] = {0};
10287 unsigned char mac[MACADDRESS_SIZE] = {0};
10288 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
10289 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
10290 fp = popen(buf,"r");
10291 if(fp == NULL)
10292 return RETURN_ERR;
10293 else
10294 {
10295 fgets(path,sizeof(path),fp);
10296 maccount = atoi(path);
10297 }
10298 pclose(fp);
10299 *output_array_size = maccount;
10300 wifi_associated_dev3_t* temp = NULL;
10301 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
10302 *associated_dev_array = temp;
10303 if(temp == NULL)
10304 {
10305 printf("Error Statement. Insufficient memory \n");
10306 return RETURN_ERR;
10307 }
10308 memset(buf,0,sizeof(buf));
10309 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
10310 fp = popen(buf,"r");
10311 if (fp == NULL) {
10312 fprintf(stderr, "%s: failed pipe command %s.\n", __func__, buf);
10313 return RETURN_ERR;
10314 }
10315 for(count = 0; count < maccount ; count++)
10316 {
10317 fgets(path,sizeof(path),fp);
10318 for(i = 0; path[i]!='\n';i++)
10319 str[i]=path[i];
10320 str[i]='\0';
10321 getIPAddress(str,ipaddr);
10322 memset(buf,0,sizeof(buf));
10323 if(strlen(ipaddr) > 0)
10324 {
10325 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
10326 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
10327 {
10328 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
10329 {
10330 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
10331 {
10332 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
10333
10334 }
10335 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
10336 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]);
10337 }
10338 temp[count].cli_AuthenticationState = 0; //TODO
developer69b61b02023-03-07 17:17:44 +080010339 temp[count].cli_Active = 0; //TODO
developer72fb0bb2023-01-11 09:46:29 +080010340 temp[count].cli_SignalStrength = 0;
10341 }
10342 else //Active wireless clients info
10343 {
10344 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
10345 {
10346 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
10347 {
10348 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
10349
10350 }
10351 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
10352 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]);
10353 }
10354 temp[count].cli_Active = 1;
10355 }
10356 }
10357 memset(ipaddr,0,sizeof(ipaddr));
10358 }
10359 pclose(fp);
10360 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10361 return RETURN_OK;
10362}
10363//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
10364//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
10365//To get Band Steering Capability
10366INT wifi_getBandSteeringCapability(BOOL *support)
10367{
10368 *support = FALSE;
10369 return RETURN_OK;
10370}
10371
10372
10373//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
10374//To get Band Steering enable status
10375INT wifi_getBandSteeringEnable(BOOL *enable)
10376{
10377 *enable = FALSE;
10378 return RETURN_OK;
10379}
10380
10381//To turn on/off Band steering
10382INT wifi_setBandSteeringEnable(BOOL enable)
10383{
10384 return RETURN_OK;
10385}
10386
10387//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
10388//To get Band Steering AP group
10389INT wifi_getBandSteeringApGroup(char *output_ApGroup)
10390{
10391 if (NULL == output_ApGroup)
10392 return RETURN_ERR;
10393
10394 strcpy(output_ApGroup, "1,2");
10395 return RETURN_OK;
10396}
10397
10398//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
10399//to set and read the band steering BandUtilizationThreshold parameters
10400INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
10401{
10402 return RETURN_ERR;
10403}
10404
10405INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
10406{
10407 return RETURN_ERR;
10408}
10409
10410//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
10411//to set and read the band steering RSSIThreshold parameters
10412INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
10413{
10414 return RETURN_ERR;
10415}
10416
10417INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
10418{
10419 return RETURN_ERR;
10420}
10421
10422
10423//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
10424//to set and read the band steering physical modulation rate threshold parameters
10425INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
10426{
10427 //If chip is not support, return -1
10428 return RETURN_ERR;
10429}
10430
10431INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
10432{
10433 //If chip is not support, return -1
10434 return RETURN_ERR;
10435}
10436
10437//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
10438//to set and read the inactivity time (in seconds) for steering under overload condition
10439INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
10440{
10441 return RETURN_ERR;
10442}
10443
10444INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
10445{
10446 return RETURN_ERR;
10447}
10448
10449//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
10450//to set and read the inactivity time (in seconds) for steering under Idle condition
10451INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
10452{
10453 return RETURN_ERR;
10454}
10455
10456INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
10457{
10458 return RETURN_ERR;
10459}
10460
10461//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
10462//pClientMAC[64]
10463//pSourceSSIDIndex[64]
10464//pDestSSIDIndex[64]
10465//pSteeringReason[256]
10466INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
10467{
10468 //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
10469 *pSteeringTime=time(NULL);
10470 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
10471 return RETURN_OK;
10472}
10473
10474INT wifi_ifConfigDown(INT apIndex)
10475{
10476 INT status = RETURN_OK;
10477 char cmd[64];
10478
10479 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
10480 printf("%s: %s\n", __func__, cmd);
10481 system(cmd);
10482
10483 return status;
10484}
10485
10486INT wifi_ifConfigUp(INT apIndex)
10487{
10488 char interface_name[16] = {0};
10489 char cmd[128];
10490 char buf[1024];
10491
10492 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
10493 return RETURN_ERR;
10494 snprintf(cmd, sizeof(cmd), "ifconfig %s up 2>/dev/null", interface_name);
10495 _syscmd(cmd, buf, sizeof(buf));
10496 return 0;
10497}
10498
10499//>> Deprecated. Replace with wifi_applyRadioSettings
10500INT wifi_pushBridgeInfo(INT apIndex)
10501{
developerb2977562023-05-24 17:54:12 +080010502 char ip[32] = {0};
10503 char subnet[32] = {0};
10504 char bridge[32] = {0};
10505 char cmd[128] = {0};
10506 char buf[1024] = {0};
developer72fb0bb2023-01-11 09:46:29 +080010507
developerb2977562023-05-24 17:54:12 +080010508 wifi_getApBridgeInfo(apIndex, bridge, ip, subnet);
developer72fb0bb2023-01-11 09:46:29 +080010509
developerb2977562023-05-24 17:54:12 +080010510 snprintf(cmd, sizeof(cmd), "ifconfig %s %s netmask %s ", bridge, ip, subnet);
10511 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +080010512
developerb2977562023-05-24 17:54:12 +080010513 return 0;
developer72fb0bb2023-01-11 09:46:29 +080010514}
10515
10516INT wifi_pushChannel(INT radioIndex, UINT channel)
10517{
10518 char interface_name[16] = {0};
10519 char cmd[128];
10520 char buf[1024];
10521 int apIndex;
10522
developer69b61b02023-03-07 17:17:44 +080010523 apIndex=(radioIndex==0)?0:1;
developer72fb0bb2023-01-11 09:46:29 +080010524 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
10525 return RETURN_ERR;
10526 snprintf(cmd, sizeof(cmd), "iwconfig %s freq %d",interface_name,channel);
10527 _syscmd(cmd,buf, sizeof(buf));
10528
10529 return 0;
10530}
10531
10532INT wifi_pushChannelMode(INT radioIndex)
10533{
10534 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
10535 return RETURN_ERR;
10536}
10537
10538INT wifi_pushDefaultValues(INT radioIndex)
10539{
10540 //Apply Comcast specified default radio settings instantly
10541 //AMPDU=1
10542 //AMPDUFrames=32
10543 //AMPDULim=50000
10544 //txqueuelen=1000
10545
10546 return RETURN_ERR;
10547}
10548
10549INT wifi_pushTxChainMask(INT radioIndex)
10550{
10551 //Apply default TxChainMask instantly
10552 return RETURN_ERR;
10553}
10554
10555INT wifi_pushRxChainMask(INT radioIndex)
10556{
10557 //Apply default RxChainMask instantly
10558 return RETURN_ERR;
10559}
10560
10561INT wifi_pushSSID(INT apIndex, CHAR *ssid)
10562{
developer7e4a2a62023-04-06 19:56:03 +080010563 INT status;
developer72fb0bb2023-01-11 09:46:29 +080010564
developer7e4a2a62023-04-06 19:56:03 +080010565 status = wifi_setSSIDName(apIndex, ssid);
10566 wifi_quick_reload_ap(apIndex);
developer72fb0bb2023-01-11 09:46:29 +080010567
developer7e4a2a62023-04-06 19:56:03 +080010568 return status;
developer72fb0bb2023-01-11 09:46:29 +080010569}
10570
10571INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
10572{
10573 //Apply default Ssid Advertisement instantly
10574 return RETURN_ERR;
10575}
10576
10577INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
10578{
developere82c0ca2023-05-10 16:25:35 +080010579 time_t now;
10580
10581 time(&now);
10582 if (now > radio_up_time[radioIndex])
10583 *output = now - radio_up_time[radioIndex];
10584 else {
10585 *output = 0;
10586 return RETURN_ERR;
10587 }
10588
10589 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +080010590}
10591
10592INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
10593{
10594 return RETURN_OK;
10595}
10596
10597INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
10598{
10599 return RETURN_OK;
10600}
10601
10602//To-do
10603INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
10604{
10605 char output[16]={'\0'};
10606 char config_file[MAX_BUF_SIZE] = {0};
10607
10608 if (!output_string)
10609 return RETURN_ERR;
10610
10611 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
10612 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
10613
10614 if (strlen(output) == 0)
10615 snprintf(output_string, 64, "Disabled");
10616 else if (strncmp(output, "0", 1) == 0)
10617 snprintf(output_string, 64, "Disabled");
10618 else if (strncmp(output, "1", 1) == 0)
10619 snprintf(output_string, 64, "Optional");
10620 else if (strncmp(output, "2", 1) == 0)
10621 snprintf(output_string, 64, "Required");
10622 else {
10623 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
10624 return RETURN_ERR;
10625 }
10626
10627 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
10628 return RETURN_OK;
10629}
10630INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
10631{
10632 char str[MAX_BUF_SIZE]={'\0'};
10633 char cmd[MAX_CMD_SIZE]={'\0'};
10634 struct params params;
10635 char config_file[MAX_BUF_SIZE] = {0};
10636
10637 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10638 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
10639 return RETURN_ERR;
10640
10641 params.name = "ieee80211w";
10642 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
10643 params.value = "0";
10644 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
10645 params.value = "1";
10646 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
10647 params.value = "2";
10648 else{
10649 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
10650 return RETURN_ERR;
10651 }
10652 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
10653 wifi_hostapdWrite(config_file, &params, 1);
10654 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
10655 return RETURN_OK;
10656}
10657INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
10658{
10659 char output[16]={'\0'};
10660 char config_file[MAX_BUF_SIZE] = {0};
10661
10662 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developerc0772e62023-05-18 15:10:48 +080010663 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer262f4cb2023-05-24 12:22:04 +080010664 wifi_datfileRead(config_file, "AutoChannelSelect" , output, sizeof(output));
developer72fb0bb2023-01-11 09:46:29 +080010665
developer262f4cb2023-05-24 12:22:04 +080010666 if (output == NULL)
10667 *output_bool = FALSE;
developer47a56bf2023-05-30 13:38:57 +080010668 else if (strncmp(output, "0", 1) == 0)
10669 *output_bool = FALSE;
developer262f4cb2023-05-24 12:22:04 +080010670 else if (strncmp(output, "1", 1) == 0)
10671 *output_bool = TRUE;
10672 else if (strncmp(output, "2", 1) == 0)
10673 *output_bool = TRUE;
10674 else if (strncmp(output, "3", 1) == 0)
10675 *output_bool = TRUE;
10676 else
10677 *output_bool = FALSE;
developer72fb0bb2023-01-11 09:46:29 +080010678 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
10679
10680 return RETURN_OK;
10681}
10682
10683INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
10684{
10685 return RETURN_OK;
10686}
10687
10688INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
10689{
10690 return RETURN_OK;
10691}
10692
10693INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
10694{
10695 return RETURN_OK;
10696}
10697
10698INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
10699{
10700 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10701 char config_file[MAX_BUF_SIZE] = {0};
10702
10703 if (NULL == output)
10704 return RETURN_ERR;
10705 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
10706 wifi_hostapdRead(config_file,"hw_mode",output,64);
10707
10708 if(strcmp(output,"b")==0)
10709 sprintf(output, "%s", "1,2,5.5,11");
10710 else if (strcmp(output,"a")==0)
10711 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
10712 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
10713 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
10714
10715 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10716 return RETURN_OK;
10717}
10718
10719INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
10720{
10721 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10722 char *temp;
10723 char temp_output[128];
10724 char temp_TransmitRates[128];
10725 char config_file[MAX_BUF_SIZE] = {0};
10726
10727 if (NULL == output)
10728 return RETURN_ERR;
10729
10730 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
10731 wifi_hostapdRead(config_file,"supported_rates",output,64);
10732
10733 if (strlen(output) == 0) {
10734 wifi_getRadioSupportedDataTransmitRates(wlanIndex, output);
10735 return RETURN_OK;
10736 }
10737 strcpy(temp_TransmitRates,output);
10738 strcpy(temp_output,"");
10739 temp = strtok(temp_TransmitRates," ");
10740 while(temp!=NULL)
10741 {
10742 temp[strlen(temp)-1]=0;
10743 if((temp[0]=='5') && (temp[1]=='\0'))
10744 {
10745 temp="5.5";
10746 }
10747 strcat(temp_output,temp);
10748 temp = strtok(NULL," ");
10749 if(temp!=NULL)
10750 {
10751 strcat(temp_output,",");
10752 }
10753 }
10754 strcpy(output,temp_output);
10755 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10756
10757 return RETURN_OK;
10758}
10759
10760INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
10761{
10762 return RETURN_OK;
10763}
10764
10765
10766INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
10767{
10768 int i=0;
10769 char *temp;
10770 char temp1[128] = {0};
10771 char temp_output[128] = {0};
10772 char temp_TransmitRates[128] = {0};
10773 struct params params={'\0'};
10774 char config_file[MAX_BUF_SIZE] = {0};
10775 wifi_band band = wifi_index_to_band(wlanIndex);
10776
10777 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10778 if(NULL == output)
10779 return RETURN_ERR;
10780 strcpy(temp_TransmitRates,output);
10781
10782 for(i=0;i<strlen(temp_TransmitRates);i++)
10783 {
10784 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
10785 {
10786 continue;
10787 }
10788 else
10789 {
10790 return RETURN_ERR;
10791 }
10792 }
10793 strcpy(temp_output,"");
10794 temp = strtok(temp_TransmitRates,",");
10795 while(temp!=NULL)
10796 {
10797 strcpy(temp1,temp);
10798 if(band == band_5)
10799 {
10800 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
10801 {
10802 return RETURN_ERR;
10803 }
10804 }
10805
10806 if(strcmp(temp,"5.5")==0)
10807 {
10808 strcpy(temp1,"55");
10809 }
10810 else
10811 {
10812 strcat(temp1,"0");
10813 }
10814 strcat(temp_output,temp1);
10815 temp = strtok(NULL,",");
10816 if(temp!=NULL)
10817 {
10818 strcat(temp_output," ");
10819 }
10820 }
10821 strcpy(output,temp_output);
10822
10823 params.name = "supported_rates";
10824 params.value = output;
10825
10826 wifi_dbg_printf("\n%s:",__func__);
10827 wifi_dbg_printf("params.value=%s\n",params.value);
10828 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
10829 wifi_hostapdWrite(config_file,&params,1);
10830 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10831
10832 return RETURN_OK;
10833}
10834
10835
10836static char *sncopy(char *dst, int dst_sz, const char *src)
10837{
10838 if (src && dst && dst_sz > 0) {
10839 strncpy(dst, src, dst_sz);
10840 dst[dst_sz - 1] = '\0';
10841 }
10842 return dst;
10843}
10844
10845static int util_get_sec_chan_offset(int channel, const char* ht_mode)
10846{
10847 if (0 == strcmp(ht_mode, "HT40") ||
10848 0 == strcmp(ht_mode, "HT80") ||
10849 0 == strcmp(ht_mode, "HT160")) {
10850 switch (channel) {
10851 case 1 ... 7:
10852 case 36:
10853 case 44:
10854 case 52:
10855 case 60:
10856 case 100:
10857 case 108:
10858 case 116:
10859 case 124:
10860 case 132:
10861 case 140:
10862 case 149:
10863 case 157:
10864 return 1;
10865 case 8 ... 13:
10866 case 40:
10867 case 48:
10868 case 56:
10869 case 64:
10870 case 104:
10871 case 112:
10872 case 120:
10873 case 128:
10874 case 136:
10875 case 144:
10876 case 153:
10877 case 161:
10878 return -1;
10879 default:
10880 return -EINVAL;
10881 }
10882 }
10883
10884 return -EINVAL;
10885}
10886
10887static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
10888{
10889 int idx = channel%8;
10890 if (0 == strcmp(ht_mode, "HT40") ||
10891 0 == strcmp(ht_mode, "HT80") ||
10892 0 == strcmp(ht_mode, "HT160")) {
10893 switch (idx) {
10894 case 1:
10895 return 1;
10896 case 5:
10897 return -1;
10898 default:
10899 return -EINVAL;
10900 }
10901 }
10902
10903 return -EINVAL;
10904}
10905static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
10906{
10907 if (NULL == hw_mode) return;
10908
10909 if (0 == strcmp(hw_mode, "ac"))
10910 sncopy(bw_mode, bw_mode_len, "ht vht");
10911
10912 if (0 == strcmp(hw_mode, "n"))
10913 sncopy(bw_mode, bw_mode_len, "ht");
10914
10915 return;
10916}
10917
10918static int util_chan_to_freq(int chan)
10919{
10920 if (chan == 14)
10921 return 2484;
10922 else if (chan < 14)
10923 return 2407 + chan * 5;
10924 else if (chan >= 182 && chan <= 196)
10925 return 4000 + chan * 5;
10926 else
10927 return 5000 + chan * 5;
10928 return 0;
10929}
10930
10931static int util_6G_chan_to_freq(int chan)
10932{
10933 if (chan)
10934 return 5950 + chan * 5;
10935 else
10936 return 0;
developer69b61b02023-03-07 17:17:44 +080010937
developer72fb0bb2023-01-11 09:46:29 +080010938}
10939const int *util_unii_5g_chan2list(int chan, int width)
10940{
10941 static const int lists[] = {
10942 // <width>, <chan1>, <chan2>..., 0,
10943 20, 36, 0,
10944 20, 40, 0,
10945 20, 44, 0,
10946 20, 48, 0,
10947 20, 52, 0,
10948 20, 56, 0,
10949 20, 60, 0,
10950 20, 64, 0,
10951 20, 100, 0,
10952 20, 104, 0,
10953 20, 108, 0,
10954 20, 112, 0,
10955 20, 116, 0,
10956 20, 120, 0,
10957 20, 124, 0,
10958 20, 128, 0,
10959 20, 132, 0,
10960 20, 136, 0,
10961 20, 140, 0,
10962 20, 144, 0,
10963 20, 149, 0,
10964 20, 153, 0,
10965 20, 157, 0,
10966 20, 161, 0,
10967 20, 165, 0,
10968 40, 36, 40, 0,
10969 40, 44, 48, 0,
10970 40, 52, 56, 0,
10971 40, 60, 64, 0,
10972 40, 100, 104, 0,
10973 40, 108, 112, 0,
10974 40, 116, 120, 0,
10975 40, 124, 128, 0,
10976 40, 132, 136, 0,
10977 40, 140, 144, 0,
10978 40, 149, 153, 0,
10979 40, 157, 161, 0,
10980 80, 36, 40, 44, 48, 0,
10981 80, 52, 56, 60, 64, 0,
10982 80, 100, 104, 108, 112, 0,
10983 80, 116, 120, 124, 128, 0,
10984 80, 132, 136, 140, 144, 0,
10985 80, 149, 153, 157, 161, 0,
10986 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
10987 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
10988 -1 // final delimiter
10989 };
10990 const int *start;
10991 const int *p;
10992
10993 for (p = lists; *p != -1; p++) {
10994 if (*p == width) {
10995 for (start = ++p; *p != 0; p++) {
10996 if (*p == chan)
10997 return start;
10998 }
10999 }
11000 // move to the end of channel list of given width
11001 while (*p != 0) {
11002 p++;
11003 }
11004 }
11005
11006 return NULL;
11007}
11008
11009static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
11010{
11011 if (NULL == ht_mode)
11012 return 0;
11013
11014 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
11015 const int *chans = util_unii_5g_chan2list(channel, width);
11016 int sum = 0;
11017 int cnt = 0;
11018
11019 if (NULL == chans)
11020 return 0;
11021
11022 while (*chans) {
11023 sum += *chans;
11024 cnt++;
11025 chans++;
11026 }
11027 if (cnt == 0)
11028 return 0;
11029 return sum / cnt;
11030}
11031
11032static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
11033{
11034 if (NULL == ht_mode)
11035 return 0;
11036
11037 int width = strtol((ht_mode + 2), NULL, 10);
11038
11039 int idx = 0 ;
11040 int centerchan = 0;
11041 int chan_ofs = 1;
11042
11043 if (width == 40){
11044 idx = ((channel/4) + chan_ofs)%2;
11045 switch (idx) {
11046 case 0:
11047 centerchan = (channel - 2);
11048 break;
11049 case 1:
11050 centerchan = (channel + 2);
developer69b61b02023-03-07 17:17:44 +080011051 break;
developer72fb0bb2023-01-11 09:46:29 +080011052 default:
11053 return -EINVAL;
11054 }
11055 }else if (width == 80){
developer69b61b02023-03-07 17:17:44 +080011056 idx = ((channel/4) + chan_ofs)%4;
developer72fb0bb2023-01-11 09:46:29 +080011057 switch (idx) {
11058 case 0:
11059 centerchan = (channel - 6);
11060 break;
11061 case 1:
11062 centerchan = (channel + 6);
11063 break;
11064 case 2:
11065 centerchan = (channel + 2);
11066 break;
11067 case 3:
11068 centerchan = (channel - 2);
11069 break;
11070 default:
11071 return -EINVAL;
developer69b61b02023-03-07 17:17:44 +080011072 }
developer72fb0bb2023-01-11 09:46:29 +080011073 }else if (width == 160){
11074 switch (channel) {
11075 case 1 ... 29:
11076 centerchan = 15;
11077 break;
11078 case 33 ... 61:
11079 centerchan = 47;
11080 break;
11081 case 65 ... 93:
11082 centerchan = 79;
11083 break;
11084 case 97 ... 125:
11085 centerchan = 111;
11086 break;
11087 case 129 ... 157:
11088 centerchan = 143;
11089 break;
11090 case 161 ... 189:
11091 centerchan = 175;
11092 break;
11093 case 193 ... 221:
11094 centerchan = 207;
11095 break;
11096 default:
11097 return -EINVAL;
developer69b61b02023-03-07 17:17:44 +080011098 }
developer72fb0bb2023-01-11 09:46:29 +080011099 }
11100 return centerchan;
11101}
11102static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
11103{
11104 BOOL onlyG, onlyN, onlyA;
11105 CHAR tmp[64];
11106 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
11107 if (ret == RETURN_OK) {
11108 sncopy(hw_mode, hw_mode_size, tmp);
11109 }
11110 return ret;
11111}
11112
11113INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
11114{
11115 // Sample commands:
11116 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
11117 // hostapd_cli -i wifi0 chan_switch 30 2437
developer72fb0bb2023-01-11 09:46:29 +080011118 int freq = 0, ret = 0;
11119 char center_freq1_str[32] = ""; // center_freq1=%d
11120 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
11121 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
11122 char hw_mode[16] = ""; // n|ac
11123 char bw_mode[16] = ""; // ht|ht vht
11124 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
11125 char interface_name[16] = {0};
11126 int sec_chan_offset;
11127 int width;
11128 char config_file[64] = {0};
11129 BOOL stbcEnable = FALSE;
11130 char *ext_str = "None";
11131 wifi_band band = band_invalid;
11132 int center_chan = 0;
11133 int center_freq1 = 0;
11134
11135 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
11136
11137 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
11138 return RETURN_ERR;
11139
11140 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11141
11142 band = wifi_index_to_band(radioIndex);
11143
11144 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
11145
11146 // Get radio mode HT20|HT40|HT80 etc.
11147 if (channel){
11148 if (band == band_6){
11149 freq = util_6G_chan_to_freq(channel);
11150 }else{
11151 freq = util_chan_to_freq(channel);
11152 }
11153 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
11154
11155 // Provide bandwith if specified
11156 if (channel_width_MHz > 20) {
11157 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
11158 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
11159 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
11160
11161 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
11162 }else if (channel_width_MHz == 20){
11163 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
11164 }
11165
11166
11167 if (channel_width_MHz > 20) {
11168 if (band == band_6){
11169 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
11170 if(center_chan){
11171 center_freq1 = util_6G_chan_to_freq(center_chan);
11172 }
11173 }else{
11174 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
11175 if(center_chan){
11176 center_freq1 = util_chan_to_freq(center_chan);
11177 }
11178 }
developer69b61b02023-03-07 17:17:44 +080011179
developer72fb0bb2023-01-11 09:46:29 +080011180 if (center_freq1)
11181 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
developer69b61b02023-03-07 17:17:44 +080011182
developer72fb0bb2023-01-11 09:46:29 +080011183 }
11184
11185 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
11186 if (band == band_6){
11187 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
11188 }else{
11189 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
11190 }
11191 if (sec_chan_offset != -EINVAL)
11192 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
11193
11194 // Only the first AP, other are hanging on the same radio
developerfead3972023-05-25 20:15:02 +080011195 ret = wifi_setChannel_netlink(radioIndex, &channel, NULL);
developerd1824452023-05-18 12:30:04 +080011196 if (ret != RETURN_OK) {
developerfead3972023-05-25 20:15:02 +080011197 fprintf(stderr, "%s: wifi_setChannel return error.\n", __func__);
developerd1824452023-05-18 12:30:04 +080011198 return RETURN_ERR;
11199 }
11200 /* wifi_dbg_printf("execute: '%s'\n", cmd);
developerf6a87542023-05-16 15:47:28 +080011201 ret = _syscmd(cmd, buf, sizeof(buf));
developerd1824452023-05-18 12:30:04 +080011202 wifi_reloadAp(radioIndex); */
developer72fb0bb2023-01-11 09:46:29 +080011203
11204 ret = wifi_setRadioChannel(radioIndex, channel);
11205 if (ret != RETURN_OK) {
11206 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
11207 return RETURN_ERR;
11208 }
11209
developer262f4cb2023-05-24 12:22:04 +080011210 if (sec_chan_offset == 1)
11211 ext_str = "Above";
11212 else if (sec_chan_offset == -1)
11213 ext_str = "Below";
developer72fb0bb2023-01-11 09:46:29 +080011214
developerd1824452023-05-18 12:30:04 +080011215 /*wifi_setRadioCenterChannel(radioIndex, center_chan); */
developer72fb0bb2023-01-11 09:46:29 +080011216
11217 } else {
11218 if (channel_width_MHz > 20)
11219 ext_str = "Above";
11220 }
11221
11222 wifi_setRadioExtChannel(radioIndex, ext_str);
11223
11224 char mhz_str[16];
11225 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
11226 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
11227
11228 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11229
11230 return RETURN_OK;
11231}
11232
11233INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
11234{
11235 int index = -1;
11236 wifi_neighbor_ap2_t *scan_array = NULL;
11237 char cmd[256]={0};
11238 char buf[128]={0};
11239 char file_name[32] = {0};
11240 char filter_SSID[32] = {0};
11241 char line[256] = {0};
11242 char interface_name[16] = {0};
11243 char *ret = NULL;
11244 int freq=0;
11245 FILE *f = NULL;
11246 size_t len=0;
11247 int channels_num = 0;
11248 int vht_channel_width = 0;
11249 int get_noise_ret = RETURN_ERR;
11250 bool filter_enable = false;
11251 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
11252 int phyId = 0;
11253
11254 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
11255
11256 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
11257 f = fopen(file_name, "r");
11258 if (f != NULL) {
11259 fgets(filter_SSID, sizeof(file_name), f);
11260 if (strlen(filter_SSID) != 0)
11261 filter_enable = true;
11262 fclose(f);
11263 }
11264
11265 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
11266 return RETURN_ERR;
11267
11268 phyId = radio_index_to_phy(radio_index);
11269
11270 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
11271 _syscmd(cmd, buf, sizeof(buf));
11272 channels_num = strtol(buf, NULL, 10);
11273
11274 sprintf(cmd, "iw dev %s scan dump | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
11275 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", interface_name, interface_name);
11276 fprintf(stderr, "cmd: %s\n", cmd);
11277 if ((f = popen(cmd, "r")) == NULL) {
11278 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
11279 return RETURN_ERR;
11280 }
developer69b61b02023-03-07 17:17:44 +080011281
developer72fb0bb2023-01-11 09:46:29 +080011282 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
11283 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
developer69b61b02023-03-07 17:17:44 +080011284
developer72fb0bb2023-01-11 09:46:29 +080011285 ret = fgets(line, sizeof(line), f);
11286 while (ret != NULL) {
11287 if(strstr(line, "BSS") != NULL) { // new neighbor info
developer69b61b02023-03-07 17:17:44 +080011288 // 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 +080011289 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
11290 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
11291
11292 if (!filter_BSS) {
11293 index++;
11294 wifi_neighbor_ap2_t *tmp;
11295 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
11296 if (tmp == NULL) { // no more memory to use
11297 index--;
11298 wifi_dbg_printf("%s: realloc failed\n", __func__);
11299 break;
11300 }
11301 scan_array = tmp;
11302 }
11303 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
11304
11305 filter_BSS = false;
11306 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
11307 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
11308 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
11309 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
11310 } else if (strstr(line, "freq") != NULL) {
11311 sscanf(line," freq: %d", &freq);
11312 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
11313
11314 if (freq >= 2412 && freq <= 2484) {
11315 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
11316 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
11317 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
11318 }
11319 else if (freq >= 5160 && freq <= 5805) {
11320 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
11321 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
11322 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
11323 }
11324
11325 scan_array[index].ap_Noise = 0;
11326 if (get_noise_ret == RETURN_OK) {
11327 for (int i = 0; i < channels_num; i++) {
11328 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
11329 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
11330 break;
11331 }
11332 }
11333 }
11334 } else if (strstr(line, "beacon interval") != NULL) {
11335 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
11336 } else if (strstr(line, "signal") != NULL) {
11337 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
11338 } else if (strstr(line,"SSID") != NULL) {
11339 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
11340 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
11341 filter_BSS = true;
11342 }
11343 } else if (strstr(line, "Supported rates") != NULL) {
11344 char SRate[80] = {0}, *tmp = NULL;
11345 memset(buf, 0, sizeof(buf));
11346 strcpy(SRate, line);
11347 tmp = strtok(SRate, ":");
11348 tmp = strtok(NULL, ":");
11349 strcpy(buf, tmp);
11350 memset(SRate, 0, sizeof(SRate));
11351
11352 tmp = strtok(buf, " \n");
11353 while (tmp != NULL) {
11354 strcat(SRate, tmp);
11355 if (SRate[strlen(SRate) - 1] == '*') {
11356 SRate[strlen(SRate) - 1] = '\0';
11357 }
11358 strcat(SRate, ",");
11359
11360 tmp = strtok(NULL, " \n");
11361 }
11362 SRate[strlen(SRate) - 1] = '\0';
11363 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
11364 } else if (strstr(line, "DTIM") != NULL) {
11365 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
11366 } else if (strstr(line, "VHT capabilities") != NULL) {
11367 strcat(scan_array[index].ap_SupportedStandards, ",ac");
11368 strcpy(scan_array[index].ap_OperatingStandards, "ac");
11369 } else if (strstr(line, "HT capabilities") != NULL) {
11370 strcat(scan_array[index].ap_SupportedStandards, ",n");
11371 strcpy(scan_array[index].ap_OperatingStandards, "n");
11372 } else if (strstr(line, "VHT operation") != NULL) {
11373 ret = fgets(line, sizeof(line), f);
11374 sscanf(line," * channel width: %d", &vht_channel_width);
11375 if(vht_channel_width == 1) {
11376 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
11377 } else {
11378 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
11379 }
11380 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
11381 continue;
11382 } else if (strstr(line, "HT operation") != NULL) {
11383 ret = fgets(line, sizeof(line), f);
11384 sscanf(line," * secondary channel offset: %s", &buf);
11385 if (!strcmp(buf, "above")) {
11386 //40Mhz +
11387 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radio_index%1 ? "A": "G");
11388 }
11389 else if (!strcmp(buf, "below")) {
11390 //40Mhz -
11391 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
11392 } else {
11393 //20Mhz
11394 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radio_index%1 ? "A": "G");
11395 }
11396 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
11397 continue;
11398 } else if (strstr(line, "HE capabilities") != NULL) {
11399 strcat(scan_array[index].ap_SupportedStandards, ",ax");
11400 strcpy(scan_array[index].ap_OperatingStandards, "ax");
11401 ret = fgets(line, sizeof(line), f);
11402 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
11403 if (strstr(line, "HE40/2.4GHz") != NULL)
11404 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
11405 else
11406 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
11407 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
11408 if (strstr(line, "HE80/5GHz") != NULL) {
11409 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
11410 ret = fgets(line, sizeof(line), f);
11411 } else
11412 continue;
11413 if (strstr(line, "HE160/5GHz") != NULL)
11414 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
11415 }
11416 continue;
11417 } else if (strstr(line, "WPA") != NULL) {
11418 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
11419 } else if (strstr(line, "RSN") != NULL) {
11420 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
11421 } else if (strstr(line, "Group cipher") != NULL) {
11422 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
11423 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
11424 strcpy(scan_array[index].ap_EncryptionMode, "AES");
11425 }
11426 }
11427 ret = fgets(line, sizeof(line), f);
11428 }
11429
11430 if (!filter_BSS) {
11431 *output_array_size = index + 1;
11432 } else {
11433 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
11434 *output_array_size = index;
11435 }
11436 *neighbor_ap_array = scan_array;
11437 pclose(f);
11438 free(channels_noise_arr);
11439 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11440 return RETURN_OK;
11441}
11442
11443INT wifi_getApAssociatedDeviceStats(
11444 INT apIndex,
11445 mac_address_t *clientMacAddress,
11446 wifi_associated_dev_stats_t *associated_dev_stats,
11447 u64 *handle)
11448{
11449 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
11450 char interface_name[50] = {0};
11451 char cmd[1024] = {0};
11452 char mac_str[18] = {0};
11453 char *key = NULL;
11454 char *val = NULL;
11455 FILE *f = NULL;
11456 char *line = NULL;
11457 size_t len = 0;
11458
11459 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
11460 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
11461 return RETURN_ERR;
11462 }
11463
11464 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
11465 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
11466 if((f = popen(cmd, "r")) == NULL) {
11467 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
11468 return RETURN_ERR;
11469 }
11470
11471 while ((getline(&line, &len, f)) != -1) {
11472 key = strtok(line,":");
11473 val = strtok(NULL,":");
11474
11475 if(!strncmp(key,"rx bytes",8))
11476 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
11477 if(!strncmp(key,"tx bytes",8))
11478 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
11479 if(!strncmp(key,"rx packets",10))
11480 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
11481 if(!strncmp(key,"tx packets",10))
11482 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
11483 if(!strncmp(key,"tx retries",10))
11484 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
11485 if(!strncmp(key,"tx failed",9))
11486 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
11487 if(!strncmp(key,"rx drop misc",13))
11488 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
11489 if(!strncmp(key,"rx bitrate",10)) {
11490 val = strtok(val, " ");
11491 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
11492 }
11493 if(!strncmp(key,"tx bitrate",10)) {
11494 val = strtok(val, " ");
11495 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
11496 }
11497 }
11498 free(line);
11499 pclose(f);
11500 return RETURN_OK;
11501}
11502
11503INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
11504{
developer7e4a2a62023-04-06 19:56:03 +080011505 char interface_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +080011506 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
11507
developer7e4a2a62023-04-06 19:56:03 +080011508 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
11509
developer72fb0bb2023-01-11 09:46:29 +080011510 if (NULL == output_string)
11511 return RETURN_ERR;
11512
11513 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
11514 return RETURN_ERR;
developer7e4a2a62023-04-06 19:56:03 +080011515
11516 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 +080011517 _syscmd(cmd, buf, sizeof(buf));
11518
11519 //size of SSID name restricted to value less than 32 bytes
11520 snprintf(output_string, 32, "%s", buf);
developer7e4a2a62023-04-06 19:56:03 +080011521 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +080011522
11523 return RETURN_OK;
11524}
11525
11526INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
11527{
developer2edaf012023-05-24 14:24:53 +080011528 char *mac_arry_buf = NULL;
11529 INT policy = -1;
11530 INT buf_size = 1024;
developer72fb0bb2023-01-11 09:46:29 +080011531
developer2edaf012023-05-24 14:24:53 +080011532 mac_arry_buf = malloc(buf_size);
11533 if (!mac_arry_buf) {
11534 wifi_debug(DEBUG_ERROR,"malloc mac_arry_buf fails\n");
developer7e4a2a62023-04-06 19:56:03 +080011535 return RETURN_ERR;
developer2edaf012023-05-24 14:24:53 +080011536 }
11537 memset(mac_arry_buf, 0, buf_size);
11538 if (mtk_wifi_getApAclDevices(apIndex, mac_arry_buf, buf_size) != RETURN_OK) {
11539 wifi_debug(DEBUG_ERROR,"mtk_wifi_getApAclDevices get fails\n");
11540 goto err;
11541 }
11542 /*
11543 mtk format to get policy:
11544 "policy=1
11545 00:11:22:33:44:55
11546 00:11:22:33:44:66
11547 "
11548 */
11549 if (strlen(mac_arry_buf) < strlen("policy=1") || sscanf(mac_arry_buf, "policy=%01d", &policy) != 1) {
11550 wifi_debug(DEBUG_ERROR,"mac_arry_buf(%s) invalid\n", mac_arry_buf);
11551 goto err;
11552 }
11553 if (!(policy >=0 && policy <= 2)){
11554 wifi_debug(DEBUG_ERROR,"policy(%d) is invalid\n", policy);
11555 goto err;
11556 }
11557 *output_filterMode = policy;
11558 wifi_debug(DEBUG_NOTICE, "output_filterMode(%d), success\n", *output_filterMode);
11559 free(mac_arry_buf);
11560 mac_arry_buf = NULL;
11561 return RETURN_OK;
11562err:
11563 free(mac_arry_buf);
11564 mac_arry_buf = NULL;
11565 wifi_debug(DEBUG_NOTICE, "output_filterMode(%d), fails\n", *output_filterMode);
11566 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +080011567}
11568
developer2edaf012023-05-24 14:24:53 +080011569
developer72fb0bb2023-01-11 09:46:29 +080011570INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
11571{
11572 FILE *fp = NULL;
11573 char str[MAX_BUF_SIZE] = {0};
11574 int wificlientindex = 0 ;
11575 int count = 0;
11576 int signalstrength = 0;
11577 int arr[MACADDRESS_SIZE] = {0};
11578 unsigned char mac[MACADDRESS_SIZE] = {0};
11579 UINT wifi_count = 0;
11580 char virtual_interface_name[MAX_BUF_SIZE] = {0};
11581 char pipeCmd[MAX_CMD_SIZE] = {0};
11582
11583 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11584 *output_array_size = 0;
11585 *associated_dev_array = NULL;
11586 char interface_name[50] = {0};
11587
11588 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
11589 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
11590 return RETURN_ERR;
11591 }
11592
11593 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
11594 fp = popen(pipeCmd, "r");
11595 if (fp == NULL)
11596 {
11597 printf("Failed to run command inside function %s\n",__FUNCTION__ );
11598 return RETURN_ERR;
11599 }
11600
11601 /* Read the output a line at a time - output it. */
11602 fgets(str, sizeof(str)-1, fp);
11603 wifi_count = (unsigned int) atoi ( str );
11604 *output_array_size = wifi_count;
11605 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
11606 pclose(fp);
11607
11608 if(wifi_count == 0)
11609 {
11610 return RETURN_OK;
11611 }
11612 else
11613 {
11614 wifi_associated_dev2_t* temp = NULL;
11615 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
11616 *associated_dev_array = temp;
11617 if(temp == NULL)
11618 {
11619 printf("Error Statement. Insufficient memory \n");
11620 return RETURN_ERR;
11621 }
11622
11623 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
11624 system(pipeCmd);
11625
11626 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
11627 if(fp == NULL)
11628 {
11629 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
11630 return RETURN_ERR;
11631 }
11632 fclose(fp);
11633
11634 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
11635 fp = popen(pipeCmd, "r");
11636 if(fp)
11637 {
11638 for(count =0 ; count < wifi_count; count++)
11639 {
11640 fgets(str, MAX_BUF_SIZE, fp);
11641 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
11642 {
11643 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
11644 {
11645 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
11646
11647 }
11648 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
11649 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]);
11650 }
11651 temp[count].cli_AuthenticationState = 1; //TODO
11652 temp[count].cli_Active = 1; //TODO
11653 }
11654 pclose(fp);
11655 }
11656
11657 //Updating RSSI per client
11658 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt");
11659 fp = popen(pipeCmd, "r");
11660 if(fp)
11661 {
11662 pclose(fp);
11663 }
11664 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
11665 if(fp)
11666 {
11667 for(count =0 ; count < wifi_count ;count++)
11668 {
11669 fgets(str, MAX_BUF_SIZE, fp);
11670 signalstrength = atoi(str);
11671 temp[count].cli_RSSI = signalstrength;
11672 }
11673 pclose(fp);
11674 }
11675
11676
11677 //LastDataDownlinkRate
11678 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt");
11679 fp = popen(pipeCmd, "r");
11680 if (fp)
11681 {
11682 pclose(fp);
11683 }
11684 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
11685 if (fp)
11686 {
11687 for (count = 0; count < wifi_count; count++)
11688 {
11689 fgets(str, MAX_BUF_SIZE, fp);
11690 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
11691 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
11692 }
11693 pclose(fp);
11694 }
11695
11696 //LastDataUplinkRate
11697 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt");
11698 fp = popen(pipeCmd, "r");
11699 if (fp)
11700 {
11701 pclose(fp);
11702 }
11703 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
11704 if (fp)
11705 {
11706 for (count = 0; count < wifi_count; count++)
11707 {
11708 fgets(str, MAX_BUF_SIZE, fp);
11709 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
11710 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
11711 }
11712 pclose(fp);
11713 }
11714 }
11715 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11716 return RETURN_OK;
11717
11718}
11719
11720INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
11721{
11722#if 0
11723 /*char buf[1024] = {0};
11724 sprintf(cmd, "ifconfig %s ", interface_name);
11725 _syscmd(cmd, buf, sizeof(buf));*/
11726
11727 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
11728 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
11729 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
11730 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
11731
11732 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.
11733 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].
11734 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].
11735 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].
11736 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
11737 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
11738
11739 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
11740 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
11741 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
11742 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.
11743 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.
11744 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.
11745 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.
11746 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.
11747 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.
11748 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.
11749 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
11750#endif
11751
11752 FILE *fp = NULL;
11753 char interface_name[50] = {0};
11754 char pipeCmd[128] = {0};
11755 char str[256] = {0};
11756 wifi_ssidTrafficStats2_t *out = output_struct;
11757
11758 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
11759 if (!output_struct)
11760 return RETURN_ERR;
11761
11762 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
11763 if (wifi_GetInterfaceName(ssidIndex, interface_name) != RETURN_OK)
11764 return RETURN_ERR;
11765 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
11766
11767 fp = popen(pipeCmd, "r");
11768 if (fp == NULL) {
11769 fprintf(stderr, "%s: popen failed\n", __func__);
11770 return RETURN_ERR;
11771 }
11772 fgets(str, sizeof(str), fp);
11773 pclose(fp);
11774
11775 if (strlen(str) == 0) // interface not exist
11776 return RETURN_OK;
11777
11778 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
11779 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
11780
11781 memset(str, 0, sizeof(str));
11782 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
11783 fp = popen(pipeCmd, "r");
11784 if (fp == NULL) {
11785 fprintf(stderr, "%s: popen failed\n", __func__);
11786 return RETURN_ERR;
11787 }
11788 fgets(str, sizeof(str), fp);
11789
11790 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
11791 &out->ssid_BroadcastPacketsSent);
11792 pclose(fp);
11793
11794 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
11795 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
11796
11797 // Not supported
11798 output_struct->ssid_RetransCount = 0;
11799 output_struct->ssid_FailedRetransCount = 0;
11800 output_struct->ssid_RetryCount = 0;
11801 output_struct->ssid_MultipleRetryCount = 0;
11802 output_struct->ssid_ACKFailureCount = 0;
11803 output_struct->ssid_AggregatedPacketCount = 0;
11804
11805 return RETURN_OK;
11806}
11807
11808//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).
11809INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
11810{
11811 char output_val[16]={'\0'};
11812 char config_file[MAX_BUF_SIZE] = {0};
11813
11814 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11815 if (!output)
11816 return RETURN_ERR;
11817 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
11818 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
11819
11820 if( strcmp(output_val,"1") == 0 )
11821 *output = TRUE;
11822 else
11823 *output = FALSE;
11824 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11825
11826 return RETURN_OK;
11827}
11828
11829INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
11830{
11831 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11832 char str[MAX_BUF_SIZE]={'\0'};
11833 char string[MAX_BUF_SIZE]={'\0'};
11834 char cmd[MAX_CMD_SIZE]={'\0'};
11835 char *ch;
11836 char config_file[MAX_BUF_SIZE] = {0};
11837 struct params params;
11838
11839 if(enable == TRUE)
11840 strcpy(string,"1");
11841 else
11842 strcpy(string,"0");
11843
11844 params.name = "ap_isolate";
11845 params.value = string;
11846
11847 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
11848 wifi_hostapdWrite(config_file,&params,1);
11849 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11850
11851 return RETURN_OK;
11852}
11853
11854INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
11855{
developera1255e42023-05-13 17:45:02 +080011856 char mgmtpwr_file[32] = {0};
11857 char cmd[64] = {0};
11858 char buf[32]={0};
11859
developer72fb0bb2023-01-11 09:46:29 +080011860 if (NULL == output_dBm)
11861 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +080011862 snprintf(mgmtpwr_file, sizeof(mgmtpwr_file), "%s%d.txt", MGMT_POWER_CTRL, apIndex);
11863 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mgmtpwr_file);
11864 _syscmd(cmd, buf, sizeof(buf));
11865 if (strlen(buf) > 0)
11866 *output_dBm = strtol(buf, NULL, 10);
11867 else
11868 *output_dBm = 23;
developer72fb0bb2023-01-11 09:46:29 +080011869 return RETURN_OK;
11870}
11871
11872INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
11873{
developera1255e42023-05-13 17:45:02 +080011874 char interface_name[16] = {0};
developera1255e42023-05-13 17:45:02 +080011875 char mgmt_pwr_file[128]={0};
11876 FILE *f = NULL;
developerfead3972023-05-25 20:15:02 +080011877 int if_idx, ret = 0;
11878 struct nl_msg *msg = NULL;
11879 struct nlattr * msg_data = NULL;
11880 struct mtk_nl80211_param param;
11881 struct unl unl_ins;
11882 char power[16] = {0};
developera1255e42023-05-13 17:45:02 +080011883
11884 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11885
11886 if (wifi_GetInterfaceName(wlanIndex, interface_name) != RETURN_OK)
11887 return RETURN_ERR;
developerfead3972023-05-25 20:15:02 +080011888
11889 if_idx = if_nametoindex(interface_name);
11890 /*init mtk nl80211 vendor cmd*/
11891 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_TXPOWER;
11892 param.if_type = NL80211_ATTR_IFINDEX;
11893 param.if_idx = if_idx;
11894
11895 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
11896 if (ret) {
11897 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
11898 return RETURN_ERR;
11899 }
11900
11901 /*add mtk vendor cmd data*/
11902 snprintf(power, sizeof(power), "%d", dBm);
11903 if (nla_put(msg, MTK_NL80211_VENDOR_ATTR_TXPWR_MGMT, strlen(power), power)) {
11904 wifi_debug(DEBUG_ERROR, "Nla put attribute error\n");
11905 nlmsg_free(msg);
11906 goto err;
11907 }
11908
11909 /*send mtk nl80211 vendor msg*/
11910 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
11911 if (ret) {
11912 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
11913 goto err;
11914 }
11915
11916 /*deinit mtk nl80211 vendor msg*/
11917 mtk_nl80211_deint(&unl_ins);
11918 wifi_debug(DEBUG_NOTICE, "set cmd success.\n");
11919
developera1255e42023-05-13 17:45:02 +080011920 snprintf(mgmt_pwr_file, sizeof(mgmt_pwr_file), "%s%d.txt", MGMT_POWER_CTRL, wlanIndex);
11921 f = fopen(mgmt_pwr_file, "w");
11922 if (f == NULL) {
11923 fprintf(stderr, "%s: fopen failed\n", __func__);
11924 return RETURN_ERR;
11925 }
11926 fprintf(f, "%d", dBm);
11927 fclose(f);
developer72fb0bb2023-01-11 09:46:29 +080011928 return RETURN_OK;
developerfead3972023-05-25 20:15:02 +080011929err:
11930 mtk_nl80211_deint(&unl_ins);
11931 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
11932 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +080011933}
11934INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
11935{
11936 return RETURN_OK;
11937}
11938INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
11939{
11940 return RETURN_OK;
11941}
11942INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
11943{
11944 return RETURN_OK;
11945}
11946INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
11947{
11948 return RETURN_OK;
11949}
11950INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
11951{
11952 char config_file[MAX_BUF_SIZE] = {0};
11953 struct params list;
11954
11955 list.name = "bss_transition";
11956 list.value = activate?"1":"0";
11957 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
11958 wifi_hostapdWrite(config_file, &list, 1);
11959
11960 return RETURN_OK;
11961}
11962wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
11963
11964void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
11965{
11966 return;
11967}
11968
11969INT wifi_setApCsaDeauth(INT apIndex, INT mode)
11970{
11971 // TODO Implement me!
11972 return RETURN_OK;
11973}
11974
11975INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
11976{
11977 char file_name[128] = {0};
11978 char buf[128] = {0};
11979 FILE *f = NULL;
11980 int max_num_radios = 0;
11981
11982 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11983
11984 wifi_getMaxRadioNumber(&max_num_radios);
11985 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
11986 for (int index = 0; index < max_num_radios; index++) {
11987 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
11988 f = fopen(file_name, "w");
11989 if (f == NULL)
11990 return RETURN_ERR;
11991 // For mode == 0 is to disable filter, just don't write to the file.
11992 if (mode)
11993 fprintf(f, "%s", essid);
11994
11995 fclose(f);
11996 }
11997 } else { // special case, need to set AP's SSID as filter for each radio.
11998 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
11999 f = fopen(file_name, "w");
12000 if (f == NULL)
12001 return RETURN_ERR;
12002
12003 // For mode == 0 is to disable filter, just don't write to the file.
12004 if (mode)
12005 fprintf(f, "%s", essid);
12006
12007 fclose(f);
12008 }
12009
12010 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12011 return RETURN_OK;
12012}
12013
12014INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
12015{
12016 // TODO Implement me!
12017 //Apply wifi_pushRadioChannel() instantly
12018 return RETURN_ERR;
12019}
12020
12021INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
12022{
12023 // TODO Implement me!
12024 return RETURN_OK;
12025}
12026
12027#ifdef HAL_NETLINK_IMPL
12028static int tidStats_callback(struct nl_msg *msg, void *arg) {
12029 struct nlattr *tb[NL80211_ATTR_MAX + 1];
12030 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
12031 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
12032 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
12033 int rem , tid_index = 0;
12034
12035 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
12036 wifi_associated_dev_tid_entry_t *stats_entry;
12037
12038 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
12039 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
12040 };
12041 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
12042 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
12043 };
12044
12045 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
12046 genlmsg_attrlen(gnlh, 0), NULL);
12047
12048
12049 if (!tb[NL80211_ATTR_STA_INFO]) {
12050 fprintf(stderr, "station stats missing!\n");
12051 return NL_SKIP;
12052 }
12053
12054 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
12055 tb[NL80211_ATTR_STA_INFO],
12056 stats_policy)) {
12057 fprintf(stderr, "failed to parse nested attributes!\n");
12058 return NL_SKIP;
12059 }
12060
developer386281b2023-05-20 15:43:13 +080012061 if (sinfo[NL80211_STA_INFO_TID_STATS]) {
12062 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
12063 {
12064 stats_entry = &out->tid_array[tid_index];
developer72fb0bb2023-01-11 09:46:29 +080012065
developer386281b2023-05-20 15:43:13 +080012066 stats_entry->tid = tid_index;
12067 stats_entry->ac = _tid_ac_index_get[tid_index];
developer72fb0bb2023-01-11 09:46:29 +080012068
developer386281b2023-05-20 15:43:13 +080012069 if(sinfo[NL80211_STA_INFO_TID_STATS])
12070 {
12071 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
12072 printf("failed to parse nested stats attributes!");
12073 return NL_SKIP;
12074 }
developer72fb0bb2023-01-11 09:46:29 +080012075 }
developer386281b2023-05-20 15:43:13 +080012076 if(stats_info[NL80211_TID_STATS_TX_MSDU])
12077 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
developer72fb0bb2023-01-11 09:46:29 +080012078
developer386281b2023-05-20 15:43:13 +080012079 if(tid_index < (PS_MAX_TID - 1))
12080 tid_index++;
12081 }
developer72fb0bb2023-01-11 09:46:29 +080012082 }
12083 //ToDo: sum_time_ms, ewma_time_ms
12084 return NL_SKIP;
12085}
12086#endif
12087
12088INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
12089{
12090#ifdef HAL_NETLINK_IMPL
12091 Netlink nl;
12092 char if_name[10];
12093 char interface_name[16] = {0};
12094
12095 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
12096 return RETURN_ERR;
12097
12098 snprintf(if_name, sizeof(if_name), "%s", interface_name);
12099
12100 nl.id = initSock80211(&nl);
12101
12102 if (nl.id < 0) {
12103 fprintf(stderr, "Error initializing netlink \n");
12104 return -1;
12105 }
12106
12107 struct nl_msg* msg = nlmsg_alloc();
12108
12109 if (!msg) {
12110 fprintf(stderr, "Failed to allocate netlink message.\n");
12111 nlfree(&nl);
12112 return -2;
12113 }
12114
12115 genlmsg_put(msg,
developer8dd72532023-05-17 19:58:35 +080012116 NL_AUTO_PID,
developer72fb0bb2023-01-11 09:46:29 +080012117 NL_AUTO_SEQ,
12118 nl.id,
12119 0,
12120 0,
12121 NL80211_CMD_GET_STATION,
12122 0);
12123
12124 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
12125 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
12126 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
developer8dd72532023-05-17 19:58:35 +080012127 nl_send_auto_complete(nl.socket, msg);
developer72fb0bb2023-01-11 09:46:29 +080012128 nl_recvmsgs(nl.socket, nl.cb);
12129 nlmsg_free(msg);
12130 nlfree(&nl);
12131 return RETURN_OK;
12132#else
12133//iw implementation
12134#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
12135#define TOTAL_MAX_LINES 50
12136
12137 char buf[256] = {'\0'}; /* or other suitable maximum line size */
12138 char if_name[32] = {0};
12139 FILE *fp=NULL;
12140 char pipeCmd[1024]= {'\0'};
12141 int lines,tid_index=0;
12142 char mac_addr[20] = {'\0'};
12143
12144 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
12145 return RETURN_ERR;
12146
12147 wifi_associated_dev_tid_entry_t *stats_entry;
12148
12149 strcpy(mac_addr,clientMacAddress);
12150
12151 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
12152 fp= popen(pipeCmd,"r");
12153 if(fp == NULL)
12154 {
12155 perror("popen for station dump failed\n");
12156 return RETURN_ERR;
12157 }
12158 pclose(fp);
12159
12160 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
12161 fp=popen(pipeCmd,"r");
12162 if(fp == NULL)
12163 {
12164 perror("popen for grep station failed\n");
12165 return RETURN_ERR;
12166 }
12167 else if(fgets(buf,sizeof(buf),fp) != NULL)
12168 lines=atoi(buf);
12169 else
12170 {
12171 pclose(fp);
12172 fprintf(stderr,"No devices are connected \n");
12173 return RETURN_ERR;
12174 }
12175 pclose(fp);
12176
12177 if(lines == 1)
12178 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
12179
12180 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
12181 {
12182 stats_entry = &tid_stats->tid_array[tid_index];
12183 stats_entry->tid = tid_index;
12184
12185 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);
12186
12187 fp=popen(pipeCmd,"r");
12188 if(fp ==NULL)
12189 {
12190 perror("Failed to read from tid file \n");
12191 return RETURN_ERR;
12192 }
12193 else if(fgets(buf,sizeof(buf),fp) != NULL)
12194 stats_entry->num_msdus = atol(buf);
12195
12196 pclose(fp);
12197 stats_entry->ac = _tid_ac_index_get[tid_index];
12198// TODO:
12199// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
12200// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
12201 }
12202 return RETURN_OK;
12203#endif
12204}
12205
12206
12207INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
12208{
12209 char interface_name[16] = {0};
12210 char cmd[128]={0};
12211 char buf[128]={0};
12212 int freq = 0;
12213
12214 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12215
12216 // full mode is used to scan all channels.
12217 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
12218 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
12219 ieee80211_channel_to_frequency(chan_list[0], &freq);
12220
12221 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
12222 return RETURN_ERR;
12223
12224 if (freq)
12225 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d freq %d", interface_name, dwell_time, freq);
12226 else
12227 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d", interface_name, dwell_time);
12228
12229 _syscmd(cmd, buf, sizeof(buf));
12230 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12231
12232 return RETURN_OK;
12233}
12234
12235
12236INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
12237{
12238 // TODO Implement me!
12239 return RETURN_ERR;
12240}
12241
12242INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
12243{
12244 // TODO Implement me!
12245 return RETURN_ERR;
12246}
12247
12248INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
12249{
12250 // TODO Implement me!
12251 return RETURN_ERR;
12252}
12253
12254INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
12255{
12256 // TODO Implement me!
12257 return RETURN_ERR;
12258}
12259
12260INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
12261{
12262 // TODO Implement me!
12263 return RETURN_ERR;
12264}
12265
12266INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
12267{
12268 // TODO Implement me!
12269 return RETURN_ERR;
12270}
12271
12272INT wifi_steering_eventUnregister(void)
12273{
12274 // TODO Implement me!
12275 return RETURN_ERR;
12276}
12277
12278INT wifi_delApAclDevices(INT apIndex)
12279{
developer7e4a2a62023-04-06 19:56:03 +080012280 char inf_name[IF_NAME_SIZE] = {0};
developer2edaf012023-05-24 14:24:53 +080012281 struct unl unl_ins;
12282 int if_idx = 0, ret = 0;
12283 struct nl_msg *msg = NULL;
12284 struct nlattr * msg_data = NULL;
12285 struct mtk_nl80211_param param;
developer72fb0bb2023-01-11 09:46:29 +080012286
developer7e4a2a62023-04-06 19:56:03 +080012287 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
12288 return RETURN_ERR;
developer2edaf012023-05-24 14:24:53 +080012289 if_idx = if_nametoindex(inf_name);
12290 if (!if_idx) {
12291 wifi_debug(DEBUG_ERROR,"can't finde ifname(%s) index,ERROR\n", inf_name);
12292 return RETURN_ERR;
12293 }
12294 /*init mtk nl80211 vendor cmd*/
12295 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_ACL;
12296 param.if_type = NL80211_ATTR_IFINDEX;
12297 param.if_idx = if_idx;
12298 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
12299 if (ret) {
12300 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
12301 return RETURN_ERR;
12302 }
12303 /*add mtk vendor cmd data*/
12304 if (nla_put_flag(msg, MTK_NL80211_VENDOR_ATTR_ACL_CLEAR_ALL)) {
12305 wifi_debug(DEBUG_ERROR, "Nla put attribute error\n");
12306 nlmsg_free(msg);
12307 goto err;
12308 }
12309 /*send mtk nl80211 vendor msg*/
12310 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
12311 if (ret) {
12312 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
12313 goto err;
12314 }
12315 /*deinit mtk nl80211 vendor msg*/
12316 mtk_nl80211_deint(&unl_ins);
12317 wifi_debug(DEBUG_NOTICE, "set cmd success.\n");
12318 return RETURN_OK;
12319err:
12320 mtk_nl80211_deint(&unl_ins);
12321 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
12322 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +080012323
12324 return RETURN_OK;
12325}
12326
12327#ifdef HAL_NETLINK_IMPL
12328static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
12329 struct nlattr *tb[NL80211_ATTR_MAX + 1];
12330 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
12331 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
12332 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
12333 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
12334 char mac_addr[20],dev[20];
12335
12336 nla_parse(tb,
12337 NL80211_ATTR_MAX,
12338 genlmsg_attrdata(gnlh, 0),
12339 genlmsg_attrlen(gnlh, 0),
12340 NULL);
12341
12342 if(!tb[NL80211_ATTR_STA_INFO]) {
12343 fprintf(stderr, "sta stats missing!\n");
12344 return NL_SKIP;
12345 }
12346
12347 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
12348 fprintf(stderr, "failed to parse nested attributes!\n");
12349 return NL_SKIP;
12350 }
12351 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
12352
12353 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
12354
developer386281b2023-05-20 15:43:13 +080012355 if (sinfo[NL80211_STA_INFO_RX_BITRATE]) {
12356 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
12357 fprintf(stderr, "failed to parse nested rate attributes!");
12358 return NL_SKIP;
12359 }
developer72fb0bb2023-01-11 09:46:29 +080012360 }
12361
12362 if(sinfo[NL80211_STA_INFO_TID_STATS])
12363 {
12364 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
12365 printf("failed to parse nested stats attributes!");
12366 return NL_SKIP;
12367 }
12368 }
developer5a1194f2023-05-24 16:00:03 +080012369 if (tb[NL80211_ATTR_VHT_CAPABILITY]) {
developer72fb0bb2023-01-11 09:46:29 +080012370
developereb1ea832023-05-24 14:46:27 +080012371 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
12372 {
12373 printf("Type is VHT\n");
12374 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
12375 ((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 +080012376
developereb1ea832023-05-24 14:46:27 +080012377 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
12378 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
12379 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
12380 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
12381 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
12382 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
12383 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
12384 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
12385 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
12386 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
12387 }
12388 else
12389 {
12390 printf(" OFDM or CCK \n");
12391 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
12392 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
12393 }
12394 }
developer72fb0bb2023-01-11 09:46:29 +080012395
developereff896f2023-05-29 14:52:55 +080012396 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
12397 if(rinfo[NL80211_RATE_INFO_MCS])
12398 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
12399 }
12400 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
12401 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
12402 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
12403 ((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 +080012404
developereff896f2023-05-29 14:52:55 +080012405 if(sinfo[NL80211_STA_INFO_TID_STATS]) {
12406 if(stats_info[NL80211_TID_STATS_RX_MSDU])
12407 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
12408 }
developer72fb0bb2023-01-11 09:46:29 +080012409
developereff896f2023-05-29 14:52:55 +080012410 if (sinfo[NL80211_STA_INFO_SIGNAL])
12411 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
12412 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
12413 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
12414 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
12415 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
12416 //rssi_array need to be filled
12417 return NL_SKIP;
developer72fb0bb2023-01-11 09:46:29 +080012418}
12419#endif
12420
12421INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
12422{
12423#ifdef HAL_NETLINK_IMPL
12424 Netlink nl;
12425 char if_name[32];
12426 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
12427 return RETURN_ERR;
12428
12429 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
12430
12431 if (*output_array_size <= 0)
12432 return RETURN_OK;
12433
12434 nl.id = initSock80211(&nl);
12435
12436 if (nl.id < 0) {
12437 fprintf(stderr, "Error initializing netlink \n");
12438 return 0;
12439 }
12440
12441 struct nl_msg* msg = nlmsg_alloc();
12442
12443 if (!msg) {
12444 fprintf(stderr, "Failed to allocate netlink message.\n");
12445 nlfree(&nl);
12446 return 0;
12447 }
12448
12449 genlmsg_put(msg,
developer8dd72532023-05-17 19:58:35 +080012450 NL_AUTO_PID,
developer72fb0bb2023-01-11 09:46:29 +080012451 NL_AUTO_SEQ,
12452 nl.id,
12453 0,
12454 0,
12455 NL80211_CMD_GET_STATION,
12456 0);
12457
12458 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
12459 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
12460 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
developer8dd72532023-05-17 19:58:35 +080012461 nl_send_auto_complete(nl.socket, msg);
developer72fb0bb2023-01-11 09:46:29 +080012462 nl_recvmsgs(nl.socket, nl.cb);
12463 nlmsg_free(msg);
12464 nlfree(&nl);
12465 return RETURN_OK;
12466#else
12467 //TODO Implement me
12468 return RETURN_OK;
12469#endif
12470}
12471
12472#ifdef HAL_NETLINK_IMPL
12473static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
12474 struct nlattr *tb[NL80211_ATTR_MAX + 1];
12475 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
12476 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
12477 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
12478 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
12479 char mac_addr[20],dev[20];
12480
12481 nla_parse(tb,
12482 NL80211_ATTR_MAX,
12483 genlmsg_attrdata(gnlh, 0),
12484 genlmsg_attrlen(gnlh, 0),
12485 NULL);
12486
12487 if(!tb[NL80211_ATTR_STA_INFO]) {
12488 fprintf(stderr, "sta stats missing!\n");
12489 return NL_SKIP;
12490 }
12491
12492 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
12493 fprintf(stderr, "failed to parse nested attributes!\n");
12494 return NL_SKIP;
12495 }
12496
12497 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
12498
12499 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
12500
developer386281b2023-05-20 15:43:13 +080012501 if (sinfo[NL80211_STA_INFO_TX_BITRATE]) {
12502 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
12503 fprintf(stderr, "failed to parse nested rate attributes!");
12504 return NL_SKIP;
12505 }
developer72fb0bb2023-01-11 09:46:29 +080012506 }
12507
12508 if(sinfo[NL80211_STA_INFO_TID_STATS])
12509 {
12510 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
12511 printf("failed to parse nested stats attributes!");
12512 return NL_SKIP;
12513 }
12514 }
developera6beea42023-05-24 16:44:05 +080012515 if (tb[NL80211_ATTR_VHT_CAPABILITY]) {
developereb1ea832023-05-24 14:46:27 +080012516 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
12517 {
12518 printf("Type is VHT\n");
12519 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
12520 ((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 +080012521
developereb1ea832023-05-24 14:46:27 +080012522 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
12523 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
12524 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
12525 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
12526 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
12527 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
12528 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
12529 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
12530 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
12531 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
12532 }
12533 else
12534 {
12535 printf(" OFDM or CCK \n");
developer72fb0bb2023-01-11 09:46:29 +080012536 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
developereb1ea832023-05-24 14:46:27 +080012537 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
12538 }
developer72fb0bb2023-01-11 09:46:29 +080012539 }
12540
12541 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
12542 if(rinfo[NL80211_RATE_INFO_MCS])
12543 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
12544 }
12545
12546 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
12547 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
12548 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
12549 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
12550
12551 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
developereff896f2023-05-29 14:52:55 +080012552 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
12553 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
developer72fb0bb2023-01-11 09:46:29 +080012554
developereff896f2023-05-29 14:52:55 +080012555 if(sinfo[NL80211_STA_INFO_TID_STATS]) {
12556 if(stats_info[NL80211_TID_STATS_TX_MSDU])
12557 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
12558 }
developer72fb0bb2023-01-11 09:46:29 +080012559
12560 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
12561 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
12562
developereff896f2023-05-29 14:52:55 +080012563 if(sinfo[NL80211_STA_INFO_TX_FAILED] && sinfo[NL80211_STA_INFO_TX_PACKETS])
12564 ((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 +080012565
12566 return NL_SKIP;
12567}
12568#endif
12569
12570INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
12571{
12572#ifdef HAL_NETLINK_IMPL
12573 Netlink nl;
12574 char if_name[10];
12575 char interface_name[16] = {0};
12576 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
12577 return RETURN_ERR;
12578
12579 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
12580
12581 if (*output_array_size <= 0)
12582 return RETURN_OK;
12583
12584 snprintf(if_name, sizeof(if_name), "%s", interface_name);
12585
12586 nl.id = initSock80211(&nl);
12587
12588 if(nl.id < 0) {
12589 fprintf(stderr, "Error initializing netlink \n");
12590 return 0;
12591 }
12592
12593 struct nl_msg* msg = nlmsg_alloc();
12594
12595 if(!msg) {
12596 fprintf(stderr, "Failed to allocate netlink message.\n");
12597 nlfree(&nl);
12598 return 0;
12599 }
12600
12601 genlmsg_put(msg,
developer8dd72532023-05-17 19:58:35 +080012602 NL_AUTO_PID,
developer72fb0bb2023-01-11 09:46:29 +080012603 NL_AUTO_SEQ,
12604 nl.id,
12605 0,
12606 0,
12607 NL80211_CMD_GET_STATION,
12608 0);
12609
12610 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
12611 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
12612 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
developer8dd72532023-05-17 19:58:35 +080012613 nl_send_auto_complete(nl.socket, msg);
developer72fb0bb2023-01-11 09:46:29 +080012614 nl_recvmsgs(nl.socket, nl.cb);
12615 nlmsg_free(msg);
12616 nlfree(&nl);
12617 return RETURN_OK;
12618#else
12619 //TODO Implement me
12620 return RETURN_OK;
12621#endif
12622}
12623
12624INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
12625{
12626 // TODO Implement me!
12627 char buf[MAX_BUF_SIZE] = {0};
12628 char config_file[MAX_BUF_SIZE] = {0};
12629
12630 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
12631 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
12632 *activate = (strncmp("1",buf,1) == 0);
12633
12634 return RETURN_OK;
12635}
12636
12637INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
12638{
12639 char config_file[MAX_BUF_SIZE] = {0};
12640 struct params list;
12641
12642 list.name = "rrm_neighbor_report";
12643 list.value = activate?"1":"0";
12644 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
12645 wifi_hostapdWrite(config_file, &list, 1);
12646
12647 return RETURN_OK;
12648}
12649
12650INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
12651{
12652 char buf[32] = {0};
12653 char config_file[MAX_BUF_SIZE] = {0};
12654
12655 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
12656 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
12657 *activate = (strncmp("1",buf,1) == 0);
12658
12659 return RETURN_OK;
12660}
12661#undef HAL_NETLINK_IMPL
12662#ifdef HAL_NETLINK_IMPL
12663static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
12664 struct nlattr *tb[NL80211_ATTR_MAX + 1];
12665 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
12666 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
12667 char dev[20];
12668 int freq =0 ;
12669 static int i=0;
12670
12671 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
12672
12673 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
12674 };
12675
12676 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
12677
12678 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
12679
12680 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
12681 fprintf(stderr, "survey data missing!\n");
12682 return NL_SKIP;
12683 }
12684
12685 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
12686 {
12687 fprintf(stderr, "failed to parse nested attributes!\n");
12688 return NL_SKIP;
12689 }
12690
12691
12692 if(out[0].array_size == 1 )
12693 {
12694 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
12695 {
12696 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
12697 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
12698 out[0].ch_number = ieee80211_frequency_to_channel(freq);
12699
12700 if (sinfo[NL80211_SURVEY_INFO_NOISE])
12701 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
12702 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
12703 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
12704 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
12705 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
12706 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
12707 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
12708 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
12709 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
12710 if (sinfo[NL80211_SURVEY_INFO_TIME])
12711 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
12712 return NL_STOP;
12713 }
12714 }
12715 else
12716 {
12717 if ( i <= out[0].array_size )
12718 {
12719 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
12720 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
12721 out[i].ch_number = ieee80211_frequency_to_channel(freq);
12722
12723 if (sinfo[NL80211_SURVEY_INFO_NOISE])
12724 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
12725 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
12726 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
12727 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
12728 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
12729 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
12730 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
12731 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
12732 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
12733 if (sinfo[NL80211_SURVEY_INFO_TIME])
12734 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
12735 }
12736 }
12737
12738 i++;
12739 return NL_SKIP;
12740}
12741#endif
12742
12743static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
12744{
12745 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
12746 FILE *fp;
12747
12748 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
12749 {
12750 printf("Creating Frequency-Channel Map\n");
12751 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
12752 }
12753 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
12754 if((fp = popen(command, "r")))
12755 {
12756 fgets(output, sizeof(output), fp);
12757 *freqMHz = atoi(output);
12758 pclose(fp);
12759 }
12760
12761 return 0;
12762}
12763
12764static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
12765{
12766 int freqMHz = -1;
12767 char cmd[MAX_CMD_SIZE] = {'\0'};
12768 char interface_name[16] = {0};
12769
12770 ieee80211_channel_to_frequency(channel, &freqMHz);
12771 if (freqMHz == -1) {
12772 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
12773 return -1;
12774 }
12775
12776 wifi_GetInterfaceName(radioIndex, interface_name);
12777 if (sprintf(cmd,"iw dev %s survey dump | grep -A5 %d | tr -d '\\t'", interface_name, freqMHz) < 0) {
12778 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
12779 radioIndex, freqMHz);
12780 return -1;
12781 }
12782
12783 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
12784 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
12785 return -1;
12786 }
12787
12788 return 0;
12789}
12790
12791static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
12792{
12793 const char *ptr = buf;
12794 char *key = NULL;
12795 char *val = NULL;
12796 char line[256] = { '\0' };
12797
12798 while (ptr = get_line_from_str_buf(ptr, line)) {
12799 if (strstr(line, "Frequency")) continue;
12800
12801 key = strtok(line, ":");
12802 val = strtok(NULL, " ");
12803 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
12804
12805 if (!strcmp(key, "noise")) {
12806 sscanf(val, "%d", &stats->ch_noise);
12807 if (stats->ch_noise == 0) {
12808 // Workaround for missing noise information.
12809 // Assume -95 for 2.4G and -103 for 5G
12810 if (radioIndex == 0) stats->ch_noise = -95;
12811 if (radioIndex == 1) stats->ch_noise = -103;
12812 }
12813 }
12814 else if (!strcmp(key, "channel active time")) {
12815 sscanf(val, "%llu", &stats->ch_utilization_total);
12816 }
12817 else if (!strcmp(key, "channel busy time")) {
12818 sscanf(val, "%llu", &stats->ch_utilization_busy);
12819 }
12820 else if (!strcmp(key, "channel receive time")) {
12821 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
12822 }
12823 else if (!strcmp(key, "channel transmit time")) {
12824 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
12825 }
12826 };
12827
12828 return 0;
12829}
12830
12831INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
12832{
12833 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12834#ifdef HAL_NETLINK_IMPL
12835 Netlink nl;
12836 wifi_channelStats_t_loc local[array_size];
12837 char if_name[32];
12838
12839 local[0].array_size = array_size;
12840
12841 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
12842 return RETURN_ERR;
12843
12844 nl.id = initSock80211(&nl);
12845
12846 if (nl.id < 0) {
12847 fprintf(stderr, "Error initializing netlink \n");
12848 return -1;
12849 }
12850
12851 struct nl_msg* msg = nlmsg_alloc();
12852
12853 if (!msg) {
12854 fprintf(stderr, "Failed to allocate netlink message.\n");
12855 nlfree(&nl);
12856 return -2;
12857 }
12858
12859 genlmsg_put(msg,
developer8dd72532023-05-17 19:58:35 +080012860 NL_AUTO_PID,
developer72fb0bb2023-01-11 09:46:29 +080012861 NL_AUTO_SEQ,
12862 nl.id,
12863 0,
12864 NLM_F_DUMP,
12865 NL80211_CMD_GET_SURVEY,
12866 0);
12867
12868 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
developer8dd72532023-05-17 19:58:35 +080012869 nl_send_auto_complete(nl.socket, msg);
developer72fb0bb2023-01-11 09:46:29 +080012870 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
12871 nl_recvmsgs(nl.socket, nl.cb);
12872 nlmsg_free(msg);
12873 nlfree(&nl);
12874 //Copying the Values
12875 for(int i=0;i<array_size;i++)
12876 {
12877 input_output_channelStats_array[i].ch_number = local[i].ch_number;
12878 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
12879 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
12880 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
12881 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
12882 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
12883 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
12884 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
12885 }
12886#else
12887 ULONG channel = 0;
12888 int i;
12889 int number_of_channels = array_size;
12890 char buf[512];
12891 INT ret;
12892 wifi_channelStats_t tmp_stats;
12893
12894 if (number_of_channels == 0) {
12895 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
12896 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
12897 return RETURN_ERR;
12898 }
12899 number_of_channels = 1;
12900 input_output_channelStats_array[0].ch_number = channel;
12901 }
12902
12903 for (i = 0; i < number_of_channels; i++) {
12904
12905 input_output_channelStats_array[i].ch_noise = 0;
12906 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
12907 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
12908 input_output_channelStats_array[i].ch_utilization_busy = 0;
12909 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
12910 input_output_channelStats_array[i].ch_utilization_total = 0;
12911
12912 memset(buf, 0, sizeof(buf));
12913 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
12914 return RETURN_ERR;
12915 }
12916 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
12917 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
12918 return RETURN_ERR;
12919 }
12920
12921 // XXX: fake missing 'self' counter which is not available in iw survey output
12922 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
12923 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
12924
12925 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
12926 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
12927 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
12928 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
12929 input_output_channelStats_array[i].ch_utilization_total *= 1000;
12930
12931 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",
12932 __func__,
12933 input_output_channelStats_array[i].ch_number,
12934 input_output_channelStats_array[i].ch_noise,
12935 input_output_channelStats_array[i].ch_utilization_total,
12936 input_output_channelStats_array[i].ch_utilization_busy,
12937 input_output_channelStats_array[i].ch_utilization_busy_rx,
12938 input_output_channelStats_array[i].ch_utilization_busy_tx,
12939 input_output_channelStats_array[i].ch_utilization_busy_self,
12940 input_output_channelStats_array[i].ch_utilization_busy_ext);
12941 }
12942#endif
12943 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12944 return RETURN_OK;
12945}
12946#define HAL_NETLINK_IMPL
12947
12948/* Hostapd events */
12949
12950#ifndef container_of
12951#define offset_of(st, m) ((size_t)&(((st *)0)->m))
12952#define container_of(ptr, type, member) \
12953 ((type *)((char *)ptr - offset_of(type, member)))
12954#endif /* container_of */
12955
12956struct ctrl {
12957 char sockpath[128];
12958 char sockdir[128];
12959 char bss[IFNAMSIZ];
12960 char reply[4096];
12961 int ssid_index;
12962 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
12963 void (*overrun)(struct ctrl *ctrl);
12964 struct wpa_ctrl *wpa;
12965 unsigned int ovfl;
12966 size_t reply_len;
12967 int initialized;
12968 ev_timer retry;
12969 ev_timer watchdog;
12970 ev_stat stat;
12971 ev_io io;
12972};
12973static wifi_newApAssociatedDevice_callback clients_connect_cb;
12974static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
12975static struct ctrl wpa_ctrl[MAX_APS];
12976static int initialized;
12977
12978static unsigned int ctrl_get_drops(struct ctrl *ctrl)
12979{
12980 char cbuf[256] = {};
12981 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
12982 struct cmsghdr *cmsg;
12983 unsigned int ovfl = ctrl->ovfl;
12984 unsigned int drop;
12985
12986 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
12987 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
12988 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
12989 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
12990
12991 drop = ovfl - ctrl->ovfl;
12992 ctrl->ovfl = ovfl;
12993
12994 return drop;
12995}
12996
12997static void ctrl_close(struct ctrl *ctrl)
12998{
12999 if (ctrl->io.cb)
13000 ev_io_stop(EV_DEFAULT_ &ctrl->io);
13001 if (ctrl->retry.cb)
13002 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
13003 if (!ctrl->wpa)
13004 return;
13005
13006 wpa_ctrl_detach(ctrl->wpa);
13007 wpa_ctrl_close(ctrl->wpa);
13008 ctrl->wpa = NULL;
13009 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
13010}
13011
13012static void ctrl_process(struct ctrl *ctrl)
13013{
13014 const char *str;
13015 int drops;
13016 int level;
13017 int err;
13018
13019 /* Example events:
13020 *
13021 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
13022 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
13023 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
13024 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
13025 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
13026 */
13027 if (!(str = index(ctrl->reply, '>')))
13028 return;
13029 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
13030 return;
13031
13032 str++;
13033
13034 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
13035 if (!(str = index(ctrl->reply, ' ')))
13036 return;
13037 wifi_associated_dev_t sta;
13038 memset(&sta, 0, sizeof(sta));
13039
13040 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
13041 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
13042 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
13043
13044 sta.cli_Active=true;
13045
13046 (clients_connect_cb)(ctrl->ssid_index, &sta);
13047 goto handled;
13048 }
13049
13050 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
13051 if (!(str = index(ctrl->reply, ' ')))
13052 return;
13053
13054 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
13055 goto handled;
13056 }
13057
13058 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
13059 printf("CTRL_WPA: handle TERMINATING event\n");
13060 goto retry;
13061 }
13062
13063 if (strncmp("AP-DISABLED", str, 11) == 0) {
13064 printf("CTRL_WPA: handle AP-DISABLED\n");
13065 goto retry;
13066 }
13067
13068 printf("Event not supported!!\n");
13069
13070handled:
13071
13072 if ((drops = ctrl_get_drops(ctrl))) {
13073 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
13074 if (ctrl->overrun)
13075 ctrl->overrun(ctrl);
13076 }
13077
13078 return;
13079
13080retry:
13081 printf("WPA_CTRL: closing\n");
13082 ctrl_close(ctrl);
13083 printf("WPA_CTRL: retrying from ctrl prcoess\n");
13084 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
13085}
13086
13087static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
13088{
13089 struct ctrl *ctrl = container_of(io, struct ctrl, io);
13090 int err;
13091
13092 memset(ctrl->reply, 0, sizeof(ctrl->reply));
13093 ctrl->reply_len = sizeof(ctrl->reply) - 1;
13094 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
13095 ctrl->reply[ctrl->reply_len] = 0;
13096 if (err < 0) {
13097 if (errno == EAGAIN || errno == EWOULDBLOCK)
13098 return;
13099 ctrl_close(ctrl);
13100 ev_timer_again(EV_A_ &ctrl->retry);
13101 return;
13102 }
13103
13104 ctrl_process(ctrl);
13105}
13106
13107static int ctrl_open(struct ctrl *ctrl)
13108{
13109 int fd;
13110
13111 if (ctrl->wpa)
13112 return 0;
13113
13114 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
13115 if (!ctrl->wpa)
13116 goto err;
13117
13118 if (wpa_ctrl_attach(ctrl->wpa) < 0)
13119 goto err_close;
13120
13121 fd = wpa_ctrl_get_fd(ctrl->wpa);
13122 if (fd < 0)
13123 goto err_detach;
13124
13125 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
13126 goto err_detach;
13127
13128 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
13129 ev_io_start(EV_DEFAULT_ &ctrl->io);
13130
13131 return 0;
13132
13133err_detach:
13134 wpa_ctrl_detach(ctrl->wpa);
13135err_close:
13136 wpa_ctrl_close(ctrl->wpa);
13137err:
13138 ctrl->wpa = NULL;
13139 return -1;
13140}
13141
13142static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
13143{
13144 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
13145
13146 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
13147 ctrl_open(ctrl);
13148}
13149
13150static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
13151{
13152 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
13153
13154 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
13155 if (ctrl_open(ctrl) == 0) {
13156 printf("WPA_CTRL: retry successful\n");
13157 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
13158 }
13159}
13160
13161int ctrl_enable(struct ctrl *ctrl)
13162{
13163 if (ctrl->wpa)
13164 return 0;
13165
13166 if (!ctrl->stat.cb) {
13167 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
13168 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
13169 }
13170
13171 if (!ctrl->retry.cb) {
13172 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
13173 }
13174
13175 return ctrl_open(ctrl);
13176}
13177
13178static void
13179ctrl_msg_cb(char *buf, size_t len)
13180{
13181 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
13182
13183 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
13184 ctrl_process(ctrl);
13185}
13186
13187static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
13188{
13189 int err;
13190
13191 if (!ctrl->wpa)
13192 return -1;
13193 if (*reply_len < 2)
13194 return -1;
13195
13196 (*reply_len)--;
13197 ctrl->reply_len = sizeof(ctrl->reply);
13198 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
13199 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
13200 if (err < 0)
13201 return err;
13202
13203 if (ctrl->reply_len > *reply_len)
13204 ctrl->reply_len = *reply_len;
13205
13206 *reply_len = ctrl->reply_len;
13207 memcpy(reply, ctrl->reply, *reply_len);
13208 reply[*reply_len - 1] = 0;
13209 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
13210 return 0;
13211}
13212
13213static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
13214{
13215 const char *pong = "PONG";
13216 const char *ping = "PING";
13217 char reply[1024];
13218 size_t len = sizeof(reply);
13219 int err;
13220 ULONG s, snum;
13221 INT ret;
13222 BOOL status;
13223
13224 printf("WPA_CTRL: watchdog cb\n");
13225
13226 ret = wifi_getSSIDNumberOfEntries(&snum);
13227 if (ret != RETURN_OK) {
13228 printf("%s: failed to get SSID count", __func__);
13229 return;
13230 }
13231
13232 if (snum > MAX_APS) {
13233 printf("more ssid than supported! %lu\n", snum);
13234 return;
13235 }
13236
13237 for (s = 0; s < snum; s++) {
13238 if (wifi_getApEnable(s, &status) != RETURN_OK) {
13239 printf("%s: failed to get AP Enable for index: %lu\n", __func__, s);
13240 continue;
13241 }
13242 if (status == false) continue;
13243
13244 memset(reply, 0, sizeof(reply));
13245 len = sizeof(reply);
13246 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
13247 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
13248 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
13249 continue;
13250
13251 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
13252 ctrl_close(&wpa_ctrl[s]);
13253 printf("WPA_CTRL: ev_timer_again %lu\n", s);
13254 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
13255 }
13256}
13257
13258static int init_wpa()
13259{
13260 int ret = 0, i = 0;
13261 ULONG s, snum;
13262
13263 ret = wifi_getSSIDNumberOfEntries(&snum);
13264 if (ret != RETURN_OK) {
13265 printf("%s: failed to get SSID count", __func__);
13266 return RETURN_ERR;
13267 }
13268
13269 if (snum > MAX_APS) {
13270 printf("more ssid than supported! %lu\n", snum);
13271 return RETURN_ERR;
13272 }
13273
13274 for (s = 0; s < snum; s++) {
13275 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
13276 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
13277 wpa_ctrl[s].ssid_index = s;
13278 ctrl_enable(&wpa_ctrl[s]);
13279 }
13280
13281 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
13282 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
13283
13284 initialized = 1;
13285 printf("WPA_CTRL: initialized\n");
13286
13287 return RETURN_OK;
13288}
13289
13290void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
13291{
13292 clients_connect_cb = callback_proc;
13293 if (!initialized)
13294 init_wpa();
13295}
13296
13297void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
13298{
13299 clients_disconnect_cb = callback_proc;
13300 if (!initialized)
13301 init_wpa();
13302}
13303
13304INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
13305{
13306 // TODO Implement me!
13307 return RETURN_ERR;
13308}
13309
13310INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
13311{
13312 // TODO Implement me!
13313 return RETURN_ERR;
13314}
13315
13316INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
13317{
13318 int i;
developerd1824452023-05-18 12:30:04 +080013319 int phyId = -1;
13320 char cmd[256] = {0};
13321 char channel_numbers_buf[256] = {0};
13322 char dfs_state_buf[256] = {0};
13323 char line[256] = {0};
developer72fb0bb2023-01-11 09:46:29 +080013324 const char *ptr;
developerd1824452023-05-18 12:30:04 +080013325 BOOL dfs_enable = false;
developer72fb0bb2023-01-11 09:46:29 +080013326
developerd1824452023-05-18 12:30:04 +080013327 memset(outputMap, 0, outputMapSize*sizeof(wifi_channelMap_t)); // all unused entries should be zero
developer72fb0bb2023-01-11 09:46:29 +080013328
developerd1824452023-05-18 12:30:04 +080013329 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
13330 phyId = radio_index_to_phy(radioIndex);
developer72fb0bb2023-01-11 09:46:29 +080013331
developerd1824452023-05-18 12:30:04 +080013332 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 +080013333
developerd1824452023-05-18 12:30:04 +080013334 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
13335 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
13336 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +080013337 }
13338
developerd1824452023-05-18 12:30:04 +080013339 ptr = channel_numbers_buf;
13340 i = 0;
13341 while (ptr = get_line_from_str_buf(ptr, line)) {
13342 if (i >= outputMapSize) {
13343 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
13344 return RETURN_ERR;
13345 }
13346 sscanf(line, "%d", &outputMap[i].ch_number);
13347
13348 memset(cmd, 0, sizeof(cmd));
13349 // Below command should fetch string for DFS state (usable, available or unavailable)
13350 // Example line: "DFS state: usable (for 78930 sec)"
13351 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) {
13352 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
developer72fb0bb2023-01-11 09:46:29 +080013353 return RETURN_ERR;
13354 }
13355
developerd1824452023-05-18 12:30:04 +080013356 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
13357 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
developer72fb0bb2023-01-11 09:46:29 +080013358 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
13359 return RETURN_ERR;
13360 }
13361
developerd1824452023-05-18 12:30:04 +080013362 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
developer59fda4f2023-05-16 15:47:38 +080013363
developerd1824452023-05-18 12:30:04 +080013364 if (!strcmp(dfs_state_buf, "usable")) {
13365 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
13366 } else if (!strcmp(dfs_state_buf, "available")) {
13367 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
13368 } else if (!strcmp(dfs_state_buf, "unavailable")) {
13369 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
13370 } else {
13371 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
developer72fb0bb2023-01-11 09:46:29 +080013372 }
developerd1824452023-05-18 12:30:04 +080013373 i++;
developer59fda4f2023-05-16 15:47:38 +080013374 }
developer40ba1762023-05-13 11:03:49 +080013375
developerd1824452023-05-18 12:30:04 +080013376 return RETURN_OK;
13377
developer72fb0bb2023-01-11 09:46:29 +080013378 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
13379 return RETURN_ERR;
13380}
13381
13382INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
13383{
13384 // TODO Implement me!
13385 return RETURN_ERR;
13386}
13387
13388INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
13389{
13390 return RETURN_OK;
13391}
13392
13393INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
13394{
13395 // TODO Implement me!
13396 return RETURN_ERR;
13397}
13398
13399INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
13400{
13401 // TODO API refrence Implementaion is present on RPI hal
13402 return RETURN_ERR;
13403}
13404
13405INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
13406{
developera1255e42023-05-13 17:45:02 +080013407/*
developer72fb0bb2023-01-11 09:46:29 +080013408 char interface_name[16] = {0};
13409 char cmd[128]={'\0'};
13410 char buf[128]={'\0'};
13411 char *support;
13412 int maximum_tx = 0, current_tx = 0;
developera1255e42023-05-13 17:45:02 +080013413*/ ULONG pwr_percentage = 0;
developer72fb0bb2023-01-11 09:46:29 +080013414
13415 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13416 if(txpwr_pcntg == NULL)
13417 return RETURN_ERR;
13418
developera1255e42023-05-13 17:45:02 +080013419 wifi_getRadioTransmitPower(apIndex, &pwr_percentage);
13420 *txpwr_pcntg = pwr_percentage;
13421/* if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72fb0bb2023-01-11 09:46:29 +080013422 return RETURN_ERR;
13423
13424 // Get the maximum tx power of the device
13425 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", interface_name);
13426 _syscmd(cmd, buf, sizeof(buf));
13427 maximum_tx = strtol(buf, NULL, 10);
13428
13429 // Get the current tx power
13430 memset(cmd, 0, sizeof(cmd));
13431 memset(buf, 0, sizeof(buf));
13432 snprintf(cmd, sizeof(cmd), "iw %s info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", interface_name);
13433 _syscmd(cmd, buf, sizeof(buf));
13434 current_tx = strtol(buf, NULL, 10);
13435
13436 // Get the power supported list and find the current power percentage in supported list
13437 memset(buf, 0, sizeof(buf));
13438 wifi_getRadioTransmitPowerSupported(apIndex, buf);
13439 support = strtok(buf, ",");
13440 while(true)
13441 {
13442 if(support == NULL) { // current power is not in supported list, this should not happen if the power is set by hal.
13443 *txpwr_pcntg = 100;
13444 wifi_dbg_printf("current power is not in supported list\n");
13445 return RETURN_OK;
13446 }
13447 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
13448 if (tmp == current_tx) {
13449 *txpwr_pcntg = strtol(support, NULL, 10);
13450 break;
13451 }
13452 support = strtok(NULL, ",");
13453 }
developera1255e42023-05-13 17:45:02 +080013454*/
developer72fb0bb2023-01-11 09:46:29 +080013455 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13456 return RETURN_OK;
13457}
13458
13459INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
13460{
13461 // TODO precac feature.
developerd1824452023-05-18 12:30:04 +080013462 struct params params[2] = {0};
developer72fb0bb2023-01-11 09:46:29 +080013463 char config_file[128] = {0};
developerd1824452023-05-18 12:30:04 +080013464 BOOL dfs_enable = false;
13465 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +080013466
13467 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developerd1824452023-05-18 12:30:04 +080013468 band = wifi_index_to_band(radioIndex);
13469 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
developer72fb0bb2023-01-11 09:46:29 +080013470
developerd1824452023-05-18 12:30:04 +080013471 if (dfs_enable == false) {
13472 WIFI_ENTRY_EXIT_DEBUG("Please enable DFS firstly!: %s\n", __func__);
13473 return RETURN_ERR;
13474 }
13475 params[0].name = "DfsZeroWaitDefault";
13476 params[0].value = enable?"1":"0";
13477 params[1].name = "DfsDedicatedZeroWait";
13478 params[1].value = enable?"1":"0";
13479 snprintf(config_file, sizeof(config_file), "%s%d.dat", LOGAN_DAT_FILE, band);
13480 wifi_datfileWrite(config_file, params, 2);
developerc0772e62023-05-18 15:10:48 +080013481 wifi_reloadAp(radioIndex);
developer72fb0bb2023-01-11 09:46:29 +080013482 /* TODO precac feature */
13483
13484 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13485 return RETURN_OK;
13486}
13487
13488INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
13489{
13490 char config_file[128] = {0};
developerd1824452023-05-18 12:30:04 +080013491 char buf1[32] = {0};
13492 char buf2[32] = {0};
13493 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +080013494
13495 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13496 if (NULL == enable || NULL == precac)
13497 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +080013498 band = wifi_index_to_band(radioIndex);
13499 snprintf(config_file, sizeof(config_file), "%s%d.dat", LOGAN_DAT_FILE, band);
13500 wifi_datfileRead(config_file, "DfsZeroWaitDefault", buf1, sizeof(buf1));
13501 wifi_datfileRead(config_file, "DfsDedicatedZeroWait", buf2, sizeof(buf2));
13502 if ((strncmp(buf1, "1", 1) == 0) && (strncmp(buf2, "1", 1) == 0))
developer72fb0bb2023-01-11 09:46:29 +080013503 *enable = true;
13504 else
13505 *enable = false;
13506
13507 /* TODO precac feature */
13508
13509 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13510 return RETURN_OK;
13511}
13512
13513INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
13514{
13515 *supported = TRUE;
13516 return RETURN_OK;
13517}
13518
13519INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
13520{
developera1255e42023-05-13 17:45:02 +080013521 UCHAR dat_file[64] = {0};
13522 wifi_band band = band_invalid;
13523 char cmd[128] = {0};
13524 char buf[256] = {0};
13525 char ofdmabuf[32] = {'\0'};
13526 char mimobuf[32] = {'\0'};
13527 char new_ofdmabuf[32] = {'\0'};
13528 char new_mimobuf[32] = {'\0'};
13529 struct params params[2];
13530 char *str_zero = "0;0;0;0;0;0;0;0;0;0;0;0;0;0;0";/*default 15bss per band.*/
13531 char *str_one = "1;1;1;1;1;1;1;1;1;1;1;1;1;1;1";
13532 UCHAR bss_cnt = 0;
13533 UCHAR val_cnt = 0;
13534 char *token = NULL;
developer72fb0bb2023-01-11 09:46:29 +080013535
developera1255e42023-05-13 17:45:02 +080013536 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13537 if ((mu_type < WIFI_DL_MU_TYPE_NONE)
13538 || (mu_type > WIFI_DL_MU_TYPE_OFDMA_MIMO)) {
13539 printf("%s:mu_type input Error", __func__);
13540 return RETURN_ERR;
13541 }
13542 band = wifi_index_to_band(radio_index);
13543 if (band == band_invalid) {
13544 printf("%s:Band Error\n", __func__);
13545 return RETURN_ERR;
13546 }
13547 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
13548 /*get current value in dat file*/
13549 wifi_datfileRead(dat_file, "MuOfdmaDlEnable", ofdmabuf, sizeof(ofdmabuf));
13550 wifi_datfileRead(dat_file, "MuMimoDlEnable", mimobuf, sizeof(mimobuf));
13551 WIFI_ENTRY_EXIT_DEBUG("%s:ofdma-%s, mimo-%s\n", __func__, ofdmabuf, mimobuf);
13552 get_bssnum_byindex(radio_index, &bss_cnt);
13553 val_cnt = 2*bss_cnt - 1;
13554 WIFI_ENTRY_EXIT_DEBUG("bss number: %d\n", bss_cnt);
13555 if ((val_cnt >= sizeof(new_ofdmabuf))
13556 || (val_cnt >= sizeof(new_mimobuf))) {
13557 printf("%s:bss cnt Error", __func__, bss_cnt);
13558 return RETURN_ERR;
13559 }
13560 /*translate set value*/
13561 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
13562 strncpy(new_ofdmabuf, str_zero, val_cnt);
13563 strncpy(new_mimobuf, str_zero, val_cnt);
developer72fb0bb2023-01-11 09:46:29 +080013564 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
developera1255e42023-05-13 17:45:02 +080013565 strncpy(new_ofdmabuf, str_one, val_cnt);
13566 strncpy(new_mimobuf, str_zero, val_cnt);
developer72fb0bb2023-01-11 09:46:29 +080013567 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
developera1255e42023-05-13 17:45:02 +080013568 strncpy(new_ofdmabuf, str_zero, val_cnt);
13569 strncpy(new_mimobuf, str_one, val_cnt);
13570 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO) {
13571 strncpy(new_ofdmabuf, str_one, val_cnt);
13572 strncpy(new_mimobuf, str_one, val_cnt);
developer72fb0bb2023-01-11 09:46:29 +080013573 }
developera1255e42023-05-13 17:45:02 +080013574 WIFI_ENTRY_EXIT_DEBUG("%s:new_ofdmabuf-%s, new_mimobuf-%s\n", __func__, new_ofdmabuf, new_mimobuf);
13575 /*same value, not operation*/
13576 if ((strncmp(new_mimobuf, mimobuf, 1) ==0)
13577 && (strncmp(new_ofdmabuf, ofdmabuf, 1) ==0)) {
13578 printf("%s:Reduntant value\n", __func__);
13579 return RETURN_OK;
13580 }
13581 /*modify dat file to new file*/
13582 params[0].name="MuOfdmaDlEnable";
13583 params[0].value=new_ofdmabuf;
13584 params[1].name="MuMimoDlEnable";
13585 params[1].value=new_mimobuf;
13586 wifi_datfileWrite(dat_file, params, 2);
13587 /*hostapd control restarp ap to take effect on these new value*/
13588 wifi_reloadAp(radio_index);
developer72fb0bb2023-01-11 09:46:29 +080013589 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13590 return RETURN_OK;
13591}
13592
13593INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
13594{
13595 struct params params={0};
13596 char config_file[64] = {0};
13597 char buf[64] = {0};
13598 unsigned int get_mu_type = 0;
developera1255e42023-05-13 17:45:02 +080013599 UCHAR dat_file[64] = {0};
13600 wifi_band band = band_invalid;
13601 char ofdmabuf[32] = {'\0'};
13602 char mimobuf[32] = {'\0'};
13603 char *token = NULL;
13604 UCHAR ofdma = 0;
13605 UCHAR mimo = 0;
developer72fb0bb2023-01-11 09:46:29 +080013606
13607 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13608
13609 if (mu_type == NULL)
13610 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +080013611 band = wifi_index_to_band(radio_index);
13612 if (band == band_invalid) {
13613 printf("%s:Band Error\n", __func__);
13614 return RETURN_ERR;
13615 }
13616 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
13617 /*get current value in dat file*/
13618 wifi_datfileRead(dat_file, "MuOfdmaDlEnable", ofdmabuf, sizeof(ofdmabuf));
13619 wifi_datfileRead(dat_file, "MuMimoDlEnable", mimobuf, sizeof(mimobuf));
developer72fb0bb2023-01-11 09:46:29 +080013620
developera1255e42023-05-13 17:45:02 +080013621 token = strtok(ofdmabuf, ";");
13622 ofdma = strtol(token, NULL, 10);
13623 token = strtok(mimobuf, ";");
13624 mimo = strtol(token, NULL, 10);
13625 WIFI_ENTRY_EXIT_DEBUG("%s:ofdma=%d,mimo=%d\n", __func__, ofdma, mimo);
13626 if ((ofdma == 1) && (mimo == 1))
13627 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
13628 else if ((ofdma == 0) && (mimo == 1))
13629 *mu_type = WIFI_DL_MU_TYPE_MIMO;
13630 else if ((ofdma == 1) && (mimo == 0))
13631 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
13632 else
13633 *mu_type = WIFI_DL_MU_TYPE_NONE;
developer72fb0bb2023-01-11 09:46:29 +080013634 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13635 return RETURN_OK;
13636}
13637
13638INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
13639{
13640 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
developera1255e42023-05-13 17:45:02 +080013641 UCHAR dat_file[64] = {0};
13642 wifi_band band = band_invalid;
13643 char cmd[128] = {0};
13644 char buf[256] = {0};
13645 char ofdmabuf[32] = {'\0'};
13646 char mimobuf[32] = {'\0'};
13647 char new_ofdmabuf[32] = {'\0'};
13648 char new_mimobuf[32] = {'\0'};
13649 struct params params[2];
13650 char *str_zero = "0;0;0;0;0;0;0;0;0;0;0;0;0;0;0";/*default 15bss per band.*/
13651 char *str_one = "1;1;1;1;1;1;1;1;1;1;1;1;1;1;1";
13652 UCHAR bss_cnt = 0;
13653 UCHAR val_cnt = 0;
developer72fb0bb2023-01-11 09:46:29 +080013654
developera1255e42023-05-13 17:45:02 +080013655 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13656 band = wifi_index_to_band(radio_index);
13657 if (band == band_invalid) {
13658 printf("%s:Band Error\n", __func__);
13659 return RETURN_ERR;
13660 }
13661 if ((mu_type < WIFI_UL_MU_TYPE_NONE)
13662 || (mu_type > WIFI_UL_MU_TYPE_OFDMA)) {
13663 printf("%s:mu_type input Error\n", __func__);
13664 return RETURN_ERR;
13665 }
13666 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
13667 /*get current value in dat file*/
13668 wifi_datfileRead(dat_file, "MuOfdmaUlEnable", ofdmabuf, sizeof(ofdmabuf));
13669 wifi_datfileRead(dat_file, "MuMimoUlEnable", mimobuf, sizeof(mimobuf));
13670 WIFI_ENTRY_EXIT_DEBUG("%s:ofdma-%s, mimo-%s\n", __func__, ofdmabuf, mimobuf);
13671 get_bssnum_byindex(radio_index, &bss_cnt);
13672 val_cnt = 2*bss_cnt - 1;
13673 printf("bssNumber:%d,ValCnt:%d\n", bss_cnt, val_cnt);
13674 if ((val_cnt >= sizeof(new_ofdmabuf))
13675 || (val_cnt >= sizeof(new_mimobuf))) {
13676 printf("%s:bss cnt Error\n", __func__, val_cnt);
13677 return RETURN_ERR;
13678 }
13679 /*translate set value*/
13680 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
13681 strncpy(new_ofdmabuf, str_zero, val_cnt);
13682 strncpy(new_mimobuf, str_zero, val_cnt);
developer72fb0bb2023-01-11 09:46:29 +080013683 }
developera1255e42023-05-13 17:45:02 +080013684 if (mu_type == WIFI_UL_MU_TYPE_OFDMA) {
13685 strncpy(new_ofdmabuf, str_one, val_cnt);
13686 strncpy(new_mimobuf, str_zero, val_cnt);
13687 }
13688 printf("%s:new_ofdmabuf-%s, new_mimobuf-%s\n", __func__, new_ofdmabuf, new_mimobuf);
13689 /*same value, not operation*/
13690 if ((strncmp(new_mimobuf, mimobuf, 1) ==0)
13691 && (strncmp(new_ofdmabuf, ofdmabuf, 1) ==0)) {
13692 printf("%s:Reduntant value\n", __func__);
13693 return RETURN_OK;
13694 }
13695 /*modify dat file to new file*/
13696 params[0].name="MuOfdmaUlEnable";
13697 params[0].value=new_ofdmabuf;
13698 params[1].name="MuMimoUlEnable";
13699 params[1].value=new_mimobuf;
13700 wifi_datfileWrite(dat_file, params, 2);
13701 wifi_reloadAp(radio_index);
developer72fb0bb2023-01-11 09:46:29 +080013702 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13703 return RETURN_OK;
13704}
13705
13706INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
13707{
13708 struct params params={0};
13709 char config_file[64] = {0};
13710 char buf[64] = {0};
13711 unsigned int get_mu_type = 0;
developera1255e42023-05-13 17:45:02 +080013712 UCHAR dat_file[64] = {0};
13713 wifi_band band = band_invalid;
13714 char ofdmabuf[32] = {'\0'};
13715 char mimobuf[32] = {'\0'};
13716 char *token = NULL;
13717 UCHAR ofdma = 0;
13718 UCHAR mimo = 0;
developer72fb0bb2023-01-11 09:46:29 +080013719
13720 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13721
13722 if (mu_type == NULL)
13723 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +080013724 band = wifi_index_to_band(radio_index);
13725 if (band == band_invalid) {
13726 printf("%s:Band Error", __func__);
13727 return RETURN_ERR;
13728 }
13729 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
13730 /*get current value in dat file*/
13731 wifi_datfileRead(dat_file, "MuOfdmaUlEnable", ofdmabuf, sizeof(ofdmabuf));
13732 wifi_datfileRead(dat_file, "MuMimoUlEnable", mimobuf, sizeof(mimobuf));
developer72fb0bb2023-01-11 09:46:29 +080013733
developera1255e42023-05-13 17:45:02 +080013734 token = strtok(ofdmabuf, ";");
13735 ofdma = strtol(token, NULL, 10);
13736 token = strtok(mimobuf, ";");
13737 mimo = strtol(token, NULL, 10);
13738 WIFI_ENTRY_EXIT_DEBUG("%s:ofdma=%d, mimo=%d\n", __func__, ofdma, mimo);
13739 if ((ofdma == 1) && (mimo == 0))
13740 *mu_type = WIFI_UL_MU_TYPE_OFDMA;
13741 else
13742 *mu_type = WIFI_UL_MU_TYPE_NONE;
developer72fb0bb2023-01-11 09:46:29 +080013743 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13744 return RETURN_OK;
13745}
13746
13747
13748INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
13749{
13750 char cmd[128] = {0};
13751 char buf[256] = {0};
13752 char config_file[64] = {0};
13753 char GI[8] = {0};
13754 int mode_map = 0;
13755 FILE *f = NULL;
13756 wifi_band band = band_invalid;
developera1255e42023-05-13 17:45:02 +080013757 char dat_file[64] = {'\0'};
13758 struct params params[3];
developer72fb0bb2023-01-11 09:46:29 +080013759
13760 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13761
13762 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
13763 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
13764 return RETURN_ERR;
13765 }
developera1255e42023-05-13 17:45:02 +080013766 /*sanity check*/
13767 if (((guard_interval == wifi_guard_interval_1600)
13768 || (guard_interval == wifi_guard_interval_3200))
13769 && (mode_map & (WIFI_MODE_BE | WIFI_MODE_AX) == 0)) {
13770 wifi_dbg_printf("%s: N/AC Mode not support 1600/3200ns GI\n", __func__);
13771 return RETURN_ERR;
13772 }
developer72fb0bb2023-01-11 09:46:29 +080013773 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
13774 band = wifi_index_to_band(radio_index);
13775
13776 // Hostapd are not supported HE mode GI 1600, 3200 ns.
13777 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
13778 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
13779 _syscmd(cmd, buf, sizeof(buf));
13780 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
13781 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
13782 if (strstr(buf, "[SHORT-GI-") == NULL) {
13783 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[SHORT-GI-20][SHORT-GI-40]/' %s", config_file);
13784 _syscmd(cmd, buf, sizeof(buf));
13785 }
13786 if (band == band_5) {
13787 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
13788 if (strstr(buf, "[SHORT-GI-") == NULL) {
13789 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SHORT-GI-80][SHORT-GI-160]/' %s", config_file);
13790 _syscmd(cmd, buf, sizeof(buf));
13791 }
13792 }
13793 }
developera1255e42023-05-13 17:45:02 +080013794 /*wifi_reloadAp(radio_index);
13795 caller "wifi_setRadioOperatingParameters" have done this step.
13796 */
13797 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
13798 if (guard_interval == wifi_guard_interval_400) {
13799 params[0].name = "HT_GI";
13800 params[0].value = "1";
13801 params[1].name = "VHT_SGI";
13802 params[1].value = "1";
13803 wifi_datfileWrite(dat_file, params, 2);
developer72fb0bb2023-01-11 09:46:29 +080013804 strcpy(GI, "0.4");
developera1255e42023-05-13 17:45:02 +080013805 } else {
13806 params[0].name = "HT_GI";
13807 params[0].value = "0";
13808 params[1].name = "VHT_SGI";
13809 params[1].value = "0";
13810 /*should enable FIXED_HE_GI_SUPPORT in driver*/
13811 params[2].name = "FgiFltf";
13812 if (guard_interval == wifi_guard_interval_800) {
13813 params[2].value = "800";
13814 strcpy(GI, "0.8");
13815 } else if (guard_interval == wifi_guard_interval_1600) {
13816 params[2].value = "1600";
13817 strcpy(GI, "1.6");
13818 } else if (guard_interval == wifi_guard_interval_3200) {
13819 params[2].value = "3200";
13820 strcpy(GI, "3.2");
13821 } else if (guard_interval == wifi_guard_interval_auto) {
13822 params[2].value = "0";
13823 strcpy(GI, "auto");
13824 }
13825 wifi_datfileWrite(dat_file, params, 3);
13826 }
developer72fb0bb2023-01-11 09:46:29 +080013827 // Record GI for get GI function
13828 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
13829 f = fopen(buf, "w");
13830 if (f == NULL)
13831 return RETURN_ERR;
13832 fprintf(f, "%s", GI);
13833 fclose(f);
13834 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13835 return RETURN_OK;
13836}
13837
13838INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
13839{
13840 char buf[32] = {0};
13841 char cmd[64] = {0};
13842
13843 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13844
13845 if (guard_interval == NULL)
13846 return RETURN_ERR;
13847
developera1255e42023-05-13 17:45:02 +080013848 snprintf(cmd, sizeof(cmd), "cat %s%d.txt 2> /dev/null", GUARD_INTERVAL_FILE, radio_index);
developer72fb0bb2023-01-11 09:46:29 +080013849 _syscmd(cmd, buf, sizeof(buf));
13850
13851 if (strncmp(buf, "0.4", 3) == 0)
13852 *guard_interval = wifi_guard_interval_400;
13853 else if (strncmp(buf, "0.8", 3) == 0)
13854 *guard_interval = wifi_guard_interval_800;
13855 else if (strncmp(buf, "1.6", 3) == 0)
13856 *guard_interval = wifi_guard_interval_1600;
13857 else if (strncmp(buf, "3.2", 3) == 0)
13858 *guard_interval = wifi_guard_interval_3200;
13859 else
13860 *guard_interval = wifi_guard_interval_auto;
13861
13862 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13863 return RETURN_OK;
13864}
13865
13866INT wifi_setBSSColor(INT radio_index, UCHAR color)
13867{
13868 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13869 struct params params = {0};
13870 char config_file[128] = {0};
13871 char bss_color[4] ={0};
13872
developera1255e42023-05-13 17:45:02 +080013873 if (color < 1 || color > 63) {
13874 wifi_dbg_printf("color value is err:%d.\n", color);
13875 return RETURN_ERR;
13876 }
developer72fb0bb2023-01-11 09:46:29 +080013877 params.name = "he_bss_color";
13878 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
13879 params.value = bss_color;
13880 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
13881 wifi_hostapdWrite(config_file, &params, 1);
developera1255e42023-05-13 17:45:02 +080013882 //wifi_hostapdProcessUpdate(radio_index, &params, 1);
13883 wifi_reloadAp(radio_index);
developer69b61b02023-03-07 17:17:44 +080013884
developer72fb0bb2023-01-11 09:46:29 +080013885 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13886 return RETURN_OK;
13887}
13888
13889INT wifi_getBSSColor(INT radio_index, UCHAR *color)
13890{
13891 char config_file[128] = {0};
13892 char buf[64] = {0};
13893 char temp_output[128] = {'\0'};
13894
13895 wifi_dbg_printf("\nFunc=%s\n", __func__);
13896 if (NULL == color)
13897 return RETURN_ERR;
13898
13899 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
13900 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
13901
13902 if(strlen(buf) > 0) {
13903 snprintf(temp_output, sizeof(temp_output), "%s", buf);
13904 } else {
13905 snprintf(temp_output, sizeof(temp_output), "1"); // default value
13906 }
13907
13908 *color = (UCHAR)strtoul(temp_output, NULL, 10);
13909 wifi_dbg_printf("\noutput_string=%s\n", color);
13910
13911 return RETURN_OK;
13912}
13913
13914/* multi-psk support */
13915INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
13916{
13917 char cmd[256];
13918 char interface_name[16] = {0};
13919
13920 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
13921 return RETURN_ERR;
13922
13923 sprintf(cmd, "hostapd_cli -i %s sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
13924 interface_name,
13925 mac[0],
13926 mac[1],
13927 mac[2],
13928 mac[3],
13929 mac[4],
13930 mac[5]
13931 );
13932 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
13933 _syscmd(cmd, key->wifi_keyId, 64);
13934
13935
13936 return RETURN_OK;
13937}
13938
13939INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
13940{
13941 char interface_name[16] = {0};
13942 FILE *fd = NULL;
13943 char fname[100];
13944 char cmd[128] = {0};
13945 char out[64] = {0};
13946 wifi_key_multi_psk_t * key = NULL;
13947 if(keysNumber < 0)
13948 return RETURN_ERR;
13949
13950 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
13951 fd = fopen(fname, "w");
13952 if (!fd) {
13953 return RETURN_ERR;
13954 }
13955 key= (wifi_key_multi_psk_t *) keys;
13956 for(int i=0; i<keysNumber; ++i, key++) {
13957 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
13958 }
13959 fclose(fd);
13960
13961 //reload file
13962 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
13963 return RETURN_ERR;
13964 sprintf(cmd, "hostapd_cli -i%s raw RELOAD_WPA_PSK", interface_name);
13965 _syscmd(cmd, out, 64);
13966 return RETURN_OK;
13967}
13968
13969INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
13970{
13971 FILE *fd = NULL;
13972 char fname[100];
13973 char * line = NULL;
13974 char * pos = NULL;
13975 size_t len = 0;
13976 ssize_t read = 0;
13977 INT ret = RETURN_OK;
13978 wifi_key_multi_psk_t *keys_it = NULL;
13979
13980 if (keysNumber < 1) {
13981 return RETURN_ERR;
13982 }
13983
13984 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
13985 fd = fopen(fname, "r");
13986 if (!fd) {
13987 return RETURN_ERR;
13988 }
13989
13990 if (keys == NULL) {
13991 ret = RETURN_ERR;
13992 goto close;
13993 }
13994
13995 keys_it = keys;
13996 while ((read = getline(&line, &len, fd)) != -1) {
13997 //Strip trailing new line if present
13998 if (read > 0 && line[read-1] == '\n') {
13999 line[read-1] = '\0';
14000 }
14001
14002 if(strcmp(line,"keyid=")) {
14003 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
14004 if (!(pos = index(line, ' '))) {
14005 ret = RETURN_ERR;
14006 goto close;
14007 }
14008 pos++;
14009 //Here should be 00:00:00:00:00:00
14010 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
14011 printf("Not supported MAC: %s\n", pos);
14012 }
14013 if (!(pos = index(pos, ' '))) {
14014 ret = RETURN_ERR;
14015 goto close;
14016 }
14017 pos++;
14018
14019 //The rest is PSK
14020 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
14021 keys_it++;
14022
14023 if(--keysNumber <= 0)
14024 break;
14025 }
14026 }
14027
14028close:
14029 free(line);
14030 fclose(fd);
14031 return ret;
14032}
14033/* end of multi-psk support */
14034
14035INT wifi_setNeighborReports(UINT apIndex,
14036 UINT numNeighborReports,
14037 wifi_NeighborReport_t *neighborReports)
14038{
14039 char cmd[256] = { 0 };
14040 char hex_bssid[13] = { 0 };
14041 char bssid[18] = { 0 };
14042 char nr[256] = { 0 };
14043 char ssid[256];
14044 char hex_ssid[256];
14045 char interface_name[16] = {0};
14046 INT ret;
14047
14048 /*rmeove all neighbors*/
14049 wifi_dbg_printf("\n[%s]: removing all neighbors from %s\n", __func__, interface_name);
14050 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
14051 return RETURN_ERR;
14052 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);
14053 system(cmd);
14054
14055 for(unsigned int i = 0; i < numNeighborReports; i++)
14056 {
14057 memset(ssid, 0, sizeof(ssid));
14058 ret = wifi_getSSIDName(apIndex, ssid);
14059 if (ret != RETURN_OK)
14060 return RETURN_ERR;
14061
14062 memset(hex_ssid, 0, sizeof(hex_ssid));
14063 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
14064 sprintf(hex_ssid + k,"%02x", ssid[j]);
14065
14066 snprintf(hex_bssid, sizeof(hex_bssid),
14067 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
14068 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
14069 snprintf(bssid, sizeof(bssid),
14070 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
14071 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
14072
14073 snprintf(nr, sizeof(nr),
14074 "%s" // bssid
14075 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
14076 "%02hhx" // operclass
14077 "%02hhx" // channel
14078 "%02hhx", // phy_mode
14079 hex_bssid,
14080 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
14081 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
14082 neighborReports[i].opClass,
14083 neighborReports[i].channel,
14084 neighborReports[i].phyTable);
14085
14086 snprintf(cmd, sizeof(cmd),
14087 "hostapd_cli set_neighbor "
14088 "%s " // bssid
14089 "ssid=%s " // ssid
14090 "nr=%s " // nr
14091 "-i %s",
14092 bssid,hex_ssid,nr, interface_name);
14093
14094 if (WEXITSTATUS(system(cmd)) != 0)
14095 {
14096 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
14097 }
14098 }
14099
14100 return RETURN_OK;
14101}
14102
14103INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
14104{
14105 return RETURN_OK;
14106}
14107
14108#ifdef _WIFI_HAL_TEST_
14109int main(int argc,char **argv)
14110{
14111 int index;
14112 INT ret=0;
14113 char buf[1024]="";
14114
14115 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
14116 if(argc<3)
14117 {
14118 if(argc==2)
14119 {
14120 if(!strcmp(argv[1], "init"))
14121 return wifi_init();
14122 if(!strcmp(argv[1], "reset"))
14123 return wifi_reset();
14124 if(!strcmp(argv[1], "wifi_getHalVersion"))
14125 {
14126 char buffer[64];
14127 if(wifi_getHalVersion(buffer)==RETURN_OK)
14128 printf("Version: %s\n", buffer);
14129 else
14130 printf("Error in wifi_getHalVersion\n");
14131 return RETURN_OK;
14132 }
14133 }
14134 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
14135 exit(-1);
14136 }
14137
14138 index = atoi(argv[2]);
14139 if(strstr(argv[1], "wifi_getApName")!=NULL)
14140 {
14141 wifi_getApName(index,buf);
14142 printf("Ap name is %s \n",buf);
14143 return 0;
14144 }
developerfead3972023-05-25 20:15:02 +080014145 if(strstr(argv[1], "wifi_setRadioMode")!=NULL)
14146 {
14147 UINT pureMode = atoi(argv[3]);
14148
14149 wifi_setRadioMode(index, NULL, pureMode);
14150 printf("Ap SET Radio mode 0x%x\n", pureMode);
14151 return 0;
14152 }
14153 if(strstr(argv[1], "wifi_setRadioTransmitPower")!=NULL)
14154 {
14155 ULONG TransmitPower = atoi(argv[3]);
14156
14157 wifi_setRadioTransmitPower(index, TransmitPower);
14158 printf("Ap SET TransmitPower %lu\n", TransmitPower);
14159 return 0;
14160 }
14161 if(strstr(argv[1], "wifi_setApManagementFramePowerControl")!=NULL)
14162 {
14163 INT TransmitPower = atoi(argv[3]);
14164
14165 wifi_setApManagementFramePowerControl(index, TransmitPower);
14166 printf("Ap SET Mgnt TransmitPower %d\n", TransmitPower);
14167 return 0;
14168 }
14169 if(strstr(argv[1], "wifi_setRadioBW")!=NULL)
14170 {
14171 CHAR *bandwith = argv[3];
14172
14173 wifi_setRadioOperatingChannelBandwidth(index, bandwith);
14174 printf("Ap SET bw %s\n", bandwith);
14175 return 0;
14176 }
14177 if(strstr(argv[1], "wifi_factoryResetRadio")!=NULL)
14178 {
14179 wifi_factoryResetRadio(index);
14180 printf("wifi_factoryResetRadio ok!\n");
14181 return 0;
14182 }
14183 if(strstr(argv[1], "wifi_getRadioResetCount")!=NULL)
14184 {
14185 ULONG rst_cnt;
14186 wifi_getRadioResetCount(index, &rst_cnt);
14187 printf("wifi_factoryResetRadio rst_cnt = %lu\n", rst_cnt);
14188 return 0;
14189 }
developer2edaf012023-05-24 14:24:53 +080014190 if (strncmp(argv[1], "wifi_addApAclDevice", strlen(argv[1])) == 0) {
developer49b17232023-05-19 16:35:19 +080014191 if(argc <= 3 )
14192 {
developer2edaf012023-05-24 14:24:53 +080014193 wifi_debug(DEBUG_ERROR, "Insufficient arguments \n");
developer49b17232023-05-19 16:35:19 +080014194 exit(-1);
14195 }
14196 wifi_addApAclDevice(index, argv[3]);
14197 return 0;
14198 }
developer2edaf012023-05-24 14:24:53 +080014199 if (strncmp(argv[1], "wifi_getApAclDevices", strlen(argv[1])) == 0) {
14200 wifi_getApAclDevices(index, buf, 1024);
14201 wifi_debug(DEBUG_NOTICE, "Ap acl Devices: %s\n", buf);
developer121a8e72023-05-22 09:19:39 +080014202 return 0;
14203 }
developer2edaf012023-05-24 14:24:53 +080014204 if (strncmp(argv[1], "wifi_delApAclDevice", strlen(argv[1])) == 0) {
14205 if(argc <= 3 )
14206 {
14207 wifi_debug(DEBUG_ERROR, "Insufficient arguments \n");
14208 exit(-1);
14209 }
14210 wifi_delApAclDevice(index, argv[3]);
14211 return 0;
14212 }
14213 if (strncmp(argv[1], "wifi_delApAclDevices", strlen(argv[1])) == 0) {
14214 wifi_delApAclDevices(index);
14215 return 0;
14216 }
14217 if (strncmp(argv[1], "wifi_getApAclDeviceNum", strlen(argv[1])) == 0) {
14218 int acl_num = 0;
14219 wifi_getApAclDeviceNum(index, &acl_num);
14220 wifi_debug(DEBUG_NOTICE, "Ap acl numbers: %d\n", acl_num);
14221 return 0;
14222 }
14223 if (strncmp(argv[1], "wifi_getApDenyAclDevices", strlen(argv[1])) == 0) {
14224 wifi_getApDenyAclDevices(index, buf, 1024);
14225 wifi_debug(DEBUG_NOTICE, "Ap Deny Acl Devices: %s\n", buf);
14226 return 0;
14227 }
14228 if (strncmp(argv[1], "wifi_setApMacAddressControlMode", strlen(argv[1])) == 0) {
14229 int filter_mode = 0;
14230 if(argc <= 3 )
14231 {
14232 wifi_debug(DEBUG_ERROR, "Insufficient arguments \n");
14233 exit(-1);
14234 }
14235 filter_mode = atoi(argv[3]);
14236 wifi_setApMacAddressControlMode(index,filter_mode);
14237 return 0;
14238 }
developer5cd4c862023-05-26 09:34:42 +080014239 if (strncmp(argv[1], "wifi_getRadioDeclineBARequestEnable", strlen(argv[1])) == 0) {
14240 BOOL output_bool = 0;
14241 wifi_getRadioDeclineBARequestEnable(index, &output_bool);
14242 wifi_debug(DEBUG_NOTICE, "Ap get radio ba decline enable: %d\n", output_bool);
14243 return 0;
14244 }
14245 if (strncmp(argv[1], "wifi_getRadioAutoBlockAckEnable", strlen(argv[1])) == 0) {
14246 BOOL output_bool = 0;
14247 wifi_getRadioAutoBlockAckEnable(index, &output_bool);
14248 wifi_debug(DEBUG_NOTICE, "Ap get radio auto_ba enable: %d\n", output_bool);
14249 return 0;
14250 }
14251
14252 if (strncmp(argv[1], "wifi_getApMacAddressControlMode", strlen(argv[1])) == 0) {
14253 int filter_mode = 0;
14254 wifi_getApMacAddressControlMode(index, &filter_mode);
14255 wifi_debug(DEBUG_NOTICE, "Ap MacAddress Control Mode: %d\n", filter_mode);
14256 return 0;
14257 }
14258 if (strncmp(argv[1], "wifi_setRadioIGMPSnoopingEnable", strlen(argv[1])) == 0) {
14259 int enable = 0;
14260 if(argc <= 3 )
14261 {
14262 wifi_debug(DEBUG_ERROR, "Insufficient arguments \n");
14263 exit(-1);
14264 }
14265 enable = (BOOL)atoi(argv[3]);
14266 wifi_setRadioIGMPSnoopingEnable(index, enable);
14267 wifi_debug(DEBUG_NOTICE, "Ap set IGMP Snooping Enable: %d\n", enable);
14268 return 0;
14269 }
14270
14271 if (strncmp(argv[1], "wifi_getRadioIGMPSnoopingEnable", strlen(argv[1])) == 0) {
14272 BOOL out_status = 0;
14273 wifi_getRadioIGMPSnoopingEnable(index, &out_status);
14274 wifi_debug(DEBUG_NOTICE, "Ap get IGMP Snooping Enable: %d\n", out_status);
14275 return 0;
14276 }
developer121a8e72023-05-22 09:19:39 +080014277
developer95c045d2023-05-24 19:26:28 +080014278 if (strncmp(argv[1], "wifi_setApWmmEnable", strlen(argv[1])) == 0) {
14279 int enable = 0;
14280 if(argc <= 3)
14281 {
14282 wifi_debug(DEBUG_ERROR, "Insufficient arguments \n");
14283 exit(-1);
14284 }
14285 enable = atoi(argv[3]);
14286 wifi_setApWmmEnable(index,enable);
14287 return 0;
14288 }
developer56fbedb2023-05-30 16:47:05 +080014289 if (strncmp(argv[1], "wifi_down", strlen(argv[1])) == 0) {
14290 wifi_down();
14291 return 0;
14292 }
developer95c045d2023-05-24 19:26:28 +080014293
developer56fbedb2023-05-30 16:47:05 +080014294 if (strncmp(argv[1], "wifi_getRadioStatus", strlen(argv[1])) == 0) {
14295 BOOL enable = 0;
14296
14297 wifi_getRadioStatus(index, &enable);
14298 wifi_debug(DEBUG_NOTICE, "wifi_getRadioStatus enable: %d\n", (int)enable);
14299 return 0;
14300 }
developer333c1eb2023-05-31 14:59:39 +080014301
developer95c045d2023-05-24 19:26:28 +080014302 if (strncmp(argv[1], "wifi_getApWMMCapability", strlen(argv[1])) == 0) {
14303 BOOL enable = 0;
14304
14305 wifi_getApWMMCapability(index, &enable);
14306 wifi_debug(DEBUG_NOTICE, "wifi_getApWMMCapability enable: %d\n", (int)enable);
14307 return 0;
14308 }
14309
14310 if (strncmp(argv[1], "wifi_getApWmmEnable", strlen(argv[1])) == 0) {
14311 BOOL enable = 0;
14312
14313 wifi_getApWmmEnable(index, &enable);
14314 wifi_debug(DEBUG_NOTICE, "wifi_getApWmmEnable enable: %d\n", (int)enable);
14315 return 0;
14316 }
14317
developer2edaf012023-05-24 14:24:53 +080014318 if (strncmp(argv[1], "wifi_getApMacAddressControlMode", strlen(argv[1])) == 0) {
14319 int filter_mode = 0;
14320 wifi_getApMacAddressControlMode(index, &filter_mode);
14321 wifi_debug(DEBUG_NOTICE, "Ap MacAddress Control Mode: %d\n", filter_mode);
14322 return 0;
14323 }
developer0f10c772023-05-16 21:43:39 +080014324 if(strstr(argv[1], "wifi_getRadioMode")!=NULL)
14325 {
14326 int mode = 0;
14327
14328 wifi_getRadioMode(index, buf, &mode);
14329 printf("Ap Radio mode is %s , mode = 0x%x\n", buf, mode);
14330 return 0;
14331 }
developer72fb0bb2023-01-11 09:46:29 +080014332 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
14333 {
14334 BOOL b = FALSE;
14335 BOOL *output_bool = &b;
14336 wifi_getRadioAutoChannelEnable(index,output_bool);
14337 printf("Channel enabled = %d \n",b);
14338 return 0;
14339 }
14340 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
14341 {
14342 wifi_getApWpaEncryptionMode(index,buf);
14343 printf("encryption enabled = %s\n",buf);
14344 return 0;
14345 }
14346 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
14347 {
14348 BOOL b = FALSE;
14349 BOOL *output_bool = &b;
14350 wifi_getApSsidAdvertisementEnable(index,output_bool);
14351 printf("advertisment enabled = %d\n",b);
14352 return 0;
14353 }
14354 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
14355 {
14356 if(argc <= 3 )
14357 {
14358 printf("Insufficient arguments \n");
14359 exit(-1);
14360 }
14361
14362 char sta[20] = {'\0'};
14363 ULLONG handle= 0;
14364 strcpy(sta,argv[3]);
14365 mac_address_t st;
14366 mac_addr_aton(st,sta);
14367
14368 wifi_associated_dev_tid_stats_t tid_stats;
14369 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
14370 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
14371 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);
14372 }
14373
14374 if(strstr(argv[1], "getApEnable")!=NULL) {
14375 BOOL enable;
14376 ret=wifi_getApEnable(index, &enable);
14377 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
14378 }
14379 else if(strstr(argv[1], "setApEnable")!=NULL) {
14380 BOOL enable = atoi(argv[3]);
14381 ret=wifi_setApEnable(index, enable);
14382 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
14383 }
14384 else if(strstr(argv[1], "getApStatus")!=NULL) {
developer69b61b02023-03-07 17:17:44 +080014385 char status[64];
developer72fb0bb2023-01-11 09:46:29 +080014386 ret=wifi_getApStatus(index, status);
14387 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
14388 }
14389 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
14390 {
14391 wifi_getSSIDNameStatus(index,buf);
14392 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
14393 return 0;
developer2202b332023-05-24 16:23:22 +080014394 } else if(strstr(argv[1], "wifi_resetApVlanCfg")!=NULL) {
14395 wifi_resetApVlanCfg(index);
14396 printf("%s %d: wifi_resetApVlanCfg : %s\n",argv[1], index,buf);
14397 return 0;
developer72fb0bb2023-01-11 09:46:29 +080014398 }
14399 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
14400 wifi_ssidTrafficStats2_t stats={0};
14401 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
14402 printf("%s %d: returns %d\n", argv[1], index, ret);
14403 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
14404 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
14405 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
14406 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
14407 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
14408 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
14409 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
14410 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
14411 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
14412 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
14413 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
14414 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
14415 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
14416 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
14417 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
14418 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
14419 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
14420 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
14421 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
14422 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
14423 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
14424 }
14425 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
14426 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
14427 UINT array_size=0;
14428 UINT i=0;
14429 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
14430 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
developer69b61b02023-03-07 17:17:44 +080014431 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
developer72fb0bb2023-01-11 09:46:29 +080014432 printf(" neighbor %d:\n", i);
14433 printf(" ap_SSID =%s\n", pt->ap_SSID);
14434 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
14435 printf(" ap_Mode =%s\n", pt->ap_Mode);
14436 printf(" ap_Channel =%d\n", pt->ap_Channel);
14437 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
14438 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
14439 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
14440 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
14441 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
14442 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
14443 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
14444 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
14445 printf(" ap_Noise =%d\n", pt->ap_Noise);
14446 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
14447 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
14448 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
developer69b61b02023-03-07 17:17:44 +080014449 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
developer72fb0bb2023-01-11 09:46:29 +080014450 }
14451 if(neighbor_ap_array)
14452 free(neighbor_ap_array); //make sure to free the list
14453 }
14454 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
14455 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
14456 UINT array_size=0;
14457 UINT i=0;
14458 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
14459 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
developer69b61b02023-03-07 17:17:44 +080014460 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
developer72fb0bb2023-01-11 09:46:29 +080014461 printf(" associated_dev %d:\n", i);
14462 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
14463 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
14464 printf(" cli_SNR =%d\n", pt->cli_SNR);
14465 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
14466 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
14467 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
14468 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
14469 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
14470 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
14471 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
14472 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
14473 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
14474 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
14475 }
14476 if(associated_dev_array)
14477 free(associated_dev_array); //make sure to free the list
14478 }
14479
14480 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
14481 {
14482#define MAX_ARRAY_SIZE 64
14483 int i, array_size;
14484 char *p, *ch_str;
14485 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
14486
14487 if(argc != 5)
14488 {
14489 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
14490 exit(-1);
14491 }
14492 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
14493
14494 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
14495 {
14496 strtok_r(ch_str, ",", &p);
14497 input_output_channelStats_array[i].ch_number = atoi(ch_str);
14498 }
14499 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
14500 if(!array_size)
14501 array_size=1;//Need to print current channel statistics
14502 for(i=0; i<array_size; i++)
14503 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
14504 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
14505 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
14506 input_output_channelStats_array[i].ch_number,\
14507 input_output_channelStats_array[i].ch_noise,\
14508 input_output_channelStats_array[i].ch_utilization_busy_rx,\
14509 input_output_channelStats_array[i].ch_utilization_busy_tx,\
14510 input_output_channelStats_array[i].ch_utilization_busy,\
14511 input_output_channelStats_array[i].ch_utilization_busy_ext,\
14512 input_output_channelStats_array[i].ch_utilization_total);
14513 }
14514
14515 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
14516 {
14517 if(argc <= 3 )
14518 {
14519 printf("Insufficient arguments \n");
14520 exit(-1);
14521 }
14522 char mac_addr[20] = {'\0'};
14523 wifi_device_t output_struct;
14524 int dev_index = atoi(argv[3]);
14525
14526 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
14527 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
14528 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);
14529 }
14530
14531 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
14532 {
14533 if (argc <= 3)
14534 {
14535 printf("Insufficient arguments\n");
14536 exit(-1);
14537 }
14538 char args[256];
14539 wifi_NeighborReport_t *neighborReports;
14540
14541 neighborReports = calloc(argc - 2, sizeof(neighborReports));
14542 if (!neighborReports)
14543 {
14544 printf("Failed to allocate memory");
14545 exit(-1);
14546 }
14547
14548 for (int i = 3; i < argc; ++i)
14549 {
14550 char *val;
14551 int j = 0;
14552 memset(args, 0, sizeof(args));
14553 strncpy(args, argv[i], sizeof(args));
14554 val = strtok(args, ";");
14555 while (val != NULL)
14556 {
14557 if (j == 0)
14558 {
14559 mac_addr_aton(neighborReports[i - 3].bssid, val);
14560 } else if (j == 1)
14561 {
14562 neighborReports[i - 3].info = strtol(val, NULL, 16);
14563 } else if (j == 2)
14564 {
14565 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
14566 } else if (j == 3)
14567 {
14568 neighborReports[i - 3].channel = strtol(val, NULL, 16);
14569 } else if (j == 4)
14570 {
14571 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
14572 } else {
14573 printf("Insufficient arguments]n\n");
14574 exit(-1);
14575 }
14576 val = strtok(NULL, ";");
14577 j++;
14578 }
14579 }
14580
14581 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
14582 if (ret != RETURN_OK)
14583 {
14584 printf("wifi_setNeighborReports ret = %d", ret);
14585 exit(-1);
14586 }
14587 }
14588 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
14589 {
14590 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
14591 printf("%s.\n", buf);
14592 else
14593 printf("Error returned\n");
14594 }
14595 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
14596 {
14597 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
14598 printf("%s.\n", buf);
14599 else
14600 printf("Error returned\n");
14601 }
14602 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
14603 {
14604 if (argc <= 2)
14605 {
14606 printf("Insufficient arguments\n");
14607 exit(-1);
14608 }
14609 char buf[64]= {'\0'};
14610 wifi_getRadioOperatingChannelBandwidth(index,buf);
14611 printf("Current bandwidth is %s \n",buf);
14612 return 0;
14613 }
14614 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
14615 {
14616 if (argc <= 5)
14617 {
14618 printf("Insufficient arguments\n");
14619 exit(-1);
14620 }
14621 UINT channel = atoi(argv[3]);
14622 UINT width = atoi(argv[4]);
14623 UINT beacon = atoi(argv[5]);
14624 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
14625 printf("Result = %d", ret);
14626 }
14627
14628 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
14629 return 0;
14630}
14631
14632#endif
14633
14634#ifdef WIFI_HAL_VERSION_3
14635
14636INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
14637{
14638 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
14639 if (bitMap & WIFI_BITRATE_1MBPS)
14640 strcat(BasicRate, "1,");
14641 if (bitMap & WIFI_BITRATE_2MBPS)
14642 strcat(BasicRate, "2,");
14643 if (bitMap & WIFI_BITRATE_5_5MBPS)
14644 strcat(BasicRate, "5.5,");
14645 if (bitMap & WIFI_BITRATE_6MBPS)
14646 strcat(BasicRate, "6,");
14647 if (bitMap & WIFI_BITRATE_9MBPS)
14648 strcat(BasicRate, "9,");
14649 if (bitMap & WIFI_BITRATE_11MBPS)
14650 strcat(BasicRate, "11,");
14651 if (bitMap & WIFI_BITRATE_12MBPS)
14652 strcat(BasicRate, "12,");
14653 if (bitMap & WIFI_BITRATE_18MBPS)
14654 strcat(BasicRate, "18,");
14655 if (bitMap & WIFI_BITRATE_24MBPS)
14656 strcat(BasicRate, "24,");
14657 if (bitMap & WIFI_BITRATE_36MBPS)
14658 strcat(BasicRate, "36,");
14659 if (bitMap & WIFI_BITRATE_48MBPS)
14660 strcat(BasicRate, "48,");
14661 if (bitMap & WIFI_BITRATE_54MBPS)
14662 strcat(BasicRate, "54,");
14663 if (strlen(BasicRate) != 0) // remove last comma
14664 BasicRate[strlen(BasicRate) - 1] = '\0';
14665 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
14666 return RETURN_OK;
14667}
14668
14669INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
14670{
14671 UINT BitMap = 0;
14672 char *rate;
14673
14674 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
14675 rate = strtok(BasicRatesList, ",");
14676 while(rate != NULL)
14677 {
14678 if (strcmp(rate, "1") == 0)
14679 BitMap |= WIFI_BITRATE_1MBPS;
14680 else if (strcmp(rate, "2") == 0)
14681 BitMap |= WIFI_BITRATE_2MBPS;
14682 else if (strcmp(rate, "5.5") == 0)
14683 BitMap |= WIFI_BITRATE_5_5MBPS;
14684 else if (strcmp(rate, "6") == 0)
14685 BitMap |= WIFI_BITRATE_6MBPS;
14686 else if (strcmp(rate, "9") == 0)
14687 BitMap |= WIFI_BITRATE_9MBPS;
14688 else if (strcmp(rate, "11") == 0)
14689 BitMap |= WIFI_BITRATE_11MBPS;
14690 else if (strcmp(rate, "12") == 0)
14691 BitMap |= WIFI_BITRATE_12MBPS;
14692 else if (strcmp(rate, "18") == 0)
14693 BitMap |= WIFI_BITRATE_18MBPS;
14694 else if (strcmp(rate, "24") == 0)
14695 BitMap |= WIFI_BITRATE_24MBPS;
14696 else if (strcmp(rate, "36") == 0)
14697 BitMap |= WIFI_BITRATE_36MBPS;
14698 else if (strcmp(rate, "48") == 0)
14699 BitMap |= WIFI_BITRATE_48MBPS;
14700 else if (strcmp(rate, "54") == 0)
14701 BitMap |= WIFI_BITRATE_54MBPS;
14702 rate = strtok(NULL, ",");
14703 }
14704 *basicRateBitMap = BitMap;
14705 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
14706 return RETURN_OK;
14707}
14708
14709// This API is used to configured all radio operation parameter in a single set. it includes channel number, channelWidth, mode and auto chammel configuration.
14710INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
14711{
14712 char buf[128] = {0};
14713 char cmd[128] = {0};
14714 char config_file[64] = {0};
14715 int bandwidth;
14716 int set_mode = 0;
developer56fbedb2023-05-30 16:47:05 +080014717 BOOL drv_dat_change = 0, hapd_conf_change = 0;
developer72fb0bb2023-01-11 09:46:29 +080014718 wifi_radio_operationParam_t current_param;
14719
14720 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
14721
14722 multiple_set = TRUE;
14723 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
14724 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
14725 return RETURN_ERR;
14726 }
14727 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
14728 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
14729 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
14730 return RETURN_ERR;
14731 }
developer333c1eb2023-05-31 14:59:39 +080014732 drv_dat_change = TRUE;
developer72fb0bb2023-01-11 09:46:29 +080014733 }
developer333c1eb2023-05-31 14:59:39 +080014734 if (current_param.channelWidth != operationParam->channelWidth ||
14735 current_param.channel != operationParam->channel ||
14736 current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
14737 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
14738 bandwidth = 20;
14739 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
14740 bandwidth = 40;
14741 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
14742 bandwidth = 80;
14743 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
14744 bandwidth = 160;
developer72fb0bb2023-01-11 09:46:29 +080014745
developer333c1eb2023-05-31 14:59:39 +080014746 if (operationParam->autoChannelEnabled) {
14747 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
14748 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
14749 return RETURN_ERR;
14750 }
14751 } else {
14752 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
14753 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
14754 return RETURN_ERR;
14755 }
developer72fb0bb2023-01-11 09:46:29 +080014756 }
developer333c1eb2023-05-31 14:59:39 +080014757 drv_dat_change = TRUE;
developer72fb0bb2023-01-11 09:46:29 +080014758 }
developer72fb0bb2023-01-11 09:46:29 +080014759 if (current_param.variant != operationParam->variant) {
14760 // Two different definition bit map, so need to check every bit.
14761 if (operationParam->variant & WIFI_80211_VARIANT_A)
14762 set_mode |= WIFI_MODE_A;
14763 if (operationParam->variant & WIFI_80211_VARIANT_B)
14764 set_mode |= WIFI_MODE_B;
14765 if (operationParam->variant & WIFI_80211_VARIANT_G)
14766 set_mode |= WIFI_MODE_G;
14767 if (operationParam->variant & WIFI_80211_VARIANT_N)
14768 set_mode |= WIFI_MODE_N;
14769 if (operationParam->variant & WIFI_80211_VARIANT_AC)
14770 set_mode |= WIFI_MODE_AC;
14771 if (operationParam->variant & WIFI_80211_VARIANT_AX)
14772 set_mode |= WIFI_MODE_AX;
14773 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
14774 memset(buf, 0, sizeof(buf));
developer56fbedb2023-05-30 16:47:05 +080014775 drv_dat_change = TRUE;
developer0f10c772023-05-16 21:43:39 +080014776 if (wifi_setRadioMode_by_dat(index, set_mode) != RETURN_OK) {
developer72fb0bb2023-01-11 09:46:29 +080014777 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
14778 return RETURN_ERR;
14779 }
14780 }
14781 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
developer56fbedb2023-05-30 16:47:05 +080014782 hapd_conf_change = TRUE;
developer72fb0bb2023-01-11 09:46:29 +080014783 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
14784 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
14785 return RETURN_ERR;
14786 }
14787 }
14788 if (current_param.beaconInterval != operationParam->beaconInterval) {
developer56fbedb2023-05-30 16:47:05 +080014789 hapd_conf_change = TRUE;
developer72fb0bb2023-01-11 09:46:29 +080014790 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
14791 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
14792 return RETURN_ERR;
14793 }
14794 }
14795 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
developer56fbedb2023-05-30 16:47:05 +080014796 hapd_conf_change = TRUE;
developer72fb0bb2023-01-11 09:46:29 +080014797 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
14798 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
14799 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
14800 return RETURN_ERR;
14801 }
14802 }
14803 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
developer56fbedb2023-05-30 16:47:05 +080014804 hapd_conf_change = TRUE;
developer72fb0bb2023-01-11 09:46:29 +080014805 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
14806 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
14807 return RETURN_ERR;
14808 }
14809 }
14810 if (current_param.guardInterval != operationParam->guardInterval) {
developer56fbedb2023-05-30 16:47:05 +080014811 hapd_conf_change = TRUE;
14812 drv_dat_change = TRUE;
14813 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
developer72fb0bb2023-01-11 09:46:29 +080014814 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
14815 return RETURN_ERR;
14816 }
14817 }
14818 if (current_param.transmitPower != operationParam->transmitPower) {
developer56fbedb2023-05-30 16:47:05 +080014819 drv_dat_change = TRUE;
developer72fb0bb2023-01-11 09:46:29 +080014820 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
14821 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
14822 return RETURN_ERR;
14823 }
14824 }
14825 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
developer56fbedb2023-05-30 16:47:05 +080014826 hapd_conf_change = TRUE;
developer72fb0bb2023-01-11 09:46:29 +080014827 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
14828 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
14829 return RETURN_ERR;
14830 }
14831 }
14832 if (current_param.obssCoex != operationParam->obssCoex) {
developer56fbedb2023-05-30 16:47:05 +080014833 hapd_conf_change = TRUE;
developer72fb0bb2023-01-11 09:46:29 +080014834 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
14835 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
14836 return RETURN_ERR;
14837 }
14838 }
14839 if (current_param.stbcEnable != operationParam->stbcEnable) {
developer56fbedb2023-05-30 16:47:05 +080014840 hapd_conf_change = TRUE;
14841 drv_dat_change = TRUE;
developer72fb0bb2023-01-11 09:46:29 +080014842 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
14843 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
14844 return RETURN_ERR;
14845 }
14846 }
14847 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
14848 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
14849 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
14850 return RETURN_ERR;
14851 }
14852 }
14853
developer56fbedb2023-05-30 16:47:05 +080014854 /* only down/up interface when dat file has been changed,
14855 * if enable is true, then restart the radio.
14856 */
14857 if (drv_dat_change == TRUE) {
14858 wifi_setRadioEnable(index, FALSE);
14859 if (operationParam->enable == TRUE)
14860 wifi_setRadioEnable(index, TRUE);
14861 } else if (hapd_conf_change == TRUE) {
14862 hostapd_raw_remove_bss(index);
14863 if (operationParam->enable == TRUE)
14864 hostapd_raw_add_bss(index);
14865 }
14866
developer72fb0bb2023-01-11 09:46:29 +080014867 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
14868
14869 return RETURN_OK;
14870}
14871
14872INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
14873{
14874 char band[64] = {0};
14875 char buf[256] = {0};
14876 char config_file[64] = {0};
14877 char cmd[128] = {0};
14878 int ret = RETURN_ERR;
14879 int mode = 0;
14880 ULONG channel = 0;
14881 BOOL enabled = FALSE;
14882
14883 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
14884 printf("Entering %s index = %d\n", __func__, (int)index);
14885
14886 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
14887 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
14888 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
14889 {
14890 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
14891 return RETURN_ERR;
14892 }
14893 operationParam->enable = enabled;
14894
14895 memset(band, 0, sizeof(band));
14896 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
14897 {
14898 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
14899 return RETURN_ERR;
14900 }
14901
14902 if (!strcmp(band, "2.4GHz"))
14903 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
14904 else if (!strcmp(band, "5GHz"))
14905 operationParam->band = WIFI_FREQUENCY_5_BAND;
14906 else if (!strcmp(band, "6GHz"))
14907 operationParam->band = WIFI_FREQUENCY_6_BAND;
14908 else
14909 {
14910 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
14911 band);
14912 }
14913
14914 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
14915 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
14916 operationParam->channel = 0;
14917 operationParam->autoChannelEnabled = TRUE;
14918 } else {
14919 operationParam->channel = strtol(buf, NULL, 10);
14920 operationParam->autoChannelEnabled = FALSE;
14921 }
14922
14923 memset(buf, 0, sizeof(buf));
14924 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
14925 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
14926 return RETURN_ERR;
14927 }
14928 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
14929 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
14930 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
14931 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
14932 else
14933 {
14934 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
14935 return false;
14936 }
14937
14938 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
14939 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
14940 return RETURN_ERR;
14941 }
14942 // Two different definition bit map, so need to check every bit.
14943 if (mode & WIFI_MODE_A)
14944 operationParam->variant |= WIFI_80211_VARIANT_A;
14945 if (mode & WIFI_MODE_B)
14946 operationParam->variant |= WIFI_80211_VARIANT_B;
14947 if (mode & WIFI_MODE_G)
14948 operationParam->variant |= WIFI_80211_VARIANT_G;
14949 if (mode & WIFI_MODE_N)
14950 operationParam->variant |= WIFI_80211_VARIANT_N;
14951 if (mode & WIFI_MODE_AC)
14952 operationParam->variant |= WIFI_80211_VARIANT_AC;
14953 if (mode & WIFI_MODE_AX)
14954 operationParam->variant |= WIFI_80211_VARIANT_AX;
14955 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
14956 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
14957 return RETURN_ERR;
14958 }
14959 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
14960 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
14961 return RETURN_ERR;
14962 }
14963 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
14964 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
14965 return RETURN_ERR;
14966 }
14967
14968 memset(buf, 0, sizeof(buf));
14969 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
14970 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
14971 return RETURN_ERR;
14972 }
14973 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
14974
14975 memset(buf, 0, sizeof(buf));
14976 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
14977 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
14978 return RETURN_ERR;
14979 }
14980 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
14981
14982 memset(buf, 0, sizeof(buf));
14983 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
14984 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
14985
14986 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
14987 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
14988 return RETURN_ERR;
14989 }
developera1255e42023-05-13 17:45:02 +080014990 if (wifi_getRadioPercentageTransmitPower(index, (ULONG *)&operationParam->transmitPower) != RETURN_OK) {
developer72fb0bb2023-01-11 09:46:29 +080014991 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
14992 return RETURN_ERR;
14993 }
14994
14995 memset(buf, 0, sizeof(buf));
14996 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
14997 if (strcmp(buf, "-1") == 0) {
14998 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
14999 operationParam->ctsProtection = FALSE;
15000 } else {
15001 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
15002 operationParam->ctsProtection = TRUE;
15003 }
15004
15005 memset(buf, 0, sizeof(buf));
15006 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
15007 if (strcmp(buf, "0") == 0)
15008 operationParam->obssCoex = FALSE;
15009 else
15010 operationParam->obssCoex = TRUE;
15011
15012 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
15013 _syscmd(cmd, buf, sizeof(buf));
15014 if (strlen(buf) != 0)
15015 operationParam->stbcEnable = TRUE;
15016 else
15017 operationParam->stbcEnable = FALSE;
15018
15019 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
15020 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
15021 return RETURN_ERR;
15022 }
15023
15024 // Below value is hardcoded
15025
15026 operationParam->numSecondaryChannels = 0;
15027 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
15028 operationParam->channelSecondary[i] = 0;
15029 }
15030 operationParam->csa_beacon_count = 15;
15031 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
15032
15033 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
15034 return RETURN_OK;
15035}
15036
15037static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
15038{
15039 int max_radio_num = 0;
15040
15041 wifi_getMaxRadioNumber(&max_radio_num);
15042 if (radioIndex >= max_radio_num) {
15043 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
15044 return RETURN_ERR;
15045 }
15046
15047 return (arrayIndex * max_radio_num) + radioIndex;
15048}
15049
developer96b38512023-02-22 11:17:45 +080015050static int vap_index_to_array_index(int vapIndex, int *radioIndex, int *arrayIndex)
15051{
15052 int max_radio_num = 0;
15053
15054 if ((vapIndex < 0) || (vapIndex > MAX_NUM_VAP_PER_RADIO*MAX_NUM_RADIOS))
15055 return -1;
15056
15057 wifi_getMaxRadioNumber(&max_radio_num);
15058
15059 (*radioIndex) = vapIndex % max_radio_num;
15060 (*arrayIndex) = vapIndex / max_radio_num;
15061
15062 return 0;
15063}
15064
15065
developer72fb0bb2023-01-11 09:46:29 +080015066wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
15067 if (strncmp(beaconRate, "1Mbps", 5) == 0)
15068 return WIFI_BITRATE_1MBPS;
15069 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
15070 return WIFI_BITRATE_2MBPS;
15071 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
15072 return WIFI_BITRATE_5_5MBPS;
15073 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
15074 return WIFI_BITRATE_6MBPS;
15075 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
15076 return WIFI_BITRATE_9MBPS;
15077 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
15078 return WIFI_BITRATE_11MBPS;
15079 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
15080 return WIFI_BITRATE_12MBPS;
15081 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
15082 return WIFI_BITRATE_18MBPS;
15083 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
15084 return WIFI_BITRATE_24MBPS;
15085 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
15086 return WIFI_BITRATE_36MBPS;
15087 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
15088 return WIFI_BITRATE_48MBPS;
15089 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
15090 return WIFI_BITRATE_54MBPS;
15091 return WIFI_BITRATE_DEFAULT;
15092}
15093
15094INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
15095{
15096 if (beacon == WIFI_BITRATE_1MBPS)
15097 strcpy(beacon_str, "1Mbps");
15098 else if (beacon == WIFI_BITRATE_2MBPS)
15099 strcpy(beacon_str, "2Mbps");
15100 else if (beacon == WIFI_BITRATE_5_5MBPS)
15101 strcpy(beacon_str, "5.5Mbps");
15102 else if (beacon == WIFI_BITRATE_6MBPS)
15103 strcpy(beacon_str, "6Mbps");
15104 else if (beacon == WIFI_BITRATE_9MBPS)
15105 strcpy(beacon_str, "9Mbps");
15106 else if (beacon == WIFI_BITRATE_11MBPS)
15107 strcpy(beacon_str, "11Mbps");
15108 else if (beacon == WIFI_BITRATE_12MBPS)
15109 strcpy(beacon_str, "12Mbps");
15110 else if (beacon == WIFI_BITRATE_18MBPS)
15111 strcpy(beacon_str, "18Mbps");
15112 else if (beacon == WIFI_BITRATE_24MBPS)
15113 strcpy(beacon_str, "24Mbps");
15114 else if (beacon == WIFI_BITRATE_36MBPS)
15115 strcpy(beacon_str, "36Mbps");
15116 else if (beacon == WIFI_BITRATE_48MBPS)
15117 strcpy(beacon_str, "48Mbps");
15118 else if (beacon == WIFI_BITRATE_54MBPS)
15119 strcpy(beacon_str, "54Mbps");
15120 return RETURN_OK;
15121}
15122
15123INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
15124{
15125 INT mode = 0;
15126 INT ret = -1;
15127 INT output = 0;
15128 int i = 0;
15129 int vap_index = 0;
15130 BOOL enabled = FALSE;
15131 char buf[256] = {0};
15132 wifi_vap_security_t security = {0};
developer72fb0bb2023-01-11 09:46:29 +080015133
15134 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
15135 printf("Entering %s index = %d\n", __func__, (int)index);
15136
developerfde01262023-05-22 15:15:24 +080015137 ret = wifi_BandProfileRead(0, index, "BssidNum", buf, sizeof(buf), "0");
15138 if (ret != 0) {
15139 fprintf(stderr, "%s: wifi_BandProfileRead BssidNum failed\n", __func__);
15140 return RETURN_ERR;
15141 }
15142
15143 map->num_vaps = atoi(buf);
15144 if (map->num_vaps <= 0) {
15145 fprintf(stderr, "%s: invalid BssidNum %s\n", __func__, buf);
15146 return RETURN_ERR;
15147 }
15148
15149 for (i = 0; i < map->num_vaps; i++)
developer72fb0bb2023-01-11 09:46:29 +080015150 {
15151 map->vap_array[i].radio_index = index;
15152
15153 vap_index = array_index_to_vap_index(index, i);
15154 if (vap_index < 0)
15155 return RETURN_ERR;
15156
15157 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
15158
15159 map->vap_array[i].vap_index = vap_index;
15160
15161 memset(buf, 0, sizeof(buf));
15162 ret = wifi_getApName(vap_index, buf);
15163 if (ret != RETURN_OK) {
15164 printf("%s: wifi_getApName return error\n", __func__);
15165 return RETURN_ERR;
15166 }
15167 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
15168
15169 memset(buf, 0, sizeof(buf));
15170 ret = wifi_getSSIDName(vap_index, buf);
15171 if (ret != RETURN_OK) {
15172 printf("%s: wifi_getSSIDName return error\n", __func__);
15173 return RETURN_ERR;
15174 }
15175 snprintf(map->vap_array[i].u.bss_info.ssid, sizeof(map->vap_array[i].u.bss_info.ssid), "%s", buf);
15176
developere740c2a2023-05-23 18:34:32 +080015177#if 0
developer72fb0bb2023-01-11 09:46:29 +080015178 ret = wifi_getSSIDEnable(vap_index, &enabled);
15179 if (ret != RETURN_OK) {
15180 printf("%s: wifi_getSSIDEnable return error\n", __func__);
15181 return RETURN_ERR;
15182 }
developere740c2a2023-05-23 18:34:32 +080015183#endif
15184 map->vap_array[i].u.bss_info.enabled = true;
developer72fb0bb2023-01-11 09:46:29 +080015185
15186 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
15187 if (ret != RETURN_OK) {
15188 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
15189 return RETURN_ERR;
15190 }
15191 map->vap_array[i].u.bss_info.showSsid = enabled;
developer69b61b02023-03-07 17:17:44 +080015192
developer72fb0bb2023-01-11 09:46:29 +080015193 ret = wifi_getApIsolationEnable(vap_index, &enabled);
15194 if (ret != RETURN_OK) {
15195 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
15196 return RETURN_ERR;
15197 }
15198 map->vap_array[i].u.bss_info.isolation = enabled;
15199
15200 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
15201 if (ret != RETURN_OK) {
15202 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
15203 return RETURN_ERR;
15204 }
15205 map->vap_array[i].u.bss_info.bssMaxSta = output;
15206
15207 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
15208 if (ret != RETURN_OK) {
15209 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
15210 return RETURN_ERR;
15211 }
15212 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
15213
15214 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
15215 if (ret != RETURN_OK) {
15216 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
15217 return RETURN_ERR;
15218 }
15219 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
15220
15221 ret = wifi_getApSecurity(vap_index, &security);
15222 if (ret != RETURN_OK) {
15223 printf("%s: wifi_getApSecurity return error\n", __func__);
15224 return RETURN_ERR;
15225 }
15226 map->vap_array[i].u.bss_info.security = security;
15227
15228 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
15229 if (ret != RETURN_OK) {
15230 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
15231 return RETURN_ERR;
15232 }
developer69b61b02023-03-07 17:17:44 +080015233 if (mode == 0)
developer72fb0bb2023-01-11 09:46:29 +080015234 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
developer69b61b02023-03-07 17:17:44 +080015235 else
developer72fb0bb2023-01-11 09:46:29 +080015236 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
developer69b61b02023-03-07 17:17:44 +080015237 if (mode == 1)
developer72fb0bb2023-01-11 09:46:29 +080015238 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
developer69b61b02023-03-07 17:17:44 +080015239 else if (mode == 2)
developer72fb0bb2023-01-11 09:46:29 +080015240 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
15241
15242 ret = wifi_getApWmmEnable(vap_index, &enabled);
15243 if (ret != RETURN_OK) {
15244 printf("%s: wifi_getApWmmEnable return error\n", __func__);
15245 return RETURN_ERR;
15246 }
15247 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
15248
15249 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
15250 if (ret != RETURN_OK) {
15251 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
15252 return RETURN_ERR;
15253 }
15254 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
15255
15256 memset(buf, 0, sizeof(buf));
15257 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
15258 if (ret != RETURN_OK) {
15259 printf("%s: wifi_getApBeaconRate return error\n", __func__);
15260 return RETURN_ERR;
15261 }
15262 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
15263
15264 memset(buf, 0, sizeof(buf));
15265 ret = wifi_getBaseBSSID(vap_index, buf);
15266 if (ret != RETURN_OK) {
15267 printf("%s: wifi_getBaseBSSID return error\n", __func__);
15268 return RETURN_ERR;
15269 }
developer5b2f10c2023-05-25 17:02:21 +080015270 if (hwaddr_aton2(buf, map->vap_array[i].u.bss_info.bssid) < 0) {
15271 printf("%s: hwaddr_aton2 fail\n", __func__);
15272 return RETURN_ERR;
15273 }
developer72fb0bb2023-01-11 09:46:29 +080015274
15275 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
15276 if (ret != RETURN_OK) {
15277 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
15278 return RETURN_ERR;
15279 }
15280 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
15281
15282 // TODO: wps, noack
15283 }
15284 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
15285 return RETURN_OK;
15286}
15287
developer47cc27a2023-05-17 23:09:58 +080015288void checkVapStatus(int apIndex, BOOL *enable)
developer72fb0bb2023-01-11 09:46:29 +080015289{
15290 char if_name[16] = {0};
15291 char cmd[128] = {0};
15292 char buf[128] = {0};
15293
15294 *enable = FALSE;
15295 if (wifi_GetInterfaceName(apIndex, if_name) != RETURN_OK)
15296 return;
15297
15298 snprintf(cmd, sizeof(cmd), "cat %s | grep ^%s=1", VAP_STATUS_FILE, if_name);
15299 _syscmd(cmd, buf, sizeof(buf));
15300 if (strlen(buf) > 0)
15301 *enable = TRUE;
15302 return;
15303}
15304
15305static int prepareInterface(UINT apIndex, char *new_interface)
15306{
15307 char cur_interface[16] = {0};
15308 char config_file[128] = {0};
developer8a3bbbf2023-03-15 17:47:23 +080015309 char cmd[MAX_CMD_SIZE] = {0};
15310 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +080015311 int max_radio_num = 0;
15312 int radioIndex = -1;
15313 int phyIndex = -1;
developer8a3bbbf2023-03-15 17:47:23 +080015314 struct params params;
developer72fb0bb2023-01-11 09:46:29 +080015315
15316 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
15317 wifi_hostapdRead(config_file, "interface", cur_interface, sizeof(cur_interface));
15318
15319 if (strncmp(cur_interface, new_interface, sizeof(cur_interface)) != 0) {
developer8a3bbbf2023-03-15 17:47:23 +080015320 wifi_getMaxRadioNumber(&max_radio_num);
developer72fb0bb2023-01-11 09:46:29 +080015321 radioIndex = apIndex % max_radio_num;
15322 phyIndex = radio_index_to_phy(radioIndex);
15323 // disable and del old interface, then add new interface
15324 wifi_setApEnable(apIndex, FALSE);
developer8a3bbbf2023-03-15 17:47:23 +080015325
15326 params.name = "interface";
15327 params.value = new_interface;
15328 wifi_hostapdWrite(config_file, &params, 1);
15329
15330 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyIndex, config_file);
15331 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +080015332 }
developer8a3bbbf2023-03-15 17:47:23 +080015333
developer72fb0bb2023-01-11 09:46:29 +080015334 // update the vap status file
15335 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=1' %s", cur_interface, new_interface, VAP_STATUS_FILE);
15336 _syscmd(cmd, buf, sizeof(buf));
15337 return RETURN_OK;
15338}
15339
developer56fbedb2023-05-30 16:47:05 +080015340int hostapd_manage_bss(INT apIndex, BOOL enable)
15341{
15342 char interface_name[16] = {0};
15343 char config_file[MAX_BUF_SIZE] = {0};
15344 char cmd[MAX_CMD_SIZE] = {0};
15345 char buf[MAX_BUF_SIZE] = {0};
15346 BOOL status = FALSE;
15347 int max_radio_num = 0;
15348 int phyId = 0;
15349
15350 wifi_getApEnable(apIndex, &status);
15351
15352 wifi_getMaxRadioNumber(&max_radio_num);
15353 if (enable == status)
15354 return RETURN_OK;
15355
15356 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
15357 return RETURN_ERR;
15358
15359 if (enable == TRUE) {
15360 int radioIndex = apIndex % max_radio_num;
15361 phyId = radio_index_to_phy(radioIndex);
15362 fprintf(stderr, "%s %d\n", __func__, __LINE__);
15363 snprintf(config_file, MAX_BUF_SIZE, "%s%d.conf", CONFIG_PREFIX, apIndex);
15364 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyId, config_file);
15365 _syscmd(cmd, buf, sizeof(buf));
15366 } else {
15367 fprintf(stderr, "%s %d\n", __func__, __LINE__);
15368 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw REMOVE %s", interface_name);
15369 _syscmd(cmd, buf, sizeof(buf));
15370 }
15371 snprintf(cmd, MAX_CMD_SIZE, "sed -i -n -e '/^%s=/!p' -e '$a%s=%d' %s",
15372 interface_name, interface_name, enable, VAP_STATUS_FILE);
15373 _syscmd(cmd, buf, sizeof(buf));
15374 //Wait for wifi up/down to apply
15375 return RETURN_OK;
15376}
15377
15378int hostapd_raw_add_bss(int apIndex)
15379{
15380 return hostapd_manage_bss(apIndex, TRUE);
15381}
15382
15383int hostapd_raw_remove_bss(int apIndex)
15384{
15385 return hostapd_manage_bss(apIndex, FALSE);
15386}
15387
15388int hostapd_raw_restart_bss(int apIndex)
developer333c1eb2023-05-31 14:59:39 +080015389{
developer56fbedb2023-05-30 16:47:05 +080015390 hostapd_raw_remove_bss(apIndex);
15391 hostapd_raw_add_bss(apIndex);
15392}
15393
developer72fb0bb2023-01-11 09:46:29 +080015394INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
15395{
15396 char interface_name[16] = {0};
15397 unsigned int i;
15398 wifi_vap_info_t *vap_info = NULL;
15399 int acl_mode;
15400 int ret = 0;
15401 char *sec_str = NULL;
15402 char buf[256] = {0};
15403 char cmd[128] = {0};
15404 char config_file[64] = {0};
developer72fb0bb2023-01-11 09:46:29 +080015405 char psk_file[64] = {0};
developer47cc27a2023-05-17 23:09:58 +080015406 BOOL enable = FALSE;
developere740c2a2023-05-23 18:34:32 +080015407 int band_idx;
15408
developer72fb0bb2023-01-11 09:46:29 +080015409
15410 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
15411 printf("Entering %s index = %d\n", __func__, (int)index);
15412 for (i = 0; i < map->num_vaps; i++)
15413 {
15414 multiple_set = TRUE;
15415 vap_info = &map->vap_array[i];
15416
15417 // Check vap status file to enable multiple ap if the system boot.
15418 checkVapStatus(vap_info->vap_index, &enable);
15419 if (vap_info->u.bss_info.enabled == FALSE && enable == FALSE)
15420 continue;
15421
15422 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
15423
developere740c2a2023-05-23 18:34:32 +080015424 band_idx = radio_index_to_band(index);
15425 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
15426 snprintf(cmd, sizeof(cmd), "cp /etc/hostapd-%s.conf %s", wifi_band_str[band_idx], config_file);
15427 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +080015428
developer56fbedb2023-05-30 16:47:05 +080015429 struct params params[3];
developer72fb0bb2023-01-11 09:46:29 +080015430 params[0].name = "interface";
15431 params[0].value = vap_info->vap_name;
developer72fb0bb2023-01-11 09:46:29 +080015432 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", vap_info->vap_index);
developer56fbedb2023-05-30 16:47:05 +080015433 params[1].name = "wpa_psk_file";
15434 params[1].value = psk_file;
15435 params[2].name = "ssid";
15436 params[2].value = vap_info->u.bss_info.ssid;
developer72fb0bb2023-01-11 09:46:29 +080015437
15438 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
developer56fbedb2023-05-30 16:47:05 +080015439 wifi_hostapdWrite(config_file, params, 3);
developer72fb0bb2023-01-11 09:46:29 +080015440
15441 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
15442 _syscmd(cmd, buf, sizeof(buf));
15443
15444 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
15445 if (ret != RETURN_OK) {
15446 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
15447 return RETURN_ERR;
15448 }
15449
15450 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
15451 if (ret != RETURN_OK) {
15452 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
15453 return RETURN_ERR;
15454 }
15455
15456 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
15457 if (ret != RETURN_OK) {
15458 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
15459 return RETURN_ERR;
15460 }
15461
15462 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
15463 if (ret != RETURN_OK) {
15464 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
15465 return RETURN_ERR;
15466 }
15467
15468 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
15469 if (ret != RETURN_OK) {
15470 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
15471 return RETURN_ERR;
15472 }
15473
15474 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
15475 if (ret != RETURN_OK) {
15476 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
15477 return RETURN_ERR;
15478 }
15479
15480 if (vap_info->u.bss_info.mac_filter_enable == false){
15481 acl_mode = 0;
15482 }else {
15483 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
15484 acl_mode = 2;
15485 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
15486 _syscmd(cmd, buf, sizeof(buf));
15487 }else{
15488 acl_mode = 1;
15489 }
15490 }
15491
15492 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
15493 if (ret != RETURN_OK) {
15494 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
15495 return RETURN_ERR;
15496 }
15497
15498 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
15499 if (ret != RETURN_OK) {
15500 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
15501 return RETURN_ERR;
15502 }
15503
developer0f10c772023-05-16 21:43:39 +080015504 memset(buf, 0, sizeof(buf));
15505 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
15506 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
15507 if (ret != RETURN_OK) {
15508 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
15509 return RETURN_ERR;
15510 }
developer72fb0bb2023-01-11 09:46:29 +080015511
15512 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
15513 if (ret != RETURN_OK) {
15514 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable\n", __func__);
15515 return RETURN_ERR;
15516 }
15517
developer72fb0bb2023-01-11 09:46:29 +080015518 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
15519 if (ret != RETURN_OK) {
15520 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
15521 return RETURN_ERR;
15522 }
developer333c1eb2023-05-31 14:59:39 +080015523
developer56fbedb2023-05-30 16:47:05 +080015524 hostapd_raw_restart_bss(vap_info->vap_index);
developer72fb0bb2023-01-11 09:46:29 +080015525
developer23e71282023-01-18 10:25:19 +080015526 multiple_set = FALSE;
15527
15528 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
developer72fb0bb2023-01-11 09:46:29 +080015529 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
15530 if (ret != RETURN_OK) {
15531 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
15532 return RETURN_ERR;
15533 }
15534
15535 // TODO mgmtPowerControl, interworking, wps
15536 }
15537 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
15538 return RETURN_OK;
15539}
15540
15541int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
15542{
15543 char *token, *next;
15544 const char s[2] = ",";
15545 int count =0;
15546
15547 /* get the first token */
15548 token = strtok_r(pchannels, s, &next);
15549
15550 /* walk through other tokens */
15551 while( token != NULL && count < MAX_CHANNELS) {
15552 chlistptr->channels_list[count++] = atoi(token);
15553 token = strtok_r(NULL, s, &next);
15554 }
15555
15556 return count;
15557}
15558
15559static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
15560{
15561 INT status;
15562 wifi_channels_list_t *chlistp;
15563 CHAR output_string[64];
15564 CHAR pchannels[128];
15565 CHAR interface_name[16] = {0};
15566 wifi_band band;
15567
15568 if(rcap == NULL)
15569 {
15570 return RETURN_ERR;
15571 }
15572
15573 rcap->numSupportedFreqBand = 1;
15574 band = wifi_index_to_band(radioIndex);
15575
15576 if (band == band_2_4)
15577 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
15578 else if (band == band_5)
15579 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
15580 else if (band == band_6)
15581 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
15582
15583 chlistp = &(rcap->channel_list[0]);
15584 memset(pchannels, 0, sizeof(pchannels));
15585
15586 /* possible number of radio channels */
15587 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
15588 {
15589 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
15590 }
15591 /* Number of channels and list*/
15592 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
15593
15594 /* autoChannelSupported */
15595 /* always ON with wifi_getRadioAutoChannelSupported */
15596 rcap->autoChannelSupported = TRUE;
15597
15598 /* DCSSupported */
15599 /* always ON with wifi_getRadioDCSSupported */
15600 rcap->DCSSupported = TRUE;
15601
15602 /* zeroDFSSupported - TBD */
15603 rcap->zeroDFSSupported = FALSE;
15604
15605 /* Supported Country List*/
15606 memset(output_string, 0, sizeof(output_string));
15607 status = wifi_getRadioCountryCode(radioIndex, output_string);
15608 if( status != 0 ) {
15609 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
15610 return RETURN_ERR;
15611 } else {
15612 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
15613 }
15614 if(!strcmp(output_string,"US")){
15615 rcap->countrySupported[0] = wifi_countrycode_US;
15616 rcap->countrySupported[1] = wifi_countrycode_CA;
15617 } else if (!strcmp(output_string,"CA")) {
15618 rcap->countrySupported[0] = wifi_countrycode_CA;
15619 rcap->countrySupported[1] = wifi_countrycode_US;
15620 } else {
15621 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
15622 }
15623
15624 rcap->numcountrySupported = 2;
15625
15626 /* csi */
15627 rcap->csi.maxDevices = 8;
15628 rcap->csi.soudingFrameSupported = TRUE;
15629
15630 wifi_GetInterfaceName(radioIndex, interface_name);
15631 snprintf(rcap->ifaceName, sizeof(interface_name), "%s",interface_name);
15632
15633 /* channelWidth - all supported bandwidths */
15634 int i=0;
15635 rcap->channelWidth[i] = 0;
15636 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
15637 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
15638 WIFI_CHANNELBANDWIDTH_40MHZ);
15639
15640 }
15641 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
15642 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
15643 WIFI_CHANNELBANDWIDTH_40MHZ |
15644 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
15645 }
15646
15647
15648 /* mode - all supported variants */
15649 // rcap->mode[i] = WIFI_80211_VARIANT_H;
15650 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
15651 rcap->mode[i] = ( WIFI_80211_VARIANT_B | WIFI_80211_VARIANT_G | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AX );
15652 }
15653 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
15654 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
15655 }
15656 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
15657 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
15658 }
15659 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
15660 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
15661
15662 /* supportedBitRate - all supported bitrates */
15663 rcap->supportedBitRate[i] = 0;
15664 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
15665 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
15666 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
15667 }
15668 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
15669 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
15670 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
15671 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
15672 }
15673
15674
15675 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
15676 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
15677 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
15678 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
15679 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
15680 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
15681 rcap->cipherSupported = 0;
15682 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
15683 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
15684
15685 return RETURN_OK;
15686}
15687
15688INT wifi_getHalCapability(wifi_hal_capability_t *cap)
15689{
15690 INT status = 0, radioIndex = 0;
15691 char cmd[MAX_BUF_SIZE] = {0}, output[MAX_BUF_SIZE] = {0};
15692 int iter = 0;
15693 unsigned int j = 0;
15694 int max_num_radios;
15695 wifi_interface_name_idex_map_t *iface_info = NULL;
15696
15697 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
15698
15699 memset(cap, 0, sizeof(wifi_hal_capability_t));
15700
15701 /* version */
15702 cap->version.major = WIFI_HAL_MAJOR_VERSION;
15703 cap->version.minor = WIFI_HAL_MINOR_VERSION;
15704
15705 /* number of radios platform property */
15706 wifi_getMaxRadioNumber(&max_num_radios);
15707 cap->wifi_prop.numRadios = max_num_radios;
15708
15709 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
15710 {
15711 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
15712 if (status != 0) {
15713 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
15714 return RETURN_ERR;
15715 }
15716
15717 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
15718 {
15719 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
15720 {
15721 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
15722 return RETURN_ERR;
15723 }
15724 iface_info = &cap->wifi_prop.interface_map[iter];
15725 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
15726 iface_info->rdk_radio_index = radioIndex;
15727 memset(output, 0, sizeof(output));
15728 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
15729 {
15730 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
15731 }
15732 // TODO: bridge name
15733 // TODO: vlan id
15734 // TODO: primary
15735 iface_info->index = array_index_to_vap_index(radioIndex, j);
15736 memset(output, 0, sizeof(output));
15737 if (wifi_getApName(iface_info->index, output) == RETURN_OK)
15738 {
15739 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
15740 }
15741 iter++;
15742 }
15743 }
15744
15745 cap->BandSteeringSupported = FALSE;
15746 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
15747 return RETURN_OK;
15748}
15749
15750INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
15751{
15752 struct params h_config={0};
15753 char config_file[64] = {0};
15754
15755 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
15756
15757 h_config.name = "okc";
15758 h_config.value = okc_enable?"1":"0";
15759
15760 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
15761 wifi_hostapdWrite(config_file, &h_config, 1);
15762 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
15763
15764 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
15765 return RETURN_OK;
15766}
15767
15768INT wifi_setSAEMFP(int ap_index, BOOL enable)
15769{
15770 struct params h_config={0};
15771 char config_file[64] = {0};
15772 char buf[128] = {0};
15773
15774 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
15775
15776 h_config.name = "sae_require_mfp";
15777 h_config.value = enable?"1":"0";
15778
15779 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
15780 wifi_hostapdWrite(config_file, &h_config, 1);
15781 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
15782
15783 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
15784 return RETURN_OK;
15785}
15786
15787INT wifi_setSAEpwe(int ap_index, int sae_pwe)
15788{
15789 struct params h_config={0};
15790 char config_file[64] = {0};
15791 char buf[128] = {0};
15792
15793 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
15794
15795 h_config.name = "sae_pwe";
15796 snprintf(buf, sizeof(buf), "%d", sae_pwe);
15797 h_config.value = buf;
15798
15799 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
15800 wifi_hostapdWrite(config_file, &h_config, 1);
15801 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
15802
15803 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
15804 return RETURN_OK;
15805}
15806
15807INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
15808{
15809 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
15810 struct params h_config={0};
15811 char config_file[64] = {0};
15812
15813 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
15814
15815 h_config.name = "wpa_disable_eapol_key_retries";
15816 h_config.value = disable_EAPOL_retries?"1":"0";
15817
15818 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
15819 wifi_hostapdWrite(config_file, &h_config, 1);
15820 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
15821
15822 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
15823 return RETURN_OK;
15824}
15825
15826INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
15827{
15828 char buf[128] = {0};
15829 char config_file[128] = {0};
developere5750452023-05-15 16:46:42 +080015830 char cmd[128] = {0};
developer72fb0bb2023-01-11 09:46:29 +080015831 char password[64] = {0};
15832 char mfp[32] = {0};
15833 char wpa_mode[32] = {0};
15834 BOOL okc_enable = FALSE;
15835 BOOL sae_MFP = FALSE;
15836 BOOL disable_EAPOL_retries = TRUE;
15837 int sae_pwe = 0;
15838 struct params params = {0};
15839 wifi_band band = band_invalid;
15840
15841 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
15842
15843 multiple_set = TRUE;
15844 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
15845 if (security->mode == wifi_security_mode_none) {
15846 strcpy(wpa_mode, "None");
15847 } else if (security->mode == wifi_security_mode_wpa_personal)
15848 strcpy(wpa_mode, "WPA-Personal");
15849 else if (security->mode == wifi_security_mode_wpa2_personal)
15850 strcpy(wpa_mode, "WPA2-Personal");
15851 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
15852 strcpy(wpa_mode, "WPA-WPA2-Personal");
15853 else if (security->mode == wifi_security_mode_wpa_enterprise)
15854 strcpy(wpa_mode, "WPA-Enterprise");
15855 else if (security->mode == wifi_security_mode_wpa2_enterprise)
15856 strcpy(wpa_mode, "WPA2-Enterprise");
15857 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
15858 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
15859 else if (security->mode == wifi_security_mode_wpa3_personal) {
15860 strcpy(wpa_mode, "WPA3-Personal");
15861 okc_enable = TRUE;
15862 sae_MFP = TRUE;
15863 sae_pwe = 2;
15864 disable_EAPOL_retries = FALSE;
15865 } else if (security->mode == wifi_security_mode_wpa3_transition) {
15866 strcpy(wpa_mode, "WPA3-Personal-Transition");
15867 okc_enable = TRUE;
15868 sae_MFP = TRUE;
15869 sae_pwe = 2;
15870 disable_EAPOL_retries = FALSE;
15871 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
15872 strcpy(wpa_mode, "WPA3-Enterprise");
15873 sae_MFP = TRUE;
15874 sae_pwe = 2;
15875 disable_EAPOL_retries = FALSE;
developerd01e3e82023-04-26 19:10:38 +080015876 } else if (security->mode == wifi_security_mode_enhanced_open) {
developer3086e2f2023-01-17 09:40:01 +080015877 strcpy(wpa_mode, "OWE");
15878 sae_MFP = TRUE;
15879 sae_pwe = 2;
15880 disable_EAPOL_retries = FALSE;
developer72fb0bb2023-01-11 09:46:29 +080015881 }
15882
15883 band = wifi_index_to_band(ap_index);
15884 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
15885 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
15886 return RETURN_ERR;
15887 }
15888
15889 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
15890 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
15891 wifi_setSAEMFP(ap_index, sae_MFP);
15892 wifi_setSAEpwe(ap_index, sae_pwe);
15893 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
15894
developerd01e3e82023-04-26 19:10:38 +080015895 if (security->mode != wifi_security_mode_none && security->mode != wifi_security_mode_enhanced_open) {
developere5750452023-05-15 16:46:42 +080015896 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) {
15897 int key_len = strlen(security->u.key.key);
15898 // wpa_psk and wpa_passphrase cann;t use at the same time, the command replace one with the other.
15899 if (key_len == 64) { // set wpa_psk
15900 strncpy(password, security->u.key.key, 64); // 64 characters
15901 password[64] = '\0';
15902 wifi_setApSecurityPreSharedKey(ap_index, password);
15903 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_passphrase=/!p' %s", config_file);
15904 } else if (key_len >= 8 && key_len < 64) { // set wpa_passphrase
15905 strncpy(password, security->u.key.key, 63);
15906 password[63] = '\0';
15907 wifi_setApSecurityKeyPassphrase(ap_index, password);
15908 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_psk=/!p' %s", config_file);
15909 } else
15910 return RETURN_ERR;
15911 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +080015912 }
15913 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
15914 params.name = "sae_password";
15915 params.value = security->u.key.key;
15916 wifi_hostapdWrite(config_file, &params, 1);
developere5750452023-05-15 16:46:42 +080015917 } else { // remove sae_password
15918 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^sae_password=/!p' %s", config_file);
15919 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +080015920 }
15921 }
15922
15923 if (security->mode != wifi_security_mode_none) {
15924 memset(&params, 0, sizeof(params));
15925 params.name = "wpa_pairwise";
15926 if (security->encr == wifi_encryption_tkip)
15927 params.value = "TKIP";
15928 else if (security->encr == wifi_encryption_aes)
15929 params.value = "CCMP";
15930 else if (security->encr == wifi_encryption_aes_tkip)
15931 params.value = "TKIP CCMP";
15932 wifi_hostapdWrite(config_file, &params, 1);
15933 }
15934
15935 if (security->mfp == wifi_mfp_cfg_disabled)
15936 strcpy(mfp, "Disabled");
15937 else if (security->mfp == wifi_mfp_cfg_optional)
15938 strcpy(mfp, "Optional");
15939 else if (security->mfp == wifi_mfp_cfg_required)
15940 strcpy(mfp, "Required");
15941 wifi_setApSecurityMFPConfig(ap_index, mfp);
15942
15943 memset(&params, 0, sizeof(params));
15944 params.name = "transition_disable";
15945 if (security->wpa3_transition_disable == TRUE)
15946 params.value = "0x01";
15947 else
15948 params.value = "0x00";
15949 wifi_hostapdWrite(config_file, &params, 1);
15950
15951 memset(&params, 0, sizeof(params));
15952 params.name = "wpa_group_rekey";
15953 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
15954 params.value = buf;
15955 wifi_hostapdWrite(config_file, &params, 1);
15956
15957 memset(&params, 0, sizeof(params));
15958 params.name = "wpa_strict_rekey";
15959 params.value = security->strict_rekey?"1":"0";
15960 wifi_hostapdWrite(config_file, &params, 1);
15961
15962 memset(&params, 0, sizeof(params));
15963 params.name = "wpa_pairwise_update_count";
developere5750452023-05-15 16:46:42 +080015964 if (security->eapol_key_retries == 0)
15965 security->eapol_key_retries = 4; // 0 is invalid, set to default value.
developer72fb0bb2023-01-11 09:46:29 +080015966 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
15967 params.value = buf;
15968 wifi_hostapdWrite(config_file, &params, 1);
15969
15970 memset(&params, 0, sizeof(params));
15971 params.name = "disable_pmksa_caching";
15972 params.value = security->disable_pmksa_caching?"1":"0";
15973 wifi_hostapdWrite(config_file, &params, 1);
15974
developer23e71282023-01-18 10:25:19 +080015975 if (multiple_set == FALSE) {
15976 wifi_setApEnable(ap_index, FALSE);
15977 wifi_setApEnable(ap_index, TRUE);
15978 }
developer72fb0bb2023-01-11 09:46:29 +080015979
15980 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
15981
15982 return RETURN_OK;
15983}
15984
15985INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
15986{
15987 char buf[256] = {0};
15988 char config_file[128] = {0};
15989 int disable = 0;
developere5750452023-05-15 16:46:42 +080015990 bool set_sae = FALSE;
developer72fb0bb2023-01-11 09:46:29 +080015991
15992 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
15993 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
15994 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
15995 security->mode = wifi_security_mode_none;
15996 if (strlen(buf) != 0) {
15997 if (!strcmp(buf, "WPA-Personal"))
15998 security->mode = wifi_security_mode_wpa_personal;
15999 else if (!strcmp(buf, "WPA2-Personal"))
16000 security->mode = wifi_security_mode_wpa2_personal;
16001 else if (!strcmp(buf, "WPA-WPA2-Personal"))
16002 security->mode = wifi_security_mode_wpa_wpa2_personal;
16003 else if (!strcmp(buf, "WPA-Enterprise"))
16004 security->mode = wifi_security_mode_wpa_enterprise;
16005 else if (!strcmp(buf, "WPA2-Enterprise"))
16006 security->mode = wifi_security_mode_wpa2_enterprise;
16007 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
16008 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
16009 else if (!strcmp(buf, "WPA3-Personal"))
16010 security->mode = wifi_security_mode_wpa3_personal;
16011 else if (!strcmp(buf, "WPA3-Personal-Transition"))
16012 security->mode = wifi_security_mode_wpa3_transition;
16013 else if (!strcmp(buf, "WPA3-Enterprise"))
16014 security->mode = wifi_security_mode_wpa3_enterprise;
developer3086e2f2023-01-17 09:40:01 +080016015 else if (!strcmp(buf, "OWE"))
developerd01e3e82023-04-26 19:10:38 +080016016 security->mode = wifi_security_mode_enhanced_open;
developer72fb0bb2023-01-11 09:46:29 +080016017 }
16018
16019 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
16020 if (security->mode == wifi_security_mode_none)
16021 security->encr = wifi_encryption_none;
16022 else {
16023 if (strcmp(buf, "TKIP") == 0)
16024 security->encr = wifi_encryption_tkip;
16025 else if (strcmp(buf, "CCMP") == 0)
16026 security->encr = wifi_encryption_aes;
16027 else
16028 security->encr = wifi_encryption_aes_tkip;
16029 }
16030
16031 if (security->mode != wifi_encryption_none) {
16032 memset(buf, 0, sizeof(buf));
16033 // wpa3 can use one or both configs as password, so we check sae_password first.
16034 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
developere5750452023-05-15 16:46:42 +080016035 if (strlen(buf) != 0) {
16036 if (security->mode == wifi_security_mode_wpa3_personal || security->mode == wifi_security_mode_wpa3_transition)
16037 security->u.key.type = wifi_security_key_type_sae;
16038 set_sae = TRUE;
16039 strncpy(security->u.key.key, buf, sizeof(buf));
16040 }
16041 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
16042 if (strlen(buf) != 0){
16043 if (set_sae == TRUE)
16044 security->u.key.type = wifi_security_key_type_psk_sae;
16045 else if (strlen(buf) == 64)
16046 security->u.key.type = wifi_security_key_type_psk;
16047 else
16048 security->u.key.type = wifi_security_key_type_pass;
16049 strncpy(security->u.key.key, buf, sizeof(security->u.key.key));
developer72fb0bb2023-01-11 09:46:29 +080016050 }
developer72fb0bb2023-01-11 09:46:29 +080016051 security->u.key.key[255] = '\0';
16052 }
16053
16054 memset(buf, 0, sizeof(buf));
16055 wifi_getApSecurityMFPConfig(ap_index, buf);
16056 if (strcmp(buf, "Disabled") == 0)
16057 security->mfp = wifi_mfp_cfg_disabled;
16058 else if (strcmp(buf, "Optional") == 0)
16059 security->mfp = wifi_mfp_cfg_optional;
16060 else if (strcmp(buf, "Required") == 0)
16061 security->mfp = wifi_mfp_cfg_required;
16062
16063 memset(buf, 0, sizeof(buf));
16064 security->wpa3_transition_disable = FALSE;
16065 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
16066 disable = strtol(buf, NULL, 16);
16067 if (disable != 0)
16068 security->wpa3_transition_disable = TRUE;
16069
16070 memset(buf, 0, sizeof(buf));
16071 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
16072 if (strlen(buf) == 0)
16073 security->rekey_interval = 86400;
16074 else
16075 security->rekey_interval = strtol(buf, NULL, 10);
16076
16077 memset(buf, 0, sizeof(buf));
16078 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
16079 if (strlen(buf) == 0)
16080 security->strict_rekey = 1;
16081 else
16082 security->strict_rekey = strtol(buf, NULL, 10);
16083
16084 memset(buf, 0, sizeof(buf));
16085 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
16086 if (strlen(buf) == 0)
16087 security->eapol_key_retries = 4;
16088 else
16089 security->eapol_key_retries = strtol(buf, NULL, 10);
16090
16091 memset(buf, 0, sizeof(buf));
16092 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
16093 if (strlen(buf) == 0)
16094 security->disable_pmksa_caching = FALSE;
16095 else
16096 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
16097
16098 /* TODO
16099 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
16100 */
16101 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
16102 security->eap_identity_req_timeout = 0;
16103 security->eap_identity_req_retries = 0;
16104 security->eap_req_timeout = 0;
16105 security->eap_req_retries = 0;
16106 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
16107 return RETURN_OK;
16108}
16109
16110#endif /* WIFI_HAL_VERSION_3 */
16111
16112#ifdef WIFI_HAL_VERSION_3_PHASE2
16113INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
16114{
16115 char interface_name[16] = {0};
16116 char cmd[128] = {0};
16117 char buf[128] = {0};
16118 char *mac_addr = NULL;
16119 BOOL status = FALSE;
16120 size_t len = 0;
16121
16122 if(ap_index > MAX_APS)
16123 return RETURN_ERR;
16124
16125 *output_numDevices = 0;
16126 wifi_getApEnable(ap_index, &status);
16127 if (status == FALSE)
16128 return RETURN_OK;
16129
16130 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
16131 return RETURN_ERR;
16132 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
16133 _syscmd(cmd, buf, sizeof(buf));
16134
16135 mac_addr = strtok(buf, "\n");
16136 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
16137 *output_numDevices = i + 1;
16138 fprintf(stderr, "mac_addr: %s\n", mac_addr);
16139 addr_ptr = output_deviceMacAddressArray[i];
16140 mac_addr_aton(addr_ptr, mac_addr);
16141 mac_addr = strtok(NULL, "\n");
16142 }
16143
16144 return RETURN_OK;
16145}
16146#else
16147INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
16148{
16149 char interface_name[16] = {0};
16150 char cmd[128];
16151 BOOL status = false;
16152
16153 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
16154 return RETURN_ERR;
16155
16156 output_buf[0] = '\0';
16157
16158 wifi_getApEnable(ap_index,&status);
16159 if (!status)
16160 return RETURN_OK;
16161
16162 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
16163 return RETURN_ERR;
16164 sprintf(cmd, "hostapd_cli -i %s list_sta | tr '\\n' ',' | sed 's/.$//'", interface_name);
16165 _syscmd(cmd, output_buf, output_buf_size);
developer69b61b02023-03-07 17:17:44 +080016166
developer72fb0bb2023-01-11 09:46:29 +080016167 return RETURN_OK;
16168}
16169#endif
16170
16171INT wifi_getProxyArp(INT apIndex, BOOL *enable)
16172{
16173 char output[16]={'\0'};
16174 char config_file[MAX_BUF_SIZE] = {0};
16175
16176 if (!enable)
16177 return RETURN_ERR;
16178
16179 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
16180 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
16181
16182 if (strlen(output) == 0)
16183 *enable = FALSE;
16184 else if (strncmp(output, "1", 1) == 0)
16185 *enable = TRUE;
16186 else
16187 *enable = FALSE;
16188
16189 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
16190 return RETURN_OK;
16191}
16192
16193INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
16194{
16195 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
16196 return RETURN_ERR;
16197 *output_enable=TRUE;
16198 return RETURN_OK;
16199}
16200
16201INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
16202{
16203 char cmd[128] = {0};
16204 char buf[128] = {0};
16205 char line[128] = {0};
16206 size_t len = 0;
16207 FILE *f = NULL;
16208 int index = 0;
16209 int exp = 0;
16210 int mantissa = 0;
16211 int duration = 0;
16212 int radio_index = 0;
16213 int max_radio_num = 0;
16214 uint twt_wake_interval = 0;
16215 int phyId = 0;
16216 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
16217
16218 wifi_getMaxRadioNumber(&max_radio_num);
16219
16220 radio_index = ap_index % max_radio_num;
16221
16222 phyId = radio_index_to_phy(radio_index);
16223 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", phyId);
16224 _syscmd(cmd, buf, sizeof(buf));
16225 *numSessionReturned = strtol(buf, NULL, 10) - 1;
16226 if (*numSessionReturned > maxNumberSessions)
16227 *numSessionReturned = maxNumberSessions;
16228 else if (*numSessionReturned < 1) {
16229 *numSessionReturned = 0;
16230 return RETURN_OK;
16231 }
16232
16233 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | tail -n %d | tr '|' ' ' | tr -s ' '", phyId, *numSessionReturned);
16234 if ((f = popen(cmd, "r")) == NULL) {
16235 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
16236 return RETURN_ERR;
16237 }
16238
16239 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
16240 while((fgets(line, sizeof(line), f)) != NULL) {
16241 char *tmp = NULL;
16242 strcpy(buf, line);
16243 tmp = strtok(buf, " ");
16244 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
16245 tmp = strtok(NULL, " ");
16246 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
16247 tmp = strtok(NULL, " ");
16248 if (strstr(tmp, "t")) {
16249 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
16250 }
16251 if (strstr(tmp, "a")) {
16252 twtSessions[index].twtParameters.operation.announced = TRUE;
16253 }
16254 tmp = strtok(NULL, " ");
16255 exp = strtol(tmp, NULL, 10);
16256 tmp = strtok(NULL, " ");
16257 mantissa = strtol(tmp, NULL, 10);
16258 tmp = strtok(NULL, " ");
16259 duration = strtol(tmp, NULL, 10);
16260
16261 // only implicit supported
16262 twtSessions[index].twtParameters.operation.implicit = TRUE;
16263 // only individual agreement supported
16264 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
16265
16266 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
16267 twt_wake_interval = mantissa * (1 << exp);
16268 if (mantissa == 0 || twt_wake_interval/mantissa != (1 << exp)) {
16269 // Overflow handling
16270 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
16271 } else {
16272 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
16273 }
16274 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
16275 index++;
16276 }
16277
16278 pclose(f);
16279 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
16280 return RETURN_OK;
16281}