blob: ce517ab5368fbf8d209b7c4b80b2ac182df77179 [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>
developercc5cbfb2023-06-13 18:29:52 +080066
67#include <sys/socket.h>
68#include <sys/ioctl.h>
69#include <arpa/inet.h>
70#include <linux/if.h>
71#include <linux/if_bridge.h>
72#include <linux/sockios.h>
73
developer72fb0bb2023-01-11 09:46:29 +080074#define MAC_ALEN 6
75
76#define MAX_BUF_SIZE 256
77#define MAX_CMD_SIZE 256
developerb149d9d2023-06-06 16:14:22 +080078#define MAX_SUB_CMD_SIZE 200
79
developer72fb0bb2023-01-11 09:46:29 +080080#define IF_NAME_SIZE 16
81#define CONFIG_PREFIX "/nvram/hostapd"
82#define ACL_PREFIX "/nvram/hostapd-acl"
83#define DENY_PREFIX "/nvram/hostapd-deny"
84//#define ACL_PREFIX "/tmp/wifi_acl_list" //RDKB convention
85#define SOCK_PREFIX "/var/run/hostapd/wifi"
86#define VAP_STATUS_FILE "/nvram/vap-status"
87#define ESSID_FILE "/tmp/essid"
88#define GUARD_INTERVAL_FILE "/nvram/guard-interval"
89#define CHANNEL_STATS_FILE "/tmp/channel_stats"
90#define DFS_ENABLE_FILE "/nvram/dfs_enable.txt"
91#define VLAN_FILE "/nvram/hostapd.vlan"
92#define PSK_FILE "/nvram/hostapd"
93#define MCS_FILE "/tmp/MCS"
developera1255e42023-05-13 17:45:02 +080094#define POWER_PERCENTAGE "/tmp/POWER"
95#define MGMT_POWER_CTRL "/tmp/mgmt_power_ctrl"
96/*LOGAN_DAT_FILE: may be different on customer's platform.*/
97#define LOGAN_DAT_FILE "/etc/wireless/mediatek/mt7990.b"
developerb2977562023-05-24 17:54:12 +080098#define ROM_LOGAN_DAT_FILE "/rom/etc/wireless/mediatek/mt7990.b"
developera1255e42023-05-13 17:45:02 +080099
developer72fb0bb2023-01-11 09:46:29 +0800100#define NOACK_MAP_FILE "/tmp/NoAckMap"
developerfead3972023-05-25 20:15:02 +0800101#define RADIO_RESET_FILE "/nvram/radio_reset"
developerf6a87542023-05-16 15:47:28 +0800102
developer72fb0bb2023-01-11 09:46:29 +0800103#define BRIDGE_NAME "brlan0"
developerd1824452023-05-18 12:30:04 +0800104#define BASE_PHY_INDEX 1
105#define BASE_RADIO_INDEX 0
developer72fb0bb2023-01-11 09:46:29 +0800106
107/*
108 MAX_APS - Number of all AP available in system
109 2x Home AP
110 2x Backhaul AP
111 2x Guest AP
112 2x Secure Onboard AP
113 2x Service AP
114
115*/
116
117
118#define MAX_APS MAX_NUM_RADIOS*5
developer7e4a2a62023-04-06 19:56:03 +0800119
120#define PREFIX_WIFI2G "ra"
121#define PREFIX_WIFI5G "rai"
122#define PREFIX_WIFI6G "rax"
developer72fb0bb2023-01-11 09:46:29 +0800123
developer47cc27a2023-05-17 23:09:58 +0800124#define PREFIX_SSID_2G "RDKB_2G"
125#define PREFIX_SSID_5G "RDKB_5G"
126#define PREFIX_SSID_6G "RDKB_6G"
127
developer72fb0bb2023-01-11 09:46:29 +0800128#ifndef RADIO_PREFIX
129#define RADIO_PREFIX "wlan"
130#endif
131
132#define MAX_ASSOCIATED_STA_NUM 2007
133
134//Uncomment to enable debug logs
135//#define WIFI_DEBUG
developer49b17232023-05-19 16:35:19 +0800136enum {
137 DEBUG_OFF = 0,
138 DEBUG_ERROR = 1,
139 DEBUG_WARN = 2,
140 DEBUG_NOTICE = 3,
141 DEBUG_INFO = 4
142};
143int wifi_debug_level = DEBUG_NOTICE;
144#define wifi_debug(level, fmt, args...) \
145{ \
146 if (level <= wifi_debug_level) \
147 { \
developer2edaf012023-05-24 14:24:53 +0800148 printf("[%s][%d]"fmt"", __func__, __LINE__, ##args); \
developer49b17232023-05-19 16:35:19 +0800149 } \
150}
developer72fb0bb2023-01-11 09:46:29 +0800151
152#ifdef WIFI_DEBUG
153#define wifi_dbg_printf printf
154#define WIFI_ENTRY_EXIT_DEBUG printf
155#else
developer2f79c922023-06-02 17:33:42 +0800156#define wifi_dbg_printf(format, args...)
157#define WIFI_ENTRY_EXIT_DEBUG(format, args...)
developer72fb0bb2023-01-11 09:46:29 +0800158#endif
159
160#define HOSTAPD_CONF_0 "/nvram/hostapd0.conf" //private-wifi-2g
161#define HOSTAPD_CONF_1 "/nvram/hostapd1.conf" //private-wifi-5g
162#define HOSTAPD_CONF_4 "/nvram/hostapd4.conf" //public-wifi-2g
163#define HOSTAPD_CONF_5 "/nvram/hostapd5.conf" //public-wifi-5g
164#define DEF_HOSTAPD_CONF_0 "/usr/ccsp/wifi/hostapd0.conf"
165#define DEF_HOSTAPD_CONF_1 "/usr/ccsp/wifi/hostapd1.conf"
166#define DEF_HOSTAPD_CONF_4 "/usr/ccsp/wifi/hostapd4.conf"
167#define DEF_HOSTAPD_CONF_5 "/usr/ccsp/wifi/hostapd5.conf"
168#define DEF_RADIO_PARAM_CONF "/usr/ccsp/wifi/radio_param_def.cfg"
169#define LM_DHCP_CLIENT_FORMAT "%63d %17s %63s %63s"
170
171#define HOSTAPD_HT_CAPAB "[LDPC][SHORT-GI-20][SHORT-GI-40][MAX-AMSDU-7935]"
172
173#define BW_FNAME "/nvram/bw_file.txt"
174
175#define PS_MAX_TID 16
176
developer96b38512023-02-22 11:17:45 +0800177#define MAX_CARD_INDEX 3
178
developer72fb0bb2023-01-11 09:46:29 +0800179static wifi_radioQueueType_t _tid_ac_index_get[PS_MAX_TID] = {
180 WIFI_RADIO_QUEUE_TYPE_BE, /* 0 */
181 WIFI_RADIO_QUEUE_TYPE_BK, /* 1 */
182 WIFI_RADIO_QUEUE_TYPE_BK, /* 2 */
183 WIFI_RADIO_QUEUE_TYPE_BE, /* 3 */
184 WIFI_RADIO_QUEUE_TYPE_VI, /* 4 */
185 WIFI_RADIO_QUEUE_TYPE_VI, /* 5 */
186 WIFI_RADIO_QUEUE_TYPE_VO, /* 6 */
187 WIFI_RADIO_QUEUE_TYPE_VO, /* 7 */
188 WIFI_RADIO_QUEUE_TYPE_BE, /* 8 */
189 WIFI_RADIO_QUEUE_TYPE_BK, /* 9 */
190 WIFI_RADIO_QUEUE_TYPE_BK, /* 10 */
191 WIFI_RADIO_QUEUE_TYPE_BE, /* 11 */
192 WIFI_RADIO_QUEUE_TYPE_VI, /* 12 */
193 WIFI_RADIO_QUEUE_TYPE_VI, /* 13 */
194 WIFI_RADIO_QUEUE_TYPE_VO, /* 14 */
195 WIFI_RADIO_QUEUE_TYPE_VO, /* 15 */
196};
197
198typedef unsigned long long u64;
199
200/* Enum to define WiFi Bands */
201typedef enum
202{
203 band_invalid = -1,
204 band_2_4 = 0,
205 band_5 = 1,
206 band_6 = 2,
207} wifi_band;
208
developer17038e62023-03-02 14:43:43 +0800209char* wifi_band_str[] = {
210 "2G",
211 "5G",
212 "6G",
213};
214
developer72fb0bb2023-01-11 09:46:29 +0800215typedef enum {
216 WIFI_MODE_A = 0x01,
217 WIFI_MODE_B = 0x02,
218 WIFI_MODE_G = 0x04,
219 WIFI_MODE_N = 0x08,
220 WIFI_MODE_AC = 0x10,
221 WIFI_MODE_AX = 0x20,
developera1255e42023-05-13 17:45:02 +0800222 WIFI_MODE_BE = 0x40,
developer72fb0bb2023-01-11 09:46:29 +0800223} wifi_ieee80211_Mode;
224
developer2f79c922023-06-02 17:33:42 +0800225typedef enum {
developerd1824452023-05-18 12:30:04 +0800226 HT_BW_20,
227 HT_BW_40,
developer2f79c922023-06-02 17:33:42 +0800228} ht_config_bw;
developerd1824452023-05-18 12:30:04 +0800229
developer2f79c922023-06-02 17:33:42 +0800230typedef enum {
developerd1824452023-05-18 12:30:04 +0800231 VHT_BW_2040,
232 VHT_BW_80,
233 VHT_BW_160,
234 VHT_BW_8080,
developer2f79c922023-06-02 17:33:42 +0800235} vht_config_bw;
developerd1824452023-05-18 12:30:04 +0800236
developer2f79c922023-06-02 17:33:42 +0800237typedef enum {
developerd1824452023-05-18 12:30:04 +0800238 EHT_BW_20,
239 EHT_BW_40,
240 EHT_BW_80,
241 EHT_BW_160,
242 EHT_BW_320,
developer2f79c922023-06-02 17:33:42 +0800243} eht_config_bw;
developerd1824452023-05-18 12:30:04 +0800244
developer72fb0bb2023-01-11 09:46:29 +0800245#ifdef WIFI_HAL_VERSION_3
246
247// Return number of elements in array
248#ifndef ARRAY_SIZE
249#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
250#endif /* ARRAY_SIZE */
251
252#ifndef ARRAY_AND_SIZE
253#define ARRAY_AND_SIZE(x) (x),ARRAY_SIZE(x)
254#endif /* ARRAY_AND_SIZE */
255
256#define WIFI_ITEM_STR(key, str) {0, sizeof(str)-1, (int)key, (intptr_t)str}
257
258typedef struct {
259 int32_t value;
260 int32_t param;
261 intptr_t key;
262 intptr_t data;
263} wifi_secur_list;
264
265static int util_unii_5g_centerfreq(const char *ht_mode, int channel);
266static int util_unii_6g_centerfreq(const char *ht_mode, int channel);
267wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key);
268wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str);
269char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key);
270static int ieee80211_channel_to_frequency(int channel, int *freqMHz);
developer47cc27a2023-05-17 23:09:58 +0800271static void wifi_PrepareDefaultHostapdConfigs(void);
272static void wifi_psk_file_reset();
developerb2977562023-05-24 17:54:12 +0800273static void wifi_dat_file_reset_by_radio(char radio_idx);
developer262f4cb2023-05-24 12:22:04 +0800274static int util_get_sec_chan_offset(int channel, const char* ht_mode);
developer2f79c922023-06-02 17:33:42 +0800275int hostapd_raw_add_bss(int apIndex);
276int hostapd_raw_remove_bss(int apIndex);
developer47cc27a2023-05-17 23:09:58 +0800277
developercc5cbfb2023-06-13 18:29:52 +0800278static inline int os_snprintf_error(size_t size, int res)
279{
280 return res < 0 || (unsigned int) res >= size;
281}
282
developer49b17232023-05-19 16:35:19 +0800283/*type define the nl80211 call back func*/
284typedef int (*mtk_nl80211_cb) (struct nl_msg *, void *);
285
286/**
287*struct mtk_nl80211_param
288* init mtk nl80211 using parameters
289* @sub_cmd: the cmd define in the mtk_vendor_nl80211.h.
290* @if_type: now only support the NL80211_ATTR_IFINDEX/NL80211_ATTR_WIPHY.
291* @if_idx: the index should match the interface or wiphy.
292* Note: NA
293**/
294struct mtk_nl80211_param {
295 unsigned int sub_cmd;
296 int if_type;
297 int if_idx;
298};
299
300/**
developer121a8e72023-05-22 09:19:39 +0800301*struct mtk_nl80211_cb_data
302* init mtk nl80211 call back parameters
303* @out_buf: store the mtk vendor output msg for wifi hal buffer.
304* @out_len: the output buffer length.
305* Note: NA
306**/
307struct mtk_nl80211_cb_data {
308 char * out_buf;
309 unsigned int out_len;
310};
311
312/**
developer49b17232023-05-19 16:35:19 +0800313*mtk_nl80211_init
314* init mtk nl80211 netlink and init the vendor msg common part.
315* @nl: netlink, just init it.
316* @msg: netlink message will alloc it.
317* the msg send success/fails is not free by app
318* only the nla_put etc api fails should use nlmsg_free.
319* @msg_data: vendor data msg attr pointer.
320* @param: init using interface and sub_cmd parameter.
321*
322*init the netlink context and mtk netlink vendor msg.
323*
324*return:
325* 0: success
326* other: fail
327**/
328
329int mtk_nl80211_init(struct unl *nl, struct nl_msg **msg,
330 struct nlattr **msg_data, struct mtk_nl80211_param *param) {
331 /*sanity check here*/
332 if (!nl || !param) {
333 (void)fprintf(stderr,
developerdaf24792023-06-06 11:40:04 +0800334 "[%s][%d]:nl(%p) or param(%p) is null, error!\n",
developer49b17232023-05-19 16:35:19 +0800335 __func__, __LINE__, nl, param);
336 return -1;
337 }
338 /*if_type check*/
339 if ( param->if_type != NL80211_ATTR_IFINDEX && param->if_type != NL80211_ATTR_WIPHY) {
340 (void)fprintf(stderr,
341 "[%s][%d]:if_type(0x%x) is not supported, only 0x%x and 0x%x supported.\n",
342 __func__, __LINE__, param->if_type, NL80211_ATTR_IFINDEX, NL80211_ATTR_WIPHY);
343 return -1;
344 }
345 /*init the nl*/
346 if (unl_genl_init(nl, "nl80211") < 0) {
347 (void)fprintf(stderr, "[%s][%d]::Failed to connect to nl80211\n",
348 __func__, __LINE__);
349 return -1;
350 }
351 /*init the msg*/
352 *msg = unl_genl_msg(nl, NL80211_CMD_VENDOR, false);
353
354 if (nla_put_u32(*msg, param->if_type, param->if_idx) ||
355 nla_put_u32(*msg, NL80211_ATTR_VENDOR_ID, MTK_NL80211_VENDOR_ID) ||
356 nla_put_u32(*msg, NL80211_ATTR_VENDOR_SUBCMD, param->sub_cmd)) {
357 (void)fprintf(stderr,
358 "[%s][%d]:Nla put error: if_type: 0x%x, if_idx: 0x%x, sub_cmd: 0x%x\n",
359 __func__, __LINE__, param->if_type, param->if_idx, param->sub_cmd);
360 goto err;
361 }
362
363 *msg_data = nla_nest_start(*msg, NL80211_ATTR_VENDOR_DATA);
364 if (!*msg_data) {
365 (void)fprintf(stderr, "[%s][%d]:Nla put NL80211_ATTR_VENDOR_DATA start error\n",
366 __func__, __LINE__);
367 goto err;
368 }
369
370 return 0;
371err:
developer49b17232023-05-19 16:35:19 +0800372 nlmsg_free(*msg);
373 unl_free(nl);
374 return -1;
375}
376
377/**
378*mtk_nl80211_send
379* set the vendor cmd call back and sent the vendor msg.
380* @nl: netlink.
381* @msg: netlink message.
382* @msg_data: vendor data msg attr pointer.
383* @handler: if the msg have call back shoud add the call back func
384* the event msg will handle by the call back func(exp:get cmd)
385* other set it as NULL(exp:set cmd).
386* @arg:call back func arg parameter.
387*add end of the netlink msg, set the call back and send msg
388*
389*return:
390* 0: success
391* other: fail
392**/
393int mtk_nl80211_send(struct unl *nl, struct nl_msg *msg,
394 struct nlattr *msg_data, mtk_nl80211_cb handler, void *arg) {
395 int ret = 0;
396 /*sanity check*/
397 if (!nl || !msg || !msg_data) {
398 (void)fprintf(stderr,
developerdaf24792023-06-06 11:40:04 +0800399 "[%s][%d]:nl(%p),msg(%p) or msg_data(%p) is null, error!\n",
developer49b17232023-05-19 16:35:19 +0800400 __func__, __LINE__, nl, msg, msg_data);
401 return -1;
402 }
403 /*end the msg attr of vendor data*/
404 nla_nest_end(msg, msg_data);
405 /*send the msg and set call back */
406 ret = unl_genl_request(nl, msg, handler, arg);
407 if (ret)
408 (void)fprintf(stderr, "send nl80211 cmd fails\n");
409 return ret;
410}
411
412/**
413*mtk_nl80211_deint
developer2edaf012023-05-24 14:24:53 +0800414* deinit the netlink.
developer49b17232023-05-19 16:35:19 +0800415* @nl: netlink.
416*
developer2edaf012023-05-24 14:24:53 +0800417*free deinit the netlink.
developer49b17232023-05-19 16:35:19 +0800418*
419*return:
420* 0: success
421**/
422
423int mtk_nl80211_deint(struct unl *nl) {
424 unl_free(nl);
425 return 0;
426}
427
developer72fb0bb2023-01-11 09:46:29 +0800428wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key)
429{
430 wifi_secur_list *item;
431 int i;
432
433 for (item = list,i = 0;i < list_sz; item++, i++) {
434 if ((int)(item->key) == key) {
435 return item;
436 }
437 }
438
439 return NULL;
440}
441
442char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key)
443{
444 wifi_secur_list *item = wifi_get_item_by_key(list, list_sz, key);
445
446 if (!item) {
447 return "";
448 }
449
450 return (char *)(item->data);
451}
452
453wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str)
454{
455 wifi_secur_list *item;
456 int i;
457
458 for (item = list,i = 0;i < list_sz; item++, i++) {
459 if (strcmp((char *)(item->data), str) == 0) {
460 return item;
461 }
462 }
463
464 return NULL;
465}
466#endif /* WIFI_HAL_VERSION_3 */
467
developer96b38512023-02-22 11:17:45 +0800468
469static char l1profile[32] = "/etc/wireless/l1profile.dat";
developer17038e62023-03-02 14:43:43 +0800470char main_prefix[MAX_NUM_RADIOS][IFNAMSIZ];
471char ext_prefix[MAX_NUM_RADIOS][IFNAMSIZ];
472#define MAX_SSID_LEN 64
473char default_ssid[MAX_NUM_RADIOS][MAX_SSID_LEN];;
developer745f0bd2023-03-06 14:32:53 +0800474int radio_band[MAX_NUM_RADIOS];
developer17038e62023-03-02 14:43:43 +0800475
476static int array_index_to_vap_index(UINT radioIndex, int arrayIndex);
477static int vap_index_to_array_index(int vapIndex, int *radioIndex, int *arrayIndex);
478
developer96b38512023-02-22 11:17:45 +0800479
480static int
481get_value(const char *conf_file, const char *param, char *value, int len)
482{
483 FILE *fp;
484 int ret = -1;
485 int param_len = strlen(param);
486 int buf_len;
487 char buf[256];
488
489 fp = fopen(conf_file, "r");
490 if (!fp) {
491 return -1;
492 }
493
494 while (fgets(buf, sizeof(buf), fp)) {
495 buf_len = strlen(buf);
496 if (buf[buf_len - 1] == '\n') {
497 buf_len--;
498 buf[buf_len] = '\0';
499 }
500 if ((buf_len > param_len) &&
501 (strncmp(buf, param, param_len) == 0) &&
502 (buf[param_len] == '=')) {
503
504 if (buf_len == (param_len + 1)) {
505 value[0] = '\0';
506 ret = 0;
507 } else {
508 ret = snprintf(value, len, "%s", buf + (param_len + 1));
509 }
510 fclose(fp);
511 return ret;
512 }
513 }
514 fclose(fp);
515 return -1;
516}
517
518static int
519get_value_by_idx(const char *conf_file, const char *param, int idx, char *value, int len)
520{
521 char buf[256];
522 int ret;
523 char *save_ptr = NULL;
524 char *tok = NULL;
525
526 ret = get_value(conf_file, param, buf, sizeof(buf));
527 if (ret < 0)
528 return ret;
529
530 tok = strtok_r(buf, ";", &save_ptr);
531 do {
532 if (idx == 0 || tok == NULL)
533 break;
534 else
535 idx--;
536
537 tok = strtok_r(NULL, ";", &save_ptr);
538 } while (tok != NULL);
539
540 if (tok) {
541 ret = snprintf(value, len, "%s", tok);
542 } else {
543 ret = 0;
544 value[0] = '\0';
545 }
546
547 return ret;
548}
549
550
developer72fb0bb2023-01-11 09:46:29 +0800551#ifdef HAL_NETLINK_IMPL
552typedef struct {
553 int id;
554 struct nl_sock* socket;
555 struct nl_cb* cb;
556} Netlink;
557
558static int mac_addr_aton(unsigned char *mac_addr, char *arg)
559{
developerdaf24792023-06-06 11:40:04 +0800560 unsigned char mac_addr_int[6]={};
developer72fb0bb2023-01-11 09:46:29 +0800561 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);
562 mac_addr[0] = mac_addr_int[0];
563 mac_addr[1] = mac_addr_int[1];
564 mac_addr[2] = mac_addr_int[2];
565 mac_addr[3] = mac_addr_int[3];
566 mac_addr[4] = mac_addr_int[4];
567 mac_addr[5] = mac_addr_int[5];
568 return 0;
569}
570
571static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
572{
573 unsigned int mac_addr_int[6]={};
574 mac_addr_int[0] = arg[0];
575 mac_addr_int[1] = arg[1];
576 mac_addr_int[2] = arg[2];
577 mac_addr_int[3] = arg[3];
578 mac_addr_int[4] = arg[4];
579 mac_addr_int[5] = arg[5];
580 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]);
581 return;
582}
583
584static int ieee80211_frequency_to_channel(int freq)
585{
586 /* see 802.11-2007 17.3.8.3.2 and Annex J */
587 if (freq == 2484)
588 return 14;
589 /* see 802.11ax D6.1 27.3.23.2 and Annex E */
590 else if (freq == 5935)
591 return 2;
592 else if (freq < 2484)
593 return (freq - 2407) / 5;
594 else if (freq >= 4910 && freq <= 4980)
595 return (freq - 4000) / 5;
596 else if (freq < 5950)
597 return (freq - 5000) / 5;
598 else if (freq <= 45000) /* DMG band lower limit */
599 /* see 802.11ax D6.1 27.3.23.2 */
600 return (freq - 5950) / 5;
601 else if (freq >= 58320 && freq <= 70200)
602 return (freq - 56160) / 2160;
603 else
604 return 0;
605}
606
607static int initSock80211(Netlink* nl) {
608 nl->socket = nl_socket_alloc();
609 if (!nl->socket) {
610 fprintf(stderr, "Failing to allocate the sock\n");
611 return -ENOMEM;
612 }
613
614 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
615
616 if (genl_connect(nl->socket)) {
617 fprintf(stderr, "Failed to connect\n");
618 nl_close(nl->socket);
619 nl_socket_free(nl->socket);
620 return -ENOLINK;
621 }
622
623 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
624 if (nl->id< 0) {
625 fprintf(stderr, "interface not found.\n");
626 nl_close(nl->socket);
627 nl_socket_free(nl->socket);
628 return -ENOENT;
629 }
630
631 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
632 if ((!nl->cb)) {
633 fprintf(stderr, "Failed to allocate netlink callback.\n");
634 nl_close(nl->socket);
635 nl_socket_free(nl->socket);
636 return ENOMEM;
637 }
638
639 return nl->id;
640}
641
642static int nlfree(Netlink *nl)
643{
644 nl_cb_put(nl->cb);
645 nl_close(nl->socket);
646 nl_socket_free(nl->socket);
647 return 0;
648}
649
650static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
651 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
652 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
653 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
654};
655
656static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
657};
658
659static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
660};
661
662typedef struct _wifi_channelStats_loc {
663 INT array_size;
664 INT ch_number;
665 BOOL ch_in_pool;
666 INT ch_noise;
667 BOOL ch_radar_noise;
668 INT ch_max_80211_rssi;
669 INT ch_non_80211_noise;
670 INT ch_utilization;
671 ULLONG ch_utilization_total;
672 ULLONG ch_utilization_busy;
673 ULLONG ch_utilization_busy_tx;
674 ULLONG ch_utilization_busy_rx;
675 ULLONG ch_utilization_busy_self;
676 ULLONG ch_utilization_busy_ext;
677} wifi_channelStats_t_loc;
678
679typedef struct wifi_device_info {
680 INT wifi_devIndex;
681 UCHAR wifi_devMacAddress[6];
682 CHAR wifi_devIPAddress[64];
683 BOOL wifi_devAssociatedDeviceAuthentiationState;
684 INT wifi_devSignalStrength;
685 INT wifi_devTxRate;
686 INT wifi_devRxRate;
687} wifi_device_info_t;
688
689#endif
690
691//For 5g Alias Interfaces
developer72fb0bb2023-01-11 09:46:29 +0800692static BOOL Radio_flag = TRUE;
693//wifi_setApBeaconRate(1, beaconRate);
694
695BOOL multiple_set = FALSE;
696
697struct params
698{
699 char * name;
700 char * value;
701};
702
703static int _syscmd(char *cmd, char *retBuf, int retBufSize)
704{
705 FILE *f;
706 char *ptr = retBuf;
707 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
708
709 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
710 if((f = popen(cmd, "r")) == NULL) {
711 fprintf(stderr,"\npopen %s error\n", cmd);
712 return RETURN_ERR;
713 }
714
715 while(!feof(f))
716 {
717 *ptr = 0;
718 if(bufSize>=128) {
719 bufbytes=128;
720 } else {
721 bufbytes=bufSize-1;
722 }
723
724 fgets(ptr,bufbytes,f);
725 readbytes=strlen(ptr);
726
727 if(!readbytes)
728 break;
729
730 bufSize-=readbytes;
731 ptr += readbytes;
732 }
733 cmd_ret = pclose(f);
734 retBuf[retBufSize-1]=0;
735 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
736
737 return cmd_ret >> 8;
738}
739
740INT radio_index_to_phy(int radioIndex)
741{
developer17038e62023-03-02 14:43:43 +0800742 /* TODO */
743 return radioIndex;
developer72fb0bb2023-01-11 09:46:29 +0800744}
745
746INT wifi_getMaxRadioNumber(INT *max_radio_num)
747{
748 char cmd[64] = {0};
749 char buf[4] = {0};
750
751 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
752
753 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
754 _syscmd(cmd, buf, sizeof(buf));
755 *max_radio_num = strtoul(buf, NULL, 10) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS:strtoul(buf, NULL, 10);
756
757 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
758
759 return RETURN_OK;
760}
761
developer17038e62023-03-02 14:43:43 +0800762wifi_band radio_index_to_band(int radioIndex)
763{
developer745f0bd2023-03-06 14:32:53 +0800764 return radio_band[radioIndex];
developer17038e62023-03-02 14:43:43 +0800765}
766
developer72fb0bb2023-01-11 09:46:29 +0800767wifi_band wifi_index_to_band(int apIndex)
768{
769 char cmd[128] = {0};
770 char buf[64] = {0};
771 int nl80211_band = 0;
772 int i = 0;
773 int phyIndex = 0;
774 int radioIndex = 0;
775 int max_radio_num = 0;
776 wifi_band band = band_invalid;
777
778 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
779
780 wifi_getMaxRadioNumber(&max_radio_num);
781 radioIndex = apIndex % max_radio_num;
782 phyIndex = radio_index_to_phy(radioIndex);
783 while(i < 10){
784 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Band .:' | tail -n 1 | tr -d ':\\n' | awk '{print $2}'", phyIndex);
785 _syscmd(cmd, buf, sizeof(buf));
786 nl80211_band = strtol(buf, NULL, 10);
787 if (nl80211_band == 1)
788 band = band_2_4;
789 else if (nl80211_band == 2)
790 band = band_5;
791 else if (nl80211_band == 4) // band == 3 is 60GHz
792 band = band_6;
793
794 if(band != band_invalid)
795 break;
developer69b61b02023-03-07 17:17:44 +0800796
developer72fb0bb2023-01-11 09:46:29 +0800797 i++;
798 sleep(1);
799 }
800
801 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
802 return band;
803}
804
805static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
806{
developer7e4a2a62023-04-06 19:56:03 +0800807 char cmd[MAX_CMD_SIZE] = {0};
808 char buf[MAX_BUF_SIZE] = {0};
809 int ret = 0;
developer72fb0bb2023-01-11 09:46:29 +0800810
developer7e4a2a62023-04-06 19:56:03 +0800811 ret = snprintf(cmd, MAX_CMD_SIZE, "cat %s 2> /dev/null | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"",
812 conf_file, param);
developer72fb0bb2023-01-11 09:46:29 +0800813
developer7e4a2a62023-04-06 19:56:03 +0800814 if (ret < 0) {
815 printf("%s: snprintf error!", __func__);
816 return -1;
817 }
818
819 ret = _syscmd(cmd, buf, sizeof(buf));
820 if ((ret != 0) && (strlen(buf) == 0)) {
821 printf("%s: _syscmd error!", __func__);
822 return -1;
823 }
824
825 snprintf(output, output_size, "%s", buf);
826
827 return 0;
developer72fb0bb2023-01-11 09:46:29 +0800828}
829
830static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
831{
developer7e4a2a62023-04-06 19:56:03 +0800832 char cmd[MAX_CMD_SIZE] = {0};
833 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +0800834
developer7e4a2a62023-04-06 19:56:03 +0800835 for (int i = 0; i < item_count; i++) {
developer72fb0bb2023-01-11 09:46:29 +0800836 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
developer7e4a2a62023-04-06 19:56:03 +0800837 if (strlen(buf) == 0) /*no such item, insert it*/
developera1255e42023-05-13 17:45:02 +0800838 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 +0800839 else /*find the item, update it*/
developer72fb0bb2023-01-11 09:46:29 +0800840 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 +0800841
developer72fb0bb2023-01-11 09:46:29 +0800842 if(_syscmd(cmd, buf, sizeof(buf)))
843 return -1;
844 }
845
developera1255e42023-05-13 17:45:02 +0800846 return 0;
847}
developerfde01262023-05-22 15:15:24 +0800848
developera1255e42023-05-13 17:45:02 +0800849static int wifi_datfileRead(char *conf_file, char *param, char *output, int output_size)
850{
851 char cmd[MAX_CMD_SIZE] = {0};
developera1255e42023-05-13 17:45:02 +0800852 int ret = 0;
developerfde01262023-05-22 15:15:24 +0800853 int len;
854
855 ret = snprintf(cmd, sizeof(cmd), "datconf -f %s get %s", conf_file, param);
856 if (ret < 0) {
857 printf("%s: snprintf error!", __func__);
858 return -1;
859 }
860
861 ret = _syscmd(cmd, output, output_size);
862 if ((ret != 0) && (strlen(output) == 0)) {
863 printf("%s: _syscmd error!", __func__);
864 return -1;
865 }
developera1255e42023-05-13 17:45:02 +0800866
developerfde01262023-05-22 15:15:24 +0800867 len = strlen(output);
868 if ((len > 0) && (output[len - 1] == '\n')) {
869 output[len - 1] = '\0';
870 }
871
872 return 0;
873}
developera1255e42023-05-13 17:45:02 +0800874
developera1255e42023-05-13 17:45:02 +0800875static int wifi_datfileWrite(char *conf_file, struct params *list, int item_count)
876{
developerfde01262023-05-22 15:15:24 +0800877 int ret;
developera1255e42023-05-13 17:45:02 +0800878 char cmd[MAX_CMD_SIZE] = {0};
879 char buf[MAX_BUF_SIZE] = {0};
880
881 for (int i = 0; i < item_count; i++) {
developerfde01262023-05-22 15:15:24 +0800882 ret = snprintf(cmd, sizeof(cmd), "datconf -f %s set %s \"%s\"", conf_file, list[i].name, list[i].value);
883 if (ret < 0) {
884 printf("%s: snprintf error!", __func__);
885 return -1;
886 }
developera1255e42023-05-13 17:45:02 +0800887
888 if(_syscmd(cmd, buf, sizeof(buf)))
889 return -1;
890 }
891
892 return 0;
893}
894
developerfde01262023-05-22 15:15:24 +0800895static int wifi_l1ProfileRead(char *param, char *output, int output_size)
896{
developerfde01262023-05-22 15:15:24 +0800897 int ret;
898
899 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
900 if (!param || !output || (output_size <= 0)) {
901 fprintf(stderr, "%s: invalid parameters", __func__);
902 return RETURN_ERR;
903 }
904
905 ret = wifi_datfileRead(l1profile, param, output, output_size);
906 if (ret != 0) {
907 fprintf(stderr, "%s: wifi_datfileRead %s from %s failed, ret:%d", __func__, param, l1profile, ret);
908 return RETURN_ERR;
909 }
910
911 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
912 return RETURN_OK;
913}
914
915static int wifi_CardProfileRead(int card_idx, char *param, char *output, int output_size)
916{
917 char option[64];
918 char card_profile_path[64];
919 int ret;
920
921 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
922
923 if (!param || !output || (output_size <= 0)) {
924 fprintf(stderr, "%s: invalid parameters", __func__);
925 return RETURN_ERR;
926 }
927
928 snprintf(option, sizeof(option), "INDEX%d_profile_path", card_idx);
929 ret = wifi_l1ProfileRead(option, card_profile_path, sizeof(card_profile_path));
930 if (ret != 0) {
931 fprintf(stderr, "%s: wifi_l1ProfileRead %s failed, ret:%d", __func__, option, ret);
932 return RETURN_ERR;
933 }
934
935 ret = wifi_datfileRead(card_profile_path, param, output, output_size);
936 if (ret != 0) {
937 fprintf(stderr, "%s: wifi_datfileRead %s from %s failed, ret:%d", __func__, param, card_profile_path, ret);
938 return RETURN_ERR;
939 }
940
941 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
942 return RETURN_OK;
943}
944
945static int wifi_BandProfileRead(int card_idx,
946 int radio_idx,
947 char *param,
948 char *output,
949 int output_size,
950 char *default_value)
951{
952 char option[64];
953 char band_profile_path[64];
954 int ret;
955
956 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
957 if (!param || !output || (output_size <= 0)) {
958 fprintf(stderr, "%s: invalid parameters", __func__);
959 return RETURN_ERR;
960 }
961
962 snprintf(option, sizeof(option), "BN%d_profile_path", radio_idx);
963 ret = wifi_CardProfileRead(card_idx, option, band_profile_path, sizeof(band_profile_path));
964 if (ret != 0) {
developerdaf24792023-06-06 11:40:04 +0800965 fprintf(stderr, "%s: wifi_CardProfileRead %s failed, ret:%d", __func__, option, ret);
developerfde01262023-05-22 15:15:24 +0800966 return RETURN_ERR;
967 }
968
969 ret = wifi_datfileRead(band_profile_path, param, output, output_size);
970 if (ret != 0) {
971 if (default_value) {
972 snprintf(output, output_size, "%s", default_value);
973 } else {
974 output[0] = '\0';
975 }
976 }
977
978 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
979 return RETURN_OK;
980}
981
developer72fb0bb2023-01-11 09:46:29 +0800982//For Getting Current Interface Name from corresponding hostapd configuration
983static int wifi_GetInterfaceName(int apIndex, char *interface_name)
984{
985 char config_file[128] = {0};
986
987 if (interface_name == NULL)
988 return RETURN_ERR;
989
990 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
991
992 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
993 wifi_hostapdRead(config_file, "interface", interface_name, 16);
994 if (strlen(interface_name) == 0)
995 return RETURN_ERR;
996
997 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
998 return RETURN_OK;
999}
1000
developera1255e42023-05-13 17:45:02 +08001001static UCHAR get_bssnum_byindex(INT radio_index, UCHAR *bss_cnt)
1002{
1003 char interface_name[IF_NAME_SIZE] = {0};
1004 char cmd[MAX_BUF_SIZE]={'\0'};
1005 char buf[MAX_CMD_SIZE]={'\0'};
1006 UCHAR channel = 0;
1007
1008 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
1009 return RETURN_ERR;
1010 /*interface name to channel number*/
1011 snprintf(cmd, sizeof(cmd), "iw dev %s info | grep -i 'channel' | cut -d ' ' -f2", interface_name);
1012 _syscmd(cmd, buf, sizeof(buf));
1013 channel = atoi(buf);
1014 WIFI_ENTRY_EXIT_DEBUG("%s:channel=%d\n", __func__, channel);
1015 /*count dev number with the same channel*/
1016 snprintf(cmd, sizeof(cmd), "iw dev | grep -i 'channel %d' | wc -l", channel);
1017 _syscmd(cmd, buf, sizeof(buf));
1018 *bss_cnt = atoi(buf) - 1;/*1 for apcli interface*/
1019 WIFI_ENTRY_EXIT_DEBUG("%s:bss_cnt=%d\n", __func__, *bss_cnt);
1020 return RETURN_OK;
1021}
developer72fb0bb2023-01-11 09:46:29 +08001022
1023static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
1024{
1025 char interface_name[16] = {0};
1026 if (multiple_set == TRUE)
1027 return RETURN_OK;
1028 char cmd[MAX_CMD_SIZE]="", output[32]="";
1029 FILE *fp;
1030 int i;
1031 //NOTE RELOAD should be done in ApplySSIDSettings
1032 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
1033 return RETURN_ERR;
1034 for(i=0; i<item_count; i++, list++)
1035 {
developerf6a87542023-05-16 15:47:28 +08001036 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s SET %s %s", interface_name, list->name, list->value);
developer72fb0bb2023-01-11 09:46:29 +08001037 if((fp = popen(cmd, "r"))==NULL)
1038 {
1039 perror("popen failed");
1040 return -1;
1041 }
1042 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
1043 {
1044 pclose(fp);
1045 perror("fgets failed");
1046 return -1;
1047 }
1048 pclose(fp);
1049 }
1050 return 0;
1051}
1052
developer7e4a2a62023-04-06 19:56:03 +08001053static int wifi_quick_reload_ap(int apIndex)
1054{
1055 char interface_name[IF_NAME_SIZE] = {0};
1056 char cmd[MAX_CMD_SIZE] = {0};
1057 char buf[MAX_BUF_SIZE] = {0};
1058
1059 if (multiple_set == TRUE)
1060 return RETURN_OK;
1061
1062 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
1063 return RETURN_ERR;
1064
1065 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s reload", interface_name);
1066 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
1067 return RETURN_ERR;
1068
1069 return RETURN_OK;
1070}
1071
developer72fb0bb2023-01-11 09:46:29 +08001072static int wifi_reloadAp(int apIndex)
1073{
1074 char interface_name[16] = {0};
developer22e0c672023-06-07 15:25:37 +08001075 int res;
1076
developer72fb0bb2023-01-11 09:46:29 +08001077 if (multiple_set == TRUE)
1078 return RETURN_OK;
1079 char cmd[MAX_CMD_SIZE]="";
1080 char buf[MAX_BUF_SIZE]="";
1081
1082 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
1083 return RETURN_ERR;
developer22e0c672023-06-07 15:25:37 +08001084 res = snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s reload", interface_name);
1085 if (os_snprintf_error(sizeof(cmd), res)) {
1086 wifi_debug(DEBUG_ERROR, "Unexpected snprintf fail\n");
1087 return RETURN_ERR;
1088 }
developer72fb0bb2023-01-11 09:46:29 +08001089 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
1090 return RETURN_ERR;
1091
developer22e0c672023-06-07 15:25:37 +08001092 res = snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s disable", interface_name);
1093 if (os_snprintf_error(sizeof(cmd), res)) {
1094 wifi_debug(DEBUG_ERROR, "Unexpected snprintf fail\n");
1095 return RETURN_ERR;
1096 }
developer72fb0bb2023-01-11 09:46:29 +08001097 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
1098 return RETURN_ERR;
1099
developer22e0c672023-06-07 15:25:37 +08001100 res = snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s enable", interface_name);
1101 if (os_snprintf_error(sizeof(cmd), res)) {
1102 wifi_debug(DEBUG_ERROR, "Unexpected snprintf fail\n");
1103 return RETURN_ERR;
1104 }
developer72fb0bb2023-01-11 09:46:29 +08001105 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
1106 return RETURN_ERR;
1107
1108 return RETURN_OK;
1109}
1110
1111INT File_Reading(CHAR *file, char *Value)
1112{
1113 FILE *fp = NULL;
1114 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
1115 int count = 0;
1116
1117 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1118 fp = popen(file,"r");
1119 if(fp == NULL)
1120 return RETURN_ERR;
1121
1122 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
1123 {
1124 for(count=0;buf[count]!='\n';count++)
1125 copy_buf[count]=buf[count];
1126 copy_buf[count]='\0';
1127 }
1128 strcpy(Value,copy_buf);
1129 pclose(fp);
1130 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1131
1132 return RETURN_OK;
1133}
1134
1135void wifi_RestartHostapd_2G()
1136{
1137 int Public2GApIndex = 4;
1138
1139 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1140 wifi_setApEnable(Public2GApIndex, FALSE);
1141 wifi_setApEnable(Public2GApIndex, TRUE);
1142 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1143}
1144
1145void wifi_RestartHostapd_5G()
1146{
1147 int Public5GApIndex = 5;
1148
1149 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1150 wifi_setApEnable(Public5GApIndex, FALSE);
1151 wifi_setApEnable(Public5GApIndex, TRUE);
1152 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1153}
1154
1155void wifi_RestartPrivateWifi_2G()
1156{
1157 int PrivateApIndex = 0;
1158
1159 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1160 wifi_setApEnable(PrivateApIndex, FALSE);
1161 wifi_setApEnable(PrivateApIndex, TRUE);
1162 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1163}
1164
1165void wifi_RestartPrivateWifi_5G()
1166{
1167 int Private5GApIndex = 1;
1168
1169 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1170 wifi_setApEnable(Private5GApIndex, FALSE);
1171 wifi_setApEnable(Private5GApIndex, TRUE);
1172 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1173}
1174
1175static int writeBandWidth(int radioIndex,char *bw_value)
1176{
1177 char buf[MAX_BUF_SIZE];
1178 char cmd[MAX_CMD_SIZE];
1179
1180 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
1181 if(_syscmd(cmd, buf, sizeof(buf)))
1182 {
1183 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
1184 _syscmd(cmd, buf, sizeof(buf));
1185 return RETURN_OK;
1186 }
1187
1188 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
1189 _syscmd(cmd,buf,sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08001190 return RETURN_OK;
1191}
1192
1193// Input could be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
1194INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
1195{
1196 struct params params={'\0'};
1197 char config_file[MAX_BUF_SIZE] = {0};
1198 char buf[MAX_BUF_SIZE] = {'\0'};
1199
1200 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1201 // Copy the numeric value
1202 if (strlen (beaconRate) >= 5) {
1203 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
1204 buf[strlen(beaconRate) - 4] = '\0';
1205 } else if (strlen(beaconRate) > 0)
1206 strcpy(buf, beaconRate);
1207 else
1208 return RETURN_ERR;
1209
1210 params.name = "beacon_rate";
1211 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
1212 if (strncmp(buf, "5.5", 3) == 0) {
1213 snprintf(buf, sizeof(buf), "55");
1214 params.value = buf;
1215 } else {
1216 strcat(buf, "0");
1217 params.value = buf;
1218 }
1219
1220 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1221 wifi_hostapdWrite(config_file, &params, 1);
1222 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1223 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1224
1225 return RETURN_OK;
1226}
1227
1228INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
1229{
1230 char config_file[128] = {'\0'};
developer5a333cf2023-06-06 18:18:50 +08001231 char temp_output[MAX_BUF_SIZE] = {'\0'};
developer72fb0bb2023-01-11 09:46:29 +08001232 char buf[128] = {'\0'};
1233 char cmd[128] = {'\0'};
1234 int rate = 0;
1235 int phyId = 0;
1236
1237 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1238 if (NULL == beaconRate)
1239 return RETURN_ERR;
1240
1241 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1242 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
1243 phyId = radio_index_to_phy(radioIndex);
1244 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
1245 if(strlen(buf) > 0) {
1246 if (strncmp(buf, "55", 2) == 0)
1247 snprintf(temp_output, sizeof(temp_output), "5.5Mbps");
1248 else {
1249 rate = strtol(buf, NULL, 10)/10;
1250 snprintf(temp_output, sizeof(temp_output), "%dMbps", rate);
1251 }
1252 } else {
1253 // config not set, so we would use lowest rate as default
1254 sprintf(cmd, "iw phy%d info | grep Bitrates -A1 | tail -n 1 | awk '{print $2}' | tr -d '.0\\n'", phyId);
1255 _syscmd(cmd, buf, sizeof(buf));
1256 snprintf(temp_output, sizeof(temp_output), "%sMbps", buf);
1257 }
developerdaf24792023-06-06 11:40:04 +08001258 strncpy(beaconRate, temp_output, strlen(temp_output));
developer72fb0bb2023-01-11 09:46:29 +08001259 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1260
1261 return RETURN_OK;
1262}
1263
1264INT wifi_setLED(INT radioIndex, BOOL enable)
1265{
1266 return 0;
1267}
1268INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
1269{
1270 return RETURN_OK;
1271}
1272/**********************************************************************************
1273 *
developer69b61b02023-03-07 17:17:44 +08001274 * Wifi Subsystem level function prototypes
developer72fb0bb2023-01-11 09:46:29 +08001275 *
1276**********************************************************************************/
1277//---------------------------------------------------------------------------------------------------
1278//Wifi system api
1279//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 +08001280INT wifi_getHalVersion(CHAR *output_string) //RDKB
developer72fb0bb2023-01-11 09:46:29 +08001281{
1282 if(!output_string)
1283 return RETURN_ERR;
1284 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
1285
1286 return RETURN_OK;
1287}
1288
1289
1290/* wifi_factoryReset() function */
1291/**
developer69b61b02023-03-07 17:17:44 +08001292* @description Clears internal variables to implement a factory reset of the Wi-Fi
developer72fb0bb2023-01-11 09:46:29 +08001293* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
1294*
1295* @param None
1296*
1297* @return The status of the operation.
1298* @retval RETURN_OK if successful.
1299* @retval RETURN_ERR if any error is detected
1300*
1301* @execution Synchronous
1302* @sideeffect None
1303*
1304* @note This function must not suspend and must not invoke any blocking system
1305* calls. It should probably just send a message to a driver event handler task.
1306*
1307*/
1308INT wifi_factoryReset()
1309{
developer47cc27a2023-05-17 23:09:58 +08001310 char cmd[MAX_CMD_SIZE] = {0};
1311 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08001312
developer47cc27a2023-05-17 23:09:58 +08001313 /*delete running hostapd conf files*/
1314 wifi_dbg_printf("\n[%s]: deleting hostapd conf file.", __func__);
1315 snprintf(cmd, MAX_CMD_SIZE, "rm -rf /nvram/*.conf");
1316 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08001317
developer47cc27a2023-05-17 23:09:58 +08001318 wifi_PrepareDefaultHostapdConfigs();
1319 wifi_psk_file_reset();
1320
1321 memset(cmd, 0, MAX_CMD_SIZE);
1322 memset(buf, 0, MAX_BUF_SIZE);
1323
1324 snprintf(cmd, MAX_CMD_SIZE, "systemctl restart hostapd.service");
1325 _syscmd(cmd, buf, sizeof(buf));
1326
1327 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08001328}
1329
1330/* wifi_factoryResetRadios() function */
1331/**
1332* @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.
1333*
1334* @param None
1335* @return The status of the operation
1336* @retval RETURN_OK if successful
1337* @retval RETURN_ERR if any error is detected
1338*
1339* @execution Synchronous
1340*
1341* @sideeffect None
1342*
1343* @note This function must not suspend and must not invoke any blocking system
1344* calls. It should probably just send a message to a driver event handler task.
1345*
1346*/
1347INT wifi_factoryResetRadios()
1348{
1349 if((RETURN_OK == wifi_factoryResetRadio(0)) && (RETURN_OK == wifi_factoryResetRadio(1)))
1350 return RETURN_OK;
1351
1352 return RETURN_ERR;
1353}
1354
developerfead3972023-05-25 20:15:02 +08001355ULONG get_radio_reset_cnt(int radioIndex)
1356{
1357 char cmd[MAX_CMD_SIZE] = {0};
1358 char buf[MAX_BUF_SIZE] = {0};
1359 ULONG reset_count = 0;
1360
1361 snprintf(cmd, MAX_CMD_SIZE, "cat %s 2> /dev/null | grep \"^reset%d=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"",
1362 RADIO_RESET_FILE, radioIndex);
1363 _syscmd(cmd, buf, sizeof(buf));
1364
1365 if (strlen(buf) == 0)
1366 return 0;
1367 else {
1368 reset_count = atol(buf);
1369 return reset_count;
1370 }
1371}
1372void update_radio_reset_cnt(int radioIndex)
1373{
1374 char cmd[MAX_CMD_SIZE] = {0};
1375 char buf[MAX_BUF_SIZE] = {0};
1376 ULONG reset_count = 0;
1377
1378 snprintf(cmd, MAX_CMD_SIZE, "cat %s 2> /dev/null | grep \"^reset%d=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"",
1379 RADIO_RESET_FILE, radioIndex);
1380 _syscmd(cmd, buf, sizeof(buf));
1381
1382 if (strlen(buf) == 0)
1383 snprintf(cmd, sizeof(cmd), "sed -i -e '$a reset%d=1' %s", radioIndex, RADIO_RESET_FILE);
1384 else {
1385 reset_count = atol(buf);
1386 reset_count++;
1387 snprintf(cmd, sizeof(cmd), "sed -i \"s/^reset%d=.*/reset%d=%lu/\" %s", radioIndex, radioIndex, reset_count, RADIO_RESET_FILE);
1388 }
1389 _syscmd(cmd, buf, sizeof(buf));
1390}
developer72fb0bb2023-01-11 09:46:29 +08001391
1392/* wifi_factoryResetRadio() function */
1393/**
1394* @description Restore selected radio parameters without touching access point parameters
1395*
1396* @param radioIndex - Index of Wi-Fi Radio channel
1397*
1398* @return The status of the operation.
1399* @retval RETURN_OK if successful.
1400* @retval RETURN_ERR if any error is detected
1401*
1402* @execution Synchronous.
1403* @sideeffect None.
1404*
1405* @note This function must not suspend and must not invoke any blocking system
1406* calls. It should probably just send a message to a driver event handler task.
1407*
1408*/
1409INT wifi_factoryResetRadio(int radioIndex) //RDKB
1410{
developer47cc27a2023-05-17 23:09:58 +08001411 char cmd[MAX_CMD_SIZE] = {0};
1412 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08001413
developer47cc27a2023-05-17 23:09:58 +08001414 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08001415
developerb2977562023-05-24 17:54:12 +08001416 wifi_dat_file_reset_by_radio(radioIndex);
developer47cc27a2023-05-17 23:09:58 +08001417
developerb2977562023-05-24 17:54:12 +08001418 /*reset gi setting*/
1419 snprintf(cmd, sizeof(cmd), "echo 'Auto' > %s%d.txt", GUARD_INTERVAL_FILE, radioIndex);
developer47cc27a2023-05-17 23:09:58 +08001420 _syscmd(cmd, buf, sizeof(buf));
1421
developerb2977562023-05-24 17:54:12 +08001422 /*TBD: check mbss issue*/
1423 wifi_factoryResetAP(radioIndex);
developerfead3972023-05-25 20:15:02 +08001424 update_radio_reset_cnt(radioIndex);
developerb2977562023-05-24 17:54:12 +08001425
developer47cc27a2023-05-17 23:09:58 +08001426 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
1427 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08001428}
1429
1430/* wifi_initRadio() function */
1431/**
1432* Description: This function call initializes the specified radio.
developer69b61b02023-03-07 17:17:44 +08001433* Implementation specifics may dictate the functionality since
developer72fb0bb2023-01-11 09:46:29 +08001434* different hardware implementations may have different initilization requirements.
1435* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
1436*
1437* @return The status of the operation.
1438* @retval RETURN_OK if successful.
1439* @retval RETURN_ERR if any error is detected
1440*
1441* @execution Synchronous.
1442* @sideeffect None.
1443*
1444* @note This function must not suspend and must not invoke any blocking system
1445* calls. It should probably just send a message to a driver event handler task.
1446*
1447*/
1448INT wifi_initRadio(INT radioIndex)
1449{
1450 //TODO: Initializes the wifi subsystem (for specified radio)
1451 return RETURN_OK;
1452}
1453void macfilter_init()
1454{
1455 char count[4]={'\0'};
1456 char buf[253]={'\0'};
1457 char tmp[19]={'\0'};
1458 int dev_count,block,mac_entry=0;
1459 char res[4]={'\0'};
1460 char acl_file_path[64] = {'\0'};
1461 FILE *fp = NULL;
1462 int index=0;
1463 char iface[10]={'\0'};
1464 char config_file[MAX_BUF_SIZE] = {0};
1465
1466
1467 sprintf(acl_file_path,"/tmp/mac_filter.sh");
1468
1469 fp=fopen(acl_file_path,"w+");
1470 if (fp == NULL) {
1471 fprintf(stderr, "%s: failed to open file %s.\n", __func__, acl_file_path);
developer17038e62023-03-02 14:43:43 +08001472 return;
developer72fb0bb2023-01-11 09:46:29 +08001473 }
1474 sprintf(buf,"#!/bin/sh \n");
1475 fprintf(fp,"%s\n",buf);
1476
1477 system("chmod 0777 /tmp/mac_filter.sh");
1478
1479 for(index=0;index<=1;index++)
1480 {
1481 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
1482 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
1483 sprintf(buf,"syscfg get %dcountfilter",index);
1484 _syscmd(buf,count,sizeof(count));
1485 mac_entry=atoi(count);
1486
1487 sprintf(buf,"syscfg get %dblockall",index);
1488 _syscmd(buf,res,sizeof(res));
1489 block = atoi(res);
1490
1491 //Allow only those macs mentioned in ACL
1492 if(block==1)
1493 {
1494 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1495 fprintf(fp,"%s\n",buf);
1496 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1497 {
1498 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1499 _syscmd(buf,tmp,sizeof(tmp));
1500 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
1501 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
1502 fprintf(fp,"%s\n",buf);
1503 }
1504 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
1505 fprintf(fp,"%s\n",buf);
1506 }
1507
1508 //Block all the macs mentioned in ACL
1509 else if(block==2)
1510 {
1511 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1512 fprintf(fp,"%s\n",buf);
1513
1514 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1515 {
1516 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1517 _syscmd(buf,tmp,sizeof(tmp));
1518 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
1519 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
1520 fprintf(fp,"%s\n",buf);
1521 }
1522 }
1523 }
1524 fclose(fp);
1525}
1526
developer17038e62023-03-02 14:43:43 +08001527
1528static void
1529wifi_ParseProfile(void)
1530{
1531 int i;
1532 int max_radio_num = 0;
1533 int card_idx;
1534 int band_idx;
1535 int phy_idx = 0;
developer745f0bd2023-03-06 14:32:53 +08001536 int wireless_mode = 0;
developer17038e62023-03-02 14:43:43 +08001537 char buf[MAX_BUF_SIZE] = {0};
1538 char chip_name[12];
1539 char card_profile[MAX_BUF_SIZE] = {0};
1540 char band_profile[MAX_BUF_SIZE] = {0};
developer17038e62023-03-02 14:43:43 +08001541
1542 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1543
1544 memset(main_prefix, 0, sizeof(main_prefix));
1545 memset(ext_prefix, 0, sizeof(ext_prefix));
1546 memset(default_ssid, 0, sizeof(default_ssid));
developer745f0bd2023-03-06 14:32:53 +08001547 for (i = 0; i < MAX_NUM_RADIOS; i++)
1548 radio_band[i] = band_invalid;
developer17038e62023-03-02 14:43:43 +08001549
1550 if (wifi_getMaxRadioNumber(&max_radio_num) != RETURN_OK) {
1551 /* LOG */
1552 return;
1553 }
1554
1555 for (card_idx = 0; card_idx < 3; card_idx++) {
1556 snprintf(buf, sizeof(buf), "INDEX%d", card_idx);
1557 if (get_value(l1profile, buf, chip_name, sizeof(chip_name)) < 0) {
1558 break;
1559 }
1560 snprintf(buf, sizeof(buf), "INDEX%d_profile_path", card_idx);
1561 if (get_value(l1profile, buf, card_profile, sizeof(card_profile)) < 0) {
1562 break;
1563 }
1564 for (band_idx = 0; band_idx < 3; band_idx++) {
1565 snprintf(buf, sizeof(buf), "BN%d_profile_path", band_idx);
1566 if (get_value(card_profile, buf, band_profile, sizeof(band_profile)) < 0) {
1567 /* LOG */
1568 break;
1569 }
1570
1571 snprintf(buf, sizeof(buf), "INDEX%d_main_ifname", card_idx);
1572 if (get_value_by_idx(l1profile, buf, band_idx, main_prefix[phy_idx], IFNAMSIZ) < 0) {
1573 /* LOG */
1574 }
1575
1576 snprintf(buf, sizeof(buf), "INDEX%d_ext_ifname", card_idx);
1577 if (get_value_by_idx(l1profile, buf, band_idx, ext_prefix[phy_idx], IFNAMSIZ) < 0) {
1578 /* LOG */
1579 }
1580
1581 if (get_value(band_profile, "SSID1", default_ssid[phy_idx], sizeof(default_ssid[phy_idx])) < 0) {
1582 /* LOG */
1583 }
developer745f0bd2023-03-06 14:32:53 +08001584 if (get_value(band_profile, "WirelessMode", buf, sizeof(buf)) < 0) {
1585 /* LOG */
1586 }
1587
1588 wireless_mode = atoi(buf);
1589 switch (wireless_mode) {
1590 case 22:
1591 case 16:
1592 case 6:
1593 case 4:
1594 case 1:
1595 radio_band[phy_idx] = band_2_4;
1596 break;
1597 case 23:
1598 case 17:
1599 case 14:
1600 case 11:
1601 case 2:
1602 radio_band[phy_idx] = band_5;
1603 break;
1604 case 24:
1605 case 18:
1606 radio_band[phy_idx] = band_6;
1607 break;
1608 }
developer17038e62023-03-02 14:43:43 +08001609 phy_idx++;
1610 }
1611 }
1612
1613 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1614}
1615
1616static void
1617wifi_PrepareDefaultHostapdConfigs(void)
1618{
developer0132ed92023-03-21 13:48:53 +08001619 int radio_idx;
1620 int bss_idx;
1621 int ap_idx;
developer0132ed92023-03-21 13:48:53 +08001622 char buf[MAX_BUF_SIZE] = {0};
developerb149d9d2023-06-06 16:14:22 +08001623 char config_file[MAX_SUB_CMD_SIZE] = {0};
developer0132ed92023-03-21 13:48:53 +08001624 char ssid[MAX_BUF_SIZE] = {0};
1625 char interface[32] = {0};
1626 char ret_buf[MAX_BUF_SIZE] = {0};
1627 char psk_file[64] = {0};
1628 struct params params[3];
developer17038e62023-03-02 14:43:43 +08001629
developer0132ed92023-03-21 13:48:53 +08001630 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1631 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++) {
developer47cc27a2023-05-17 23:09:58 +08001632
developer0132ed92023-03-21 13:48:53 +08001633 for (bss_idx = 0; bss_idx < 5; bss_idx++) {
developer47cc27a2023-05-17 23:09:58 +08001634 ap_idx = array_index_to_vap_index(radio_idx, bss_idx);
developer0132ed92023-03-21 13:48:53 +08001635
developer47cc27a2023-05-17 23:09:58 +08001636 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_idx);
developere740c2a2023-05-23 18:34:32 +08001637 snprintf(buf, sizeof(buf), "cp /etc/hostapd-%s.conf %s", wifi_band_str[radio_idx], config_file);
developer47cc27a2023-05-17 23:09:58 +08001638 _syscmd(buf, ret_buf, sizeof(ret_buf));
developer17038e62023-03-02 14:43:43 +08001639
developer47cc27a2023-05-17 23:09:58 +08001640 if (radio_idx == band_2_4) {
1641 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_2G, bss_idx);
1642 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI2G, bss_idx);
1643 } else if (radio_idx == band_5) {
1644 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_5G, bss_idx);
1645 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI5G, bss_idx);
1646 } else if (radio_idx == band_6) {
1647 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_6G, bss_idx);
1648 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI6G, bss_idx);
1649 }
developer17038e62023-03-02 14:43:43 +08001650
developer47cc27a2023-05-17 23:09:58 +08001651 /* fix wpa_psk_file path */
1652 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", ap_idx);
developer17038e62023-03-02 14:43:43 +08001653
developer47cc27a2023-05-17 23:09:58 +08001654 params[0].name = "ssid";
1655 params[0].value = ssid;
1656 params[1].name = "interface";
1657 params[1].value = interface;
1658 params[2].name = "wpa_psk_file";
1659 params[2].value = psk_file;
developer17038e62023-03-02 14:43:43 +08001660
developer47cc27a2023-05-17 23:09:58 +08001661 wifi_hostapdWrite(config_file, params, 3);
developer0132ed92023-03-21 13:48:53 +08001662 }
1663 }
1664 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer17038e62023-03-02 14:43:43 +08001665}
1666
1667static void
developer17038e62023-03-02 14:43:43 +08001668wifi_BringDownInterfacesForRadio(int radio_idx)
1669{
developer17038e62023-03-02 14:43:43 +08001670 char cmd[MAX_BUF_SIZE] = {0};
developer17038e62023-03-02 14:43:43 +08001671 char ret_buf[MAX_BUF_SIZE]={'\0'};
1672
1673 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer17038e62023-03-02 14:43:43 +08001674
developer8a3bbbf2023-03-15 17:47:23 +08001675 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s", main_prefix[radio_idx]);
1676 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1677
developer17038e62023-03-02 14:43:43 +08001678 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1679}
1680
1681
1682static void
1683wifi_BringDownInterfaces(void)
1684{
1685 int radio_idx;
developer17038e62023-03-02 14:43:43 +08001686 int band_idx;
developer17038e62023-03-02 14:43:43 +08001687
1688 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1689 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++) {
1690 band_idx = radio_index_to_band(radio_idx);
1691 if (band_idx < 0) {
1692 break;
1693 }
1694 wifi_BringDownInterfacesForRadio(radio_idx);
1695 }
1696 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1697}
1698
developerb2977562023-05-24 17:54:12 +08001699static void wifi_dat_file_reset_by_radio(char radio_idx)
1700{
developerb149d9d2023-06-06 16:14:22 +08001701 char cmd[MAX_CMD_SIZE * 2] = {0};
developerb2977562023-05-24 17:54:12 +08001702 char ret_buf[MAX_BUF_SIZE] = {0};
developerb149d9d2023-06-06 16:14:22 +08001703 char rom_dat_file[MAX_SUB_CMD_SIZE]= {0};
1704 char dat_file[MAX_SUB_CMD_SIZE]= {0};
developerb2977562023-05-24 17:54:12 +08001705
1706 snprintf(rom_dat_file, sizeof(rom_dat_file), "%s%d.dat", ROM_LOGAN_DAT_FILE, radio_idx);
1707 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, radio_idx);
developerb149d9d2023-06-06 16:14:22 +08001708 snprintf(cmd, (MAX_CMD_SIZE * 2), "cp -rf %s %s", rom_dat_file, dat_file);
developerb2977562023-05-24 17:54:12 +08001709 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1710
1711}
1712
developer47cc27a2023-05-17 23:09:58 +08001713static void wifi_psk_file_reset()
1714{
1715 char cmd[MAX_CMD_SIZE] = {0};
1716 char ret_buf[MAX_BUF_SIZE] = {0};
developerb149d9d2023-06-06 16:14:22 +08001717 char psk_file[MAX_SUB_CMD_SIZE]= {0};
developer47cc27a2023-05-17 23:09:58 +08001718 char vap_idx = 0;
1719
1720 for (vap_idx = 0; vap_idx < MAX_APS; vap_idx++) {
1721 snprintf(psk_file, sizeof(psk_file), "%s%d.psk", PSK_FILE, vap_idx);
1722
1723 if (access(psk_file, F_OK) != 0) {
1724 snprintf(cmd, MAX_CMD_SIZE, "touch %s", psk_file);
1725 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1726 } else {
1727 snprintf(cmd, MAX_CMD_SIZE, "echo '' > %s", psk_file);
1728 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1729 }
1730 }
developerb2977562023-05-24 17:54:12 +08001731}
1732
developer8a3bbbf2023-03-15 17:47:23 +08001733static void wifi_vap_status_reset()
1734{
1735 char cmd[MAX_CMD_SIZE] = {0};
1736 char ret_buf[MAX_BUF_SIZE] = {0};
developer863a4a62023-06-06 16:55:59 +08001737 int radio_idx = 0;
developer8a3bbbf2023-03-15 17:47:23 +08001738 char bss_idx = 0;
developer8666b312023-03-24 14:05:31 +08001739
developer8a3bbbf2023-03-15 17:47:23 +08001740 if (access(VAP_STATUS_FILE, F_OK) != 0) {
1741 snprintf(cmd, MAX_CMD_SIZE, "touch %s", VAP_STATUS_FILE);
1742 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1743 } else {
1744 snprintf(cmd, MAX_CMD_SIZE, "echo '' > %s", VAP_STATUS_FILE);
1745 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1746 }
1747
1748 memset(cmd, 0, MAX_CMD_SIZE);
1749 memset(ret_buf, 0, MAX_BUF_SIZE);
1750
1751 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++)
1752 for (bss_idx = 0; bss_idx < 5; bss_idx++) {
1753 snprintf(cmd, MAX_CMD_SIZE, "echo %s%d=0 >> %s", ext_prefix[radio_idx], bss_idx, VAP_STATUS_FILE);
1754 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1755 }
1756
developerfead3972023-05-25 20:15:02 +08001757}
1758
1759static void wifi_radio_reset_count_reset()
1760{
1761 char cmd[MAX_CMD_SIZE] = {0};
1762 char ret_buf[MAX_BUF_SIZE] = {0};
1763
1764 if (access(VAP_STATUS_FILE, F_OK) != 0) {
1765 snprintf(cmd, MAX_CMD_SIZE, "touch %s", RADIO_RESET_FILE);
1766 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1767 } else {
1768 snprintf(cmd, MAX_CMD_SIZE, "echo '' > %s", RADIO_RESET_FILE);
1769 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1770 }
developer8a3bbbf2023-03-15 17:47:23 +08001771}
developer17038e62023-03-02 14:43:43 +08001772
developer72fb0bb2023-01-11 09:46:29 +08001773// Initializes the wifi subsystem (all radios)
1774INT wifi_init() //RDKB
1775{
developer96b38512023-02-22 11:17:45 +08001776 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developercc9a4f32023-05-30 17:40:02 +08001777 static int CallOnce = 1;
developer96b38512023-02-22 11:17:45 +08001778 //Not intitializing macfilter for Turris-Omnia Platform for now
1779 //macfilter_init();
developercc9a4f32023-05-30 17:40:02 +08001780 if (CallOnce) {
1781 wifi_ParseProfile();
1782 wifi_PrepareDefaultHostapdConfigs();
1783 wifi_psk_file_reset();
1784 //system("/usr/sbin/iw reg set US");
1785 system("systemctl start hostapd.service");
1786 sleep(2);
developer8a3bbbf2023-03-15 17:47:23 +08001787
developercc9a4f32023-05-30 17:40:02 +08001788 wifi_vap_status_reset();
1789 wifi_radio_reset_count_reset();
1790 CallOnce = 0;
1791 }
developer96b38512023-02-22 11:17:45 +08001792
1793 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08001794
1795 return RETURN_OK;
1796}
1797
1798/* wifi_reset() function */
1799/**
1800* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
developer69b61b02023-03-07 17:17:44 +08001801* Implementation specifics may dictate what is actualy reset since
developer72fb0bb2023-01-11 09:46:29 +08001802* different hardware implementations may have different requirements.
1803* Parameters : None
1804*
1805* @return The status of the operation.
1806* @retval RETURN_OK if successful.
1807* @retval RETURN_ERR if any error is detected
1808*
1809* @execution Synchronous.
1810* @sideeffect None.
1811*
1812* @note This function must not suspend and must not invoke any blocking system
1813* calls. It should probably just send a message to a driver event handler task.
1814*
1815*/
1816INT wifi_reset()
1817{
developer17038e62023-03-02 14:43:43 +08001818
1819 wifi_BringDownInterfaces();
1820 sleep(2);
1821
developer96b38512023-02-22 11:17:45 +08001822 //TODO: resets the wifi subsystem, deletes all APs
1823 system("systemctl stop hostapd.service");
1824 sleep(2);
developer17038e62023-03-02 14:43:43 +08001825
developer96b38512023-02-22 11:17:45 +08001826 system("systemctl start hostapd.service");
1827 sleep(5);
developer17038e62023-03-02 14:43:43 +08001828
1829 wifi_PrepareDefaultHostapdConfigs();
developer47cc27a2023-05-17 23:09:58 +08001830 wifi_psk_file_reset();
developer17038e62023-03-02 14:43:43 +08001831 sleep(2);
developer8a3bbbf2023-03-15 17:47:23 +08001832
1833 wifi_vap_status_reset();
1834
developer72fb0bb2023-01-11 09:46:29 +08001835 return RETURN_OK;
1836}
1837
1838/* wifi_down() function */
1839/**
1840* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
developer69b61b02023-03-07 17:17:44 +08001841* Implementation specifics may dictate some functionality since
developer72fb0bb2023-01-11 09:46:29 +08001842* different hardware implementations may have different requirements.
1843*
1844* @param None
1845*
1846* @return The status of the operation
1847* @retval RETURN_OK if successful
1848* @retval RETURN_ERR if any error is detected
1849*
1850* @execution Synchronous
1851* @sideeffect None
1852*
1853* @note This function must not suspend and must not invoke any blocking system
1854* calls. It should probably just send a message to a driver event handler task.
1855*
1856*/
1857INT wifi_down()
1858{
developer96b38512023-02-22 11:17:45 +08001859 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developerb2977562023-05-24 17:54:12 +08001860 int max_num_radios = 0;
1861 wifi_getMaxRadioNumber(&max_num_radios);
developer17038e62023-03-02 14:43:43 +08001862
developerb2977562023-05-24 17:54:12 +08001863 for (int radioIndex = 0; radioIndex < max_num_radios; radioIndex++)
1864 wifi_setRadioEnable(radioIndex, FALSE);
1865
developer72fb0bb2023-01-11 09:46:29 +08001866 return RETURN_OK;
1867}
1868
1869
1870/* wifi_createInitialConfigFiles() function */
1871/**
1872* @description This function creates wifi configuration files. The format
developer69b61b02023-03-07 17:17:44 +08001873* and content of these files are implementation dependent. This function call is
1874* used to trigger this task if necessary. Some implementations may not need this
1875* function. If an implementation does not need to create config files the function call can
developer72fb0bb2023-01-11 09:46:29 +08001876* do nothing and return RETURN_OK.
1877*
1878* @param None
1879*
1880* @return The status of the operation
1881* @retval RETURN_OK if successful
1882* @retval RETURN_ERR if any error is detected
1883*
1884* @execution Synchronous
1885* @sideeffect None
1886*
1887* @note This function must not suspend and must not invoke any blocking system
1888* calls. It should probably just send a message to a driver event handler task.
1889*
1890*/
1891INT wifi_createInitialConfigFiles()
1892{
1893 //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)
1894 return RETURN_OK;
1895}
1896
developer7e4a2a62023-04-06 19:56:03 +08001897/* outputs the country code to a max 64 character string */
developer72fb0bb2023-01-11 09:46:29 +08001898INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1899{
developerfde01262023-05-22 15:15:24 +08001900 int ret;
developer72fb0bb2023-01-11 09:46:29 +08001901
developerfde01262023-05-22 15:15:24 +08001902 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer7e4a2a62023-04-06 19:56:03 +08001903
developerfde01262023-05-22 15:15:24 +08001904 ret = wifi_BandProfileRead(0, radioIndex, "CountryCode", output_string, 64, NULL);
1905 if (ret != 0) {
1906 fprintf(stderr, "%s: wifi_BandProfileRead CountryCode failed\n", __func__);
1907 return RETURN_ERR;
1908 }
developer7e4a2a62023-04-06 19:56:03 +08001909
developerfde01262023-05-22 15:15:24 +08001910 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer7e4a2a62023-04-06 19:56:03 +08001911
developerfde01262023-05-22 15:15:24 +08001912 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08001913}
1914
1915INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1916{
developer7e4a2a62023-04-06 19:56:03 +08001917 /*Set wifi config. Wait for wifi reset to apply*/
developer7e4a2a62023-04-06 19:56:03 +08001918 struct params params;
1919 char config_file[MAX_BUF_SIZE] = {0};
1920 int ret = 0;
developer72fb0bb2023-01-11 09:46:29 +08001921
developer7e4a2a62023-04-06 19:56:03 +08001922 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08001923
developer7e4a2a62023-04-06 19:56:03 +08001924 if(NULL == CountryCode || strlen(CountryCode) >= 32 ) {
1925 printf("%s: input para error!!!\n", __func__);
1926 return RETURN_ERR;
1927 }
developer72fb0bb2023-01-11 09:46:29 +08001928
developerc79e9172023-06-06 19:48:03 +08001929 if (!strlen(CountryCode)) {
1930 memcpy(CountryCode, "US", strlen("US")); /*default set the code to US*/
1931 CountryCode[2] = '\0';
1932 }
developer72fb0bb2023-01-11 09:46:29 +08001933
developer7e4a2a62023-04-06 19:56:03 +08001934 params.name = "country_code";
1935 params.value = CountryCode;
developer72fb0bb2023-01-11 09:46:29 +08001936
developer7e4a2a62023-04-06 19:56:03 +08001937 snprintf(config_file, MAX_BUF_SIZE, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1938 ret = wifi_hostapdWrite(config_file, &params, 1);
1939
1940 if (ret) {
1941 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n",
1942 __func__, ret);
1943 }
1944
1945 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1946
1947 if (ret) {
1948 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n",
1949 __func__, ret);
1950 }
1951
1952 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
1953
1954 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08001955}
1956
1957INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1958{
1959 char interface_name[16] = {0};
1960 char channel_util_file[64] = {0};
1961 char cmd[128] = {0};
1962 char buf[128] = {0};
developer2f79c922023-06-02 17:33:42 +08001963 char *line = NULL;
developer72fb0bb2023-01-11 09:46:29 +08001964 char *param = NULL, *value = NULL;
1965 int read = 0;
1966 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1967 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1968 size_t len = 0;
1969 FILE *f = NULL;
1970
1971 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1972
1973 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
1974 return RETURN_ERR;
1975 snprintf(cmd, sizeof(cmd), "iw %s scan | grep signal | awk '{print $2}' | sort -n | tail -n1", interface_name);
1976 _syscmd(cmd, buf, sizeof(buf));
1977 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1978
1979 memset(cmd, 0, sizeof(cmd));
1980 memset(buf, 0, sizeof(buf));
1981 snprintf(cmd, sizeof(cmd), "iw %s survey dump | grep 'in use' -A6", interface_name);
1982 if ((f = popen(cmd, "r")) == NULL) {
1983 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1984 return RETURN_ERR;
1985 }
1986
1987 read = getline(&line, &len, f);
1988 while (read != -1) {
1989 param = strtok(line, ":\t");
1990 value = strtok(NULL, " ");
1991 if(strstr(param, "frequency") != NULL) {
1992 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1993 }
1994 if(strstr(param, "noise") != NULL) {
1995 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1996 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1997 }
1998 if(strstr(param, "channel active time") != NULL) {
1999 ActiveTime = strtol(value, NULL, 10);
2000 }
2001 if(strstr(param, "channel busy time") != NULL) {
2002 BusyTime = strtol(value, NULL, 10);
2003 }
2004 if(strstr(param, "channel transmit time") != NULL) {
2005 TransmitTime = strtol(value, NULL, 10);
2006 }
2007 read = getline(&line, &len, f);
2008 }
2009 pclose(f);
2010
2011 // The file should store the last active, busy and transmit time
2012 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
2013 f = fopen(channel_util_file, "r");
2014 if (f != NULL) {
2015 read = getline(&line, &len, f);
2016 preActiveTime = strtol(line, NULL, 10);
2017 read = getline(&line, &len, f);
2018 preBusyTime = strtol(line, NULL, 10);
2019 read = getline(&line, &len, f);
2020 preTransmitTime = strtol(line, NULL, 10);
2021 fclose(f);
2022 }
2023
2024 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
2025 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
2026
2027 f = fopen(channel_util_file, "w");
2028 if (f != NULL) {
2029 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
2030 fclose(f);
2031 }
2032 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2033 return RETURN_OK;
2034}
2035
2036/**********************************************************************************
2037 *
2038 * Wifi radio level function prototypes
2039 *
2040**********************************************************************************/
2041
2042//Get the total number of radios in this wifi subsystem
2043INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
2044{
2045 if (NULL == output)
2046 return RETURN_ERR;
2047 *output = MAX_NUM_RADIOS;
2048
2049 return RETURN_OK;
2050}
2051
developer69b61b02023-03-07 17:17:44 +08002052//Get the total number of SSID entries in this wifi subsystem
developer72fb0bb2023-01-11 09:46:29 +08002053INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
2054{
2055 if (NULL == output)
2056 return RETURN_ERR;
2057 *output = MAX_APS;
2058
2059 return RETURN_OK;
2060}
2061
2062//Get the Radio enable config parameter
2063INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
2064{
developer56fbedb2023-05-30 16:47:05 +08002065 char interface_name[16] = {0};
2066 char buf[128] = {0}, cmd[128] = {0};
2067 int apIndex;
2068 int max_radio_num = 0;
developer3a85ab82023-05-25 11:59:38 +08002069
developer56fbedb2023-05-30 16:47:05 +08002070 if (NULL == output_bool)
2071 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08002072
developer56fbedb2023-05-30 16:47:05 +08002073 *output_bool = FALSE;
developer72fb0bb2023-01-11 09:46:29 +08002074
developer56fbedb2023-05-30 16:47:05 +08002075 wifi_getMaxRadioNumber(&max_radio_num);
developer72fb0bb2023-01-11 09:46:29 +08002076
developer56fbedb2023-05-30 16:47:05 +08002077 if (radioIndex >= max_radio_num)
2078 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08002079
developer56fbedb2023-05-30 16:47:05 +08002080 /* loop all interface in radio, if any is enable, reture true, else return false */
2081 for(apIndex = radioIndex; apIndex < MAX_APS; apIndex += max_radio_num)
2082 {
2083 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
2084 continue;
2085 memset(cmd, 0, sizeof(cmd));
2086 sprintf(cmd, "ifconfig %s 2> /dev/null | grep UP", interface_name);
2087 *output_bool = _syscmd(cmd, buf, sizeof(buf)) ? FALSE : TRUE;
2088 if (*output_bool == TRUE)
2089 break;
2090 }
2091
2092 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08002093}
2094
developere82c0ca2023-05-10 16:25:35 +08002095typedef long time_t;
2096static time_t radio_up_time[MAX_NUM_RADIOS];
2097
developer72fb0bb2023-01-11 09:46:29 +08002098INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
2099{
2100 char interface_name[16] = {0};
2101 char cmd[MAX_CMD_SIZE] = {0};
developer8a3bbbf2023-03-15 17:47:23 +08002102 char buf[MAX_BUF_SIZE] = {0};
developer2f79c922023-06-02 17:33:42 +08002103 int apIndex;
developer69b61b02023-03-07 17:17:44 +08002104 int max_radio_num = 0;
developer72fb0bb2023-01-11 09:46:29 +08002105 int phyId = 0;
2106
2107 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2108
2109 phyId = radio_index_to_phy(radioIndex);
2110
2111 wifi_getMaxRadioNumber(&max_radio_num);
2112
developer8a3bbbf2023-03-15 17:47:23 +08002113 if(enable == FALSE) {
developer47cc27a2023-05-17 23:09:58 +08002114
2115 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
2116 return RETURN_ERR;
2117
2118 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s", interface_name);
developer8a3bbbf2023-03-15 17:47:23 +08002119 _syscmd(cmd, buf, sizeof(buf));
developer56fbedb2023-05-30 16:47:05 +08002120 memset(cmd, 0, sizeof(cmd));
2121 snprintf(cmd, MAX_CMD_SIZE, "ifconfig %s down", interface_name);
2122 _syscmd(cmd, buf, sizeof(buf));
developere82c0ca2023-05-10 16:25:35 +08002123 if(strncmp(buf, "OK", 2))
2124 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
developer8a3bbbf2023-03-15 17:47:23 +08002125 } else {
developere82c0ca2023-05-10 16:25:35 +08002126 for (apIndex = radioIndex; apIndex < MAX_APS; apIndex += max_radio_num) {
developer72fb0bb2023-01-11 09:46:29 +08002127 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
2128 return RETURN_ERR;
2129
developer8a3bbbf2023-03-15 17:47:23 +08002130 memset(cmd, 0, MAX_CMD_SIZE);
2131 memset(buf, 0, MAX_BUF_SIZE);
2132
developer72fb0bb2023-01-11 09:46:29 +08002133 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
2134 _syscmd(cmd, buf, sizeof(buf));
developer8a3bbbf2023-03-15 17:47:23 +08002135
2136 if(*buf == '1') {
developer56fbedb2023-05-30 16:47:05 +08002137 snprintf(cmd, MAX_CMD_SIZE, "ifconfig %s up", interface_name);
2138 _syscmd(cmd, buf, sizeof(buf));
developer8a3bbbf2023-03-15 17:47:23 +08002139
2140 memset(cmd, 0, MAX_CMD_SIZE);
2141 memset(buf, 0, MAX_BUF_SIZE);
2142
developer72fb0bb2023-01-11 09:46:29 +08002143 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
2144 phyId, apIndex);
2145 _syscmd(cmd, buf, sizeof(buf));
developer8a3bbbf2023-03-15 17:47:23 +08002146
developer72fb0bb2023-01-11 09:46:29 +08002147 }
2148 }
developere82c0ca2023-05-10 16:25:35 +08002149 time(&radio_up_time[radioIndex]);
developer72fb0bb2023-01-11 09:46:29 +08002150 }
2151
2152 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2153 return RETURN_OK;
2154}
2155
2156//Get the Radio enable status
2157INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
2158{
2159 if (NULL == output_bool)
2160 return RETURN_ERR;
2161
2162 return wifi_getRadioEnable(radioIndex, output_bool);
2163}
2164
2165//Get the Radio Interface name from platform, eg "wlan0"
2166INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
2167{
2168 if (NULL == output_string || radioIndex>=MAX_NUM_RADIOS || radioIndex<0)
2169 return RETURN_ERR;
2170 return wifi_GetInterfaceName(radioIndex, output_string);
2171}
2172
2173//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
2174//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.
2175INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
2176{
2177 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
2178 // For max bit rate, we should always choose the best MCS
2179 char mode[64] = {0};
2180 char channel_bandwidth_str[64] = {0};
developer72fb0bb2023-01-11 09:46:29 +08002181 UINT mode_map = 0;
2182 UINT num_subcarrier = 0;
2183 UINT code_bits = 0;
2184 float code_rate = 0; // use max code rate
2185 int NSS = 0;
2186 UINT Symbol_duration = 0;
developer69b61b02023-03-07 17:17:44 +08002187 UINT GI_duration = 0;
developer72fb0bb2023-01-11 09:46:29 +08002188 wifi_guard_interval_t gi = wifi_guard_interval_auto;
2189 BOOL enable = FALSE;
2190 float bit_rate = 0;
developera1255e42023-05-13 17:45:02 +08002191 int ant_bitmap = 0;
developer72fb0bb2023-01-11 09:46:29 +08002192
2193 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2194 if (NULL == output_string)
2195 return RETURN_ERR;
2196
2197 wifi_getRadioEnable(radioIndex, &enable);
2198 if (enable == FALSE) {
2199 snprintf(output_string, 64, "0 Mb/s");
2200 return RETURN_OK;
2201 }
2202
2203 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
2204 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
2205 return RETURN_ERR;
2206 }
2207
2208 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
2209 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
2210 return RETURN_ERR;
2211 }
2212
2213 if (gi == wifi_guard_interval_3200)
2214 GI_duration = 32;
2215 else if (gi == wifi_guard_interval_1600)
2216 GI_duration = 16;
2217 else if (gi == wifi_guard_interval_800)
2218 GI_duration = 8;
2219 else // auto, 400
2220 GI_duration = 4;
2221
2222 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
2223 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
2224 return RETURN_ERR;
2225 }
2226
2227 if (strstr(channel_bandwidth_str, "80+80") != NULL)
2228 strcpy(channel_bandwidth_str, "160");
2229
2230 if (mode_map & WIFI_MODE_AX) {
2231 if (strstr(channel_bandwidth_str, "160") != NULL)
2232 num_subcarrier = 1960;
2233 else if (strstr(channel_bandwidth_str, "80") != NULL)
2234 num_subcarrier = 980;
2235 else if (strstr(channel_bandwidth_str, "40") != NULL)
2236 num_subcarrier = 468;
2237 else if (strstr(channel_bandwidth_str, "20") != NULL)
2238 num_subcarrier = 234;
2239 code_bits = 10;
2240 code_rate = (float)5/6;
2241 Symbol_duration = 128;
developera1255e42023-05-13 17:45:02 +08002242 GI_duration = 8;/*HE no GI 400ns*/
developer72fb0bb2023-01-11 09:46:29 +08002243 } else if (mode_map & WIFI_MODE_AC) {
2244 if (strstr(channel_bandwidth_str, "160") != NULL)
2245 num_subcarrier = 468;
2246 else if (strstr(channel_bandwidth_str, "80") != NULL)
2247 num_subcarrier = 234;
2248 else if (strstr(channel_bandwidth_str, "40") != NULL)
2249 num_subcarrier = 108;
2250 else if (strstr(channel_bandwidth_str, "20") != NULL)
2251 num_subcarrier = 52;
2252 code_bits = 8;
2253 code_rate = (float)5/6;
2254 Symbol_duration = 32;
2255 } else if (mode_map & WIFI_MODE_N) {
2256 if (strstr(channel_bandwidth_str, "160") != NULL)
2257 num_subcarrier = 468;
2258 else if (strstr(channel_bandwidth_str, "80") != NULL)
2259 num_subcarrier = 234;
2260 else if (strstr(channel_bandwidth_str, "40") != NULL)
2261 num_subcarrier = 108;
2262 else if (strstr(channel_bandwidth_str, "20") != NULL)
2263 num_subcarrier = 52;
2264 code_bits = 6;
2265 code_rate = (float)3/4;
2266 Symbol_duration = 32;
2267 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
2268 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
2269 snprintf(output_string, 64, "65 Mb/s");
2270 return RETURN_OK;
2271 } else {
2272 snprintf(output_string, 64, "0 Mb/s");
2273 return RETURN_OK;
2274 }
2275
2276 // Spatial streams
developera1255e42023-05-13 17:45:02 +08002277 if (wifi_getRadioTxChainMask(radioIndex, &ant_bitmap) != RETURN_OK) {
developer72fb0bb2023-01-11 09:46:29 +08002278 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
2279 return RETURN_ERR;
2280 }
developera1255e42023-05-13 17:45:02 +08002281 for (; ant_bitmap > 0; ant_bitmap >>= 1)
2282 NSS += ant_bitmap & 1;
developer72fb0bb2023-01-11 09:46:29 +08002283
2284 // multiple 10 is to align duration unit (0.1 us)
2285 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
2286 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
developera1255e42023-05-13 17:45:02 +08002287 WIFI_ENTRY_EXIT_DEBUG("%s:num_subcarrier=%d, code_bits=%d, code_rate=%.3f, nss=%d, symbol time=%u, %.1f Mb/s\n",
2288 __func__, num_subcarrier, code_bits, code_rate, NSS, Symbol_duration + GI_duration, bit_rate);
developer72fb0bb2023-01-11 09:46:29 +08002289 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2290
2291 return RETURN_OK;
2292}
2293#if 0
2294INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
2295{
2296 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2297 char cmd[64];
2298 char buf[1024];
2299 int apIndex;
2300
developer69b61b02023-03-07 17:17:44 +08002301 if (NULL == output_string)
developer72fb0bb2023-01-11 09:46:29 +08002302 return RETURN_ERR;
2303
2304 apIndex=(radioIndex==0)?0:1;
2305
2306 snprintf(cmd, sizeof(cmd), "iwconfig %s | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", interface_name);
2307 _syscmd(cmd,buf, sizeof(buf));
2308
2309 snprintf(output_string, 64, "%s", buf);
2310 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2311 return RETURN_OK;
2312}
2313#endif
2314
2315
2316//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
2317//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.
2318INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
2319{
2320 wifi_band band = band_invalid;
2321
2322 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2323 if (NULL == output_string)
2324 return RETURN_ERR;
2325
2326 band = wifi_index_to_band(radioIndex);
2327
2328 memset(output_string, 0, 10);
2329 if (band == band_2_4)
2330 strcpy(output_string, "2.4GHz");
2331 else if (band == band_5)
2332 strcpy(output_string, "5GHz");
2333 else if (band == band_6)
2334 strcpy(output_string, "6GHz");
2335 else
2336 return RETURN_ERR;
2337 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2338
2339 return RETURN_OK;
2340#if 0
2341 char buf[MAX_BUF_SIZE]={'\0'};
2342 char str[MAX_BUF_SIZE]={'\0'};
2343 char cmd[MAX_CMD_SIZE]={'\0'};
2344 char *ch=NULL;
2345 char *ch2=NULL;
2346
2347 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2348 if (NULL == output_string)
2349 return RETURN_ERR;
2350
2351
2352 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2353
2354 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
2355 {
2356 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2357 return RETURN_ERR;
2358 }
2359 ch=strchr(buf,'\n');
2360 *ch='\0';
2361 ch=strchr(buf,'=');
2362 if(ch==NULL)
2363 return RETURN_ERR;
2364
2365
2366 ch++;
2367
2368 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
2369 strcpy(buf,"0");
2370 if(strlen(ch) == 1)
2371 ch=strcat(buf,ch);
2372
2373
2374 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2375
2376 if(_syscmd(cmd,str,64) == RETURN_ERR)
2377 {
2378 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2379 return RETURN_ERR;
2380 }
2381
2382
2383 ch2=strchr(str,'\n');
2384 //replace \n with \0
2385 *ch2='\0';
2386 ch2=strchr(str,'=');
2387 if(ch2==NULL)
2388 {
2389 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2390 return RETURN_ERR;
2391 }
2392 else
2393 wifi_dbg_printf("%s",ch2+1);
2394
2395
2396 ch2++;
2397
2398
2399 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
2400
2401 memset(buf,'\0',sizeof(buf));
2402 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
2403 {
2404 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2405 return RETURN_ERR;
2406 }
2407 if (strstr(buf,"2.4") != NULL )
2408 strcpy(output_string,"2.4GHz");
2409 else if(strstr(buf,"5.") != NULL )
2410 strcpy(output_string,"5GHz");
2411 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2412
2413 return RETURN_OK;
2414#endif
2415}
2416
2417//Get the frequency band at which the radio is operating, eg: "2.4GHz"
2418//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.
2419INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
2420{
2421 wifi_band band = band_invalid;
2422 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2423 if (NULL == output_string)
2424 return RETURN_ERR;
2425 band = wifi_index_to_band(radioIndex);
2426
developer69b61b02023-03-07 17:17:44 +08002427 if (band == band_2_4)
developer72fb0bb2023-01-11 09:46:29 +08002428 snprintf(output_string, 64, "2.4GHz");
2429 else if (band == band_5)
developer69b61b02023-03-07 17:17:44 +08002430 snprintf(output_string, 64, "5GHz");
developer72fb0bb2023-01-11 09:46:29 +08002431 else if (band == band_6)
2432 snprintf(output_string, 64, "6GHz");
2433
2434 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2435
2436 return RETURN_OK;
2437#if 0
2438 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2439 char buf[MAX_BUF_SIZE]={'\0'};
2440 char str[MAX_BUF_SIZE]={'\0'};
2441 char cmd[MAX_CMD_SIZE]={'\0'};
2442 char *ch=NULL;
2443 char *ch2=NULL;
2444 char ch1[5]="0";
2445
2446 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2447
2448 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
2449 {
2450 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2451 return RETURN_ERR;
2452 }
2453
2454 ch=strchr(buf,'\n');
2455 *ch='\0';
2456 ch=strchr(buf,'=');
2457 if(ch==NULL)
2458 return RETURN_ERR;
2459 ch++;
2460
2461 if(strlen(ch)==1)
2462 {
2463 strcat(ch1,ch);
2464
2465 }
2466 else
2467 {
2468 strcpy(ch1,ch);
2469 }
2470
2471
2472
2473 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2474 if(_syscmd(cmd,str,64) == RETURN_ERR)
2475 {
2476 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2477 return RETURN_ERR;
2478 }
2479
2480
2481 ch2=strchr(str,'\n');
2482 //replace \n with \0
2483 *ch2='\0';
2484 ch2=strchr(str,'=');
2485 if(ch2==NULL)
2486 {
2487 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2488 return RETURN_ERR;
2489 }
2490 else
2491 wifi_dbg_printf("%s",ch2+1);
2492 ch2++;
2493
2494
2495 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
2496 memset(buf,'\0',sizeof(buf));
2497 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
2498 {
2499 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2500 return RETURN_ERR;
2501 }
2502
2503
2504 if(strstr(buf,"2.4")!=NULL)
2505 {
2506 strcpy(output_string,"2.4GHz");
2507 }
2508 if(strstr(buf,"5.")!=NULL)
2509 {
2510 strcpy(output_string,"5GHz");
2511 }
2512 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2513 return RETURN_OK;
2514#endif
2515}
2516
2517//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
2518//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.
2519INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
2520{
2521 char cmd[128]={0};
2522 char buf[128]={0};
2523 char temp_output[128] = {0};
2524 wifi_band band;
2525 int phyId = 0;
2526
2527 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer69b61b02023-03-07 17:17:44 +08002528 if (NULL == output_string)
developer72fb0bb2023-01-11 09:46:29 +08002529 return RETURN_ERR;
2530
2531 band = wifi_index_to_band(radioIndex);
2532 if (band == band_2_4) {
2533 strcat(temp_output, "b,g,");
2534 } else if (band == band_5) {
2535 strcat(temp_output, "a,");
2536 }
2537 phyId = radio_index_to_phy(radioIndex);
2538 // ht capabilities
2539 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);
2540 _syscmd(cmd, buf, sizeof(buf));
2541 if (strlen(buf) >= 4 && strncmp(buf, "0x00", 4) != 0) {
2542 strcat(temp_output, "n,");
2543 }
2544
2545 // vht capabilities
2546 if (band == band_5) {
2547 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'VHT Capabilities' | cut -d '(' -f2 | cut -c1-10 | tr -d '\\n'", phyId);
2548 _syscmd(cmd, buf, sizeof(buf));
2549 if (strlen(buf) >= 10 && strncmp(buf, "0x00000000", 10) != 0) {
2550 strcat(temp_output, "ac,");
2551 }
2552 }
2553
2554 // he capabilities
2555 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);
2556 _syscmd(cmd, buf, sizeof(buf));
2557 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
2558 strcat(temp_output, "ax,");
2559 }
2560
developere82c0ca2023-05-10 16:25:35 +08002561 // eht capabilities
2562 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);
2563 _syscmd(cmd, buf, sizeof(buf));
2564 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
2565 strcat(temp_output, "be,");
2566 }
2567
developer72fb0bb2023-01-11 09:46:29 +08002568 // Remove the last comma
2569 if (strlen(temp_output) != 0)
2570 temp_output[strlen(temp_output)-1] = '\0';
2571 strncpy(output_string, temp_output, strlen(temp_output));
2572 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2573 return RETURN_OK;
2574}
2575
2576//Get the radio operating mode, and pure mode flag. eg: "ac"
2577//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.
2578INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
2579{
2580 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2581 if (NULL == output_string)
2582 return RETURN_ERR;
2583
2584 if (radioIndex == 0) {
2585 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
2586 *gOnly = FALSE;
2587 *nOnly = TRUE;
2588 *acOnly = FALSE;
2589 } else {
2590 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
2591 *gOnly = FALSE;
2592 *nOnly = FALSE;
2593 *acOnly = FALSE;
2594 }
2595 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2596
2597 return RETURN_OK;
2598#if 0
2599 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2600 char buf[64] = {0};
2601 char config_file[MAX_BUF_SIZE] = {0};
2602
developer69b61b02023-03-07 17:17:44 +08002603 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
developer72fb0bb2023-01-11 09:46:29 +08002604 return RETURN_ERR;
2605
2606 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2607 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
2608
2609 wifi_dbg_printf("\nhw_mode=%s\n",buf);
developer69b61b02023-03-07 17:17:44 +08002610 if (strlen(buf) == 0)
developer72fb0bb2023-01-11 09:46:29 +08002611 {
2612 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
2613 return RETURN_ERR;
2614 }
2615 if(strcmp(buf,"g")==0)
2616 {
2617 wifi_dbg_printf("\nG\n");
2618 *gOnly=TRUE;
2619 *nOnly=FALSE;
2620 *acOnly=FALSE;
2621 }
2622 else if(strcmp(buf,"n")==0)
2623 {
2624 wifi_dbg_printf("\nN\n");
2625 *gOnly=FALSE;
2626 *nOnly=TRUE;
2627 *acOnly=FALSE;
2628 }
2629 else if(strcmp(buf,"ac")==0)
2630 {
2631 wifi_dbg_printf("\nac\n");
2632 *gOnly=FALSE;
2633 *nOnly=FALSE;
2634 *acOnly=TRUE;
2635 }
2636 /* hostapd-5G.conf has "a" as hw_mode */
2637 else if(strcmp(buf,"a")==0)
2638 {
2639 wifi_dbg_printf("\na\n");
2640 *gOnly=FALSE;
2641 *nOnly=FALSE;
2642 *acOnly=FALSE;
2643 }
2644 else
2645 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
2646
2647 //for a,n mode
2648 if(radioIndex == 1)
2649 {
2650 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
2651 if(strcmp(buf,"1")==0)
2652 {
2653 strncpy(output_string, "n", 1);
2654 *nOnly=FALSE;
2655 }
2656 }
2657
2658 wifi_dbg_printf("\nReturning from getRadioStandard\n");
2659 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2660 return RETURN_OK;
2661#endif
2662}
2663
developer0f10c772023-05-16 21:43:39 +08002664enum WIFI_MODE {
2665 WMODE_INVALID = 0,
2666 WMODE_A = 1 << 0,
2667 WMODE_B = 1 << 1,
2668 WMODE_G = 1 << 2,
2669 WMODE_GN = 1 << 3,
2670 WMODE_AN = 1 << 4,
2671 WMODE_AC = 1 << 5,
2672 WMODE_AX_24G = 1 << 6,
2673 WMODE_AX_5G = 1 << 7,
2674 WMODE_AX_6G = 1 << 8,
2675 WMODE_BE_24G = 1 << 9,
2676 WMODE_BE_5G = 1 << 10,
2677 WMODE_BE_6G = 1 << 11,
2678 /*
2679 * total types of supported wireless mode,
2680 * add this value once yow add new type
2681 */
2682 WMODE_COMP = 12,
2683};
2684
2685#define RADIO_MODE_LEN 32
developerfead3972023-05-25 20:15:02 +08002686
2687int get_radio_mode_handler(struct nl_msg *msg, void *cb)
developer72fb0bb2023-01-11 09:46:29 +08002688{
developerfead3972023-05-25 20:15:02 +08002689 struct nlattr *tb[NL80211_ATTR_MAX + 1];
2690 struct nlattr *vndr_tb[MTK_NL80211_VENDOR_ATTR_GET_RUNTIME_INFO_MAX + 1];
2691 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
2692 unsigned int *phymode;
2693 int err = 0;
2694 struct mtk_nl80211_cb_data *cb_data = cb;
developer72fb0bb2023-01-11 09:46:29 +08002695
developerfead3972023-05-25 20:15:02 +08002696 if (!msg || !cb_data) {
developerdaf24792023-06-06 11:40:04 +08002697 wifi_debug(DEBUG_ERROR, "msg(%p) or cb_data(%p) is null,error.\n", msg, cb_data);
developerfead3972023-05-25 20:15:02 +08002698 return NL_SKIP;
2699 }
developer72fb0bb2023-01-11 09:46:29 +08002700
developerfead3972023-05-25 20:15:02 +08002701 err = nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
2702 genlmsg_attrlen(gnlh, 0), NULL);
2703 if (err < 0) {
2704 wifi_debug(DEBUG_ERROR, "nla_parse radio nl80211 msg fails,error.\n");
2705 return NL_SKIP;
2706 }
developer0f10c772023-05-16 21:43:39 +08002707
developerfead3972023-05-25 20:15:02 +08002708 if (tb[NL80211_ATTR_VENDOR_DATA]) {
2709 err = nla_parse_nested(vndr_tb, MTK_NL80211_VENDOR_ATTR_GET_RUNTIME_INFO_MAX,
2710 tb[NL80211_ATTR_VENDOR_DATA], NULL);
2711 if (err < 0)
2712 return NL_SKIP;
developer72fb0bb2023-01-11 09:46:29 +08002713
developerfead3972023-05-25 20:15:02 +08002714 if (vndr_tb[MTK_NL80211_VENDOR_ATTR_GET_RUNTIME_INFO_GET_WMODE]) {
2715 phymode = (unsigned int *)nla_data(vndr_tb[MTK_NL80211_VENDOR_ATTR_GET_RUNTIME_INFO_GET_WMODE]);
2716
2717 memset(cb_data->out_buf, 0, cb_data->out_len);
2718 memmove(cb_data->out_buf, phymode, sizeof(unsigned int));
2719 }
2720 } else
2721 wifi_debug(DEBUG_ERROR, "No Stats from driver.\n");
2722
2723 return NL_OK;
2724}
developer0f10c772023-05-16 21:43:39 +08002725
developerfead3972023-05-25 20:15:02 +08002726void phymode_to_puremode(INT radioIndex, CHAR *output_string, UINT *pureMode, UINT phymode)
2727{
2728 wifi_band band;
2729 unsigned char radio_mode_tem_len;
2730
2731 band = wifi_index_to_band(radioIndex);
developer0f10c772023-05-16 21:43:39 +08002732 // puremode is a bit map
developer72fb0bb2023-01-11 09:46:29 +08002733 *pureMode = 0;
developer0f10c772023-05-16 21:43:39 +08002734 memset(output_string, 0, RADIO_MODE_LEN);
2735
2736 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2737
2738 switch (band) {
2739 case band_2_4:
2740 if (phymode & WMODE_B) {
2741 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "b,");
2742 *pureMode |= WIFI_MODE_B;
2743 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2744 }
2745 if (phymode & WMODE_G) {
2746 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "g,");
2747 *pureMode |= WIFI_MODE_G;
2748 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2749 }
2750 if (phymode & WMODE_GN) {
2751 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "n,");
2752 *pureMode |= WIFI_MODE_N;
2753 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2754 }
2755 if (phymode & WMODE_AX_24G) {
2756 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "ax,");
2757 *pureMode |= WIFI_MODE_AX;
2758 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2759 }
2760 if (phymode & WMODE_BE_24G) {
2761 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "be,");
2762 *pureMode |= WIFI_MODE_BE;
2763 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2764 }
2765 break;
2766 case band_5:
2767 if (phymode & WMODE_A) {
2768 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "a,");
2769 *pureMode |= WIFI_MODE_A;
2770 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2771 }
2772 if (phymode & WMODE_AN) {
2773 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "n,");
2774 *pureMode |= WIFI_MODE_N;
2775 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2776 }
2777 if (phymode & WMODE_AC) {
2778 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "ac,");
2779 *pureMode |= WIFI_MODE_AC;
2780 }
2781 if (phymode & WMODE_AX_5G) {
2782 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "ax,");
2783 *pureMode |= WIFI_MODE_AX;
2784 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2785 }
2786 if (phymode & WMODE_BE_5G) {
2787 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "be,");
2788 *pureMode |= WIFI_MODE_BE;
2789 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2790 }
2791 break;
2792 case band_6:
2793 if (phymode & WMODE_AX_6G) {
2794 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "ax,");
2795 *pureMode |= WIFI_MODE_AX;
2796 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2797 }
2798 if (phymode & WMODE_BE_6G) {
2799 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "be,");
2800 *pureMode |= WIFI_MODE_BE;
2801 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2802 }
2803 break;
2804 default:
2805 fprintf(stderr, "%s band_idx invalid\n", __func__);
2806 break;
2807 }
2808
2809 /* Remove the last comma */
2810 if (strlen(output_string) != 0)
2811 output_string[strlen(output_string)-1] = '\0';
developer72fb0bb2023-01-11 09:46:29 +08002812
developerfead3972023-05-25 20:15:02 +08002813}
2814
2815INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
2816{
2817 unsigned int phymode;
2818 char interface_name[IF_NAME_SIZE] = {0};
developerfead3972023-05-25 20:15:02 +08002819 int ret = -1;
2820 unsigned int if_idx = 0;
2821 struct unl unl_ins;
2822 struct nl_msg *msg = NULL;
2823 struct nlattr * msg_data = NULL;
2824 struct mtk_nl80211_param param;
2825 struct mtk_nl80211_cb_data cb_data;
2826
2827 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developerdaf24792023-06-06 11:40:04 +08002828 if (NULL == output_string || NULL == pureMode)
2829 return RETURN_ERR;
developerfead3972023-05-25 20:15:02 +08002830
2831 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
2832 return RETURN_ERR;
2833
2834 if_idx = if_nametoindex(interface_name);
2835 if (!if_idx) {
2836 wifi_debug(DEBUG_ERROR, "can't finde ifname(%s) index,ERROR\n", interface_name);
2837 return RETURN_ERR;
2838 }
2839 /*init mtk nl80211 vendor cmd*/
2840 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_GET_RUNTIME_INFO;
2841 param.if_type = NL80211_ATTR_IFINDEX;
2842 param.if_idx = if_idx;
2843
2844 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
2845 if (ret) {
2846 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
2847 return RETURN_ERR;
2848 }
2849
2850 /*add mtk vendor cmd data*/
2851 if (nla_put_u16(msg, MTK_NL80211_VENDOR_ATTR_GET_RUNTIME_INFO_GET_WMODE, 0)) {
2852 wifi_debug(DEBUG_ERROR, "Nla put GET_RUNTIME_INFO_GET_WMODE attribute error\n");
2853 nlmsg_free(msg);
2854 goto err;
2855 }
2856
2857 /*send mtk nl80211 vendor msg*/
2858 cb_data.out_buf = (char *)&phymode;
2859 cb_data.out_len = sizeof(unsigned int);
2860
2861 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, get_radio_mode_handler, &cb_data);
2862
2863 if (ret) {
2864 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
2865 goto err;
2866 }
2867 /*deinit mtk nl80211 vendor msg*/
2868 mtk_nl80211_deint(&unl_ins);
2869
2870 phymode_to_puremode(radioIndex, output_string, pureMode, phymode);
2871 wifi_debug(DEBUG_NOTICE,"send cmd success\n");
2872
developer72fb0bb2023-01-11 09:46:29 +08002873 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2874 return RETURN_OK;
developerfead3972023-05-25 20:15:02 +08002875err:
2876 mtk_nl80211_deint(&unl_ins);
2877 wifi_debug(DEBUG_ERROR,"send cmd fails\n");
2878 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08002879}
2880
2881// Set the radio operating mode, and pure mode flag.
2882INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
2883{
developer69b61b02023-03-07 17:17:44 +08002884 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
developer72fb0bb2023-01-11 09:46:29 +08002885 if (strcmp (channelMode,"11A") == 0)
2886 {
2887 writeBandWidth(radioIndex,"20MHz");
2888 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2889 printf("\nChannel Mode is 802.11a (5GHz)\n");
2890 }
2891 else if (strcmp (channelMode,"11NAHT20") == 0)
2892 {
2893 writeBandWidth(radioIndex,"20MHz");
2894 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2895 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
2896 }
2897 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
2898 {
2899 writeBandWidth(radioIndex,"40MHz");
2900 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2901 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
2902 }
2903 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
2904 {
2905 writeBandWidth(radioIndex,"40MHz");
2906 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2907 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
2908 }
2909 else if (strcmp (channelMode,"11ACVHT20") == 0)
2910 {
2911 writeBandWidth(radioIndex,"20MHz");
2912 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2913 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
2914 }
2915 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
2916 {
2917 writeBandWidth(radioIndex,"40MHz");
2918 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2919 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2920 }
2921 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
2922 {
2923 writeBandWidth(radioIndex,"40MHz");
2924 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2925 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2926 }
2927 else if (strcmp (channelMode,"11ACVHT80") == 0)
2928 {
2929 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
2930 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
2931 }
2932 else if (strcmp (channelMode,"11ACVHT160") == 0)
2933 {
2934 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
2935 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
developer69b61b02023-03-07 17:17:44 +08002936 }
developer72fb0bb2023-01-11 09:46:29 +08002937 else if (strcmp (channelMode,"11B") == 0)
2938 {
2939 writeBandWidth(radioIndex,"20MHz");
2940 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2941 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
2942 }
2943 else if (strcmp (channelMode,"11G") == 0)
2944 {
2945 writeBandWidth(radioIndex,"20MHz");
2946 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2947 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
2948 }
2949 else if (strcmp (channelMode,"11NGHT20") == 0)
2950 {
2951 writeBandWidth(radioIndex,"20MHz");
2952 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2953 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
2954 }
2955 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
2956 {
2957 writeBandWidth(radioIndex,"40MHz");
2958 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2959 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2960 }
2961 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
2962 {
2963 writeBandWidth(radioIndex,"40MHz");
2964 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2965 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2966 }
developer69b61b02023-03-07 17:17:44 +08002967 else
developer72fb0bb2023-01-11 09:46:29 +08002968 {
2969 return RETURN_ERR;
2970 }
2971 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2972
2973 return RETURN_OK;
2974}
2975
developer0f10c772023-05-16 21:43:39 +08002976typedef enum _RT_802_11_PHY_MODE {
2977 PHY_11BG_MIXED = 0,
2978 PHY_11B = 1,
2979 PHY_11A = 2,
2980 PHY_11ABG_MIXED = 3,
2981 PHY_11G = 4,
2982 PHY_11ABGN_MIXED = 5, /* both band 5 */
2983 PHY_11N_2_4G = 6, /* 11n-only with 2.4G band 6 */
2984 PHY_11GN_MIXED = 7, /* 2.4G band 7 */
2985 PHY_11AN_MIXED = 8, /* 5G band 8 */
2986 PHY_11BGN_MIXED = 9, /* if check 802.11b. 9 */
2987 PHY_11AGN_MIXED = 10, /* if check 802.11b. 10 */
2988 PHY_11N_5G = 11, /* 11n-only with 5G band 11 */
2989 PHY_11VHT_N_ABG_MIXED = 12, /* 12 -> AC/A/AN/B/G/GN mixed */
2990 PHY_11VHT_N_AG_MIXED = 13, /* 13 -> AC/A/AN/G/GN mixed */
2991 PHY_11VHT_N_A_MIXED = 14, /* 14 -> AC/AN/A mixed in 5G band */
2992 PHY_11VHT_N_MIXED = 15, /* 15 -> AC/AN mixed in 5G band */
2993 PHY_11AX_24G = 16,
2994 PHY_11AX_5G = 17,
2995 PHY_11AX_6G = 18,
2996 PHY_11AX_24G_6G = 19,
2997 PHY_11AX_5G_6G = 20,
2998 PHY_11AX_24G_5G_6G = 21,
2999 PHY_11BE_24G = 22,
3000 PHY_11BE_5G = 23,
3001 PHY_11BE_6G = 24,
3002 PHY_11BE_24G_6G = 25,
3003 PHY_11BE_5G_6G = 26,
3004 PHY_11BE_24G_5G_6G = 27,
3005 PHY_MODE_MAX,
3006} RT_802_11_PHY_MODE;
3007
3008unsigned int puremode_to_wireless_mode(INT radioIndex, UINT pureMode)
3009{
3010 int band_idx = 0;
developerfead3972023-05-25 20:15:02 +08003011 unsigned char wireless_mode = PHY_MODE_MAX;
developer0f10c772023-05-16 21:43:39 +08003012
3013 band_idx = radio_index_to_band(radioIndex);
3014
3015 switch (band_idx) {
3016 case band_2_4:
3017 if (pureMode == (WIFI_MODE_G | WIFI_MODE_N))
3018 wireless_mode = PHY_11GN_MIXED;
3019 if (pureMode == (WIFI_MODE_B | WIFI_MODE_G | WIFI_MODE_N))
3020 wireless_mode = PHY_11BGN_MIXED;
3021 if (pureMode & WIFI_MODE_AX)
3022 wireless_mode = PHY_11AX_24G;
3023 if (pureMode & WIFI_MODE_BE)
3024 wireless_mode = PHY_11BE_24G;
3025 break;
3026 case band_5:
3027 if (pureMode == WIFI_MODE_N)
3028 wireless_mode = PHY_11N_5G;
3029 if ((pureMode == WIFI_MODE_AC) || (pureMode == (WIFI_MODE_N | WIFI_MODE_AC)))
3030 wireless_mode = PHY_11VHT_N_MIXED;
3031 if (pureMode == (WIFI_MODE_A | WIFI_MODE_N | WIFI_MODE_AC))
3032 wireless_mode = PHY_11VHT_N_A_MIXED;
3033 if (pureMode & WIFI_MODE_AX)
3034 wireless_mode = PHY_11AX_5G;
3035 if (pureMode & WIFI_MODE_BE)
3036 wireless_mode = PHY_11BE_5G;
3037 break;
3038 case band_6:
3039 if (pureMode & WIFI_MODE_AX)
3040 wireless_mode = PHY_11AX_6G;
3041 if (pureMode & WIFI_MODE_BE)
3042 wireless_mode = PHY_11BE_6G;
3043 break;
3044 default:
3045 fprintf(stderr, "%s band_idx invalid\n", __func__);
3046 break;
3047 }
3048
3049 return wireless_mode;
3050}
3051
developer72fb0bb2023-01-11 09:46:29 +08003052// Set the radio operating mode, and pure mode flag.
3053INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
3054{
developerfead3972023-05-25 20:15:02 +08003055 unsigned char wireless_mode = PHY_MODE_MAX;
developer69b61b02023-03-07 17:17:44 +08003056
developer0f10c772023-05-16 21:43:39 +08003057 char interface_name[IF_NAME_SIZE] = {0};
developerfead3972023-05-25 20:15:02 +08003058 int ret = -1;
3059 unsigned int if_idx = 0;
3060 struct unl unl_ins;
3061 struct nl_msg *msg = NULL;
3062 struct nlattr * msg_data = NULL;
3063 struct mtk_nl80211_param param;
developer72fb0bb2023-01-11 09:46:29 +08003064
developer0f10c772023-05-16 21:43:39 +08003065 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08003066
developer0f10c772023-05-16 21:43:39 +08003067 wireless_mode = puremode_to_wireless_mode(radioIndex, pureMode);
developer72fb0bb2023-01-11 09:46:29 +08003068
developer0f10c772023-05-16 21:43:39 +08003069 if (wireless_mode == PHY_MODE_MAX) {
3070 fprintf(stderr, "%s wireless_mode invalid pureMode = %x\n", __func__, pureMode);
3071 return RETURN_ERR;
3072 }
developer72fb0bb2023-01-11 09:46:29 +08003073
developer0f10c772023-05-16 21:43:39 +08003074 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3075 return RETURN_ERR;
developerfead3972023-05-25 20:15:02 +08003076
3077 if_idx = if_nametoindex(interface_name);
3078 if (!if_idx) {
3079 wifi_debug(DEBUG_ERROR,"can't finde ifname(%s) index,ERROR\n", interface_name);
3080 return RETURN_ERR;
3081 }
3082 /*init mtk nl80211 vendor cmd*/
3083 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_AP_BSS;
3084 param.if_type = NL80211_ATTR_IFINDEX;
3085 param.if_idx = if_idx;
3086
3087 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
3088 if (ret) {
3089 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
3090 return RETURN_ERR;
3091 }
3092
3093 /*add mtk vendor cmd data*/
3094 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_AP_WIRELESS_MODE, wireless_mode)) {
3095 wifi_debug(DEBUG_ERROR, "Nla put AP_WIRELESS_MODE attribute error\n");
3096 nlmsg_free(msg);
3097 goto err;
3098 }
3099 /*send mtk nl80211 vendor msg*/
3100 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
3101 if (ret) {
3102 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
3103 goto err;
3104 }
3105 /*deinit mtk nl80211 vendor msg*/
3106 mtk_nl80211_deint(&unl_ins);
3107 wifi_debug(DEBUG_NOTICE, "set cmd success.\n");
developer72fb0bb2023-01-11 09:46:29 +08003108
developer0f10c772023-05-16 21:43:39 +08003109 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3110
3111 return RETURN_OK;
developerfead3972023-05-25 20:15:02 +08003112err:
3113 mtk_nl80211_deint(&unl_ins);
3114 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
3115 return RETURN_ERR;
developer0f10c772023-05-16 21:43:39 +08003116}
3117
3118INT wifi_setRadioMode_by_dat(INT radioIndex, UINT pureMode)
3119{
developerfead3972023-05-25 20:15:02 +08003120 unsigned char wireless_mode = PHY_MODE_MAX;
developer0f10c772023-05-16 21:43:39 +08003121 char buf[MAX_BUF_SIZE] = {0};
developer0f10c772023-05-16 21:43:39 +08003122 char dat_file[MAX_BUF_SIZE] = {0};
3123 struct params params={0};
3124
3125 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, pureMode, __LINE__);
3126
3127 wireless_mode = puremode_to_wireless_mode(radioIndex, pureMode);
3128
3129 if (wireless_mode == PHY_MODE_MAX) {
3130 fprintf(stderr, "%s wireless_mode invalid pureMode = %x\n", __func__, pureMode);
3131 return RETURN_ERR;
3132 }
3133
3134 params.name = "WirelessMode";
3135 snprintf(buf, sizeof(buf), "%d", wireless_mode);
3136 params.value = buf;
3137
3138 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, radioIndex);
3139 wifi_datfileWrite(dat_file, &params, 1);
3140
developer72fb0bb2023-01-11 09:46:29 +08003141 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3142
3143 return RETURN_OK;
3144}
3145
3146INT wifi_setRadioHwMode(INT radioIndex, CHAR *hw_mode) {
3147
3148 char config_file[64] = {0};
3149 char buf[64] = {0};
3150 struct params params = {0};
3151 wifi_band band = band_invalid;
3152
3153 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3154
3155 band = wifi_index_to_band(radioIndex);
3156
3157 if (strncmp(hw_mode, "a", 1) == 0 && (band != band_5 && band != band_6))
3158 return RETURN_ERR;
3159 else if ((strncmp(hw_mode, "b", 1) == 0 || strncmp(hw_mode, "g", 1) == 0) && band != band_2_4)
3160 return RETURN_ERR;
3161 else if ((strncmp(hw_mode, "a", 1) && strncmp(hw_mode, "b", 1) && strncmp(hw_mode, "g", 1)) || band == band_invalid)
3162 return RETURN_ERR;
3163
3164 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3165 params.name = "hw_mode";
3166 params.value = hw_mode;
3167 wifi_hostapdWrite(config_file, &params, 1);
3168 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3169
3170 if (band == band_2_4) {
3171 if (strncmp(hw_mode, "b", 1) == 0) {
3172 wifi_setRadioMode(radioIndex, "20MHz", WIFI_MODE_B);
3173 snprintf(buf, sizeof(buf), "%s", "1,2,5.5,11");
3174 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
3175 snprintf(buf, sizeof(buf), "%s", "1,2");
3176 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
3177 } else {
3178 // We don't set mode here, because we don't know whitch mode should be set (g, n or ax?).
3179
3180 snprintf(buf, sizeof(buf), "%s", "6,9,12,18,24,36,48,54");
3181 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
3182 snprintf(buf, sizeof(buf), "%s", "6,12,24");
3183 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
3184 }
3185 }
3186
3187 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3188 return RETURN_OK;
3189}
3190
3191INT wifi_setNoscan(INT radioIndex, CHAR *noscan)
3192{
3193 char config_file[64] = {0};
3194 struct params params = {0};
3195 wifi_band band = band_invalid;
3196
3197 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3198
3199 band = wifi_index_to_band(radioIndex);
3200 if (band != band_2_4)
3201 return RETURN_OK;
3202
3203 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3204 params.name = "noscan";
3205 params.value = noscan;
3206 wifi_hostapdWrite(config_file, &params, 1);
3207 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3208
3209 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3210 return RETURN_OK;
3211}
3212
3213//Get the list of supported channel. eg: "1-11"
3214//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.
3215INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
3216{
3217 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer69b61b02023-03-07 17:17:44 +08003218 if (NULL == output_string)
developer72fb0bb2023-01-11 09:46:29 +08003219 return RETURN_ERR;
3220 char cmd[256] = {0};
3221 char buf[128] = {0};
3222 BOOL dfs_enable = false;
3223 int phyId = 0;
3224
3225 // Parse possible channel number and separate them with commas.
3226 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
3227 phyId = radio_index_to_phy(radioIndex);
3228 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
3229 if (dfs_enable)
3230 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 +08003231 else
developer72fb0bb2023-01-11 09:46:29 +08003232 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);
3233
3234 _syscmd(cmd,buf,sizeof(buf));
developerc79e9172023-06-06 19:48:03 +08003235 strncpy(output_string, buf, strlen(buf) < sizeof(buf) ? strlen(buf) : sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08003236
3237 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3238 return RETURN_OK;
3239}
developerd1824452023-05-18 12:30:04 +08003240//Getting current radio extension channel
3241INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
3242{
3243 CHAR buf[150] = {0};
developerd1824452023-05-18 12:30:04 +08003244
3245 wifi_datfileRead(file, "HT_EXTCHA", buf, sizeof(buf));
developer262f4cb2023-05-24 12:22:04 +08003246 if (strncmp(buf, "Below", 5) == 0) //below
developerd1824452023-05-18 12:30:04 +08003247 strcpy(Value,"BelowControlChannel");
developer262f4cb2023-05-24 12:22:04 +08003248 if(strncmp(buf, "Above", 5) == 0) //above
developerd1824452023-05-18 12:30:04 +08003249 strcpy(Value,"AboveControlChannel");
3250 return RETURN_OK;
3251}
developerf6a87542023-05-16 15:47:28 +08003252
developer72fb0bb2023-01-11 09:46:29 +08003253//Get the list for used channel. eg: "1,6,9,11"
3254//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.
3255INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
3256{
3257 char interface_name[16] = {0};
3258 char cmd[128] = {0};
3259 char buf[128] = {0};
3260 char config_file[64] = {0};
3261 int channel = 0;
3262 int freq = 0;
3263 int bandwidth = 0;
3264 int center_freq = 0;
3265 int center_channel = 0;
3266 int channel_delta = 0;
3267 wifi_band band = band_invalid;
3268
3269 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3270
3271 if (NULL == output_string)
3272 return RETURN_ERR;
3273
3274 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3275 return RETURN_ERR;
3276 sprintf(cmd, "iw %s info | grep channel | sed -e 's/[^0-9 ]//g'", interface_name);
3277 _syscmd(cmd, buf, sizeof(buf));
3278 if (strlen(buf) == 0) {
3279 fprintf(stderr, "%s: failed to get channel information from iw.\n", __func__);
3280 return RETURN_ERR;
3281 }
3282 sscanf(buf, "%d %d %d %*d %d", &channel, &freq, &bandwidth, &center_freq);
3283
3284 if (bandwidth == 20) {
3285 snprintf(output_string, 256, "%d", channel);
3286 return RETURN_OK;
3287 }
3288
3289 center_channel = ieee80211_frequency_to_channel(center_freq);
3290
3291 band = wifi_index_to_band(radioIndex);
3292 if (band == band_2_4 && bandwidth == 40) {
developerd1824452023-05-18 12:30:04 +08003293 sprintf(config_file, "%s%d.dat", LOGAN_DAT_FILE, band);
developer72fb0bb2023-01-11 09:46:29 +08003294 memset(buf, 0, sizeof(buf));
3295 wifi_halgetRadioExtChannel(config_file, buf); // read ht_capab for HT40+ or -
3296
3297 if (strncmp(buf, "AboveControlChannel", strlen("AboveControlChannel")) == 0 && channel < 10) {
3298 snprintf(output_string, 256, "%d,%d", channel, channel+4);
3299 } else if (strncmp(buf, "BelowControlChannel", strlen("BelowControlChannel")) == 0 && channel > 4) {
3300 snprintf(output_string, 256, "%d,%d", channel-4, channel);
3301 } else {
3302 fprintf(stderr, "%s: invalid channel %d set with %s\n.", __func__, channel, buf);
3303 return RETURN_ERR;
3304 }
3305 } else if (band == band_5 || band == band_6){
3306 // 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 +08003307 // 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 +08003308 channel_delta = (bandwidth-20)/10;
developerd1824452023-05-18 12:30:04 +08003309 memset(output_string, 0, 256);
3310 for (int i = center_channel-channel_delta; i <= center_channel+channel_delta; i+=4) {
3311 // If i is not the last channel, we add a comma.
3312 snprintf(buf, sizeof(buf), "%d%s", i, i==center_channel+channel_delta?"":",");
3313 strncat(output_string, buf, strlen(buf));
3314 }
developer72fb0bb2023-01-11 09:46:29 +08003315 } else
3316 return RETURN_ERR;
3317
3318 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3319 return RETURN_OK;
3320}
3321
developer69b61b02023-03-07 17:17:44 +08003322//Get the running channel number
developerd1824452023-05-18 12:30:04 +08003323INT wifi_getRadioChannel(INT radioIndex, ULONG *output_ulong) //RDKB
developer72fb0bb2023-01-11 09:46:29 +08003324{
3325 char channel_str[16] = {0};
3326 char config_file[128] = {0};
developer47a56bf2023-05-30 13:38:57 +08003327 char buf[MAX_BUF_SIZE] = {0};
3328 char cmd[MAX_CMD_SIZE] = {0};
3329 char interface_name[IF_NAME_SIZE] = {0};
developerd1824452023-05-18 12:30:04 +08003330 wifi_band band = band_invalid;
developer47a56bf2023-05-30 13:38:57 +08003331 ULONG iwChannel = 0;
3332
developer72fb0bb2023-01-11 09:46:29 +08003333 if (output_ulong == NULL)
3334 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08003335 band = wifi_index_to_band(radioIndex);
3336 snprintf(config_file, sizeof(config_file), "%s%d.dat", LOGAN_DAT_FILE, band);
3337 wifi_datfileRead(config_file, "Channel", channel_str, sizeof(channel_str));
developer72fb0bb2023-01-11 09:46:29 +08003338 *output_ulong = strtoul(channel_str, NULL, 10);
developer47a56bf2023-05-30 13:38:57 +08003339 if (*output_ulong == 0) {
3340 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3341 return RETURN_ERR;
3342 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2", interface_name);
3343 _syscmd(cmd,buf,sizeof(buf));
3344 sscanf(buf, "%lu", &iwChannel);
3345 *output_ulong = iwChannel;
3346 }
developer72fb0bb2023-01-11 09:46:29 +08003347
3348 return RETURN_OK;
3349}
3350
developer72fb0bb2023-01-11 09:46:29 +08003351INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
3352{
3353 char cmd[1024] = {0}, buf[5] = {0};
3354 char interface_name[16] = {0};
3355
3356 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3357 if (NULL == output_ulong)
3358 return RETURN_ERR;
3359
developer47a56bf2023-05-30 13:38:57 +08003360 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72fb0bb2023-01-11 09:46:29 +08003361 return RETURN_ERR;
developer47a56bf2023-05-30 13:38:57 +08003362
3363 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2", interface_name);
developer72fb0bb2023-01-11 09:46:29 +08003364 _syscmd(cmd,buf,sizeof(buf));
3365 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
3366 if (*output_ulong == 0) {
3367 return RETURN_ERR;
3368 }
3369
3370 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3371 return RETURN_OK;
3372}
developer72fb0bb2023-01-11 09:46:29 +08003373//Storing the previous channel value
3374INT wifi_storeprevchanval(INT radioIndex)
3375{
3376 char buf[256] = {0};
3377 char output[4]={'\0'};
3378 char config_file[MAX_BUF_SIZE] = {0};
developerd1824452023-05-18 12:30:04 +08003379 wifi_band band = band_invalid;
3380
3381 band = wifi_index_to_band(radioIndex);
3382 if (band == band_invalid) {
3383 return RETURN_ERR;
3384 wifi_dbg_printf("[%s]: Invalid radio index", __func__);
3385 }
3386 snprintf(config_file, sizeof(config_file), "%s%d.dat",LOGAN_DAT_FILE, band);
3387 wifi_datfileRead(config_file, "Channel", output, sizeof(output));
3388
3389 if(band == band_2_4)
developer72fb0bb2023-01-11 09:46:29 +08003390 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
developerd1824452023-05-18 12:30:04 +08003391 else if(band == band_5)
developer72fb0bb2023-01-11 09:46:29 +08003392 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
developerd1824452023-05-18 12:30:04 +08003393 else
3394 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval6G_AutoChannelEnable");
developer72fb0bb2023-01-11 09:46:29 +08003395 system(buf);
3396 Radio_flag = FALSE;
3397 return RETURN_OK;
3398}
3399
3400//Set the running channel number
3401INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
3402{
3403 // We only write hostapd config here
3404 char str_channel[8]={0};
3405 char *list_channel;
developer72fb0bb2023-01-11 09:46:29 +08003406 char possible_channels[256] = {0};
developerd1824452023-05-18 12:30:04 +08003407 char config_file_dat[128] = {0};
developerd1824452023-05-18 12:30:04 +08003408 struct params dat = {0};
3409 struct params acs = {0};
3410 wifi_band band = band_invalid;
3411 bool acs_channel = false;
developer72fb0bb2023-01-11 09:46:29 +08003412
3413 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3414
developerd1824452023-05-18 12:30:04 +08003415 if (channel == 0)
3416 acs_channel = true;
developer72fb0bb2023-01-11 09:46:29 +08003417 // Check valid
3418 sprintf(str_channel, "%lu", channel);
3419
developerd1824452023-05-18 12:30:04 +08003420
developer72fb0bb2023-01-11 09:46:29 +08003421 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
3422 list_channel = strtok(possible_channels, ",");
3423 while(true)
3424 {
3425 if(list_channel == NULL) { // input not in the list
3426 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
3427 return RETURN_ERR;
3428 }
3429 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
3430 break;
3431 list_channel = strtok(NULL, ",");
3432 }
developerd1824452023-05-18 12:30:04 +08003433 /*
developer72fb0bb2023-01-11 09:46:29 +08003434 list.name = "channel";
3435 list.value = str_channel;
3436 wifi_getMaxRadioNumber(&max_radio_num);
3437 for(int i=0; i<=MAX_APS/max_radio_num;i++)
3438 {
3439 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
3440 wifi_hostapdWrite(config_file, &list, 1);
3441 }
developerd1824452023-05-18 12:30:04 +08003442 */
3443 dat.name = "Channel";
3444 dat.value = str_channel;
3445 band = wifi_index_to_band(radioIndex);
3446 snprintf(config_file_dat, sizeof(config_file_dat), "%s%d.dat", LOGAN_DAT_FILE, band);
3447 wifi_datfileWrite(config_file_dat, &dat, 1);
3448 if (acs_channel == true) {
3449 acs.name = "AutoChannelSelect";
3450 acs.value = "3";
3451 } else {
3452 acs.name = "AutoChannelSelect";
3453 acs.value = "0";
3454 }
3455 wifi_datfileWrite(config_file_dat, &acs, 1);
developerc0772e62023-05-18 15:10:48 +08003456 wifi_reloadAp(radioIndex);
developer72fb0bb2023-01-11 09:46:29 +08003457 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3458 return RETURN_OK;
3459}
3460
3461INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
3462{
3463 struct params list[2];
3464 char str_idx[16];
3465 char config_file[64];
3466 int max_num_radios = 0;
3467 wifi_band band = band_invalid;
3468
3469 band = wifi_index_to_band(radioIndex);
3470 if (band == band_2_4)
3471 return RETURN_OK;
3472
3473 snprintf(str_idx, sizeof(str_idx), "%lu", channel);
3474 list[0].name = "vht_oper_centr_freq_seg0_idx";
3475 list[0].value = str_idx;
3476 list[1].name = "he_oper_centr_freq_seg0_idx";
3477 list[1].value = str_idx;
3478
3479 wifi_getMaxRadioNumber(&max_num_radios);
3480 for(int i=0; i<=MAX_APS/max_num_radios; i++)
3481 {
3482 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
3483 if (band == band_6)
3484 wifi_hostapdWrite(config_file, &list[1], 1);
3485 else
3486 wifi_hostapdWrite(config_file, list, 2);
3487 }
3488
3489 return RETURN_OK;
3490}
3491
3492//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
3493//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
3494INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
3495{
3496 //Set to wifi config only. Wait for wifi reset to apply.
developer72fb0bb2023-01-11 09:46:29 +08003497 ULONG Value = 0;
developer47a56bf2023-05-30 13:38:57 +08003498 char config_file_dat[128] = {0};
3499 struct params acs = {0};
3500 wifi_band band = band_invalid;
3501
3502 if(enable == TRUE) {
developer72fb0bb2023-01-11 09:46:29 +08003503 wifi_setRadioChannel(radioIndex,Value);
developer47a56bf2023-05-30 13:38:57 +08003504 } else {
3505 acs.name = "AutoChannelSelect";
3506 acs.value = "0";
3507 band = wifi_index_to_band(radioIndex);
3508 snprintf(config_file_dat, sizeof(config_file_dat), "%s%d.dat", LOGAN_DAT_FILE, band);
3509 wifi_datfileWrite(config_file_dat, &acs, 1);
developer72fb0bb2023-01-11 09:46:29 +08003510 }
3511 return RETURN_OK;
3512}
3513
3514INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
3515{
3516 if (output_bool == NULL)
3517 return RETURN_ERR;
3518
3519 *output_bool = TRUE;
3520
3521 return RETURN_OK;
3522}
3523
3524INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
3525{
developer69b61b02023-03-07 17:17:44 +08003526 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08003527 return RETURN_ERR;
3528 *output_bool=FALSE;
3529 return RETURN_OK;
3530}
3531
3532INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
3533{
developer69b61b02023-03-07 17:17:44 +08003534 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08003535 return RETURN_ERR;
3536 *output_bool=FALSE;
3537 return RETURN_OK;
3538}
3539
3540INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
3541{
3542 //Set to wifi config only. Wait for wifi reset to apply.
3543 return RETURN_OK;
3544}
3545
3546INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
3547{
3548 return RETURN_OK;
3549}
3550
3551INT wifi_factoryResetAP(int apIndex)
3552{
developerb149d9d2023-06-06 16:14:22 +08003553 char ap_config_file[MAX_SUB_CMD_SIZE] = {0};
developer47cc27a2023-05-17 23:09:58 +08003554 char cmd[MAX_CMD_SIZE] = {0};
3555 char ret_buf[MAX_BUF_SIZE] = {0};
3556 int radio_idx = 0;
3557 int bss_idx = 0;
3558 char ssid[32] = {0};
3559 char interface[IF_NAME_SIZE] = {0};
developerb149d9d2023-06-06 16:14:22 +08003560 char psk_file[MAX_SUB_CMD_SIZE] = {0};
developer47cc27a2023-05-17 23:09:58 +08003561 struct params params[3] = {0};
developer72fb0bb2023-01-11 09:46:29 +08003562
3563 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3564
developer47cc27a2023-05-17 23:09:58 +08003565 /*del old config file*/
3566 snprintf(ap_config_file, MAX_CMD_SIZE, "%s%d.conf", CONFIG_PREFIX, apIndex);
3567 snprintf(cmd, MAX_CMD_SIZE, "rm %s", ap_config_file);
3568 _syscmd(cmd, ret_buf, sizeof(ret_buf));
developer72fb0bb2023-01-11 09:46:29 +08003569
developer47cc27a2023-05-17 23:09:58 +08003570 memset(cmd, 0, sizeof(cmd));
3571 memset(ret_buf, 0, sizeof(ret_buf));
developer72fb0bb2023-01-11 09:46:29 +08003572
developer47cc27a2023-05-17 23:09:58 +08003573 vap_index_to_array_index(apIndex, &radio_idx, &bss_idx);
3574
3575 /*prepare new config file*/
developere740c2a2023-05-23 18:34:32 +08003576 snprintf(cmd, sizeof(cmd), "cp /etc/hostapd-%s.conf %s", wifi_band_str[radio_idx], ap_config_file);
developer47cc27a2023-05-17 23:09:58 +08003577 _syscmd(cmd, ret_buf, sizeof(ret_buf));
3578
3579 if (radio_idx == band_2_4) {
3580 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_2G, bss_idx);
3581 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI2G, bss_idx);
3582 } else if (radio_idx == band_5) {
3583 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_5G, bss_idx);
3584 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI5G, bss_idx);
3585 } else if (radio_idx == band_6) {
3586 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_6G, bss_idx);
3587 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI6G, bss_idx);
3588 }
3589
3590 /* fix wpa_psk_file path */
3591 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", apIndex);
3592
3593 params[0].name = "ssid";
3594 params[0].value = ssid;
3595 params[1].name = "interface";
3596 params[1].value = interface;
3597 params[2].name = "wpa_psk_file";
3598 params[2].value = psk_file;
3599
3600 wifi_hostapdWrite(ap_config_file, params, 3);
3601
3602 /*clear psk file*/
3603 memset(cmd, 0, sizeof(cmd));
3604 memset(ret_buf, 0, sizeof(ret_buf));
3605
3606 snprintf(psk_file, sizeof(psk_file), "%s%d.psk", PSK_FILE, apIndex);
3607
3608 if (access(psk_file, F_OK) != 0) {
3609 snprintf(cmd, MAX_CMD_SIZE, "touch %s", psk_file);
3610 _syscmd(cmd, ret_buf, sizeof(ret_buf));
3611 } else {
3612 snprintf(cmd, MAX_CMD_SIZE, "echo '' > %s", psk_file);
3613 _syscmd(cmd, ret_buf, sizeof(ret_buf));
3614 }
3615
developer429ba832023-05-31 11:03:35 +08003616 wifi_setApEnable(apIndex, FALSE);
3617 wifi_setApEnable(apIndex, TRUE);
developer47cc27a2023-05-17 23:09:58 +08003618 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3619
3620 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08003621}
3622
3623//To set Band Steering AP group
3624//To-do
3625INT wifi_setBandSteeringApGroup(char *ApGroup)
3626{
3627 return RETURN_OK;
3628}
3629
3630INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
3631{
3632 char config_file[128] = {'\0'};
3633 char buf[128] = {'\0'};
3634
3635 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3636 if (dtimInterval == NULL)
3637 return RETURN_ERR;
3638
3639 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developer885b56c2023-05-22 15:02:46 +08003640 wifi_hostapdRead(config_file, "dtim_period", buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08003641
3642 if (strlen(buf) == 0) {
3643 *dtimInterval = 2;
3644 } else {
3645 *dtimInterval = strtoul(buf, NULL, 10);
3646 }
3647
3648 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3649 return RETURN_OK;
3650}
3651
3652INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
3653{
3654 struct params params={0};
3655 char config_file[MAX_BUF_SIZE] = {'\0'};
3656 char buf[MAX_BUF_SIZE] = {'\0'};
3657
3658 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3659 if (dtimInterval < 1 || dtimInterval > 255) {
3660 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
3661 return RETURN_ERR;
3662 }
developer69b61b02023-03-07 17:17:44 +08003663
developer72fb0bb2023-01-11 09:46:29 +08003664 params.name = "dtim_period";
3665 snprintf(buf, sizeof(buf), "%d", dtimInterval);
3666 params.value = buf;
3667
3668 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
3669 wifi_hostapdWrite(config_file, &params, 1);
3670 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3671
3672 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3673 return RETURN_OK;
3674}
3675
3676//Check if the driver support the Dfs
3677INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
3678{
3679 wifi_band band = band_invalid;
developer69b61b02023-03-07 17:17:44 +08003680 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08003681 return RETURN_ERR;
3682 *output_bool=FALSE;
3683
3684 band = wifi_index_to_band(radioIndex);
3685 if (band == band_5)
3686 *output_bool = TRUE;
3687 return RETURN_OK;
3688}
3689
3690//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.
3691//The value of this parameter is a comma seperated list of channel number
3692INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
3693{
developer69b61b02023-03-07 17:17:44 +08003694 if (NULL == output_pool)
developer72fb0bb2023-01-11 09:46:29 +08003695 return RETURN_ERR;
3696 if (radioIndex==1)
developer69b61b02023-03-07 17:17:44 +08003697 return RETURN_OK;//TODO need to handle for 5GHz band, i think
developer72fb0bb2023-01-11 09:46:29 +08003698 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
3699
3700 return RETURN_OK;
3701}
3702
3703INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
3704{
3705 //Set to wifi config. And apply instantly.
3706 return RETURN_OK;
3707}
3708
3709INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
3710{
developer69b61b02023-03-07 17:17:44 +08003711 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
developer72fb0bb2023-01-11 09:46:29 +08003712 return RETURN_ERR;
3713 *output_interval_seconds=1800;
3714 *output_dwell_milliseconds=40;
3715
3716 return RETURN_OK;
3717}
3718
3719INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
3720{
3721 //Set to wifi config. And apply instantly.
3722 return RETURN_OK;
3723}
3724
3725INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
3726{
3727 if (output_bool == NULL)
3728 return RETURN_ERR;
developer69b61b02023-03-07 17:17:44 +08003729 *output_bool = true;
3730 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08003731}
3732
3733INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
3734{
3735 return RETURN_OK;
3736}
3737
3738//Get the Dfs enable status
3739INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
3740{
3741 char buf[16] = {0};
developerd1824452023-05-18 12:30:04 +08003742 char config_file_dat[128] = {0};
developerd1824452023-05-18 12:30:04 +08003743 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08003744
3745 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3746
3747 if (output_bool == NULL)
3748 return RETURN_ERR;
developerf6a87542023-05-16 15:47:28 +08003749 *output_bool = TRUE; // default
developerd1824452023-05-18 12:30:04 +08003750 band = wifi_index_to_band(radioIndex);
3751 snprintf(config_file_dat, sizeof(config_file_dat), "%s%d.dat", LOGAN_DAT_FILE, band);
3752
developer262f4cb2023-05-24 12:22:04 +08003753 wifi_datfileRead(config_file_dat, "DfsEnable", buf, sizeof(buf));
developerd1824452023-05-18 12:30:04 +08003754
3755 if (strncmp(buf, "0", 1) == 0)
3756 *output_bool = FALSE;
developer72fb0bb2023-01-11 09:46:29 +08003757 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3758 return RETURN_OK;
3759}
3760
3761//Set the Dfs enable status
3762INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
3763{
developerd1824452023-05-18 12:30:04 +08003764 char config_dat_file[128] = {0};
developer72fb0bb2023-01-11 09:46:29 +08003765 FILE *f = NULL;
developerd1824452023-05-18 12:30:04 +08003766 struct params dat = {0};
3767 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08003768
3769 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3770
3771 f = fopen(DFS_ENABLE_FILE, "w");
3772 if (f == NULL)
3773 return RETURN_ERR;
3774 fprintf(f, "%d", enable);
3775 fclose(f);
3776
developer72fb0bb2023-01-11 09:46:29 +08003777 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
3778
developerd1824452023-05-18 12:30:04 +08003779 dat.name = "DfsEnable";
developer262f4cb2023-05-24 12:22:04 +08003780 dat.value = enable?"1":"0";
developerd1824452023-05-18 12:30:04 +08003781 band = wifi_index_to_band(radioIndex);
3782 snprintf(config_dat_file, sizeof(config_dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
3783 wifi_datfileWrite(config_dat_file, &dat, 1);
developer72fb0bb2023-01-11 09:46:29 +08003784 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3785 return RETURN_OK;
3786}
3787
3788//Check if the driver support the AutoChannelRefreshPeriod
3789INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
3790{
developer69b61b02023-03-07 17:17:44 +08003791 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08003792 return RETURN_ERR;
3793 *output_bool=FALSE; //not support
3794
3795 return RETURN_OK;
3796}
3797
3798//Get the ACS refresh period in seconds
3799INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
3800{
developer69b61b02023-03-07 17:17:44 +08003801 if (NULL == output_ulong)
developer72fb0bb2023-01-11 09:46:29 +08003802 return RETURN_ERR;
3803 *output_ulong=300;
3804
3805 return RETURN_OK;
3806}
3807
3808//Set the ACS refresh period in seconds
3809INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
3810{
3811 return RETURN_ERR;
3812}
3813
3814//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
3815//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.
3816INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
3817{
developer5a333cf2023-06-06 18:18:50 +08003818 char cmd[MAX_CMD_SIZE] = {0}, buf[32] = {0};
developer72fb0bb2023-01-11 09:46:29 +08003819 char extchannel[128] = {0};
developer8666b312023-03-24 14:05:31 +08003820 char interface_name[64] = {0};
3821 int ret = 0, len=0;
developer72fb0bb2023-01-11 09:46:29 +08003822 BOOL radio_enable = FALSE;
3823 wifi_band band;
3824
3825 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3826
developerd1824452023-05-18 12:30:04 +08003827 if (NULL == output_string) {
3828 WIFI_ENTRY_EXIT_DEBUG("output_string is nuill %s: %d \n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08003829 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08003830 }
3831 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR) {
3832 WIFI_ENTRY_EXIT_DEBUG("wifi_getRadioEnable failed %s: %d \n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08003833 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08003834 }
3835 if (radio_enable != TRUE) {
3836 WIFI_ENTRY_EXIT_DEBUG("Radio %d is not enable failed %s: %d \n", radioIndex, __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08003837 return RETURN_OK;
developerd1824452023-05-18 12:30:04 +08003838 }
developer8666b312023-03-24 14:05:31 +08003839 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3840 return RETURN_ERR;
3841 /*IW command get BW320 to do*/
developerd1824452023-05-18 12:30:04 +08003842
developer8666b312023-03-24 14:05:31 +08003843 snprintf(cmd, sizeof(cmd),"iw dev %s info | grep 'width' | cut -d ' ' -f6 | tr -d '\\n'", interface_name);
3844 ret = _syscmd(cmd, buf, sizeof(buf));
3845 len = strlen(buf);
3846 if((ret != 0) || (len == 0))
3847 {
3848 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
3849 return RETURN_ERR;
3850 }
3851
developer72fb0bb2023-01-11 09:46:29 +08003852 band = wifi_index_to_band(radioIndex);
developer8666b312023-03-24 14:05:31 +08003853 if (band == band_2_4 && strncmp(buf, "20", 2) == 0) {
developer72fb0bb2023-01-11 09:46:29 +08003854 wifi_getRadioExtChannel(radioIndex, extchannel);
developer8666b312023-03-24 14:05:31 +08003855 if (strncmp(extchannel, "Auto", 4) != 0) // not auto means we have set HT40+/-
3856 snprintf(buf, sizeof(buf), "40");
developer72fb0bb2023-01-11 09:46:29 +08003857 }
developer8666b312023-03-24 14:05:31 +08003858 snprintf(output_string, 64, "%sMHz", buf);
developer72fb0bb2023-01-11 09:46:29 +08003859 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3860
3861 return RETURN_OK;
developerfead3972023-05-25 20:15:02 +08003862}
3863
3864enum mwctl_chan_width {
3865 MWCTL_CHAN_WIDTH_20,
3866 MWCTL_CHAN_WIDTH_40,
3867 MWCTL_CHAN_WIDTH_80,
3868 MWCTL_CHAN_WIDTH_160,
3869 MWCTL_CHAN_WIDTH_320,
3870};
3871
3872struct bw_option {
3873 unsigned int bandwith;
3874 enum mwctl_chan_width mode;
3875};
3876
3877struct bw_option bw_opt[] = {
3878 {20, MWCTL_CHAN_WIDTH_20},
3879 {40, MWCTL_CHAN_WIDTH_40},
3880 {80, MWCTL_CHAN_WIDTH_80},
3881 {160, MWCTL_CHAN_WIDTH_160},
3882 {320, MWCTL_CHAN_WIDTH_320},
3883};
3884
3885INT wifi_setChannel_netlink(INT radioIndex, UINT* channel, UINT *bandwidth)
3886{
3887 int ret = -1;
3888 int i;
3889 struct unl unl_ins;
3890 struct nl_msg *msg = NULL;
3891 struct nlattr * msg_data = NULL;
3892 struct mtk_nl80211_param param;
3893 bool b_match = FALSE;
3894
3895 /*init mtk nl80211 vendor cmd*/
3896 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_CHANNEL;
3897 param.if_type = NL80211_ATTR_WIPHY;
3898 param.if_idx = radio_index_to_phy(radioIndex);
3899
3900 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
3901 if (ret) {
3902 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
3903 return RETURN_ERR;
3904 }
3905
3906 /*add mtk vendor cmd data*/
3907 if (channel != NULL)
3908 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_CHAN_SET_NUM, *channel)) {
3909 wifi_debug(DEBUG_ERROR, "Nla put CHAN_SET_NUM attribute error\n");
3910 nlmsg_free(msg);
3911 goto err;
3912 }
3913
3914 if (bandwidth != NULL) {
3915 for (i = 0; i < (sizeof(bw_opt)/sizeof(bw_opt[0])); i++) {
3916 if (bw_opt[i].bandwith == *bandwidth) {
3917 b_match = true;
3918 if (nla_put_u32(msg, MTK_NL80211_VENDOR_ATTR_CHAN_SET_BW, bw_opt[i].mode)) {
3919 wifi_debug(DEBUG_ERROR, "Nla put CHAN_SET_BW attribute error\n");
3920 nlmsg_free(msg);
3921 goto err;
3922 }
3923 break;
3924 }
3925 }
3926
3927 if (!b_match) {
3928 wifi_debug(DEBUG_ERROR, "Cannot find bandwith error\n");
3929 nlmsg_free(msg);
3930 goto err;
3931 }
3932 }
3933
3934 /*send mtk nl80211 vendor msg*/
3935 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
3936 if (ret) {
3937 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
3938 goto err;
3939 }
3940 /*deinit mtk nl80211 vendor msg*/
3941 mtk_nl80211_deint(&unl_ins);
3942 wifi_debug(DEBUG_NOTICE, "set cmd success.\n");
3943 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3944
3945 return RETURN_OK;
3946err:
3947 mtk_nl80211_deint(&unl_ins);
3948 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
3949 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08003950}
developerfead3972023-05-25 20:15:02 +08003951
developer72fb0bb2023-01-11 09:46:29 +08003952//Set the Operating Channel Bandwidth.
3953INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
3954{
3955 char config_file[128];
developerd1824452023-05-18 12:30:04 +08003956 char ht_value[16];
3957 char vht_value[16];
3958 char eht_value[16];
3959 struct params dat[3];
3960 wifi_band band = band_invalid;
developerfead3972023-05-25 20:15:02 +08003961 unsigned int bw = 20;
3962 int ret = 0;
developer72fb0bb2023-01-11 09:46:29 +08003963
3964 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3965
3966 if(NULL == bandwidth)
3967 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08003968 band = wifi_index_to_band(radioIndex);
developer72fb0bb2023-01-11 09:46:29 +08003969
developerd1824452023-05-18 12:30:04 +08003970 if(strstr(bandwidth,"320") != NULL) {
3971 snprintf(ht_value, sizeof(ht_value), "%d", HT_BW_40);
3972 snprintf(vht_value, sizeof(vht_value), "%d", VHT_BW_160);
3973 snprintf(eht_value, sizeof(eht_value), "%d", EHT_BW_320);
developer262f4cb2023-05-24 12:22:04 +08003974 bw = 320;
developerd1824452023-05-18 12:30:04 +08003975 } else if(strstr(bandwidth,"160") != NULL) {
3976 snprintf(ht_value, sizeof(ht_value), "%d", HT_BW_40);
3977 snprintf(vht_value, sizeof(vht_value), "%d", VHT_BW_160);
3978 snprintf(eht_value, sizeof(eht_value), "%d", EHT_BW_160);
developer262f4cb2023-05-24 12:22:04 +08003979 bw = 160;
developerd1824452023-05-18 12:30:04 +08003980 } else if(strstr(bandwidth,"80") != NULL) {
3981 snprintf(ht_value, sizeof(ht_value), "%d", HT_BW_40);
3982 snprintf(vht_value, sizeof(vht_value), "%d", VHT_BW_80);
3983 snprintf(eht_value, sizeof(eht_value), "%d", EHT_BW_80);
developer262f4cb2023-05-24 12:22:04 +08003984 bw = 80;
developerd1824452023-05-18 12:30:04 +08003985 } else if(strstr(bandwidth,"40") != NULL) {
3986 snprintf(ht_value, sizeof(ht_value), "%d", HT_BW_40);
3987 snprintf(vht_value, sizeof(vht_value), "%d", VHT_BW_2040);
3988 snprintf(eht_value, sizeof(eht_value), "%d", EHT_BW_40);
developerfead3972023-05-25 20:15:02 +08003989 bw = 40;
developerd1824452023-05-18 12:30:04 +08003990 } else if(strstr(bandwidth,"20") != NULL) {
3991 snprintf(ht_value, sizeof(ht_value), "%d", HT_BW_20);
3992 snprintf(vht_value, sizeof(vht_value), "%d", VHT_BW_2040);
3993 snprintf(eht_value, sizeof(eht_value), "%d", EHT_BW_20);
developer262f4cb2023-05-24 12:22:04 +08003994 bw = 20;
developerd1824452023-05-18 12:30:04 +08003995 } else {
developer72fb0bb2023-01-11 09:46:29 +08003996 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
3997 return RETURN_ERR;
3998 }
3999
developerd1824452023-05-18 12:30:04 +08004000 snprintf(config_file, sizeof(config_file), "%s%d.dat", LOGAN_DAT_FILE, band);
4001 dat[0].name = "HT_BW";
4002 dat[0].value = ht_value;
4003 dat[1].name = "VHT_BW";
4004 dat[1].value = vht_value;
4005 dat[2].name = "EHT_ApBw";
4006 dat[2].value = eht_value;
4007 wifi_datfileWrite(config_file, dat, 3);
developerfead3972023-05-25 20:15:02 +08004008 ret = wifi_setChannel_netlink(radioIndex, NULL, &bw);
4009 if (ret != RETURN_OK) {
4010 fprintf(stderr, "%s: wifi_setChannel return error.\n", __func__);
4011 return RETURN_ERR;
4012 }
developer72fb0bb2023-01-11 09:46:29 +08004013
4014 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4015 return RETURN_OK;
4016}
4017
developer72fb0bb2023-01-11 09:46:29 +08004018//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
4019//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.
4020INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
4021{
4022 char config_file[64] = {0};
developerd1824452023-05-18 12:30:04 +08004023 char config_dat_file[64] = {0};
developer72fb0bb2023-01-11 09:46:29 +08004024 char mode_str[16] = {0};
4025 char buf[64] = {0};
developerd1824452023-05-18 12:30:04 +08004026 char cmd[MAX_CMD_SIZE] = {0};
4027 char interface_name[64] = {0};
4028 int ret = 0, len=0;
developer72fb0bb2023-01-11 09:46:29 +08004029 wifi_band band;
developerd1824452023-05-18 12:30:04 +08004030 ULONG channel = 0;
4031 int centr_channel = 0;
developer72fb0bb2023-01-11 09:46:29 +08004032 UINT mode_map = 0;
developerd1824452023-05-18 12:30:04 +08004033 int freq=0;
developer72fb0bb2023-01-11 09:46:29 +08004034
4035 if (output_string == NULL)
4036 return RETURN_ERR;
4037
4038 wifi_getRadioMode(radioIndex, mode_str, &mode_map);
4039
4040 band = wifi_index_to_band(radioIndex);
4041 if (band == band_invalid)
4042 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08004043 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4044 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08004045
4046 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4047
4048 snprintf(output_string, 64, "Auto");
developer23e71282023-01-18 10:25:19 +08004049 if (band == band_2_4 || (!(mode_map&WIFI_MODE_AC) && !(mode_map&WIFI_MODE_AX))) {
developerd1824452023-05-18 12:30:04 +08004050 // 2G band or ac and ax mode is disable, we will check HT_EXTCHA
4051 snprintf(config_dat_file, sizeof(config_dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
4052 wifi_halgetRadioExtChannel(config_dat_file, output_string);
developer23e71282023-01-18 10:25:19 +08004053 if (!(mode_map&WIFI_MODE_N))
developer72fb0bb2023-01-11 09:46:29 +08004054 snprintf(output_string, 64, "Auto");
4055 } else {
4056 // 5G and 6G band with ac or ax mode.
4057 wifi_getRadioChannel(radioIndex, &channel);
developerd1824452023-05-18 12:30:04 +08004058 snprintf(cmd, sizeof(cmd),"iw dev %s info | grep 'center1' | cut -d ' ' -f9 | tr -d '\\n'", interface_name);
4059
4060 ret = _syscmd(cmd, buf, sizeof(buf));
4061 len = strlen(buf);
4062 if((ret != 0) || (len == 0))
4063 {
4064 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
4065 return RETURN_ERR;
4066 }
4067 sscanf(buf, "%d", &freq);
4068 centr_channel = ieee80211_frequency_to_channel(freq);
4069 if (centr_channel > (int)channel)
developer72fb0bb2023-01-11 09:46:29 +08004070 snprintf(output_string, 64, "AboveControlChannel");
4071 else
4072 snprintf(output_string, 64, "BelowControlChannel");
4073 }
4074
4075 return RETURN_OK;
4076}
4077
4078//Set the extension channel.
4079INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
developer69b61b02023-03-07 17:17:44 +08004080{
developer72fb0bb2023-01-11 09:46:29 +08004081 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4082 struct params params={0};
4083 char config_file[64] = {0};
developerd1824452023-05-18 12:30:04 +08004084 char config_dat_file[64] = {0};
4085 char ext_channel[64] = {0};
developer72fb0bb2023-01-11 09:46:29 +08004086 char buf[128] = {0};
4087 char cmd[128] = {0};
4088 int max_radio_num =0, ret = 0, bandwidth = 0;
developer2f79c922023-06-02 17:33:42 +08004089 unsigned long channel = 0;
developer72fb0bb2023-01-11 09:46:29 +08004090 bool stbcEnable = FALSE;
4091 params.name = "ht_capab";
4092 wifi_band band;
4093
4094 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
4095 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
4096 _syscmd(cmd, buf, sizeof(buf));
4097 if (strlen(buf) != 0)
4098 stbcEnable = TRUE;
4099 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, buf) != RETURN_OK)
4100 return RETURN_ERR;
4101 bandwidth = strtol(buf, NULL, 10);
4102 // TDK expected to get error with 20MHz
developer262f4cb2023-05-24 12:22:04 +08004103 // we handle 20MHz in function wifi_RemoveRadioExtChannel().
developer72fb0bb2023-01-11 09:46:29 +08004104 if (bandwidth == 20 || strstr(buf, "80+80") != NULL)
4105 return RETURN_ERR;
4106
4107 band = wifi_index_to_band(radioIndex);
4108 if (band == band_invalid)
4109 return RETURN_ERR;
4110
4111 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK)
4112 return RETURN_ERR;
4113
developer262f4cb2023-05-24 12:22:04 +08004114 snprintf(buf, sizeof(buf), "HT%d", bandwidth);
4115 ret = util_get_sec_chan_offset(channel, buf);
4116 if (ret == -EINVAL)
4117 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08004118
4119 if(NULL!= strstr(string,"Above")) {
developer262f4cb2023-05-24 12:22:04 +08004120 if ((band == band_2_4 && channel > 9) || (band == band_5 && ret == -1))
4121 return RETURN_OK;
4122 strcpy(ext_channel, "Above");
developer72fb0bb2023-01-11 09:46:29 +08004123 } else if(NULL!= strstr(string,"Below")) {
developer262f4cb2023-05-24 12:22:04 +08004124 if ((band == band_2_4 && channel < 5) || (band == band_5 && ret == -1))
4125 return RETURN_OK;
4126 strcpy(ext_channel, "Below");
4127 } else {
developerd1824452023-05-18 12:30:04 +08004128 printf("%s: invalid EXT_CHA:%s\n", __func__, string);
developer262f4cb2023-05-24 12:22:04 +08004129 return RETURN_ERR;
4130 }
developerd1824452023-05-18 12:30:04 +08004131 params.name = "HT_EXTCHA";
developer72fb0bb2023-01-11 09:46:29 +08004132 params.value = ext_channel;
4133
developerd1824452023-05-18 12:30:04 +08004134 snprintf (config_dat_file, sizeof(config_dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
4135 wifi_datfileWrite(config_dat_file, &params, 1);
4136
developer72fb0bb2023-01-11 09:46:29 +08004137 wifi_getMaxRadioNumber(&max_radio_num);
4138 for(int i=0; i<=MAX_APS/max_radio_num; i++)
4139 {
4140 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(max_radio_num*i));
developer72fb0bb2023-01-11 09:46:29 +08004141 wifi_setRadioSTBCEnable(radioIndex+(max_radio_num*i), stbcEnable);
4142 }
4143
4144 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
4145 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4146 return RETURN_OK;
4147}
4148
4149//Get the guard interval value. eg "400nsec" or "800nsec"
4150//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.
4151INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
4152{
4153 wifi_guard_interval_t GI;
4154
4155 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4156
4157 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
4158 return RETURN_ERR;
4159
4160 if (GI == wifi_guard_interval_400)
4161 strcpy(output_string, "400nsec");
4162 else if (GI == wifi_guard_interval_800)
4163 strcpy(output_string, "800nsec");
4164 else if (GI == wifi_guard_interval_1600)
4165 strcpy(output_string, "1600nsec");
4166 else if (GI == wifi_guard_interval_3200)
4167 strcpy(output_string, "3200nsec");
4168 else
4169 strcpy(output_string, "Auto");
4170
4171 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4172 return RETURN_OK;
4173}
4174
4175//Set the guard interval value.
4176INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
4177{
4178 wifi_guard_interval_t GI;
4179 int ret = 0;
4180
4181 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4182
4183 if (strcmp(string, "400nsec") == 0)
4184 GI = wifi_guard_interval_400;
4185 else if (strcmp(string , "800nsec") == 0)
4186 GI = wifi_guard_interval_800;
4187 else if (strcmp(string , "1600nsec") == 0)
4188 GI = wifi_guard_interval_1600;
4189 else if (strcmp(string , "3200nsec") == 0)
4190 GI = wifi_guard_interval_3200;
4191 else
4192 GI = wifi_guard_interval_auto;
4193
4194 ret = wifi_setGuardInterval(radioIndex, GI);
4195
4196 if (ret == RETURN_ERR) {
4197 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
4198 return RETURN_ERR;
4199 }
4200
4201 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4202 return RETURN_OK;
4203}
4204
4205//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
4206INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
4207{
4208 char buf[32]={0};
4209 char mcs_file[64] = {0};
developerb149d9d2023-06-06 16:14:22 +08004210 char cmd[MAX_CMD_SIZE] = {0};
developer863a4a62023-06-06 16:55:59 +08004211 UINT mode_bitmap = 0;
developer72fb0bb2023-01-11 09:46:29 +08004212
4213 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4214 if(output_int == NULL)
4215 return RETURN_ERR;
4216 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
4217
4218 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
4219 _syscmd(cmd, buf, sizeof(buf));
4220 if (strlen(buf) > 0)
4221 *output_int = strtol(buf, NULL, 10);
4222 else {
4223 // output the max MCS for the current radio mode
4224 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
4225 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
4226 return RETURN_ERR;
4227 }
4228 if (mode_bitmap & WIFI_MODE_AX) {
4229 *output_int = 11;
4230 } else if (mode_bitmap & WIFI_MODE_AC) {
4231 *output_int = 9;
4232 } else if (mode_bitmap & WIFI_MODE_N) {
4233 *output_int = 7;
4234 }
4235 }
4236 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4237
4238 return RETURN_OK;
4239}
4240
4241//Set the Modulation Coding Scheme index
4242INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
4243{
developera1255e42023-05-13 17:45:02 +08004244 /*Only HE mode can specify MCS capability. We don't support MCS in HT mode,
4245 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 +08004246 char config_file[64] = {0};
4247 char set_value[16] = {0};
4248 char mcs_file[32] = {0};
developer72fb0bb2023-01-11 09:46:29 +08004249 struct params set_config = {0};
4250 FILE *f = NULL;
developera1255e42023-05-13 17:45:02 +08004251 INT nss = 0;
4252 int ant_bitmap = 0;
4253 unsigned short cal_value = 0;
4254 UCHAR tval = 0, i = 0;
developer72fb0bb2023-01-11 09:46:29 +08004255
4256 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4257
4258 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4259
4260 // -1 means auto
4261 if (MCS > 15 || MCS < -1) {
4262 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
4263 return RETURN_ERR;
4264 }
developera1255e42023-05-13 17:45:02 +08004265 wifi_getRadioTxChainMask(radioIndex, &ant_bitmap);/*nss is a bit map value,1111*/
4266 for(; ant_bitmap > 0; ant_bitmap >>= 1)
4267 nss += 1;
4268 //printf("%s:nss = %d\n", __func__, nss);
4269 /*16-bit combination of 2-bit values of Max HE-MCS For 1..8 SS;each 2-bit value have following meaning:
4270 0 = HE-MCS 0-7, 1 = HE-MCS 0-9, 2 = HE-MCS 0-11, 3 = not supported*/
developer72fb0bb2023-01-11 09:46:29 +08004271 if (MCS > 9 || MCS == -1)
developera1255e42023-05-13 17:45:02 +08004272 tval = 2;/*one stream value*/
developer72fb0bb2023-01-11 09:46:29 +08004273 else if (MCS > 7)
developera1255e42023-05-13 17:45:02 +08004274 tval = 1;
developer72fb0bb2023-01-11 09:46:29 +08004275 else
developera1255e42023-05-13 17:45:02 +08004276 tval = 0;
4277 for (i = 0; i < nss; i++)
4278 cal_value |= (tval << (2*i));
4279 snprintf(set_value, sizeof(set_value), "%x", cal_value);
4280 WIFI_ENTRY_EXIT_DEBUG("%s:set=%s, cal=%x\n", __func__, set_value, cal_value);
4281 set_config.name = "he_basic_mcs_nss_set";/*He capability in beacon or response*/
developer72fb0bb2023-01-11 09:46:29 +08004282 set_config.value = set_value;
4283
4284 wifi_hostapdWrite(config_file, &set_config, 1);
4285 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
4286
4287 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
4288 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
4289 f = fopen(mcs_file, "w");
4290 if (f == NULL) {
4291 fprintf(stderr, "%s: fopen failed\n", __func__);
4292 return RETURN_ERR;
4293 }
4294 fprintf(f, "%d", MCS);
4295 fclose(f);
4296
4297 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4298 return RETURN_OK;
4299}
4300
4301//Get supported Transmit Power list, eg : "0,25,50,75,100"
4302//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.
4303INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
4304{
4305 if (NULL == output_list)
4306 return RETURN_ERR;
4307 snprintf(output_list, 64,"0,25,50,75,100");
4308 return RETURN_OK;
4309}
4310
4311//Get current Transmit Power in dBm units.
4312//The transmite power level is in units of full power for this radio.
4313INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
4314{
4315 char interface_name[16] = {0};
developerb149d9d2023-06-06 16:14:22 +08004316 char cmd[MAX_CMD_SIZE]={0};
developer72fb0bb2023-01-11 09:46:29 +08004317 char buf[16]={0};
developera1255e42023-05-13 17:45:02 +08004318 char pwr_file[128]={0};
4319
developer72fb0bb2023-01-11 09:46:29 +08004320 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4321
4322 if(output_ulong == NULL)
4323 return RETURN_ERR;
4324
4325 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4326 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +08004327/*
developer72fb0bb2023-01-11 09:46:29 +08004328 snprintf(cmd, sizeof(cmd), "iw %s info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", interface_name);
4329 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08004330 *output_ulong = strtol(buf, NULL, 10);
developera1255e42023-05-13 17:45:02 +08004331*/
4332 snprintf(pwr_file, sizeof(pwr_file), "%s%d.txt", POWER_PERCENTAGE, radioIndex);
4333 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", pwr_file);
4334 _syscmd(cmd, buf, sizeof(buf));
4335 if (strlen(buf) > 0)
4336 *output_ulong = strtol(buf, NULL, 10);
4337 else
4338 *output_ulong = 100;
developer72fb0bb2023-01-11 09:46:29 +08004339 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4340 return RETURN_OK;
4341}
4342
4343//Set Transmit Power
4344//The transmite power level is in units of full power for this radio.
4345INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
4346{
4347 char interface_name[16] = {0};
4348 char *support;
developer72fb0bb2023-01-11 09:46:29 +08004349 char buf[128]={0};
4350 char txpower_str[64] = {0};
developera1255e42023-05-13 17:45:02 +08004351 char pwr_file[128]={0};
4352 FILE *f = NULL;
developerfead3972023-05-25 20:15:02 +08004353 int if_idx, ret = 0;
4354 struct nl_msg *msg = NULL;
4355 struct nlattr * msg_data = NULL;
4356 struct mtk_nl80211_param param;
4357 struct unl unl_ins;
developer72fb0bb2023-01-11 09:46:29 +08004358
4359 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4360
4361 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4362 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +08004363 // Get the Tx power supported list and check that is the input in the list
4364 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
4365 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
4366 support = strtok(buf, ",");
4367 while(true)
4368 {
4369 if(support == NULL) { // input not in the list
4370 wifi_dbg_printf("Input value is invalid.\n");
4371 return RETURN_ERR;
4372 }
4373 if (strncmp(txpower_str, support, strlen(support)) == 0) {
4374 break;
4375 }
4376 support = strtok(NULL, ",");
4377 }
developerfead3972023-05-25 20:15:02 +08004378
4379 if_idx = if_nametoindex(interface_name);
4380 /*init mtk nl80211 vendor cmd*/
4381 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_TXPOWER;
4382 param.if_type = NL80211_ATTR_IFINDEX;
4383 param.if_idx = if_idx;
4384 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
4385 if (ret) {
4386 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
4387 return RETURN_ERR;
4388 }
4389 /*add mtk vendor cmd data*/
4390 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_TXPWR_PERCENTAGE_EN, 1)) {
4391 wifi_debug(DEBUG_ERROR, "Nla put attribute error\n");
4392 nlmsg_free(msg);
4393 goto err;
4394 }
4395
4396 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_TXPWR_DROP_CTRL, TransmitPower)) {
4397 wifi_debug(DEBUG_ERROR, "Nla put attribute error\n");
4398 nlmsg_free(msg);
4399 goto err;
4400 }
4401
4402 /*send mtk nl80211 vendor msg*/
4403 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
4404 if (ret) {
4405 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
4406 goto err;
4407 }
4408 /*deinit mtk nl80211 vendor msg*/
4409 mtk_nl80211_deint(&unl_ins);
4410 wifi_debug(DEBUG_NOTICE, "set cmd success.\n");
4411
developera1255e42023-05-13 17:45:02 +08004412 snprintf(pwr_file, sizeof(pwr_file), "%s%d.txt", POWER_PERCENTAGE, radioIndex);
4413 f = fopen(pwr_file, "w");
4414 if (f == NULL) {
4415 fprintf(stderr, "%s: fopen failed\n", __func__);
4416 return RETURN_ERR;
4417 }
developerdaf24792023-06-06 11:40:04 +08004418 fprintf(f, "%lu", TransmitPower);
developera1255e42023-05-13 17:45:02 +08004419 fclose(f);
4420/* 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 +08004421 _syscmd(cmd, buf, sizeof(buf));
4422 maximum_tx = strtol(buf, NULL, 10);
4423
4424 // Get the Tx power supported list and check that is the input in the list
4425 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
4426 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
4427 support = strtok(buf, ",");
4428 while(true)
4429 {
4430 if(support == NULL) { // input not in the list
4431 wifi_dbg_printf("Input value is invalid.\n");
4432 return RETURN_ERR;
4433 }
4434 if (strncmp(txpower_str, support, strlen(support)) == 0) {
4435 break;
4436 }
4437 support = strtok(NULL, ",");
4438 }
4439 txpower = TransmitPower*maximum_tx/100;
4440 phyId = radio_index_to_phy(radioIndex);
4441 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", phyId, txpower);
4442 _syscmd(cmd, buf, sizeof(buf));
4443 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera1255e42023-05-13 17:45:02 +08004444*/
4445 return RETURN_OK;
developerfead3972023-05-25 20:15:02 +08004446err:
4447 mtk_nl80211_deint(&unl_ins);
4448 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
4449 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08004450}
4451
4452//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
4453INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
4454{
developer69b61b02023-03-07 17:17:44 +08004455 if (NULL == Supported)
developer72fb0bb2023-01-11 09:46:29 +08004456 return RETURN_ERR;
4457 *Supported = TRUE;
4458
4459 return RETURN_OK;
4460}
4461
4462//Get 80211h feature enable
4463INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
4464{
4465 char buf[64]={'\0'};
4466 char config_file[64] = {'\0'};
4467
4468 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4469 if(enable == NULL)
4470 return RETURN_ERR;
4471
4472 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
developerd1824452023-05-18 12:30:04 +08004473 /* wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf)); */
4474 wifi_datfileRead(config_file, "IEEE80211H", buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08004475
4476 if (strncmp(buf, "1", 1) == 0)
4477 *enable = TRUE;
4478 else
4479 *enable = FALSE;
4480
4481 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4482 return RETURN_OK;
4483}
4484
4485//Set 80211h feature enable
4486INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
4487{
4488 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4489 struct params params={'\0'};
developerd1824452023-05-18 12:30:04 +08004490 struct params dat={0};
developer72fb0bb2023-01-11 09:46:29 +08004491 char config_file[MAX_BUF_SIZE] = {0};
developerd1824452023-05-18 12:30:04 +08004492 char config_dat_file[MAX_BUF_SIZE] = {0};
4493 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08004494
4495 params.name = "ieee80211h";
4496
4497 if (enable) {
4498 params.value = "1";
4499 } else {
4500 params.value = "0";
4501 }
4502
developerd1824452023-05-18 12:30:04 +08004503 dat.name = "IEEE80211H";
4504 dat.value = params.value;
4505
4506 band = wifi_index_to_band(radioIndex);
4507 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4508 snprintf(config_dat_file, sizeof(config_dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
developer69b61b02023-03-07 17:17:44 +08004509
developerd1824452023-05-18 12:30:04 +08004510 wifi_hostapdWrite(config_file, &params, 1);
4511 wifi_datfileWrite(config_dat_file, &dat, 1);
developer72fb0bb2023-01-11 09:46:29 +08004512 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
4513 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4514 return RETURN_OK;
4515}
4516
4517//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.
4518INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
4519{
4520 if (NULL == output)
4521 return RETURN_ERR;
4522 *output=100;
4523
4524 return RETURN_OK;
4525}
4526
4527//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.
4528INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
4529{
4530 if (NULL == output)
4531 return RETURN_ERR;
4532 *output = -99;
4533
4534 return RETURN_OK;
4535}
4536
4537INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
4538{
4539 return RETURN_ERR;
4540}
4541
4542
4543//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
4544INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
4545{
4546 char interface_name[16] = {0};
4547 char cmd[MAX_BUF_SIZE]={'\0'};
4548 char buf[MAX_CMD_SIZE]={'\0'};
4549
4550 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4551 if(output == NULL)
4552 return RETURN_ERR;
4553
4554 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4555 return RETURN_ERR;
4556 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", interface_name);
4557 _syscmd(cmd, buf, sizeof(buf));
4558 *output = atoi(buf);
4559
4560 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4561 return RETURN_OK;
4562}
developer69b61b02023-03-07 17:17:44 +08004563
developer72fb0bb2023-01-11 09:46:29 +08004564INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
4565{
4566 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4567 struct params params={'\0'};
4568 char buf[MAX_BUF_SIZE] = {'\0'};
4569 char config_file[MAX_BUF_SIZE] = {'\0'};
4570
4571 if (BeaconPeriod < 15 || BeaconPeriod > 65535)
4572 return RETURN_ERR;
4573
4574 params.name = "beacon_int";
4575 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
4576 params.value = buf;
4577
4578 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
4579 wifi_hostapdWrite(config_file, &params, 1);
developer69b61b02023-03-07 17:17:44 +08004580
developer72fb0bb2023-01-11 09:46:29 +08004581 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
4582 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4583 return RETURN_OK;
4584}
4585
4586//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.
4587INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
4588{
4589 //TODO: need to revisit below implementation
4590 char *temp;
4591 char temp_output[128] = {0};
4592 char temp_TransmitRates[64] = {0};
4593 char config_file[64] = {0};
4594
4595 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4596 if (NULL == output)
4597 return RETURN_ERR;
4598 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
4599 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
developer69b61b02023-03-07 17:17:44 +08004600
developer72fb0bb2023-01-11 09:46:29 +08004601 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
4602 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
4603 } else {
4604 temp = strtok(temp_TransmitRates," ");
4605 while(temp!=NULL)
4606 {
4607 // Convert 100 kbps to Mbps
4608 temp[strlen(temp)-1]=0;
4609 if((temp[0]=='5') && (temp[1]=='\0'))
4610 {
4611 temp="5.5";
4612 }
4613 strcat(temp_output,temp);
4614 temp = strtok(NULL," ");
4615 if(temp!=NULL)
4616 {
4617 strcat(temp_output,",");
4618 }
4619 }
4620 strcpy(output,temp_output);
4621 }
4622 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4623 return RETURN_OK;
4624}
4625
4626INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
4627{
4628 char *temp;
4629 char temp1[128];
4630 char temp_output[128];
4631 char temp_TransmitRates[128];
4632 char set[128];
4633 char sub_set[128];
4634 int set_count=0,subset_count=0;
4635 int set_index=0,subset_index=0;
4636 char *token;
4637 int flag=0, i=0;
4638 struct params params={'\0'};
4639 char config_file[MAX_BUF_SIZE] = {0};
4640 wifi_band band = wifi_index_to_band(radioIndex);
4641
4642 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4643 if(NULL == TransmitRates)
4644 return RETURN_ERR;
4645 strcpy(sub_set,TransmitRates);
4646
4647 //Allow only supported Data transmit rate to be set
4648 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
4649 token = strtok(sub_set,",");
4650 while( token != NULL ) /* split the basic rate to be set, by comma */
4651 {
4652 sub_set[subset_count]=atoi(token);
4653 subset_count++;
4654 token=strtok(NULL,",");
4655 }
4656 token=strtok(set,",");
4657 while(token!=NULL) /* split the supported rate by comma */
4658 {
4659 set[set_count]=atoi(token);
4660 set_count++;
4661 token=strtok(NULL,",");
4662 }
4663 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
4664 {
4665 for(set_index=0;set_index < set_count;set_index++)
4666 {
4667 flag=0;
4668 if(sub_set[subset_index]==set[set_index])
4669 break;
4670 else
4671 flag=1; /* No match found */
4672 }
4673 if(flag==1)
4674 return RETURN_ERR; //If value not found return Error
4675 }
4676 strcpy(temp_TransmitRates,TransmitRates);
4677
4678 for(i=0;i<strlen(temp_TransmitRates);i++)
4679 {
4680 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
4681 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
4682 {
4683 continue;
4684 }
4685 else
4686 {
4687 return RETURN_ERR;
4688 }
4689 }
4690 strcpy(temp_output,"");
4691 temp = strtok(temp_TransmitRates,",");
4692 while(temp!=NULL)
4693 {
4694 strcpy(temp1,temp);
4695 if(band == band_5)
4696 {
4697 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
4698 {
4699 return RETURN_ERR;
4700 }
4701 }
4702
4703 if(strcmp(temp,"5.5")==0)
4704 {
4705 strcpy(temp1,"55");
4706 }
4707 else
4708 {
4709 strcat(temp1,"0");
4710 }
4711 strcat(temp_output,temp1);
4712 temp = strtok(NULL,",");
4713 if(temp!=NULL)
4714 {
4715 strcat(temp_output," ");
4716 }
4717 }
4718 strcpy(TransmitRates,temp_output);
4719
4720 params.name= "basic_rates";
4721 params.value =TransmitRates;
4722
4723 wifi_dbg_printf("\n%s:",__func__);
4724 wifi_dbg_printf("\nparams.value=%s\n",params.value);
4725 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
4726 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
4727 wifi_hostapdWrite(config_file,&params,1);
4728 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4729 return RETURN_OK;
4730}
4731
4732//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
4733INT wifi_GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
4734{
4735 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
4736 FILE *fp = NULL;
4737 char path[256] = {0}, output_string[256] = {0};
4738 int count = 0;
4739 char *interface = NULL;
4740
4741 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
4742 if (fp == NULL)
4743 {
4744 printf("Failed to run command in Function %s\n", __FUNCTION__);
4745 return RETURN_ERR;
4746 }
4747 if (fgets(path, sizeof(path) - 1, fp) != NULL)
4748 {
4749 interface = strchr(path, '=');
4750
4751 if (interface != NULL)
4752 {
4753 strcpy(output_string, interface + 1);
4754 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
4755 interface_name[count] = output_string[count];
4756
4757 interface_name[count] = '\0';
4758 }
4759 }
4760 pclose(fp);
4761 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
4762 return RETURN_OK;
4763}
4764
4765INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
4766{
4767 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
4768 output_struct->radio_BytesSent = 0;
4769 output_struct->radio_BytesReceived = 0;
4770 output_struct->radio_PacketsSent = 0;
4771 output_struct->radio_PacketsReceived = 0;
4772 output_struct->radio_ErrorsSent = 0;
4773 output_struct->radio_ErrorsReceived = 0;
4774 output_struct->radio_DiscardPacketsSent = 0;
4775 output_struct->radio_DiscardPacketsReceived = 0;
4776 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
4777 return RETURN_OK;
4778}
4779
4780
4781INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
4782{
4783 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
4784 CHAR buf[MAX_CMD_SIZE] = {0};
4785 CHAR Value[MAX_BUF_SIZE] = {0};
4786 FILE *fp = NULL;
4787
4788 if (ifname == NULL || strlen(ifname) <= 1)
4789 return RETURN_OK;
4790
4791 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
4792 system(buf);
4793
4794 fp = fopen("/tmp/Radio_Stats.txt", "r");
4795 if(fp == NULL)
4796 {
4797 printf("/tmp/Radio_Stats.txt not exists \n");
4798 return RETURN_ERR;
4799 }
4800 fclose(fp);
4801
4802 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4803 File_Reading(buf, Value);
4804 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
4805
4806 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4807 File_Reading(buf, Value);
4808 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
4809
4810 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4811 File_Reading(buf, Value);
4812 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
4813
4814 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4815 File_Reading(buf, Value);
4816 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
4817
4818 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4819 File_Reading(buf, Value);
4820 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
4821
4822 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4823 File_Reading(buf, Value);
4824 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
4825
4826 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4827 File_Reading(buf, Value);
4828 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
4829
4830 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4831 File_Reading(buf, Value);
4832 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
4833
4834 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
4835 return RETURN_OK;
4836}
4837
4838INT GetIfacestatus(CHAR *interface_name, CHAR *status)
4839{
developer7e4a2a62023-04-06 19:56:03 +08004840 CHAR buf[MAX_CMD_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08004841
developer7e4a2a62023-04-06 19:56:03 +08004842 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
4843
4844 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL) {
4845 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
4846 File_Reading(buf, status);
4847 }
4848
4849 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
4850 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08004851}
4852
4853//Get detail radio traffic static info
4854INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
4855{
4856
developer69b61b02023-03-07 17:17:44 +08004857#if 0
4858 //ifconfig radio_x
developer72fb0bb2023-01-11 09:46:29 +08004859 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
4860 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
4861 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
4862 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
4863
4864 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
4865 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
4866 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.
4867 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.
4868
developer69b61b02023-03-07 17:17:44 +08004869 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 +08004870 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].
4871 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
4872 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.
4873 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
4874 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
4875 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
4876 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
4877 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
4878
4879 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
4880 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
4881 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
4882 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.
4883
4884 return RETURN_OK;
4885#endif
4886
4887 CHAR interface_name[64] = {0};
4888 BOOL iface_status = FALSE;
4889 wifi_radioTrafficStats2_t radioTrafficStats = {0};
4890
4891 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
4892 if (NULL == output_struct)
4893 return RETURN_ERR;
4894
4895 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4896 return RETURN_ERR;
4897
4898 wifi_getApEnable(radioIndex, &iface_status);
4899
4900 if (iface_status == TRUE)
4901 wifi_halGetIfStats(interface_name, &radioTrafficStats);
4902 else
4903 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
4904
4905 output_struct->radio_BytesSent = radioTrafficStats.radio_BytesSent;
4906 output_struct->radio_BytesReceived = radioTrafficStats.radio_BytesReceived;
4907 output_struct->radio_PacketsSent = radioTrafficStats.radio_PacketsSent;
4908 output_struct->radio_PacketsReceived = radioTrafficStats.radio_PacketsReceived;
4909 output_struct->radio_ErrorsSent = radioTrafficStats.radio_ErrorsSent;
4910 output_struct->radio_ErrorsReceived = radioTrafficStats.radio_ErrorsReceived;
4911 output_struct->radio_DiscardPacketsSent = radioTrafficStats.radio_DiscardPacketsSent;
4912 output_struct->radio_DiscardPacketsReceived = radioTrafficStats.radio_DiscardPacketsReceived;
4913
4914 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
4915 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].
4916 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
4917 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.
4918 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
4919 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
4920 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
4921 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
4922 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
4923
4924 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
4925 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
4926 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
4927 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.
4928
4929 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
4930
4931 return RETURN_OK;
4932}
4933
4934//Set radio traffic static Measureing rules
4935INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
4936{
4937 //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
4938 // Else, save the MeasuringRate and MeasuringInterval for future usage
4939
4940 return RETURN_OK;
4941}
4942
4943//To start or stop RadioTrafficStats
4944INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
4945{
4946 //zqiu: If the RadioTrafficStats process running
4947 // if(enable)
4948 // return RETURN_OK.
4949 // else
4950 // Stop RadioTrafficStats process
developer69b61b02023-03-07 17:17:44 +08004951 // Else
developer72fb0bb2023-01-11 09:46:29 +08004952 // if(enable)
4953 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
4954 // else
4955 // return RETURN_OK.
4956
4957 return RETURN_OK;
4958}
4959
4960//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
4961INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
4962{
4963 //zqiu: Please ignor signalIndex.
developer69b61b02023-03-07 17:17:44 +08004964 if (NULL == SignalLevel)
developer72fb0bb2023-01-11 09:46:29 +08004965 return RETURN_ERR;
developer47cc27a2023-05-17 23:09:58 +08004966
developer72fb0bb2023-01-11 09:46:29 +08004967 *SignalLevel=(radioIndex==0)?-19:-19;
4968
4969 return RETURN_OK;
4970}
4971
4972//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
4973INT wifi_applyRadioSettings(INT radioIndex)
4974{
4975 return RETURN_OK;
4976}
4977
4978//Get the radio index assocated with this SSID entry
4979INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
4980{
4981 if(NULL == radioIndex)
4982 return RETURN_ERR;
4983 int max_radio_num = 0;
4984 wifi_getMaxRadioNumber(&max_radio_num);
4985 *radioIndex = ssidIndex%max_radio_num;
4986 return RETURN_OK;
4987}
4988
4989//Device.WiFi.SSID.{i}.Enable
4990//Get SSID enable configuration parameters (not the SSID enable status)
4991INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
4992{
developer69b61b02023-03-07 17:17:44 +08004993 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08004994 return RETURN_ERR;
4995
4996 return wifi_getApEnable(ssidIndex, output_bool);
4997}
4998
4999//Device.WiFi.SSID.{i}.Enable
5000//Set SSID enable configuration parameters
5001INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
5002{
5003 return wifi_setApEnable(ssidIndex, enable);
5004}
5005
5006//Device.WiFi.SSID.{i}.Status
5007//Get the SSID enable status
5008INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
5009{
developer72fb0bb2023-01-11 09:46:29 +08005010 BOOL output_bool;
5011
5012 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5013 if (NULL == output_string)
5014 return RETURN_ERR;
developer69b61b02023-03-07 17:17:44 +08005015
developer72fb0bb2023-01-11 09:46:29 +08005016 wifi_getApEnable(ssidIndex,&output_bool);
5017 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
5018
5019 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5020 return RETURN_OK;
5021}
5022
5023// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
5024INT wifi_getSSIDName(INT apIndex, CHAR *output)
5025{
5026 char config_file[MAX_BUF_SIZE] = {0};
5027
developer69b61b02023-03-07 17:17:44 +08005028 if (NULL == output)
developer72fb0bb2023-01-11 09:46:29 +08005029 return RETURN_ERR;
5030
5031 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5032 wifi_hostapdRead(config_file,"ssid",output,32);
5033
5034 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
5035 return RETURN_OK;
5036}
5037
developer69b61b02023-03-07 17:17:44 +08005038// Set a max 32 byte string and sets an internal variable to the SSID name
developer72fb0bb2023-01-11 09:46:29 +08005039INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
5040{
developer72fb0bb2023-01-11 09:46:29 +08005041 struct params params;
5042 char config_file[MAX_BUF_SIZE] = {0};
5043
5044 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5045 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
5046 return RETURN_ERR;
5047
5048 params.name = "ssid";
5049 params.value = ssid_string;
5050 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5051 wifi_hostapdWrite(config_file, &params, 1);
5052 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5053 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5054
5055 return RETURN_OK;
5056}
5057
5058//Get the BSSID
5059INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
5060{
developer7e4a2a62023-04-06 19:56:03 +08005061 char cmd[MAX_CMD_SIZE] = {0};
5062 char inf_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08005063
developer7e4a2a62023-04-06 19:56:03 +08005064 if (!output_string)
developerdaf24792023-06-06 11:40:04 +08005065 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08005066
developer47cc27a2023-05-17 23:09:58 +08005067 if (wifi_GetInterfaceName(ssidIndex, inf_name) != RETURN_OK)
5068 return RETURN_ERR;
developer7e4a2a62023-04-06 19:56:03 +08005069
developer5b2f10c2023-05-25 17:02:21 +08005070 if (ssidIndex < 0 || ssidIndex > MAX_APS) {
5071 wifi_debug(DEBUG_ERROR, "innvalide ssidIdex(%d)\n", ssidIndex);
5072 strncpy(output_string, "\0", 1);
5073 return RETURN_ERR;
5074 }
5075 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep bssid | cut -d '=' -f2 | tr -d '\\n'", inf_name);
5076 _syscmd(cmd, output_string, 64);
developer7e4a2a62023-04-06 19:56:03 +08005077
developer5b2f10c2023-05-25 17:02:21 +08005078 /* if hostapd does not control interface even if this interface has been brought up,
5079 * try to get its mac address by iw command.
5080 */
5081 if(strlen(output_string) == 0) {
5082 memset(cmd, 0, sizeof(cmd));
5083 snprintf(cmd, sizeof(cmd), "iw dev %s info | grep \"addr\" | awk \'{print $2}\'", inf_name);
5084 _syscmd(cmd, output_string, 64);
5085 }
developer72fb0bb2023-01-11 09:46:29 +08005086
developer5b2f10c2023-05-25 17:02:21 +08005087 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08005088}
5089
5090//Get the MAC address associated with this Wifi SSID
5091INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
5092{
5093 wifi_getBaseBSSID(ssidIndex,output_string);
5094 return RETURN_OK;
5095}
5096
5097//Get the basic SSID traffic static info
5098//Apply SSID and AP (in the case of Acess Point devices) to the hardware
5099//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
5100INT wifi_applySSIDSettings(INT ssidIndex)
5101{
5102 char interface_name[16] = {0};
5103 BOOL status = false;
5104 char cmd[MAX_CMD_SIZE] = {0};
5105 char buf[MAX_CMD_SIZE] = {0};
5106 int apIndex, ret;
5107 int max_radio_num = 0;
5108 int radioIndex = 0;
5109
5110 wifi_getMaxRadioNumber(&max_radio_num);
5111
5112 radioIndex = ssidIndex % max_radio_num;
5113
5114 wifi_getApEnable(ssidIndex,&status);
5115 // Do not apply when ssid index is disabled
5116 if (status == false)
5117 return RETURN_OK;
5118
5119 /* Doing full remove and add for ssid Index
5120 * Not all hostapd options are supported with reload
5121 * for example macaddr_acl
5122 */
5123 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
5124 return RETURN_ERR;
5125
5126 ret = wifi_setApEnable(ssidIndex,true);
5127
5128 /* Workaround for hostapd issue with multiple bss definitions
5129 * when first created interface will be removed
5130 * then all vaps other vaps on same phy are removed
5131 * after calling setApEnable to false readd all enabled vaps */
5132 for(int i=0; i < MAX_APS/max_radio_num; i++) {
5133 apIndex = max_radio_num*i+radioIndex;
5134 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5135 return RETURN_ERR;
5136 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
5137 _syscmd(cmd, buf, sizeof(buf));
5138 if(*buf == '1')
5139 wifi_setApEnable(apIndex, true);
5140 }
5141
5142 return ret;
5143}
5144
5145struct channels_noise {
5146 int channel;
5147 int noise;
5148};
5149
5150// Return noise array for each channel
5151int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
5152{
5153 char interface_name[16] = {0};
5154 FILE *f = NULL;
5155 char cmd[128] = {0};
5156 char line[256] = {0};
developer72fb0bb2023-01-11 09:46:29 +08005157 int tmp = 0, arr_index = -1;
5158
5159 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
5160 return RETURN_ERR;
5161 sprintf(cmd, "iw dev %s survey dump | grep 'frequency\\|noise' | awk '{print $2}'", interface_name);
5162
5163 if ((f = popen(cmd, "r")) == NULL) {
5164 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
5165 return RETURN_ERR;
5166 }
developer69b61b02023-03-07 17:17:44 +08005167
developer72fb0bb2023-01-11 09:46:29 +08005168 while(fgets(line, sizeof(line), f) != NULL) {
5169 if(arr_index < channels_num){
5170 sscanf(line, "%d", &tmp);
5171 if (tmp > 0) { // channel frequency, the first line must be frequency
5172 arr_index++;
5173 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
5174 } else { // noise
5175 channels_noise_arr[arr_index].noise = tmp;
5176 }
5177 }else{
5178 break;
5179 }
5180 }
5181 pclose(f);
5182 return RETURN_OK;
5183}
5184
5185//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
5186//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
developer69b61b02023-03-07 17:17:44 +08005187INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
developer72fb0bb2023-01-11 09:46:29 +08005188{
5189 int index = -1;
5190 wifi_neighbor_ap2_t *scan_array = NULL;
5191 char cmd[256]={0};
5192 char buf[128]={0};
5193 char file_name[32] = {0};
5194 char filter_SSID[32] = {0};
5195 char line[256] = {0};
5196 char interface_name[16] = {0};
5197 char *ret = NULL;
5198 int freq=0;
5199 FILE *f = NULL;
developer72fb0bb2023-01-11 09:46:29 +08005200 int channels_num = 0;
5201 int vht_channel_width = 0;
5202 int get_noise_ret = RETURN_ERR;
5203 bool filter_enable = false;
5204 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
5205 int phyId = 0;
5206
5207 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
5208
5209 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
5210 return RETURN_ERR;
5211
5212 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
5213 f = fopen(file_name, "r");
5214 if (f != NULL) {
developer47a56bf2023-05-30 13:38:57 +08005215 fgets(buf, sizeof(file_name), f);
5216 if ((strncmp(buf, "0", 1)) != 0) {
5217 fgets(filter_SSID, sizeof(file_name), f);
5218 if (strlen(filter_SSID) != 0)
5219 filter_enable = true;
5220 }
developer72fb0bb2023-01-11 09:46:29 +08005221 fclose(f);
5222 }
5223
5224 phyId = radio_index_to_phy(radioIndex);
5225 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
5226 _syscmd(cmd, buf, sizeof(buf));
5227 channels_num = strtol(buf, NULL, 10);
5228
5229
5230
5231 sprintf(cmd, "iw dev %s scan | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
5232 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", interface_name, interface_name);
5233 fprintf(stderr, "cmd: %s\n", cmd);
5234 if ((f = popen(cmd, "r")) == NULL) {
5235 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
5236 return RETURN_ERR;
5237 }
developer69b61b02023-03-07 17:17:44 +08005238
developer72fb0bb2023-01-11 09:46:29 +08005239 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
5240 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
developer69b61b02023-03-07 17:17:44 +08005241
developer72fb0bb2023-01-11 09:46:29 +08005242 ret = fgets(line, sizeof(line), f);
5243 while (ret != NULL) {
5244 if(strstr(line, "BSS") != NULL) { // new neighbor info
developer69b61b02023-03-07 17:17:44 +08005245 // 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 +08005246 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
5247 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
5248
5249 if (!filter_BSS) {
5250 index++;
5251 wifi_neighbor_ap2_t *tmp;
5252 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
5253 if (tmp == NULL) { // no more memory to use
5254 index--;
5255 wifi_dbg_printf("%s: realloc failed\n", __func__);
5256 break;
5257 }
5258 scan_array = tmp;
5259 }
5260 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
5261
5262 filter_BSS = false;
5263 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
developerc79e9172023-06-06 19:48:03 +08005264 memset(scan_array[index].ap_Mode, 0, sizeof(scan_array[index].ap_Mode));
5265 memcpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
5266 memset(scan_array[index].ap_SecurityModeEnabled, 0, sizeof(scan_array[index].ap_SecurityModeEnabled));
5267 memcpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
5268 memset(scan_array[index].ap_EncryptionMode, 0, sizeof(scan_array[index].ap_EncryptionMode));
5269 memcpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
developer72fb0bb2023-01-11 09:46:29 +08005270 } else if (strstr(line, "freq") != NULL) {
5271 sscanf(line," freq: %d", &freq);
5272 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
5273
5274 if (freq >= 2412 && freq <= 2484) {
developerc79e9172023-06-06 19:48:03 +08005275 memset(scan_array[index].ap_OperatingFrequencyBand, 0, sizeof(scan_array[index].ap_OperatingFrequencyBand));
5276 memcpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
5277 memset(scan_array[index].ap_SupportedStandards, 0, sizeof(scan_array[index].ap_SupportedStandards));
5278 memcpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
5279 memset(scan_array[index].ap_OperatingStandards, 0, sizeof(scan_array[index].ap_OperatingStandards));
5280 memcpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
developer72fb0bb2023-01-11 09:46:29 +08005281 }
5282 else if (freq >= 5160 && freq <= 5805) {
developerc79e9172023-06-06 19:48:03 +08005283 memset(scan_array[index].ap_OperatingFrequencyBand, 0, sizeof(scan_array[index].ap_OperatingFrequencyBand));
5284 memcpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
5285 memset(scan_array[index].ap_SupportedStandards, 0, sizeof(scan_array[index].ap_SupportedStandards));
5286 memcpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
5287 memset(scan_array[index].ap_OperatingStandards, 0, sizeof(scan_array[index].ap_OperatingStandards));
5288 memcpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
developer72fb0bb2023-01-11 09:46:29 +08005289 }
5290
5291 scan_array[index].ap_Noise = 0;
5292 if (get_noise_ret == RETURN_OK) {
5293 for (int i = 0; i < channels_num; i++) {
5294 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
5295 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
5296 break;
5297 }
5298 }
5299 }
5300 } else if (strstr(line, "beacon interval") != NULL) {
5301 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
5302 } else if (strstr(line, "signal") != NULL) {
5303 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
5304 } else if (strstr(line,"SSID") != NULL) {
5305 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
5306 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
5307 filter_BSS = true;
5308 }
5309 } else if (strstr(line, "Supported rates") != NULL) {
5310 char SRate[80] = {0}, *tmp = NULL;
5311 memset(buf, 0, sizeof(buf));
5312 strcpy(SRate, line);
5313 tmp = strtok(SRate, ":");
5314 tmp = strtok(NULL, ":");
5315 strcpy(buf, tmp);
5316 memset(SRate, 0, sizeof(SRate));
5317
5318 tmp = strtok(buf, " \n");
5319 while (tmp != NULL) {
5320 strcat(SRate, tmp);
5321 if (SRate[strlen(SRate) - 1] == '*') {
5322 SRate[strlen(SRate) - 1] = '\0';
5323 }
5324 strcat(SRate, ",");
5325
5326 tmp = strtok(NULL, " \n");
5327 }
5328 SRate[strlen(SRate) - 1] = '\0';
5329 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
5330 } else if (strstr(line, "DTIM") != NULL) {
developer49c83812023-06-06 14:23:53 +08005331 sscanf(line,"DTIM Period %u", &(scan_array[index].ap_DTIMPeriod));
developer72fb0bb2023-01-11 09:46:29 +08005332 } else if (strstr(line, "VHT capabilities") != NULL) {
5333 strcat(scan_array[index].ap_SupportedStandards, ",ac");
5334 strcpy(scan_array[index].ap_OperatingStandards, "ac");
5335 } else if (strstr(line, "HT capabilities") != NULL) {
5336 strcat(scan_array[index].ap_SupportedStandards, ",n");
5337 strcpy(scan_array[index].ap_OperatingStandards, "n");
5338 } else if (strstr(line, "VHT operation") != NULL) {
5339 ret = fgets(line, sizeof(line), f);
5340 sscanf(line," * channel width: %d", &vht_channel_width);
5341 if(vht_channel_width == 1) {
5342 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
5343 } else {
5344 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
5345 }
5346 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
5347 continue;
5348 } else if (strstr(line, "HT operation") != NULL) {
5349 ret = fgets(line, sizeof(line), f);
developerdaf24792023-06-06 11:40:04 +08005350 sscanf(line," * secondary channel offset: %s", buf);
developer72fb0bb2023-01-11 09:46:29 +08005351 if (!strcmp(buf, "above")) {
5352 //40Mhz +
5353 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
5354 }
5355 else if (!strcmp(buf, "below")) {
5356 //40Mhz -
5357 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
5358 } else {
5359 //20Mhz
5360 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
5361 }
5362 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
5363 continue;
5364 } else if (strstr(line, "HE capabilities") != NULL) {
5365 strcat(scan_array[index].ap_SupportedStandards, ",ax");
5366 strcpy(scan_array[index].ap_OperatingStandards, "ax");
5367 ret = fgets(line, sizeof(line), f);
5368 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
5369 if (strstr(line, "HE40/2.4GHz") != NULL)
5370 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
5371 else
5372 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
5373 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
5374 if (strstr(line, "HE80/5GHz") != NULL) {
5375 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
5376 ret = fgets(line, sizeof(line), f);
5377 } else
5378 continue;
5379 if (strstr(line, "HE160/5GHz") != NULL)
5380 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
5381 }
5382 continue;
5383 } else if (strstr(line, "WPA") != NULL) {
5384 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
5385 } else if (strstr(line, "RSN") != NULL) {
5386 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
5387 } else if (strstr(line, "Group cipher") != NULL) {
5388 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
5389 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
5390 strcpy(scan_array[index].ap_EncryptionMode, "AES");
5391 }
5392 }
5393 ret = fgets(line, sizeof(line), f);
5394 }
5395
5396 if (!filter_BSS) {
5397 *output_array_size = index + 1;
5398 } else {
5399 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
5400 *output_array_size = index;
5401 }
5402 *neighbor_ap_array = scan_array;
5403 pclose(f);
5404 free(channels_noise_arr);
5405 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5406 return RETURN_OK;
5407}
5408
5409//>> Deprecated: used for old RDKB code.
5410INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
5411{
5412 INT status = RETURN_ERR;
5413
5414 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5415 output_struct->wifi_PLCPErrorCount = 0;
5416 output_struct->wifi_FCSErrorCount = 0;
5417 output_struct->wifi_InvalidMACCount = 0;
5418 output_struct->wifi_PacketsOtherReceived = 0;
5419 output_struct->wifi_Noise = 0;
5420 status = RETURN_OK;
5421 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5422 return status;
5423}
5424
5425INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
5426{
5427 char interface_name[16] = {0};
5428 char cmd[128] = {0};
5429 char buf[1280] = {0};
5430 char *pos = NULL;
5431
5432 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5433 if (NULL == output_struct)
5434 return RETURN_ERR;
5435
5436 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5437 return RETURN_ERR;
5438
5439 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
5440
5441 snprintf(cmd, sizeof(cmd), "ifconfig %s", interface_name);
5442 _syscmd(cmd, buf, sizeof(buf));
5443
5444 pos = buf;
5445 if ((pos = strstr(pos, "RX packets:")) == NULL)
5446 return RETURN_ERR;
5447 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
5448
5449 if ((pos = strstr(pos, "TX packets:")) == NULL)
5450 return RETURN_ERR;
5451 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
5452
5453 if ((pos = strstr(pos, "RX bytes:")) == NULL)
5454 return RETURN_ERR;
5455 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
5456
5457 if ((pos = strstr(pos, "TX bytes:")) == NULL)
5458 return RETURN_ERR;
5459 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
5460
5461 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l | tr -d '\n'", interface_name);
5462 _syscmd(cmd, buf, sizeof(buf));
5463 sscanf(buf, "%lu", &output_struct->wifi_Associations);
5464
5465#if 0
5466 //TODO: need to revisit below implementation
5467 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5468 char interface_name[MAX_BUF_SIZE] = {0};
5469 char interface_status[MAX_BUF_SIZE] = {0};
5470 char Value[MAX_BUF_SIZE] = {0};
5471 char buf[MAX_CMD_SIZE] = {0};
5472 char cmd[MAX_CMD_SIZE] = {0};
5473 FILE *fp = NULL;
5474
5475 if (NULL == output_struct) {
5476 return RETURN_ERR;
5477 }
5478
5479 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
5480
5481 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
5482 {
5483 if(apIndex == 0) //private_wifi for 2.4G
5484 {
5485 wifi_GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
5486 }
5487 else if(apIndex == 1) //private_wifi for 5G
5488 {
5489 wifi_GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
5490 }
5491 else if(apIndex == 4) //public_wifi for 2.4G
5492 {
5493 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
5494 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
5495 {
5496 return RETURN_ERR;
5497 }
5498 if(buf[0] == '#')//tp-link
5499 wifi_GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
5500 else//tenda
5501 wifi_GetInterfaceName_virtualInterfaceName_2G(interface_name);
5502 }
5503 else if(apIndex == 5) //public_wifi for 5G
5504 {
5505 wifi_GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
5506 }
5507
5508 GetIfacestatus(interface_name, interface_status);
5509
5510 if(0 != strcmp(interface_status, "1"))
5511 return RETURN_ERR;
5512
5513 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
5514 system(cmd);
5515
5516 fp = fopen("/tmp/SSID_Stats.txt", "r");
5517 if(fp == NULL)
5518 {
5519 printf("/tmp/SSID_Stats.txt not exists \n");
5520 return RETURN_ERR;
5521 }
5522 fclose(fp);
5523
5524 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
5525 File_Reading(buf, Value);
5526 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
5527
5528 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
5529 File_Reading(buf, Value);
5530 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
5531
5532 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
5533 File_Reading(buf, Value);
5534 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
5535
5536 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
5537 File_Reading(buf, Value);
5538 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
5539
5540 /* There is no specific parameter from caller to associate the value wifi_Associations */
5541 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
5542 //_syscmd(cmd, buf, sizeof(buf));
5543 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
5544 }
5545#endif
5546 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5547 return RETURN_OK;
5548}
5549
5550INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
5551{
developerb149d9d2023-06-06 16:14:22 +08005552 char interface_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08005553 char interface_status[MAX_BUF_SIZE] = {0};
5554 char Value[MAX_BUF_SIZE] = {0};
5555 char buf[MAX_CMD_SIZE] = {0};
5556 char cmd[MAX_CMD_SIZE] = {0};
5557 FILE *fp = NULL;
5558
5559 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5560 if (NULL == output_struct)
5561 return RETURN_ERR;
5562
5563 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
5564
5565 if (wifi_GetInterfaceName(apIndex,interface_name) != RETURN_OK)
5566 return RETURN_ERR;
5567 GetIfacestatus(interface_name, interface_status);
5568
5569 if(0 != strcmp(interface_status, "1"))
5570 return RETURN_ERR;
5571
5572 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
5573 system(cmd);
5574
5575 fp = fopen("/tmp/SSID_Stats.txt", "r");
5576 if(fp == NULL)
5577 {
5578 printf("/tmp/SSID_Stats.txt not exists \n");
5579 return RETURN_ERR;
5580 }
5581 fclose(fp);
5582
5583 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
5584 File_Reading(buf, Value);
5585 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
5586
5587 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
5588 File_Reading(buf, Value);
5589 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
5590
5591 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
5592 File_Reading(buf, Value);
5593 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
5594
5595 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
5596 File_Reading(buf, Value);
5597 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
5598
5599 output_struct->wifi_UnicastPacketsSent = 0;
5600 output_struct->wifi_UnicastPacketsReceived = 0;
5601 output_struct->wifi_MulticastPacketsSent = 0;
5602 output_struct->wifi_MulticastPacketsReceived = 0;
5603 output_struct->wifi_BroadcastPacketsSent = 0;
5604 output_struct->wifi_BroadcastPacketsRecevied = 0;
5605 output_struct->wifi_UnknownPacketsReceived = 0;
5606
5607 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5608 return RETURN_OK;
5609}
5610
5611INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
5612{
5613 INT status = RETURN_ERR;
5614
5615 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5616 //Below values should get updated from hal
5617 output_struct->wifi_RetransCount=0;
5618 output_struct->wifi_FailedRetransCount=0;
5619 output_struct->wifi_RetryCount=0;
5620 output_struct->wifi_MultipleRetryCount=0;
5621 output_struct->wifi_ACKFailureCount=0;
5622 output_struct->wifi_AggregatedPacketCount=0;
5623
5624 status = RETURN_OK;
5625 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5626
5627 return status;
5628}
5629
5630INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
5631{
5632 INT status = RETURN_ERR;
5633 UINT index;
5634 wifi_neighbor_ap_t *pt=NULL;
5635
5636 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5637 *output_array_size=2;
5638 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
5639 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
5640 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
5641 strcpy(pt->ap_Radio,"");
5642 strcpy(pt->ap_SSID,"");
5643 strcpy(pt->ap_BSSID,"");
5644 strcpy(pt->ap_Mode,"");
5645 pt->ap_Channel=1;
5646 pt->ap_SignalStrength=0;
5647 strcpy(pt->ap_SecurityModeEnabled,"");
5648 strcpy(pt->ap_EncryptionMode,"");
5649 strcpy(pt->ap_OperatingFrequencyBand,"");
5650 strcpy(pt->ap_SupportedStandards,"");
5651 strcpy(pt->ap_OperatingStandards,"");
5652 strcpy(pt->ap_OperatingChannelBandwidth,"");
5653 pt->ap_BeaconPeriod=1;
5654 pt->ap_Noise=0;
5655 strcpy(pt->ap_BasicDataTransferRates,"");
5656 strcpy(pt->ap_SupportedDataTransferRates,"");
5657 pt->ap_DTIMPeriod=1;
5658 pt->ap_ChannelUtilization = 1;
5659 }
5660
5661 status = RETURN_OK;
5662 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5663
5664 return status;
5665}
5666
5667//----------------- AP HAL -------------------------------
5668
5669//>> Deprecated: used for old RDKB code.
5670INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
5671{
5672 if (NULL == output_ulong || NULL == output_struct)
5673 return RETURN_ERR;
5674 *output_ulong = 0;
5675 *output_struct = NULL;
5676 return RETURN_OK;
5677}
5678
5679#ifdef HAL_NETLINK_IMPL
5680static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
5681 struct nlattr *tb[NL80211_ATTR_MAX + 1];
5682 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
5683 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
5684 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
5685 char mac_addr[20];
5686 static int count=0;
5687 int rate=0;
5688
5689 wifi_device_info_t *out = (wifi_device_info_t*)arg;
5690
5691 nla_parse(tb,
5692 NL80211_ATTR_MAX,
5693 genlmsg_attrdata(gnlh, 0),
5694 genlmsg_attrlen(gnlh, 0),
5695 NULL);
5696
5697 if(!tb[NL80211_ATTR_STA_INFO]) {
5698 fprintf(stderr, "sta stats missing!\n");
5699 return NL_SKIP;
5700 }
5701
5702
5703 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
5704 fprintf(stderr, "failed to parse nested attributes!\n");
5705 return NL_SKIP;
5706 }
5707
5708 //devIndex starts from 1
5709 if( ++count == out->wifi_devIndex )
5710 {
5711 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
5712 //Getting the mac addrress
5713 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
5714
5715 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
5716 fprintf(stderr, "failed to parse nested rate attributes!");
5717 return NL_SKIP;
5718 }
5719
5720 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
developerdaf24792023-06-06 11:40:04 +08005721 if(rinfo[NL80211_RATE_INFO_BITRATE]) {
developer72fb0bb2023-01-11 09:46:29 +08005722 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
5723 out->wifi_devTxRate = rate/10;
developerdaf24792023-06-06 11:40:04 +08005724 }
developer72fb0bb2023-01-11 09:46:29 +08005725 }
5726
5727 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
5728 fprintf(stderr, "failed to parse nested rate attributes!");
5729 return NL_SKIP;
5730 }
5731
5732 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
developerdaf24792023-06-06 11:40:04 +08005733 if(rinfo[NL80211_RATE_INFO_BITRATE]) {
developer72fb0bb2023-01-11 09:46:29 +08005734 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
5735 out->wifi_devRxRate = rate/10;
developerdaf24792023-06-06 11:40:04 +08005736 }
developer72fb0bb2023-01-11 09:46:29 +08005737 }
5738 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
5739 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
5740
5741 out->wifi_devAssociatedDeviceAuthentiationState = 1;
5742 count = 0; //starts the count for next cycle
5743 return NL_STOP;
5744 }
5745
5746 return NL_SKIP;
5747
5748}
5749#endif
5750
5751INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
5752{
5753#ifdef HAL_NETLINK_IMPL
5754 Netlink nl = {0};
developerb149d9d2023-06-06 16:14:22 +08005755 char if_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08005756 char interface_name[16] = {0};
5757
5758 wifi_device_info_t info = {0};
5759 info.wifi_devIndex = devIndex;
5760
5761 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5762 return RETURN_ERR;
5763
5764 snprintf(if_name,sizeof(if_name),"%s", interface_name);
5765
5766 nl.id = initSock80211(&nl);
5767
5768 if (nl.id < 0) {
5769 fprintf(stderr, "Error initializing netlink \n");
5770 return -1;
5771 }
5772
5773 struct nl_msg* msg = nlmsg_alloc();
5774
5775 if (!msg) {
5776 fprintf(stderr, "Failed to allocate netlink message.\n");
5777 nlfree(&nl);
5778 return -2;
5779 }
5780
5781 genlmsg_put(msg,
developer8dd72532023-05-17 19:58:35 +08005782 NL_AUTO_PID,
developer72fb0bb2023-01-11 09:46:29 +08005783 NL_AUTO_SEQ,
5784 nl.id,
5785 0,
5786 NLM_F_DUMP,
5787 NL80211_CMD_GET_STATION,
5788 0);
5789
5790 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
developer8dd72532023-05-17 19:58:35 +08005791 nl_send_auto_complete(nl.socket, msg);
developer72fb0bb2023-01-11 09:46:29 +08005792 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
5793 nl_recvmsgs(nl.socket, nl.cb);
5794 nlmsg_free(msg);
5795 nlfree(&nl);
5796
5797 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
5798 output_struct->wifi_devRxRate = info.wifi_devRxRate;
5799 output_struct->wifi_devTxRate = info.wifi_devTxRate;
5800 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
5801 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
5802 return RETURN_OK;
5803#else
5804 //iw utility to retrieve station information
5805#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
5806#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
5807#define MACFILE "/tmp/wifi_AssoMac.txt"
5808#define TXRATEFILE "/tmp/wifi_txrate.txt"
5809#define RXRATEFILE "/tmp/wifi_rxrate.txt"
5810 FILE *file = NULL;
5811 char if_name[10] = {'\0'};
5812 char pipeCmd[256] = {'\0'};
5813 char line[256] = {0};
5814 char interface_name[16] = {0};
5815 int count = 0, device = 0;
5816
5817 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5818 return RETURN_ERR;
5819
5820 snprintf(if_name,sizeof(if_name),"%s", interface_name);
5821
5822 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
5823 file = popen(pipeCmd, "r");
5824
5825 if(file == NULL)
5826 return RETURN_ERR; //popen failed
5827
5828 fgets(line, sizeof line, file);
5829 device = atoi(line);
5830 pclose(file);
5831
5832 if(device == 0)
5833 return RETURN_ERR; //No devices are connected
5834
5835 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
5836 system(pipeCmd);
5837
5838 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
5839
5840 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
5841
5842 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
5843
5844 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
5845
5846 //devIndex starts from 1, ++count
5847 if((file = fopen(SIGNALFILE, "r")) != NULL )
5848 {
5849 for(count =0;fgets(line, sizeof line, file) != NULL;)
5850 {
5851 if (++count == devIndex)
5852 {
5853 output_struct->wifi_devSignalStrength = atoi(line);
5854 break;
5855 }
5856 }
5857 fclose(file);
5858 }
5859 else
5860 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
5861
5862 if((file = fopen(MACFILE, "r")) != NULL )
5863 {
5864 for(count =0;fgets(line, sizeof line, file) != NULL;)
5865 {
5866 if (++count == devIndex)
5867 {
5868 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]);
5869 break;
5870 }
5871 }
5872 fclose(file);
5873 }
5874 else
5875 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
5876
5877 if((file = fopen(TXRATEFILE, "r")) != NULL )
5878 {
5879 for(count =0;fgets(line, sizeof line, file) != NULL;)
5880 {
5881 if (++count == devIndex)
5882 {
5883 output_struct->wifi_devTxRate = atoi(line);
5884 break;
5885 }
5886 }
5887 fclose(file);
5888 }
5889 else
5890 fprintf(stderr,"fopen wifi_txrate.txt failed");
5891
5892 if((file = fopen(RXRATEFILE, "r")) != NULL)
5893 {
5894 for(count =0;fgets(line, sizeof line, file) != NULL;)
5895 {
5896 if (++count == devIndex)
5897 {
5898 output_struct->wifi_devRxRate = atoi(line);
5899 break;
5900 }
5901 }
5902 fclose(file);
5903 }
5904 else
5905 fprintf(stderr,"fopen wifi_rxrate.txt failed");
5906
5907 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
5908
5909 return RETURN_OK;
5910#endif
5911}
5912
5913INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
5914{
5915 if (NULL == device)
5916 return RETURN_ERR;
5917 return RETURN_OK;
5918}
5919//<<
5920
5921
5922//--------------wifi_ap_hal-----------------------------
5923//enables CTS protection for the radio used by this AP
5924INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
5925{
5926 //save config and Apply instantly
5927 return RETURN_ERR;
5928}
5929
5930// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
5931INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
5932{
5933 char config_file[64] = {'\0'};
developerd1824452023-05-18 12:30:04 +08005934 char config_dat_file[64] = {'\0'};
developer72fb0bb2023-01-11 09:46:29 +08005935 char buf[64] = {'\0'};
developerd1824452023-05-18 12:30:04 +08005936 struct params list = {0};
5937 struct params dat = {0};
5938 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08005939
5940 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5941 list.name = "ht_coex";
5942 snprintf(buf, sizeof(buf), "%d", enable);
5943 list.value = buf;
5944
developerd1824452023-05-18 12:30:04 +08005945 dat.name = "HT_BSSCoexistence";
5946 dat.value = buf;
5947
5948 band = wifi_index_to_band(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08005949 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developerd1824452023-05-18 12:30:04 +08005950 snprintf(config_dat_file, sizeof(config_dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
developer72fb0bb2023-01-11 09:46:29 +08005951 wifi_hostapdWrite(config_file, &list, 1);
developer262f4cb2023-05-24 12:22:04 +08005952 wifi_datfileWrite(config_dat_file, &dat, 1);
developer72fb0bb2023-01-11 09:46:29 +08005953 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5954
5955 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5956
5957 return RETURN_OK;
5958}
5959
5960//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
5961INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
5962{
5963 char config_file[MAX_BUF_SIZE] = {'\0'};
5964 char buf[MAX_BUF_SIZE] = {'\0'};
5965 struct params list;
5966
5967 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5968 if (threshold < 256 || threshold > 2346 )
5969 return RETURN_ERR;
5970 list.name = "fragm_threshold";
5971 snprintf(buf, sizeof(buf), "%d", threshold);
5972 list.value = buf;
5973
5974 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
5975 wifi_hostapdWrite(config_file, &list, 1);
5976 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5977
5978 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5979
5980 return RETURN_OK;
5981}
5982
5983// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
5984INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
5985{
5986 char config_file[64] = {'\0'};
5987 char cmd[512] = {'\0'};
5988 char buf[512] = {'\0'};
5989 char stbc_config[16] = {'\0'};
5990 wifi_band band;
5991 int iterator = 0;
5992 BOOL current_stbc = FALSE;
5993 int ant_count = 0;
5994 int ant_bitmap = 0;
5995 struct params list;
developera1255e42023-05-13 17:45:02 +08005996 char dat_file[64] = {'\0'};
developer72fb0bb2023-01-11 09:46:29 +08005997
5998 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5999
6000 band = wifi_index_to_band(radioIndex);
6001 if (band == band_invalid)
6002 return RETURN_ERR;
6003
6004 if (band == band_2_4)
6005 iterator = 1;
developera1255e42023-05-13 17:45:02 +08006006 else if ((band == band_5) || (band == band_6))
developer72fb0bb2023-01-11 09:46:29 +08006007 iterator = 2;
6008 else
6009 return RETURN_OK;
6010
6011 wifi_getRadioTxChainMask(radioIndex, &ant_bitmap);
6012 for (; ant_bitmap > 0; ant_bitmap >>= 1)
6013 ant_count += ant_bitmap & 1;
6014
6015 if (ant_count == 1 && STBC_Enable == TRUE) {
6016 fprintf(stderr, "%s: can not enable STBC when using only one antenna\n", __func__);
6017 return RETURN_OK;
6018 }
6019
6020 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
6021
6022 // set ht and vht config
6023 for (int i = 0; i < iterator; i++) {
6024 memset(stbc_config, 0, sizeof(stbc_config));
6025 memset(cmd, 0, sizeof(cmd));
6026 memset(buf, 0, sizeof(buf));
6027 list.name = (i == 0)?"ht_capab":"vht_capab";
6028 snprintf(stbc_config, sizeof(stbc_config), "%s", list.name);
6029 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
6030 _syscmd(cmd, buf, sizeof(buf));
6031 if (strlen(buf) != 0)
6032 current_stbc = TRUE;
6033 if (current_stbc == STBC_Enable)
6034 continue;
6035
6036 if (STBC_Enable == TRUE) {
6037 // Append the STBC flags in capab config
6038 memset(cmd, 0, sizeof(cmd));
6039 if (i == 0)
6040 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
6041 else
6042 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1][RX-STBC-1]/' %s", config_file);
6043 _syscmd(cmd, buf, sizeof(buf));
6044 } else if (STBC_Enable == FALSE) {
6045 // Remove the STBC flags and remain other flags in capab
6046 memset(cmd, 0, sizeof(cmd));
6047 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
6048 _syscmd(cmd, buf, sizeof(buf));
6049 memset(cmd, 0, sizeof(cmd));
6050 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
6051 _syscmd(cmd, buf, sizeof(buf));
6052 }
6053 wifi_hostapdRead(config_file, list.name, buf, sizeof(buf));
6054 list.value = buf;
6055 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
6056 }
developera1255e42023-05-13 17:45:02 +08006057 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
6058 snprintf(cmd, sizeof(cmd), "sed -r -i 's/^HT_STBC=.*/HT_STBC=%d/g' %s", STBC_Enable, dat_file);
6059 _syscmd(cmd, buf, sizeof(buf));
6060 if ((band == band_5) || (band == band_6)) {
6061 snprintf(cmd, sizeof(cmd), "sed -r -i 's/^VHT_STBC=.*/VHT_STBC=%d/g' %s", STBC_Enable, dat_file);
6062 _syscmd(cmd, buf, sizeof(buf));
6063 }
6064 /*wifi_reloadAp(radioIndex);
6065 the caller do this.*/
developer72fb0bb2023-01-11 09:46:29 +08006066
6067 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6068 return RETURN_OK;
6069}
6070
6071// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
6072INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
6073{
developer2c22d832023-05-18 17:46:26 +08006074 char dat_file[128] = {0};
developer2c22d832023-05-18 17:46:26 +08006075 wifi_band band;
6076 char amdus_buff[8] = {'\0'};
developer72fb0bb2023-01-11 09:46:29 +08006077
developer2c22d832023-05-18 17:46:26 +08006078 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08006079
developer2c22d832023-05-18 17:46:26 +08006080 band = wifi_index_to_band(radioIndex);
6081 if (band == band_invalid) {
6082 printf("%s:Band Error\n", __func__);
6083 return RETURN_ERR;
6084 }
6085 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
6086 wifi_datfileRead(dat_file, "HT_AMSDU", amdus_buff, sizeof(amdus_buff));
6087 if (strncmp(amdus_buff, "1", 1) == 0)
developer72fb0bb2023-01-11 09:46:29 +08006088 *output_bool = TRUE;
developer2c22d832023-05-18 17:46:26 +08006089 else
6090 *output_bool = FALSE;
developer72fb0bb2023-01-11 09:46:29 +08006091
developer2c22d832023-05-18 17:46:26 +08006092 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6093
6094 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006095}
6096
6097// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
6098INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
6099{
developer2c22d832023-05-18 17:46:26 +08006100 char dat_file[128] = {0};
6101 BOOL enable;
6102 wifi_band band;
6103 char amdus_buff[8] = {'\0'};
6104 struct params params = {0};
developer72fb0bb2023-01-11 09:46:29 +08006105
developer2c22d832023-05-18 17:46:26 +08006106 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08006107
developer2c22d832023-05-18 17:46:26 +08006108 band = wifi_index_to_band(radioIndex);
6109 if (band == band_invalid) {
6110 printf("%s:Band Error\n", __func__);
6111 return RETURN_ERR;
6112 }
6113 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
6114 wifi_datfileRead(dat_file, "HT_AMSDU", amdus_buff, sizeof(amdus_buff));
6115 if (strncmp(amdus_buff, "1", 1) == 0)
6116 enable = TRUE;
6117 else
6118 enable = FALSE;
6119 if (amsduEnable == enable)
6120 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006121
developer2c22d832023-05-18 17:46:26 +08006122 params.name = "HT_AMSDU";
6123 if (amsduEnable)
6124 params.value = "1";
6125 else
6126 params.value = "0";
6127 wifi_datfileWrite(dat_file, &params, 1);
6128 wifi_reloadAp(radioIndex);
developer72fb0bb2023-01-11 09:46:29 +08006129
developer2c22d832023-05-18 17:46:26 +08006130 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08006131
developer72fb0bb2023-01-11 09:46:29 +08006132 return RETURN_OK;
6133}
6134
6135//P2 // outputs the number of Tx streams
6136INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
6137{
6138 char buf[8] = {0};
6139 char cmd[128] = {0};
6140 int phyId = 0;
6141
6142 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6143
6144 phyId = radio_index_to_phy(radioIndex);
6145 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Configured Antennas' | awk '{print $4}'", phyId);
6146 _syscmd(cmd, buf, sizeof(buf));
6147
6148 *output_int = (INT)strtol(buf, NULL, 16);
6149
6150 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6151
6152 return RETURN_OK;
6153}
6154
6155INT fitChainMask(INT radioIndex, int antcount)
6156{
6157 char buf[128] = {0};
6158 char cmd[128] = {0};
6159 char config_file[64] = {0};
6160 wifi_band band;
6161 struct params list[2] = {0};
6162
6163 band = wifi_index_to_band(radioIndex);
6164 if (band == band_invalid)
6165 return RETURN_ERR;
6166
6167 list[0].name = "he_mu_beamformer";
6168 list[1].name = "he_su_beamformer";
6169
6170 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
6171 if (antcount == 1) {
6172 // remove config about multiple antennas
6173 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
6174 _syscmd(cmd, buf, sizeof(buf));
6175
6176 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SOUNDING-DIMENSION-.\\]//' %s", config_file);
6177 _syscmd(cmd, buf, sizeof(buf));
6178
6179 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SU-BEAMFORMER\\]//' %s", config_file);
6180 _syscmd(cmd, buf, sizeof(buf));
6181
6182 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[MU-BEAMFORMER\\]//' %s", config_file);
6183 _syscmd(cmd, buf, sizeof(buf));
6184
6185 list[0].value = "0";
6186 list[1].value = "0";
6187 } else {
6188 // 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.
6189 if (band == band_2_4 || band == band_5) {
6190 snprintf(cmd, sizeof(cmd), "cat %s | grep '^ht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
6191 _syscmd(cmd, buf, sizeof(buf));
6192 if (strlen(buf) > 0) {
6193 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC]/' %s", config_file);
6194 _syscmd(cmd, buf, sizeof(buf));
6195 }
6196 }
6197 if (band == band_5) {
6198 snprintf(cmd, sizeof(cmd), "cat %s | grep '^vht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
6199 _syscmd(cmd, buf, sizeof(buf));
6200 if (strlen(buf) > 0) {
6201 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1]/' %s", config_file);
6202 _syscmd(cmd, buf, sizeof(buf));
6203 }
6204 }
6205
6206 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SU-BEAMFORMER\\]'", config_file);
6207 _syscmd(cmd, buf, sizeof(buf));
6208 if (strlen(buf) == 0) {
6209 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SU-BEAMFORMER]/' %s", config_file);
6210 _syscmd(cmd, buf, sizeof(buf));
6211 }
6212
6213 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[MU-BEAMFORMER\\]'", config_file);
6214 _syscmd(cmd, buf, sizeof(buf));
6215 if (strlen(buf) == 0) {
6216 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[MU-BEAMFORMER]/' %s", config_file);
6217 _syscmd(cmd, buf, sizeof(buf));
6218 }
6219
6220 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SOUNDING-DIMENSION-.\\]'", config_file);
6221 _syscmd(cmd, buf, sizeof(buf));
6222 if (strlen(buf) == 0) {
6223 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SOUNDING-DIMENSION-%d]/' %s", antcount, config_file);
6224 } else {
6225 snprintf(cmd, sizeof(cmd), "sed -r -i 's/(SOUNDING-DIMENSION-)./\\1%d/' %s", antcount, config_file);
6226 }
6227 _syscmd(cmd, buf, sizeof(buf));
6228
6229 list[0].value = "1";
6230 list[1].value = "1";
6231 }
6232 wifi_hostapdWrite(config_file, list, 2);
developerdaf24792023-06-06 11:40:04 +08006233 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006234}
6235
6236//P2 // sets the number of Tx streams to an enviornment variable
6237INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
6238{
6239 char cmd[128] = {0};
6240 char buf[128] = {0};
6241 int phyId = 0;
6242 int cur_mask = 0;
developera1255e42023-05-13 17:45:02 +08006243 int antcountmsk = 0;
6244 INT cur_nss = 0;
developer863a4a62023-06-06 16:55:59 +08006245 CHAR dat_file[64] = {0};
developera1255e42023-05-13 17:45:02 +08006246 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08006247
6248 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6249
6250 if (numStreams <= 0) {
6251 fprintf(stderr, "%s: chainmask is not supported %d.\n", __func__, numStreams);
6252 return RETURN_ERR;
6253 }
6254
developera1255e42023-05-13 17:45:02 +08006255 wifi_getRadioTxChainMask(radioIndex, &cur_mask);//this is mask value
6256 for(; cur_mask > 0; cur_mask >>= 1)//convert to number of streams.
6257 cur_nss += 1;
6258 WIFI_ENTRY_EXIT_DEBUG("%s:cur_nss=%d, new_nss=%d\n", __func__, cur_nss, numStreams);
6259 if (cur_nss == numStreams)
developer72fb0bb2023-01-11 09:46:29 +08006260 return RETURN_OK;
6261
6262 wifi_setRadioEnable(radioIndex, FALSE);
6263
6264 phyId = radio_index_to_phy(radioIndex);
developera1255e42023-05-13 17:45:02 +08006265 //iw need mask value.
6266 for (;numStreams > 0; numStreams--)
6267 antcountmsk |= 0x1 << (numStreams - 1);
6268 snprintf(cmd, sizeof(cmd), "iw phy%d set antenna 0x%x 2>&1", phyId, antcountmsk);
developer72fb0bb2023-01-11 09:46:29 +08006269 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006270 if (strlen(buf) > 0) {
6271 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
6272 return RETURN_ERR;
6273 }
developera1255e42023-05-13 17:45:02 +08006274 band = wifi_index_to_band(radioIndex);
6275 if (band == band_invalid) {
6276 printf("%s:Band Error\n", __func__);
6277 return RETURN_ERR;
6278 }
6279 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
6280 snprintf(cmd, sizeof(cmd), "sed -r -i 's/^HT_TxStream=.*/HT_TxStream=%d/g' %s", numStreams, dat_file);
6281 _syscmd(cmd, buf, sizeof(buf));
6282 if (strlen(buf) > 0) {
6283 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
6284 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006285 }
developera1255e42023-05-13 17:45:02 +08006286 snprintf(cmd, sizeof(cmd), "sed -r -i 's/^HT_RxStream=.*/HT_RxStream=%d/g' %s", numStreams, dat_file);
6287 _syscmd(cmd, buf, sizeof(buf));
6288 if (strlen(buf) > 0) {
6289 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
6290 return RETURN_ERR;
6291 }
6292 fitChainMask(radioIndex, numStreams);
developer72fb0bb2023-01-11 09:46:29 +08006293 wifi_setRadioEnable(radioIndex, TRUE);
6294
6295 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6296 return RETURN_OK;
6297}
6298
6299//P2 // outputs the number of Rx streams
6300INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
6301{
6302 char buf[8] = {0};
6303 char cmd[128] = {0};
6304 int phyId = 0;
6305
6306 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6307
6308 phyId = radio_index_to_phy(radioIndex);
6309 sprintf(cmd, "iw phy%d info | grep 'Configured Antennas' | awk '{print $6}'", phyId);
6310 _syscmd(cmd, buf, sizeof(buf));
6311
6312 *output_int = (INT)strtol(buf, NULL, 16);
6313
6314 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6315
6316 return RETURN_OK;
6317}
6318
6319//P2 // sets the number of Rx streams to an enviornment variable
6320INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
6321{
6322 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6323 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
6324 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
6325 return RETURN_ERR;
6326 }
6327 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6328 return RETURN_ERR;
6329}
6330
6331//Get radio RDG enable setting
6332INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
6333{
developer47cc27a2023-05-17 23:09:58 +08006334 if (NULL == output_bool)
6335 return RETURN_ERR;
6336
6337 *output_bool = TRUE;
6338 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006339}
6340
6341//Get radio RDG enable setting
6342INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
6343{
developer47cc27a2023-05-17 23:09:58 +08006344 char rdg_status[2] = {0};
6345 char dat_file[MAX_CMD_SIZE] = {0};
developer47cc27a2023-05-17 23:09:58 +08006346
6347 if (NULL == output_bool)
6348 return RETURN_ERR;
6349
6350 /*prepare dat file path*/
6351 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, radioIndex);
6352
6353 wifi_datfileRead(dat_file, "HT_RDG", rdg_status, sizeof(rdg_status));
6354 if (!strncmp(rdg_status, "1", sizeof(rdg_status)))
6355 *output_bool = TRUE;
6356 else
6357 *output_bool = FALSE;
6358
6359 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006360}
6361
6362//Set radio RDG enable setting
6363INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
6364{
developer47cc27a2023-05-17 23:09:58 +08006365 char dat_file[MAX_CMD_SIZE] = {0};
6366 struct params params = {0};
6367
6368 /*prepare dat file path*/
6369 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, radioIndex);
6370
6371 params.name = "HT_RDG";
6372
6373 if (enable) {
6374 params.value = "1";
6375 } else {
6376 params.value = "0";
6377 }
6378
6379 wifi_datfileWrite(dat_file, &params, 1);
6380
6381 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006382}
6383
developer5cd4c862023-05-26 09:34:42 +08006384
6385int mtk_get_ba_auto_status_callback(struct nl_msg *msg, void *data)
developer72fb0bb2023-01-11 09:46:29 +08006386{
developer5cd4c862023-05-26 09:34:42 +08006387 struct nlattr *tb[NL80211_ATTR_MAX + 1];
6388 struct nlattr *vndr_tb[MTK_NL80211_VENDOR_AP_BA_ATTR_MAX + 1];
6389 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
6390 unsigned char status;
6391 unsigned char *out_status = data;
6392 int err = 0;
developer8e6583c2023-05-23 13:36:06 +08006393
developer5cd4c862023-05-26 09:34:42 +08006394 err = nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
6395 genlmsg_attrlen(gnlh, 0), NULL);
6396 if (err < 0){
6397 wifi_debug(DEBUG_ERROR, "get NL80211_ATTR_MAX fails\n");
6398 return err;
6399 }
developer8e6583c2023-05-23 13:36:06 +08006400
developer5cd4c862023-05-26 09:34:42 +08006401 if (tb[NL80211_ATTR_VENDOR_DATA]) {
6402 err = nla_parse_nested(vndr_tb, MTK_NL80211_VENDOR_AP_BA_ATTR_MAX,
6403 tb[NL80211_ATTR_VENDOR_DATA], NULL);
6404 if (err < 0){
6405 wifi_debug(DEBUG_ERROR, "get MTK_NL80211_VENDOR_AP_BA_ATTR_MAX fails\n");
6406 return err;
6407 }
developer8e6583c2023-05-23 13:36:06 +08006408
developer5cd4c862023-05-26 09:34:42 +08006409 if (vndr_tb[MTK_NL80211_VENDOR_ATTR_AP_BA_EN_INFO]) {
6410 status = nla_get_u8(vndr_tb[MTK_NL80211_VENDOR_ATTR_AP_BA_EN_INFO]);
6411 if (status == 0) {
6412 wifi_debug(DEBUG_NOTICE, "disabled\n");
6413 } else {
6414 wifi_debug(DEBUG_NOTICE, "enabled\n");
6415 }
6416 *out_status = status;
6417 }
6418 }
developer8e6583c2023-05-23 13:36:06 +08006419
developer5cd4c862023-05-26 09:34:42 +08006420 return 0;
6421}
developer8e6583c2023-05-23 13:36:06 +08006422
developer5cd4c862023-05-26 09:34:42 +08006423int mtk_get_ba_decline_status_callback(struct nl_msg *msg, void *data)
6424{
6425 struct nlattr *tb[NL80211_ATTR_MAX + 1];
6426 struct nlattr *vndr_tb[MTK_NL80211_VENDOR_AP_BA_ATTR_MAX + 1];
6427 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
6428 unsigned char status;
6429 unsigned char *out_status = data;
6430 int err = 0;
6431
6432 err = nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
6433 genlmsg_attrlen(gnlh, 0), NULL);
6434 if (err < 0) {
6435 wifi_debug(DEBUG_ERROR, "get NL80211_ATTR_MAX fails\n");
6436 return err;
6437 }
6438
6439 if (tb[NL80211_ATTR_VENDOR_DATA]) {
6440 err = nla_parse_nested(vndr_tb, MTK_NL80211_VENDOR_AP_BA_ATTR_MAX,
6441 tb[NL80211_ATTR_VENDOR_DATA], NULL);
6442 if (err < 0) {
6443 wifi_debug(DEBUG_ERROR, "get MTK_NL80211_VENDOR_AP_BA_ATTR_MAX fails\n");
6444 return err;
6445 }
6446
6447 if (vndr_tb[MTK_NL80211_VENDOR_ATTR_AP_BA_DECLINE_INFO]) {
6448 status = nla_get_u8(vndr_tb[MTK_NL80211_VENDOR_ATTR_AP_BA_DECLINE_INFO]);
6449 if (status == 0) {
6450 wifi_debug(DEBUG_NOTICE, "disabled\n");
6451 } else {
6452 wifi_debug(DEBUG_NOTICE, "enabled\n");
6453 }
6454 *out_status = status;
6455 }
6456 }
6457
6458 return NL_OK;
developer72fb0bb2023-01-11 09:46:29 +08006459}
6460
developer5cd4c862023-05-26 09:34:42 +08006461INT mtk_wifi_get_ba_decl_auto_status(
6462 INT apIndex, INT vendor_data_attr, mtk_nl80211_cb call_back, BOOL *output_bool)
6463{
6464 char inf_name[IF_NAME_SIZE] = {0};
developer5cd4c862023-05-26 09:34:42 +08006465 unsigned int if_idx = 0;
6466 int ret = -1;
6467 struct unl unl_ins;
6468 struct nl_msg *msg = NULL;
6469 struct nlattr * msg_data = NULL;
6470 struct mtk_nl80211_param param;
6471
6472 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
6473 return RETURN_ERR;
6474 if_idx = if_nametoindex(inf_name);
6475 if (!if_idx) {
6476 wifi_debug(DEBUG_ERROR,"can't finde ifname(%s) index,ERROR\n", inf_name);
6477 return RETURN_ERR;
6478 }
6479 /*init mtk nl80211 vendor cmd*/
6480 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_BA;
6481 param.if_type = NL80211_ATTR_IFINDEX;
6482 param.if_idx = if_idx;
6483
6484 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
6485 if (ret) {
6486 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
6487 return RETURN_ERR;
6488 }
6489 /*add mtk vendor cmd data*/
6490 if (nla_put_u8(msg, vendor_data_attr, 0xf)) {
6491 wifi_debug(DEBUG_ERROR, "Nla put vendor_data_attr(%d) attribute error\n", vendor_data_attr);
6492 nlmsg_free(msg);
6493 goto err;
6494 }
6495
6496 /*send mtk nl80211 vendor msg*/
6497 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, call_back, output_bool);
6498 if (ret) {
6499 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
6500 goto err;
6501 }
6502 /*deinit mtk nl80211 vendor msg*/
6503 mtk_nl80211_deint(&unl_ins);
6504 wifi_debug(DEBUG_NOTICE,"send cmd success, get output_bool:%d\n", *output_bool);
6505 return RETURN_OK;
6506err:
6507 mtk_nl80211_deint(&unl_ins);
6508 wifi_debug(DEBUG_ERROR,"send cmd fails\n");
6509 return RETURN_ERR;
6510}
6511//Get radio ADDBA enable setting
6512INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
6513{
6514 if (output_bool == NULL) {
6515 wifi_debug(DEBUG_ERROR, "invalid: output_bool is null\n");
6516 return RETURN_ERR;
6517 }
6518 if (mtk_wifi_get_ba_decl_auto_status(radioIndex,
6519 MTK_NL80211_VENDOR_ATTR_AP_BA_DECLINE_INFO, mtk_get_ba_decline_status_callback, output_bool) != RETURN_OK) {
6520 wifi_debug(DEBUG_ERROR, "cmd MTK_NL80211_VENDOR_ATTR_AP_BA_DECLINE_INFO(0x%x) fails\n",
6521 MTK_NL80211_VENDOR_ATTR_AP_BA_DECLINE_INFO);
6522 return RETURN_ERR;
6523 }
6524 wifi_debug(DEBUG_NOTICE, "cmd success:output_bool(%d)\n", *output_bool);
6525 return RETURN_OK;
6526}
6527
developer72fb0bb2023-01-11 09:46:29 +08006528//Set radio ADDBA enable setting
6529INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
6530{
6531 return RETURN_ERR;
6532}
6533
6534//Get radio auto block ack enable setting
6535INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
6536{
developer5cd4c862023-05-26 09:34:42 +08006537 if (output_bool == NULL) {
6538 wifi_debug(DEBUG_ERROR, "invalid: output_bool is null\n");
6539 return RETURN_ERR;
6540 }
developer8e6583c2023-05-23 13:36:06 +08006541
developer5cd4c862023-05-26 09:34:42 +08006542 if (mtk_wifi_get_ba_decl_auto_status(radioIndex,
6543 MTK_NL80211_VENDOR_ATTR_AP_BA_EN_INFO,
6544 mtk_get_ba_auto_status_callback, output_bool) != RETURN_OK) {
6545 wifi_debug(DEBUG_ERROR, "cmd MTK_NL80211_VENDOR_ATTR_AP_BA_EN_INFO(0x%x) fails\n",
6546 MTK_NL80211_VENDOR_ATTR_AP_BA_EN_INFO);
6547 return RETURN_ERR;
6548 }
6549 wifi_debug(DEBUG_NOTICE, "cmd success:output_bool(%d)\n", *output_bool);
6550 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006551}
6552
6553//Set radio auto block ack enable setting
6554INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
6555{
6556 return RETURN_ERR;
6557}
6558
6559//Get radio 11n pure mode enable support
6560INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
6561{
6562 if (NULL == output_bool)
6563 return RETURN_ERR;
6564 *output_bool = TRUE;
6565 return RETURN_OK;
6566}
6567
6568//Get radio 11n pure mode enable setting
6569INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
6570{
6571 if (NULL == output_bool)
6572 return RETURN_ERR;
6573 *output_bool = TRUE;
6574 return RETURN_OK;
6575}
6576
6577//Set radio 11n pure mode enable setting
6578INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
6579{
6580 return RETURN_ERR;
6581}
6582
developer5cd4c862023-05-26 09:34:42 +08006583
6584int mtk_get_igmp_status_callback(struct nl_msg *msg, void *data)
developer72fb0bb2023-01-11 09:46:29 +08006585{
developer5cd4c862023-05-26 09:34:42 +08006586 struct nlattr *tb[NL80211_ATTR_MAX + 1];
6587 struct nlattr *vndr_tb[MTK_NL80211_VENDOR_MCAST_SNOOP_ATTR_MAX + 1];
6588 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
6589 unsigned char status = 0, *out_status = data;
6590 int err = 0;
developer72fb0bb2023-01-11 09:46:29 +08006591
developer5cd4c862023-05-26 09:34:42 +08006592 err = nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
6593 genlmsg_attrlen(gnlh, 0), NULL);
6594 if (err < 0) {
6595 wifi_debug(DEBUG_ERROR, "get NL80211_ATTR_MAX fails\n");
6596 return err;
6597 }
developer72fb0bb2023-01-11 09:46:29 +08006598
developer5cd4c862023-05-26 09:34:42 +08006599 if (tb[NL80211_ATTR_VENDOR_DATA]) {
6600 err = nla_parse_nested(vndr_tb, MTK_NL80211_VENDOR_MCAST_SNOOP_ATTR_MAX,
6601 tb[NL80211_ATTR_VENDOR_DATA], NULL);
6602 if (err < 0){
6603 wifi_debug(DEBUG_ERROR, "get MTK_NL80211_VENDOR_MCAST_SNOOP_ATTR_MAX fails\n");
6604 return err;
6605 }
developer72fb0bb2023-01-11 09:46:29 +08006606
developer5cd4c862023-05-26 09:34:42 +08006607 if (vndr_tb[MTK_NL80211_VENDOR_ATTR_MCAST_SNOOP_ENABLE]) {
6608 status = nla_get_u8(vndr_tb[MTK_NL80211_VENDOR_ATTR_MCAST_SNOOP_ENABLE]);
6609 if (status == 0) {
6610 wifi_debug(DEBUG_NOTICE, "disabled\n");
6611 } else {
6612 wifi_debug(DEBUG_NOTICE, "enabled\n");
6613 }
6614 *out_status = status;
6615 wifi_debug(DEBUG_NOTICE, "status: %d\n", *out_status);
6616 }
6617 }
6618
6619 return 0;
6620}
6621
6622INT mtk_wifi_set_igmp_en_status(
6623 INT apIndex, INT vendor_data_attr, mtk_nl80211_cb call_back,
6624 unsigned char in_en_stat, BOOL *output_bool)
6625{
6626 char inf_name[IF_NAME_SIZE] = {0};
developer5cd4c862023-05-26 09:34:42 +08006627 unsigned int if_idx = 0;
6628 int ret = -1;
6629 struct unl unl_ins;
6630 struct nl_msg *msg = NULL;
6631 struct nlattr * msg_data = NULL;
6632 struct mtk_nl80211_param param;
6633
6634 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
6635 return RETURN_ERR;
6636 if_idx = if_nametoindex(inf_name);
6637 if (!if_idx) {
6638 wifi_debug(DEBUG_ERROR,"can't finde ifname(%s) index,ERROR\n", inf_name);
6639 return RETURN_ERR;
6640 }
6641 /*init mtk nl80211 vendor cmd*/
6642 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_MULTICAST_SNOOPING;
6643 param.if_type = NL80211_ATTR_IFINDEX;
6644 param.if_idx = if_idx;
6645
6646 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
6647 if (ret) {
6648 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
6649 return RETURN_ERR;
6650 }
6651 /*add mtk vendor cmd data*/
6652 if (nla_put_u8(msg, vendor_data_attr, in_en_stat)) {
6653 wifi_debug(DEBUG_ERROR, "Nla put vendor_data_attr(%d) attribute error\n", vendor_data_attr);
6654 nlmsg_free(msg);
6655 goto err;
6656 }
6657
6658 /*send mtk nl80211 vendor msg*/
6659 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, call_back, output_bool);
6660 if (ret) {
6661 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
6662 goto err;
6663 }
6664 /*deinit mtk nl80211 vendor msg*/
6665 mtk_nl80211_deint(&unl_ins);
6666 if (output_bool) {
6667 wifi_debug(DEBUG_NOTICE, "send cmd success, get output_bool:%d\n", *output_bool);
6668 } else {
6669 wifi_debug(DEBUG_NOTICE, "send cmd success.\n");
6670 }
6671 return RETURN_OK;
6672err:
6673 mtk_nl80211_deint(&unl_ins);
6674 wifi_debug(DEBUG_ERROR,"send cmd fails\n");
6675 return RETURN_ERR;
6676}
6677
6678
6679//Get radio IGMP snooping enable setting
6680INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
6681{
6682 if (output_bool == NULL) {
6683 wifi_debug(DEBUG_ERROR, "invalid: output_bool is null\n");
6684 return RETURN_ERR;
6685 }
6686 if (mtk_wifi_set_igmp_en_status
6687 (radioIndex, MTK_NL80211_VENDOR_ATTR_MCAST_SNOOP_ENABLE,
6688 mtk_get_igmp_status_callback, 0xf, output_bool)!= RETURN_OK) {
6689 wifi_debug(DEBUG_ERROR, "send MTK_NL80211_VENDOR_ATTR_MCAST_SNOOP_ENABLE cmd fails\n");
6690 return RETURN_ERR;
6691 }
6692 wifi_debug(DEBUG_ERROR, "send cmd success: get igmp status:(%d)\n", *output_bool);
developer72fb0bb2023-01-11 09:46:29 +08006693 return RETURN_OK;
6694}
6695
6696//Set radio IGMP snooping enable setting
6697INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
6698{
developer5cd4c862023-05-26 09:34:42 +08006699 if (mtk_wifi_set_igmp_en_status
6700 (radioIndex, MTK_NL80211_VENDOR_ATTR_MCAST_SNOOP_ENABLE,
6701 NULL, enable, NULL) != RETURN_OK) {
6702 wifi_debug(DEBUG_ERROR, "send MTK_NL80211_VENDOR_ATTR_MCAST_SNOOP_ENABLE cmd fails\n");
6703 return RETURN_ERR;
6704 }
6705 wifi_debug(DEBUG_ERROR, "send cmd success: set igmp enable(%d)\n", enable);
developer72fb0bb2023-01-11 09:46:29 +08006706 return RETURN_OK;
6707}
6708
6709//Get the Reset count of radio
developer69b61b02023-03-07 17:17:44 +08006710INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
developer72fb0bb2023-01-11 09:46:29 +08006711{
developer69b61b02023-03-07 17:17:44 +08006712 if (NULL == output_int)
developer72fb0bb2023-01-11 09:46:29 +08006713 return RETURN_ERR;
developerfead3972023-05-25 20:15:02 +08006714 *output_int = get_radio_reset_cnt(radioIndex);
developer72fb0bb2023-01-11 09:46:29 +08006715
6716 return RETURN_OK;
6717}
6718
6719
6720//---------------------------------------------------------------------------------------------------
6721//
6722// Additional Wifi AP level APIs used for Access Point devices
6723//
6724//---------------------------------------------------------------------------------------------------
6725
6726// creates a new ap and pushes these parameters to the hardware
6727INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
6728{
6729 // Deprecated when use hal version 3, use wifi_createVap() instead.
6730 return RETURN_OK;
6731}
6732
6733// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
6734INT wifi_deleteAp(INT apIndex)
6735{
developer7e4a2a62023-04-06 19:56:03 +08006736 char interface_name[16] = {0};
6737 char buf[MAX_BUF_SIZE];
6738 char cmd[MAX_CMD_SIZE];
developer72fb0bb2023-01-11 09:46:29 +08006739
developer7e4a2a62023-04-06 19:56:03 +08006740 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6741 return RETURN_ERR;
developer8a3bbbf2023-03-15 17:47:23 +08006742
developer7e4a2a62023-04-06 19:56:03 +08006743 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw REMOVE %s", interface_name);
6744 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006745
developer7e4a2a62023-04-06 19:56:03 +08006746 wifi_removeApSecVaribles(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08006747
developer7e4a2a62023-04-06 19:56:03 +08006748 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006749}
6750
6751// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
6752INT wifi_getApName(INT apIndex, CHAR *output_string)
6753{
developer7e4a2a62023-04-06 19:56:03 +08006754 char interface_name[IF_NAME_SIZE] = {0};
developer47cc27a2023-05-17 23:09:58 +08006755 int radio_idx = 0;
6756 int bss_idx = 0;
developer72fb0bb2023-01-11 09:46:29 +08006757
developer7e4a2a62023-04-06 19:56:03 +08006758 if(!output_string)
6759 return RETURN_ERR;
6760
6761 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
6762 vap_index_to_array_index(apIndex, &radio_idx, &bss_idx);
6763
6764 snprintf(output_string, IF_NAME_SIZE, "%s%d", ext_prefix[radio_idx], bss_idx); // For wifiagent generating data model.
6765 } else
6766 snprintf(output_string, IF_NAME_SIZE, "%s", interface_name);
6767
6768 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006769}
6770
6771// Outputs the index number in that corresponds to the SSID string
6772INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
6773{
developer7e4a2a62023-04-06 19:56:03 +08006774 char cmd [128] = {0};
6775 char buf[32] = {0};
6776 char ap_idx = 0;
6777 char *apIndex_str = NULL;
6778 char radio_idx = 0;
6779 char bss_idx = 0;
developer72fb0bb2023-01-11 09:46:29 +08006780
developer7e4a2a62023-04-06 19:56:03 +08006781 snprintf(cmd, sizeof(cmd), "grep -rn ^interface=%s$ /nvram/hostapd*.conf | cut -d '.' -f1 | cut -d 'd' -f2 | tr -d '\\n'",
6782 inputSsidString);
6783 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006784
developer7e4a2a62023-04-06 19:56:03 +08006785 if (strlen(buf)) {
6786 apIndex_str = strtok(buf, "\n");
6787 *output_int = strtoul(apIndex_str, NULL, 10);
6788 return RETURN_OK;
6789 }
developer72fb0bb2023-01-11 09:46:29 +08006790
developer7e4a2a62023-04-06 19:56:03 +08006791 /* If interface name is not in hostapd config, the caller maybe wifi agent to generate data model.*/
6792 if (strstr(inputSsidString, PREFIX_WIFI6G)) {
6793 bss_idx = atoi(inputSsidString + strlen(PREFIX_WIFI6G));
6794 radio_idx = 2;
6795 } else if (strstr(inputSsidString, PREFIX_WIFI5G)) {
6796 bss_idx = atoi(inputSsidString + strlen(PREFIX_WIFI5G));
6797 radio_idx = 1;
6798 } else if (strstr(inputSsidString, PREFIX_WIFI2G)) {
6799 bss_idx = atoi(inputSsidString + strlen(PREFIX_WIFI2G));
6800 radio_idx = 0;
6801 } else {
6802 printf("%s: hostapd conf not find, unknow inf(%s), return ERROR!!!(%d).\n",
6803 __func__, inputSsidString, ap_idx);
6804 *output_int = -1;
6805 return RETURN_ERR;
6806 }
6807
6808 ap_idx = array_index_to_vap_index(radio_idx, bss_idx);
6809
6810 if (ap_idx >= 0 && ap_idx < MAX_VAP) {
6811 printf("%s: hostapd conf not find, inf(%s), use inf idx(%d).\n",
6812 __func__, inputSsidString, ap_idx);
6813 *output_int = ap_idx;
6814 return RETURN_OK;
6815 }
6816
6817 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006818}
6819
6820INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
6821{
6822 return wifi_getIndexFromName(inputSsidString, output_int);
6823}
6824
6825// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
6826INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
6827{
6828 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08006829 char config_file[MAX_BUF_SIZE] = {0};
6830
6831 if(NULL == output_string)
6832 return RETURN_ERR;
6833
6834 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6835 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
6836 if((strcmp(buf,"3")==0))
6837 snprintf(output_string, 32, "WPAand11i");
6838 else if((strcmp(buf,"2")==0))
6839 snprintf(output_string, 32, "11i");
6840 else if((strcmp(buf,"1")==0))
6841 snprintf(output_string, 32, "WPA");
6842 else
6843 snprintf(output_string, 32, "None");
6844
6845 return RETURN_OK;
6846}
6847
6848// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
6849INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
6850{
6851 char config_file[MAX_BUF_SIZE] = {0};
6852 struct params list;
6853
6854 if (NULL == beaconTypeString)
6855 return RETURN_ERR;
6856 list.name = "wpa";
6857 list.value = "0";
6858
6859 if((strcmp(beaconTypeString,"WPAand11i")==0))
6860 list.value="3";
6861 else if((strcmp(beaconTypeString,"11i")==0))
6862 list.value="2";
6863 else if((strcmp(beaconTypeString,"WPA")==0))
6864 list.value="1";
6865
6866 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6867 wifi_hostapdWrite(config_file, &list, 1);
6868 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6869 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6870 return RETURN_OK;
6871}
6872
6873// sets the beacon interval on the hardware for this AP
6874INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
6875{
6876 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6877 struct params params={'\0'};
6878 char buf[MAX_BUF_SIZE] = {'\0'};
6879 char config_file[MAX_BUF_SIZE] = {'\0'};
6880
6881 params.name = "beacon_int";
6882 snprintf(buf, sizeof(buf), "%u", beaconInterval);
6883 params.value = buf;
6884
6885 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6886 wifi_hostapdWrite(config_file, &params, 1);
developer69b61b02023-03-07 17:17:44 +08006887
developer72fb0bb2023-01-11 09:46:29 +08006888 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6889 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6890 return RETURN_OK;
6891}
6892
6893INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
6894{
6895 if (wifi_setApDTIMInterval(apIndex, dtimInterval) != RETURN_OK)
6896 return RETURN_ERR;
6897 return RETURN_OK;
6898}
6899
6900// Get the packet size threshold supported.
6901INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
6902{
6903 //save config and apply instantly
6904 if (NULL == output_bool)
6905 return RETURN_ERR;
6906 *output_bool = TRUE;
6907 return RETURN_OK;
6908}
6909
6910// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
6911INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
6912{
developer72fb0bb2023-01-11 09:46:29 +08006913 char buf[16] = {0};
6914 char config_file[128] = {0};
6915 struct params param = {0};
6916
6917 if (threshold > 65535) {
6918 fprintf(stderr, "%s: rts threshold %u is too big.\n", __func__, threshold);
6919 return RETURN_ERR;
6920 }
6921
developer23e71282023-01-18 10:25:19 +08006922 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developer72fb0bb2023-01-11 09:46:29 +08006923 snprintf(buf, sizeof(buf), "%u", threshold);
6924 param.name = "rts_threshold";
6925 param.value = buf;
6926 wifi_hostapdWrite(config_file, &param, 1);
6927 wifi_hostapdProcessUpdate(apIndex, &param, 1);
6928 wifi_reloadAp(apIndex);
6929
6930 return RETURN_OK;
6931}
6932
6933// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
6934INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
6935{
6936 if (NULL == output_string)
6937 return RETURN_ERR;
6938 snprintf(output_string, 32, "TKIPandAESEncryption");
6939 return RETURN_OK;
6940
6941}
6942
6943// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
6944INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
6945{
6946 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6947 char *param_name = NULL;
6948 char buf[32] = {0}, config_file[MAX_BUF_SIZE] = {0};
developerc79e9172023-06-06 19:48:03 +08006949 unsigned int len;
developer72fb0bb2023-01-11 09:46:29 +08006950
6951 if(NULL == output_string)
6952 return RETURN_ERR;
6953
6954 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6955 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6956
6957 if(strcmp(buf,"0")==0)
6958 {
6959 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
6960 snprintf(output_string, 32, "None");
6961 return RETURN_OK;
6962 }
6963 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
6964 param_name = "rsn_pairwise";
6965 else if((strcmp(buf,"1")==0))
6966 param_name = "wpa_pairwise";
6967 else
6968 return RETURN_ERR;
6969 memset(output_string,'\0',32);
6970 wifi_hostapdRead(config_file,param_name,output_string,32);
6971 if (strlen(output_string) == 0) { // rsn_pairwise is optional. When it is empty use wpa_pairwise instead.
6972 param_name = "wpa_pairwise";
6973 memset(output_string, '\0', 32);
6974 wifi_hostapdRead(config_file, param_name, output_string, 32);
6975 }
6976 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
6977
developerc79e9172023-06-06 19:48:03 +08006978 if(strcmp(output_string,"TKIP CCMP") == 0) {
6979 len = strlen("TKIPandAESEncryption");
6980 memcpy(output_string,"TKIPandAESEncryption", len);
6981 output_string[len] = '\0';
6982 } else if(strcmp(output_string,"TKIP") == 0) {
6983 len = strlen("TKIPEncryption");
6984 memcpy(output_string,"TKIPEncryption", len);
6985 output_string[len] = '\0';
6986 } else if(strcmp(output_string,"CCMP") == 0) {
6987 len = strlen("AESEncryption");
6988 memcpy(output_string,"AESEncryption", len);
6989 output_string[len] = '\0';
6990 }
developer72fb0bb2023-01-11 09:46:29 +08006991
6992 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6993 return RETURN_OK;
6994}
6995
6996// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
6997INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
6998{
6999 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7000 struct params params={'\0'};
7001 char output_string[32];
7002 char config_file[MAX_BUF_SIZE] = {0};
7003
7004 memset(output_string,'\0',32);
developere5750452023-05-15 16:46:42 +08007005 wifi_getApBeaconType(apIndex,output_string);
developer72fb0bb2023-01-11 09:46:29 +08007006
7007 if(strcmp(encMode, "TKIPEncryption") == 0)
7008 params.value = "TKIP";
7009 else if(strcmp(encMode,"AESEncryption") == 0)
7010 params.value = "CCMP";
7011 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
7012 params.value = "TKIP CCMP";
7013
7014 if((strcmp(output_string,"WPAand11i")==0))
7015 {
7016 params.name = "wpa_pairwise";
7017 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7018 wifi_hostapdWrite(config_file, &params, 1);
7019 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7020
7021 params.name = "rsn_pairwise";
7022 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7023 wifi_hostapdWrite(config_file, &params, 1);
7024 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7025
7026 return RETURN_OK;
7027 }
7028 else if((strcmp(output_string,"11i")==0))
7029 {
7030 params.name = "rsn_pairwise";
7031 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7032 wifi_hostapdWrite(config_file, &params, 1);
7033 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7034 return RETURN_OK;
7035 }
7036 else if((strcmp(output_string,"WPA")==0))
7037 {
7038 params.name = "wpa_pairwise";
7039 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7040 wifi_hostapdWrite(config_file, &params, 1);
7041 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7042 return RETURN_OK;
7043 }
7044
7045 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7046 return RETURN_OK;
7047}
7048
7049// deletes internal security varable settings for this ap
7050INT wifi_removeApSecVaribles(INT apIndex)
7051{
7052 //TODO: remove the entry in hostapd config file
7053 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s.conf//g' /tmp/conf_filename", interface_name);
7054 //_syscmd(cmd, buf, sizeof(buf));
7055
7056 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s//g' /tmp/conf_filename", interface_name);
7057 //_syscmd(cmd, buf, sizeof(buf));
7058 return RETURN_ERR;
7059}
7060
7061// changes the hardware settings to disable encryption on this ap
7062INT wifi_disableApEncryption(INT apIndex)
7063{
7064 //Apply instantly
7065 return RETURN_ERR;
7066}
7067
7068// set the authorization mode on this ap
7069// mode mapping as: 1: open, 2: shared, 4:auto
7070INT wifi_setApAuthMode(INT apIndex, INT mode)
7071{
7072 struct params params={0};
7073 char config_file[64] = {0};
developer72fb0bb2023-01-11 09:46:29 +08007074
7075 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
7076
7077 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
7078 params.name = "auth_algs";
7079
developere5750452023-05-15 16:46:42 +08007080 if ((mode & 1 && mode & 2) || mode & 4)
developer72fb0bb2023-01-11 09:46:29 +08007081 params.value = "3";
7082 else if (mode & 2)
7083 params.value = "2";
7084 else if (mode & 1)
7085 params.value = "1";
7086 else
7087 params.value = "0";
7088
7089 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7090 wifi_hostapdWrite(config_file, &params, 1);
7091 wifi_hostapdProcessUpdate(apIndex, &params, 1);
developere5750452023-05-15 16:46:42 +08007092 wifi_reloadAp(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08007093 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
7094
7095 return RETURN_OK;
7096}
7097
7098// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
7099INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
7100{
7101 //save to wifi config, and wait for wifi restart to apply
7102 struct params params={'\0'};
7103 char config_file[MAX_BUF_SIZE] = {0};
7104 int ret;
7105
7106 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7107 if(authMode == NULL)
7108 return RETURN_ERR;
7109
7110 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
7111 params.name = "wpa_key_mgmt";
7112
7113 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
7114 params.value = "WPA-PSK";
7115 else if(strcmp(authMode,"EAPAuthentication") == 0)
7116 params.value = "WPA-EAP";
7117 else if (strcmp(authMode, "SAEAuthentication") == 0)
7118 params.value = "SAE";
7119 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
7120 params.value = "WPA-EAP-SUITE-B-192";
7121 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
7122 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer3086e2f2023-01-17 09:40:01 +08007123 else if (strcmp(authMode, "Enhanced_Open") == 0)
7124 params.value = "OWE";
developer72fb0bb2023-01-11 09:46:29 +08007125 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
7126 return RETURN_OK; //This is taken careof in beaconType
7127
7128 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7129 ret=wifi_hostapdWrite(config_file,&params,1);
7130 if(!ret)
7131 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
7132 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7133
7134 return ret;
7135}
7136
7137// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
7138INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
7139{
7140 //save to wifi config, and wait for wifi restart to apply
7141 char BeaconType[50] = {0};
7142 char config_file[MAX_BUF_SIZE] = {0};
7143
7144 *authMode = 0;
7145 wifi_getApBeaconType(apIndex,BeaconType);
7146 printf("%s____%s \n",__FUNCTION__,BeaconType);
7147
7148 if(strcmp(BeaconType,"None") == 0)
7149 strcpy(authMode,"None");
7150 else
7151 {
7152 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7153 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
7154 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
7155 if(strcmp(authMode,"WPA-PSK") == 0)
7156 strcpy(authMode,"SharedAuthentication");
7157 else if(strcmp(authMode,"WPA-EAP") == 0)
7158 strcpy(authMode,"EAPAuthentication");
7159 }
7160
7161 return RETURN_OK;
7162}
7163
7164// Outputs the number of stations associated per AP
7165INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
7166{
7167 char interface_name[16] = {0};
7168 char cmd[128]={0};
7169 char buf[128]={0};
7170 BOOL status = false;
7171
7172 if(apIndex > MAX_APS)
7173 return RETURN_ERR;
7174
7175 wifi_getApEnable(apIndex,&status);
7176 if (!status)
7177 return RETURN_OK;
7178
7179 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);//alternate method
7180 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7181 return RETURN_ERR;
7182 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l", interface_name);
7183 _syscmd(cmd, buf, sizeof(buf));
7184 sscanf(buf,"%lu", output_ulong);
7185
7186 return RETURN_OK;
7187}
7188
7189// manually removes any active wi-fi association with the device specified on this ap
7190INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
7191{
developer7e4a2a62023-04-06 19:56:03 +08007192 char inf_name[16] = {0};
7193 char cmd[MAX_CMD_SIZE] = {0};
7194 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08007195
developer7e4a2a62023-04-06 19:56:03 +08007196 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
developer72fb0bb2023-01-11 09:46:29 +08007197 return RETURN_ERR;
developer7e4a2a62023-04-06 19:56:03 +08007198
7199 snprintf(cmd, sizeof(cmd),"hostapd_cli -i %s disassociate %s", inf_name, client_mac);
7200 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08007201
7202 return RETURN_OK;
7203}
7204
7205// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
7206INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
7207{
developer7e4a2a62023-04-06 19:56:03 +08007208 int max_radio_num = 0;
7209
7210 if(NULL == output_int)
7211 return RETURN_ERR;
7212
7213 wifi_getMaxRadioNumber(&max_radio_num);
7214 *output_int = apIndex % max_radio_num;
7215
7216 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08007217}
7218
7219// sets the radio index for the specific ap
7220INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
7221{
7222 //set to config only and wait for wifi reset to apply settings
7223 return RETURN_ERR;
7224}
7225
developer121a8e72023-05-22 09:19:39 +08007226
7227#define MAX_ACL_DUMP_LEN 4096
7228int mtk_acl_list_dump_callback(struct nl_msg *msg, void *cb)
7229{
7230 struct nlattr *tb[NL80211_ATTR_MAX + 1];
7231 struct nlattr *vndr_tb[MTK_NL80211_VENDOR_AP_ACL_ATTR_MAX + 1];
7232 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
7233 char *show_str = NULL;
developer2edaf012023-05-24 14:24:53 +08007234 int err = 0;
developer121a8e72023-05-22 09:19:39 +08007235 unsigned short acl_result_len = 0;
7236 struct mtk_nl80211_cb_data *cb_data = cb;
developer121a8e72023-05-22 09:19:39 +08007237 if (!msg || !cb_data) {
developerdaf24792023-06-06 11:40:04 +08007238 wifi_debug(DEBUG_ERROR, "msg(%p) or cb_data(%p) is null,error.\n", msg, cb_data);
developer121a8e72023-05-22 09:19:39 +08007239 return NL_SKIP;
7240 }
developer121a8e72023-05-22 09:19:39 +08007241 err = nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
7242 genlmsg_attrlen(gnlh, 0), NULL);
7243 if (err < 0) {
developer2edaf012023-05-24 14:24:53 +08007244 wifi_debug(DEBUG_ERROR, "nla_parse acl list nl80211 msg fails,error.\n");
developer121a8e72023-05-22 09:19:39 +08007245 return NL_SKIP;
7246 }
developer121a8e72023-05-22 09:19:39 +08007247 if (tb[NL80211_ATTR_VENDOR_DATA]) {
7248 err = nla_parse_nested(vndr_tb, MTK_NL80211_VENDOR_AP_ACL_ATTR_MAX,
7249 tb[NL80211_ATTR_VENDOR_DATA], NULL);
7250 if (err < 0)
7251 return NL_SKIP;
7252 if (vndr_tb[MTK_NL80211_VENDOR_ATTR_ACL_LIST_INFO]) {
7253 acl_result_len = nla_len(vndr_tb[MTK_NL80211_VENDOR_ATTR_ACL_LIST_INFO]);
7254 show_str = nla_data(vndr_tb[MTK_NL80211_VENDOR_ATTR_ACL_LIST_INFO]);
7255 if (acl_result_len > MAX_ACL_DUMP_LEN) {
7256 wifi_debug(DEBUG_ERROR,"the scan result len is invalid !!!\n");
7257 return NL_SKIP;
7258 } else if (*(show_str + acl_result_len - 1) != '\0') {
7259 wifi_debug(DEBUG_INFO, "the result string is not ended with right terminator, handle it!!!\n");
7260 *(show_str + acl_result_len - 1) = '\0';
7261 }
7262 wifi_debug(DEBUG_INFO, "driver msg:%s\n", show_str);
developer2edaf012023-05-24 14:24:53 +08007263
7264 if (cb_data->out_len >= acl_result_len) {
7265 memset(cb_data->out_buf, 0, cb_data->out_len);
7266 /*skip the first line: 'policy=1\n' to find the acl mac addrs*/
7267 memmove(cb_data->out_buf, show_str, acl_result_len);
7268 wifi_debug(DEBUG_INFO, "out buff:%s\n", cb_data->out_buf);
7269 } else {
7270 memset(cb_data->out_buf, 0, cb_data->out_len);
developer121a8e72023-05-22 09:19:39 +08007271 }
developer121a8e72023-05-22 09:19:39 +08007272 } else
7273 wifi_debug(DEBUG_ERROR, "no acl result attr\n");
7274 } else
7275 wifi_debug(DEBUG_ERROR, "no any acl result from driver\n");
7276 return NL_OK;
7277}
developer72fb0bb2023-01-11 09:46:29 +08007278// Get the ACL MAC list per AP
developer2edaf012023-05-24 14:24:53 +08007279INT mtk_wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
developer72fb0bb2023-01-11 09:46:29 +08007280{
developer7e4a2a62023-04-06 19:56:03 +08007281 char inf_name[IF_NAME_SIZE] = {0};
developer121a8e72023-05-22 09:19:39 +08007282 unsigned int if_idx = 0;
7283 int ret = -1;
7284 struct unl unl_ins;
7285 struct nl_msg *msg = NULL;
7286 struct nlattr * msg_data = NULL;
7287 struct mtk_nl80211_param param;
7288 struct mtk_nl80211_cb_data cb_data;
developer7e4a2a62023-04-06 19:56:03 +08007289 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
7290 return RETURN_ERR;
developer121a8e72023-05-22 09:19:39 +08007291 if_idx = if_nametoindex(inf_name);
7292 if (!if_idx) {
developer2edaf012023-05-24 14:24:53 +08007293 wifi_debug(DEBUG_ERROR,"can't finde ifname(%s) index,ERROR\n", inf_name);
developer121a8e72023-05-22 09:19:39 +08007294 return RETURN_ERR;
7295 }
7296 /*init mtk nl80211 vendor cmd*/
7297 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_ACL;
7298 param.if_type = NL80211_ATTR_IFINDEX;
7299 param.if_idx = if_idx;
7300
7301 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
7302 if (ret) {
7303 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
7304 return RETURN_ERR;
7305 }
developer121a8e72023-05-22 09:19:39 +08007306 /*add mtk vendor cmd data*/
7307 if (nla_put_flag(msg, MTK_NL80211_VENDOR_ATTR_ACL_SHOW_ALL)) {
developer2edaf012023-05-24 14:24:53 +08007308 wifi_debug(DEBUG_ERROR, "Nla put ACL_SHOW_ALL attribute error\n");
developer121a8e72023-05-22 09:19:39 +08007309 nlmsg_free(msg);
7310 goto err;
7311 }
developer72fb0bb2023-01-11 09:46:29 +08007312
developer121a8e72023-05-22 09:19:39 +08007313 /*send mtk nl80211 vendor msg*/
7314 cb_data.out_buf = macArray;
7315 cb_data.out_len = buf_size;
7316
7317 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, mtk_acl_list_dump_callback, &cb_data);
7318 if (ret) {
7319 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
7320 goto err;
7321 }
7322 /*deinit mtk nl80211 vendor msg*/
7323 mtk_nl80211_deint(&unl_ins);
developer2edaf012023-05-24 14:24:53 +08007324 wifi_debug(DEBUG_NOTICE,"send cmd success, get out_buf:%s\n", macArray);
developer72fb0bb2023-01-11 09:46:29 +08007325 return RETURN_OK;
developer121a8e72023-05-22 09:19:39 +08007326err:
7327 mtk_nl80211_deint(&unl_ins);
developer2edaf012023-05-24 14:24:53 +08007328 wifi_debug(DEBUG_ERROR,"send cmd fails\n");
developer121a8e72023-05-22 09:19:39 +08007329 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007330}
7331
developer2edaf012023-05-24 14:24:53 +08007332INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
7333{
7334 char *mac_arry_buf = NULL;
7335
7336 mac_arry_buf = malloc(buf_size);
7337 if (!mac_arry_buf) {
7338 wifi_debug(DEBUG_ERROR,"malloc mac_arry_buf fails\n");
7339 return RETURN_ERR;
7340 }
7341 memset(mac_arry_buf, 0, buf_size);
7342 if (mtk_wifi_getApAclDevices(apIndex, mac_arry_buf, buf_size) != RETURN_OK) {
7343 wifi_debug(DEBUG_ERROR,"mtk_wifi_getApAclDevices get fails\n");
7344 free(mac_arry_buf);
7345 mac_arry_buf = NULL;
7346 return RETURN_ERR;
7347 }
7348 /*
7349 mtk format to wifi hal format:
7350 "policy=1
7351 00:11:22:33:44:55
7352 00:11:22:33:44:66
7353 "
7354 -->
7355 "00:11:22:33:44:55
7356 00:11:22:33:44:66
7357 "
7358 */
7359 memset(macArray, 0, buf_size);
7360 if (*mac_arry_buf != '\0' && strchr(mac_arry_buf,'\n')) {
7361 memmove(macArray, strchr(mac_arry_buf,'\n')+1, strlen(strchr(mac_arry_buf,'\n')+1)+1);
7362 wifi_debug(DEBUG_NOTICE,"macArray:\n%s\n", macArray);
7363 }
7364 free(mac_arry_buf);
7365 mac_arry_buf = NULL;
7366 return RETURN_OK;
7367}
7368
developer72fb0bb2023-01-11 09:46:29 +08007369INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
7370{
developer72fb0bb2023-01-11 09:46:29 +08007371
developer7e4a2a62023-04-06 19:56:03 +08007372 wifi_getApAclDevices(apIndex, macArray, buf_size);
developer72fb0bb2023-01-11 09:46:29 +08007373
7374 return RETURN_OK;
7375}
7376
7377
7378// Get the list of stations associated per AP
7379INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
7380{
developer7e4a2a62023-04-06 19:56:03 +08007381 char interface_name[IF_NAME_SIZE] = {0};
7382 char cmd[MAX_CMD_SIZE];
developer72fb0bb2023-01-11 09:46:29 +08007383
developer7e4a2a62023-04-06 19:56:03 +08007384 if(apIndex > 3) //Currently supporting apIndex upto 3
7385 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007386
developer7e4a2a62023-04-06 19:56:03 +08007387 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7388 return RETURN_ERR;
7389
7390 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s list_sta", interface_name);
7391 _syscmd(cmd, macArray, buf_size);
7392 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08007393}
7394
developer8dd72532023-05-17 19:58:35 +08007395int hex2num(char c)
7396{
7397 if (c >= '0' && c <= '9')
7398 return c - '0';
7399 if (c >= 'a' && c <= 'f')
7400 return c - 'a' + 10;
7401 if (c >= 'A' && c <= 'F')
7402 return c - 'A' + 10;
7403 return -1;
7404}
7405
7406/**
7407 * hwaddr_aton2 - Convert ASCII string to MAC address (in any known format)
7408 * @txt: MAC address as a string (e.g., 00:11:22:33:44:55 or 0011.2233.4455)
7409 * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
7410 * Returns: Characters used (> 0) on success, -1 on failure
7411 */
7412int hwaddr_aton2(const char *txt, unsigned char *addr)
7413{
7414 int i;
7415 const char *pos = txt;
7416
7417 for (i = 0; i < 6; i++) {
7418 int a, b;
7419
7420 while (*pos == ':' || *pos == '.' || *pos == '-')
7421 pos++;
7422
7423 a = hex2num(*pos++);
7424 if (a < 0)
7425 return -1;
7426 b = hex2num(*pos++);
7427 if (b < 0)
7428 return -1;
7429 *addr++ = (a << 4) | b;
7430 }
7431
7432 return pos - txt;
7433}
7434
developer72fb0bb2023-01-11 09:46:29 +08007435// adds the mac address to the filter list
7436//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
7437INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
7438{
developer7e4a2a62023-04-06 19:56:03 +08007439 char inf_name[IF_NAME_SIZE] = {0};
developer8dd72532023-05-17 19:58:35 +08007440 int if_idx, ret = 0;
developer49b17232023-05-19 16:35:19 +08007441 struct nl_msg *msg = NULL;
7442 struct nlattr * msg_data = NULL;
7443 struct mtk_nl80211_param param;
developer8dd72532023-05-17 19:58:35 +08007444 unsigned char mac[ETH_ALEN] = {0x00, 0x0c, 0x43, 0x11, 0x22, 0x33};
7445 struct unl unl_ins;
developer7e4a2a62023-04-06 19:56:03 +08007446 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
7447 return RETURN_ERR;
developer7e4a2a62023-04-06 19:56:03 +08007448 if (!DeviceMacAddress)
7449 return RETURN_ERR;
developer8dd72532023-05-17 19:58:35 +08007450 if (hwaddr_aton2(DeviceMacAddress, mac) < 0) {
developer2edaf012023-05-24 14:24:53 +08007451 wifi_debug(DEBUG_ERROR, "error device mac address=%s\n", DeviceMacAddress);
developer8dd72532023-05-17 19:58:35 +08007452 return RETURN_ERR;
7453 }
developer8dd72532023-05-17 19:58:35 +08007454 if_idx = if_nametoindex(inf_name);
developer2edaf012023-05-24 14:24:53 +08007455 if (!if_idx) {
7456 wifi_debug(DEBUG_ERROR, "can't finde ifname(%s) index,ERROR\n", inf_name);
7457 return RETURN_ERR;
7458 }
developer49b17232023-05-19 16:35:19 +08007459 /*init mtk nl80211 vendor cmd*/
7460 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_ACL;
7461 param.if_type = NL80211_ATTR_IFINDEX;
7462 param.if_idx = if_idx;
7463 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
7464 if (ret) {
7465 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
developer8dd72532023-05-17 19:58:35 +08007466 return RETURN_ERR;
7467 }
developer49b17232023-05-19 16:35:19 +08007468 /*add mtk vendor cmd data*/
7469 if (nla_put(msg, MTK_NL80211_VENDOR_ATTR_ACL_ADD_MAC, ETH_ALEN, mac)) {
developer2edaf012023-05-24 14:24:53 +08007470 wifi_debug(DEBUG_ERROR, "Nla put attribute error\n");
developer8dd72532023-05-17 19:58:35 +08007471 nlmsg_free(msg);
7472 goto err;
7473 }
developer49b17232023-05-19 16:35:19 +08007474 /*send mtk nl80211 vendor msg*/
7475 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
7476 if (ret) {
7477 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
developer8dd72532023-05-17 19:58:35 +08007478 goto err;
7479 }
developer49b17232023-05-19 16:35:19 +08007480 /*deinit mtk nl80211 vendor msg*/
7481 mtk_nl80211_deint(&unl_ins);
7482 wifi_debug(DEBUG_NOTICE, "set cmd success.\n");
developer8dd72532023-05-17 19:58:35 +08007483 return RETURN_OK;
7484err:
developer49b17232023-05-19 16:35:19 +08007485 mtk_nl80211_deint(&unl_ins);
7486 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
developer8dd72532023-05-17 19:58:35 +08007487 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007488}
7489
7490// deletes the mac address from the filter list
7491//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
7492INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
7493{
developer2edaf012023-05-24 14:24:53 +08007494 struct unl unl_ins;
7495 int if_idx = 0, ret = 0;
7496 struct nl_msg *msg = NULL;
7497 struct nlattr * msg_data = NULL;
7498 struct mtk_nl80211_param param;
developer7e4a2a62023-04-06 19:56:03 +08007499 char inf_name[IF_NAME_SIZE] = {0};
developer2edaf012023-05-24 14:24:53 +08007500 unsigned char mac[ETH_ALEN] = {0};
developer72fb0bb2023-01-11 09:46:29 +08007501
developer7e4a2a62023-04-06 19:56:03 +08007502 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
7503 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007504
developer7e4a2a62023-04-06 19:56:03 +08007505 if (!DeviceMacAddress)
7506 return RETURN_ERR;
7507
developer2edaf012023-05-24 14:24:53 +08007508 if (hwaddr_aton2(DeviceMacAddress, mac) < 0) {
7509 wifi_debug(DEBUG_ERROR, "error device mac address=%s\n", DeviceMacAddress);
7510 return RETURN_ERR;
7511 }
developer72fb0bb2023-01-11 09:46:29 +08007512
developer2edaf012023-05-24 14:24:53 +08007513 if_idx = if_nametoindex(inf_name);
7514 if (!if_idx) {
7515 wifi_debug(DEBUG_ERROR, "can't finde ifname(%s) index,ERROR\n", inf_name);
7516 return RETURN_ERR;
7517 }
7518 /*init mtk nl80211 vendor cmd*/
7519 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_ACL;
7520 param.if_type = NL80211_ATTR_IFINDEX;
7521 param.if_idx = if_idx;
7522 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
7523 if (ret) {
7524 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
7525 return RETURN_ERR;
7526 }
7527 /*add mtk vendor cmd data*/
7528 if (nla_put(msg, MTK_NL80211_VENDOR_ATTR_ACL_DEL_MAC, ETH_ALEN, mac)) {
7529 wifi_debug(DEBUG_ERROR, "Nla put attribute error\n");
7530 nlmsg_free(msg);
7531 goto err;
7532 }
7533 /*send mtk nl80211 vendor msg*/
7534 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
7535 if (ret) {
7536 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
7537 goto err;
7538 }
7539 /*deinit mtk nl80211 vendor msg*/
7540 mtk_nl80211_deint(&unl_ins);
7541 wifi_debug(DEBUG_NOTICE, "set cmd success.\n");
7542 return RETURN_OK;
7543err:
7544 mtk_nl80211_deint(&unl_ins);
7545 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
7546 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007547}
7548
7549// outputs the number of devices in the filter list
7550INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
7551{
developer2edaf012023-05-24 14:24:53 +08007552 char *mac_arry = NULL, *ptr = NULL, mac_str[18] = {0};
7553 UINT buf_size = 1024;
7554 UINT sta_num = 0;
7555 unsigned char mac[ETH_ALEN] = {0};
developer72fb0bb2023-01-11 09:46:29 +08007556 if(output_uint == NULL)
developerdaf24792023-06-06 11:40:04 +08007557 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007558
developer2edaf012023-05-24 14:24:53 +08007559 mac_arry = (char *)malloc(buf_size);
7560 if (mac_arry == NULL) {
7561 wifi_debug(DEBUG_ERROR, "malloc mac_arry fails\n");
developer7e4a2a62023-04-06 19:56:03 +08007562 return RETURN_ERR;
developer2edaf012023-05-24 14:24:53 +08007563 }
developerdaf24792023-06-06 11:40:04 +08007564 memset(mac_arry, 0, buf_size);
developer2edaf012023-05-24 14:24:53 +08007565 /*mac_arry str format: 00:11:22:33:44:55\n00:11:22:33:44:66\0*/
7566 if (wifi_getApAclDevices(apIndex, mac_arry, buf_size)!= RETURN_OK) {
7567 wifi_debug(DEBUG_ERROR, "get acl list entries fails\n");
7568 return RETURN_ERR;
7569 }
7570 /*count the acl str nums:*/
7571 wifi_debug(DEBUG_NOTICE, "mac_arry: %s\n", mac_arry);
developer7e4a2a62023-04-06 19:56:03 +08007572
developer2edaf012023-05-24 14:24:53 +08007573 /*mac addr string format:
7574 exp1: 00:11:22:33:44:55\0
7575 exp2: 00:11:22:33:44:55\n00:11:22:33:44:66\0
7576 */
7577 ptr = mac_arry;
7578 while (sscanf(ptr, "%17s", mac_str) == 1) {
7579 if (hwaddr_aton2(mac_str, mac) >= 0)
7580 sta_num++;
7581 ptr = strstr(ptr, mac_str) + strlen(mac_str);
7582 }
7583 *output_uint = sta_num;
7584 wifi_debug(DEBUG_NOTICE, "output_uint: %d\n", *output_uint);
7585 free(mac_arry);
7586 mac_arry = NULL;
developer7e4a2a62023-04-06 19:56:03 +08007587 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08007588}
7589
7590INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
7591{
developer72fb0bb2023-01-11 09:46:29 +08007592 char buf[128]={'\0'};
7593
7594 if(strcmp(action,"DENY")==0)
7595 {
7596 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
7597 system(buf);
7598 return RETURN_OK;
7599 }
7600
7601 if(strcmp(action,"ALLOW")==0)
7602 {
7603 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
7604 system(buf);
7605 return RETURN_OK;
7606 }
7607
7608 return RETURN_ERR;
7609
7610}
7611
7612// enable kick for devices on acl black list
7613INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
7614{
developer47cc27a2023-05-17 23:09:58 +08007615 char aclArray[MAX_BUF_SIZE] = {0}, *acl = NULL;
developer2f79c922023-06-02 17:33:42 +08007616 char assocArray[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08007617
7618 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
7619 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
7620
developer7e4a2a62023-04-06 19:56:03 +08007621 /* if there are no devices connected there is nothing to do */
developer72fb0bb2023-01-11 09:46:29 +08007622 if (strlen(assocArray) < 17)
7623 return RETURN_OK;
7624
developer7e4a2a62023-04-06 19:56:03 +08007625 if (enable == TRUE) {
7626 /* kick off the MAC which is in ACL array (deny list) */
7627 acl = strtok(aclArray, "\n");
developer72fb0bb2023-01-11 09:46:29 +08007628 while (acl != NULL) {
7629 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
7630 wifi_kickApAssociatedDevice(apIndex, acl);
7631
developer7e4a2a62023-04-06 19:56:03 +08007632 acl = strtok(NULL, "\n");
developer72fb0bb2023-01-11 09:46:29 +08007633 }
7634 wifi_setApMacAddressControlMode(apIndex, 2);
developer7e4a2a62023-04-06 19:56:03 +08007635 } else
developer72fb0bb2023-01-11 09:46:29 +08007636 wifi_setApMacAddressControlMode(apIndex, 0);
developer72fb0bb2023-01-11 09:46:29 +08007637
developer72fb0bb2023-01-11 09:46:29 +08007638 return RETURN_OK;
7639}
7640
7641INT wifi_setPreferPrivateConnection(BOOL enable)
7642{
7643 return RETURN_OK;
7644}
7645
7646// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
7647INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
7648{
developer2edaf012023-05-24 14:24:53 +08007649 int if_idx = 0, ret = 0;
7650 struct unl unl_ins;
7651 struct nl_msg *msg = NULL;
7652 struct nlattr * msg_data = NULL;
7653 struct mtk_nl80211_param param;
7654 int acl_policy = -1;
developer7e4a2a62023-04-06 19:56:03 +08007655 char inf_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08007656
developer7e4a2a62023-04-06 19:56:03 +08007657 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
7658 return RETURN_ERR;
developer2edaf012023-05-24 14:24:53 +08007659 if_idx = if_nametoindex(inf_name);
7660 if (!if_idx) {
7661 wifi_debug(DEBUG_ERROR, "can't finde ifname(%s) index,ERROR\n", inf_name);
7662 return RETURN_ERR;
7663 }
7664 /*init mtk nl80211 vendor cmd*/
7665 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_ACL;
7666 param.if_type = NL80211_ATTR_IFINDEX;
7667 param.if_idx = if_idx;
7668 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
7669 if (ret) {
7670 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
7671 return RETURN_ERR;
7672 }
7673 /*add mtk vendor cmd data*/
7674 if (filterMode == 0) {
7675 acl_policy = MTK_NL80211_VENDOR_ATTR_ACL_DISABLE;
7676 } else if (filterMode == 1) {
7677 acl_policy = MTK_NL80211_VENDOR_ATTR_ACL_ENABLE_WHITE_LIST;
7678 } else if (filterMode == 2) {
7679 acl_policy = MTK_NL80211_VENDOR_ATTR_ACL_ENABLE_BLACK_LIST;
7680 } else {
7681 wifi_debug(DEBUG_ERROR, "filtermode(%d) not support error\n", filterMode);
7682 nlmsg_free(msg);
7683 goto err;
7684 }
7685 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_ACL_POLICY, acl_policy)) {
7686 wifi_debug(DEBUG_ERROR, "Nla put attribute error\n");
7687 nlmsg_free(msg);
7688 goto err;
7689 }
7690 /*send mtk nl80211 vendor msg*/
7691 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
7692 if (ret) {
7693 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
7694 goto err;
7695 }
7696 /*deinit mtk nl80211 vendor msg*/
7697 mtk_nl80211_deint(&unl_ins);
7698 wifi_debug(DEBUG_NOTICE, "set cmd success.\n");
developer7e4a2a62023-04-06 19:56:03 +08007699 return RETURN_OK;
developer2edaf012023-05-24 14:24:53 +08007700err:
7701 mtk_nl80211_deint(&unl_ins);
7702 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
7703 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007704}
7705
7706// 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.
7707INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
7708{
7709 return RETURN_ERR;
7710}
7711
7712// gets the vlan ID for this ap from an internal enviornment variable
7713INT wifi_getApVlanID(INT apIndex, INT *output_int)
7714{
7715 if(apIndex==0)
7716 {
7717 *output_int=100;
7718 return RETURN_OK;
7719 }
7720
7721 return RETURN_ERR;
7722}
7723
7724// sets the vlan ID for this ap to an internal enviornment variable
7725INT wifi_setApVlanID(INT apIndex, INT vlanId)
7726{
7727 //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)
7728 return RETURN_ERR;
7729}
7730
developercc5cbfb2023-06-13 18:29:52 +08007731char br_name[IFNAMSIZ] = "brlan0";
7732
developer72fb0bb2023-01-11 09:46:29 +08007733// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
7734INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
7735{
developercc5cbfb2023-06-13 18:29:52 +08007736 int sock = socket(AF_INET, SOCK_DGRAM, 0);
7737 struct ifreq ifr;
7738 struct sockaddr_in *sin;
7739
7740 memcpy(bridgeName, br_name, strlen(br_name));
7741
7742 if (sock == -1) {
7743 wifi_debug(DEBUG_ERROR, "socket failed");
7744 return RETURN_ERR;
7745 }
7746
7747 strncpy(ifr.ifr_name, br_name, IFNAMSIZ);
7748 ifr.ifr_addr.sa_family = AF_INET;
7749 if (ioctl(sock, SIOCGIFADDR, &ifr) < 0) {
7750 wifi_debug(DEBUG_ERROR, "ioctl(SIOCGIFADDR) failed, %s, bridge_name=%s\n",
7751 strerror(errno), br_name);
7752 return RETURN_ERR;
7753 }
7754
7755 sin = (struct sockaddr_in *)&ifr.ifr_addr;
7756 wifi_debug(DEBUG_ERROR, "Bridge device %s has IP address: %s\n", br_name, inet_ntoa(sin->sin_addr));
7757 memcpy(IP, inet_ntoa(sin->sin_addr), strlen(inet_ntoa(sin->sin_addr)));
7758
7759 if (ioctl(sock, SIOCGIFNETMASK, &ifr) < 0) {
7760 wifi_debug(DEBUG_ERROR, "ioctl(SIOCGIFNETMASK) failed, %s", strerror(errno));
7761 return RETURN_ERR;
7762 }
7763
7764 wifi_debug(DEBUG_ERROR, "Bridge device %s has subnet mask: %s\n", br_name, inet_ntoa(sin->sin_addr));
7765 memcpy(subnet, inet_ntoa(sin->sin_addr), strlen(inet_ntoa(sin->sin_addr)));
7766 close(sock);
developer72fb0bb2023-01-11 09:46:29 +08007767
7768 return RETURN_OK;
7769}
7770
7771//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
7772INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
7773{
7774 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
developercc5cbfb2023-06-13 18:29:52 +08007775 struct ifreq ifr;
7776 struct sockaddr_in sin;
7777 int sock = socket(AF_INET, SOCK_DGRAM, 0);
7778
7779 if (strlen(bridgeName) >= IFNAMSIZ) {
7780 wifi_debug(DEBUG_ERROR, "invalide bridgeName length=%ld\n", strlen(bridgeName));
7781 return RETURN_ERR;
7782 }
7783
7784 if (strlen(br_name) >= IFNAMSIZ) {
7785 wifi_debug(DEBUG_ERROR, "invalide br_name length=%ld in strorage\n", strlen(br_name));
7786 return RETURN_ERR;
7787 }
7788
7789 if (sock == -1) {
7790 wifi_debug(DEBUG_ERROR, "socket failed");
7791 return RETURN_ERR;
7792 }
7793
7794 memset(&ifr, 0, sizeof(ifr));
7795 strncpy(ifr.ifr_name, br_name, strlen(br_name));
7796 if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
7797 wifi_debug(DEBUG_ERROR, "ioctl(SIOCGIFFLAGS) failed, %s", strerror(errno));
7798 return RETURN_ERR;
7799 }
7800
7801 ifr.ifr_flags = (short)(ifr.ifr_flags & ~IFF_UP);
7802 if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0) {
7803 wifi_debug(DEBUG_ERROR, "ioctl(SIOCSIFFLAGS) failed, %s", strerror(errno));
7804 return RETURN_ERR;
7805 }
7806
7807 memset(&ifr, 0, sizeof(ifr));
7808 strncpy(ifr.ifr_name, br_name, IFNAMSIZ);
7809 strncpy(ifr.ifr_newname, bridgeName, IFNAMSIZ);
7810 if (ioctl(sock, SIOCSIFNAME, &ifr) < 0) {
7811 wifi_debug(DEBUG_ERROR, "ioctl(SIOCSIFNAME) failed, %s", strerror(errno));
7812 return RETURN_ERR;
7813 }
7814
7815 memset(br_name, 0, sizeof(br_name));
7816 memcpy(br_name, bridgeName, strlen(bridgeName));
7817
7818 memset(&ifr, 0, sizeof(ifr));
7819 strncpy(ifr.ifr_name, bridgeName, IFNAMSIZ);
7820 if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
7821 wifi_debug(DEBUG_ERROR, "ioctl(SIOCGIFFLAGS) failed, %s", strerror(errno));
7822 return RETURN_ERR;
7823 }
7824 ifr.ifr_flags = (short)(ifr.ifr_flags | IFF_UP);
7825 if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0) {
7826 wifi_debug(DEBUG_ERROR, "ioctl(SIOCSIFFLAGS) failed, %s", strerror(errno));
7827 return RETURN_ERR;
7828 }
7829
7830 memset(&ifr, 0, sizeof(ifr));
7831 memcpy(ifr.ifr_name, bridgeName, strlen(bridgeName));
7832
7833 memset(&sin, 0, sizeof(struct sockaddr_in));
7834 sin.sin_family = AF_INET;
7835 if (inet_aton(IP, &(sin.sin_addr)) == 0) {
7836 wifi_debug(DEBUG_ERROR, "inet_aton failed");
7837 return RETURN_ERR;
7838 }
7839 memcpy(&ifr.ifr_addr, &sin, sizeof(struct sockaddr_in));
7840 if (ioctl(sock, SIOCSIFADDR, &ifr) < 0) {
7841 wifi_debug(DEBUG_ERROR, "ioctl(SIOCSIFADDR) failed, %s", strerror(errno));
7842 return RETURN_ERR;
7843 }
7844
7845 if (inet_aton(subnet, &((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr) == 0) {
7846 wifi_debug(DEBUG_ERROR, "inet_aton failed");
7847 return RETURN_ERR;
7848 }
7849 if (ioctl(sock, SIOCSIFNETMASK, &ifr) < -1) {
7850 wifi_debug(DEBUG_ERROR, "ioctl(SIOCSIFNETMASK) failed, %s", strerror(errno));
7851 return RETURN_ERR;
7852 }
7853
7854 close(sock);
developer72fb0bb2023-01-11 09:46:29 +08007855 return RETURN_ERR;
7856}
7857
7858// reset the vlan configuration for this ap
7859INT wifi_resetApVlanCfg(INT apIndex)
7860{
developera1255e42023-05-13 17:45:02 +08007861 char interface_name[16] = {0};
developer2202b332023-05-24 16:23:22 +08007862 int if_idx, ret = 0;
7863 struct nl_msg *msg = NULL;
7864 struct nlattr * msg_data = NULL;
7865 struct mtk_nl80211_param param;
7866 struct unl unl_ins;
7867 struct vlan_policy_param vlan_param;
developer72fb0bb2023-01-11 09:46:29 +08007868
developer2202b332023-05-24 16:23:22 +08007869 if (apIndex > MAX_APS) {
7870 wifi_debug(DEBUG_ERROR, "Invalid apIndex %d\n", apIndex);
7871 return RETURN_ERR;
7872 }
developer72fb0bb2023-01-11 09:46:29 +08007873
developer2202b332023-05-24 16:23:22 +08007874 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7875 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7876 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007877
developer2202b332023-05-24 16:23:22 +08007878 /*step 1. mwctl dev %s set vlan_tag 0*/
7879 if_idx = if_nametoindex(interface_name);
7880 /*init mtk nl80211 vendor cmd*/
7881 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_VLAN;
7882 param.if_type = NL80211_ATTR_IFINDEX;
7883 param.if_idx = if_idx;
7884 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
developer72fb0bb2023-01-11 09:46:29 +08007885
developer2202b332023-05-24 16:23:22 +08007886 if (ret) {
7887 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
7888 return RETURN_ERR;
7889 }
developer72fb0bb2023-01-11 09:46:29 +08007890
developer2202b332023-05-24 16:23:22 +08007891 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_VLAN_TAG_INFO, 0)) {
7892 printf("Nla put attribute error\n");
7893 nlmsg_free(msg);
7894 goto err;
7895 }
developer72fb0bb2023-01-11 09:46:29 +08007896
developer2202b332023-05-24 16:23:22 +08007897 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
7898 if (ret) {
7899 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vendor msg fails\n");
7900 goto err;
7901 }
7902 mtk_nl80211_deint(&unl_ins);
7903 wifi_debug(DEBUG_NOTICE, "set vlan_tag 0 cmd success.\n");
developer72fb0bb2023-01-11 09:46:29 +08007904
developer2202b332023-05-24 16:23:22 +08007905 /*step 2. mwctl dev %s set vlan_priority 0*/
7906 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
7907 if (ret) {
7908 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
7909 return RETURN_ERR;
7910 }
developer72fb0bb2023-01-11 09:46:29 +08007911
developer2202b332023-05-24 16:23:22 +08007912 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_VLAN_PRIORITY_INFO, 0)) {
7913 printf("Nla put attribute error\n");
7914 nlmsg_free(msg);
7915 goto err;
7916 }
developer72fb0bb2023-01-11 09:46:29 +08007917
developer2202b332023-05-24 16:23:22 +08007918 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
7919 if (ret) {
7920 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vendor msg fails\n");
7921 goto err;
7922 }
7923 mtk_nl80211_deint(&unl_ins);
7924 wifi_debug(DEBUG_NOTICE, "set vlan_priority 0 cmd success.\n");
7925
7926 /*step 3. mwctl dev %s set vlan_id 0*/
7927 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
7928 if (ret) {
7929 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
developera1255e42023-05-13 17:45:02 +08007930 return RETURN_ERR;
developer2202b332023-05-24 16:23:22 +08007931 }
developer72fb0bb2023-01-11 09:46:29 +08007932
developer2202b332023-05-24 16:23:22 +08007933 if (nla_put_u16(msg, MTK_NL80211_VENDOR_ATTR_VLAN_ID_INFO, 0)) {
7934 printf("Nla put attribute error\n");
7935 nlmsg_free(msg);
7936 goto err;
7937 }
7938
7939 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
7940 if (ret) {
7941 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vendor msg fails\n");
7942 goto err;
7943 }
7944 mtk_nl80211_deint(&unl_ins);
7945 wifi_debug(DEBUG_NOTICE, "set vlan_id cmd success.\n");
7946
7947 /*step 4. mwctl dev %s set vlan_en 0*/
7948 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
7949 if (ret) {
7950 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
7951 return RETURN_ERR;
7952 }
7953
7954 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_VLAN_EN_INFO, 0)) {
7955 printf("Nla put attribute error\n");
7956 nlmsg_free(msg);
7957 goto err;
7958 }
7959
7960 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
7961 if (ret) {
7962 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vendor msg fails\n");
7963 goto err;
7964 }
7965 mtk_nl80211_deint(&unl_ins);
7966 wifi_debug(DEBUG_NOTICE, "set vlan_id cmd success.\n");
7967
7968 /*step 5. mwctl dev %s set vlan_policy 0:4*/
7969 vlan_param.direction = 0;
7970 vlan_param.policy = 4;
7971 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
7972 if (ret) {
7973 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
7974 return RETURN_ERR;
7975 }
7976 if (nla_put(msg, MTK_NL80211_VENDOR_ATTR_VLAN_POLICY_INFO, sizeof(vlan_param), &vlan_param)) {
7977 printf("Nla put attribute error\n");
7978 nlmsg_free(msg);
7979 goto err;
7980 }
7981
7982 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
7983 if (ret) {
7984 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vendor msg fails\n");
7985 goto err;
7986 }
7987 mtk_nl80211_deint(&unl_ins);
7988 wifi_debug(DEBUG_NOTICE, "set vlan_policy 0:4 cmd success.\n");
7989
7990 /*step 6. mwctl dev %s set vlan_policy 1:0*/
7991 vlan_param.direction = 1;
7992 vlan_param.policy = 0;
7993 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
7994 if (ret) {
7995 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
7996 return RETURN_ERR;
7997 }
7998
7999 if (nla_put(msg, MTK_NL80211_VENDOR_ATTR_VLAN_POLICY_INFO, sizeof(vlan_param), &vlan_param)) {
8000 printf("Nla put attribute error\n");
8001 nlmsg_free(msg);
8002 goto err;
8003 }
8004
8005 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
8006 if (ret) {
8007 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vendor msg fails\n");
8008 goto err;
8009 }
8010 /*deinit mtk nl80211 vendor msg*/
8011 mtk_nl80211_deint(&unl_ins);
8012 wifi_debug(DEBUG_NOTICE, "set vlan_policy 1:0 cmd success.\n");
8013
8014 /*TODO need to modify VLAN config in dat file*/
8015 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8016
8017 return RETURN_OK;
8018err:
8019 mtk_nl80211_deint(&unl_ins);
8020 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
8021 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08008022}
8023
8024// 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.
8025INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
8026{
developercc5cbfb2023-06-13 18:29:52 +08008027 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08008028}
8029
8030// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
8031INT wifi_startHostApd()
8032{
8033 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8034 system("systemctl start hostapd.service");
8035 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8036 return RETURN_OK;
8037 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
8038}
8039
8040// stops hostapd
developer69b61b02023-03-07 17:17:44 +08008041INT wifi_stopHostApd()
developer72fb0bb2023-01-11 09:46:29 +08008042{
8043 char cmd[128] = {0};
8044 char buf[128] = {0};
8045
8046 sprintf(cmd,"systemctl stop hostapd");
8047 _syscmd(cmd, buf, sizeof(buf));
8048
8049 return RETURN_OK;
8050}
8051
8052// restart hostapd dummy function
8053INT wifi_restartHostApd()
8054{
8055 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8056 system("systemctl restart hostapd-global");
8057 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8058
developer72fb0bb2023-01-11 09:46:29 +08008059 return RETURN_OK;
8060}
8061
8062// sets the AP enable status variable for the specified ap.
8063INT wifi_setApEnable(INT apIndex, BOOL enable)
8064{
developer7e4a2a62023-04-06 19:56:03 +08008065 char interface_name[16] = {0};
developerb149d9d2023-06-06 16:14:22 +08008066 char config_file[MAX_SUB_CMD_SIZE] = {0};
developer7e4a2a62023-04-06 19:56:03 +08008067 char cmd[MAX_CMD_SIZE] = {0};
8068 char buf[MAX_BUF_SIZE] = {0};
developer47cc27a2023-05-17 23:09:58 +08008069 BOOL status = FALSE;
developer7e4a2a62023-04-06 19:56:03 +08008070 int max_radio_num = 0;
8071 int phyId = 0;
developer72fb0bb2023-01-11 09:46:29 +08008072
developer7e4a2a62023-04-06 19:56:03 +08008073 wifi_getApEnable(apIndex, &status);
developer72fb0bb2023-01-11 09:46:29 +08008074
developer7e4a2a62023-04-06 19:56:03 +08008075 wifi_getMaxRadioNumber(&max_radio_num);
8076 if (enable == status)
8077 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08008078
developer7e4a2a62023-04-06 19:56:03 +08008079 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8080 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08008081
developer7e4a2a62023-04-06 19:56:03 +08008082 if (enable == TRUE) {
8083 int radioIndex = apIndex % max_radio_num;
8084 phyId = radio_index_to_phy(radioIndex);
developerf3c7d292023-05-29 17:57:16 +08008085 snprintf(cmd, MAX_CMD_SIZE, "ifconfig %s up", interface_name);
8086 _syscmd(cmd, buf, sizeof(buf));
developer8a3bbbf2023-03-15 17:47:23 +08008087
developer7e4a2a62023-04-06 19:56:03 +08008088 snprintf(config_file, MAX_BUF_SIZE, "%s%d.conf", CONFIG_PREFIX, apIndex);
8089 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyId, config_file);
8090 _syscmd(cmd, buf, sizeof(buf));
8091 } else {
8092 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw REMOVE %s", interface_name);
8093 _syscmd(cmd, buf, sizeof(buf));
developerf3c7d292023-05-29 17:57:16 +08008094 snprintf(cmd, MAX_CMD_SIZE, "ifconfig %s down", interface_name);
8095 _syscmd(cmd, buf, sizeof(buf));
developer7e4a2a62023-04-06 19:56:03 +08008096 }
8097 snprintf(cmd, MAX_CMD_SIZE, "sed -i -n -e '/^%s=/!p' -e '$a%s=%d' %s",
8098 interface_name, interface_name, enable, VAP_STATUS_FILE);
8099 _syscmd(cmd, buf, sizeof(buf));
8100 //Wait for wifi up/down to apply
8101 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08008102}
8103
8104// Outputs the setting of the internal variable that is set by wifi_setApEnable().
8105INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
8106{
developer7e4a2a62023-04-06 19:56:03 +08008107 char interface_name[IF_NAME_SIZE] = {0};
8108 char cmd[MAX_CMD_SIZE] = {0};
developere740c2a2023-05-23 18:34:32 +08008109 int ret;
developer72fb0bb2023-01-11 09:46:29 +08008110
developer7e4a2a62023-04-06 19:56:03 +08008111 if ((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
8112 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08008113
developer7e4a2a62023-04-06 19:56:03 +08008114 *output_bool = 0;
developer72fb0bb2023-01-11 09:46:29 +08008115
developer7e4a2a62023-04-06 19:56:03 +08008116 if ((apIndex >= 0) && (apIndex < MAX_APS)) {
8117 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
8118 *output_bool = FALSE;
8119 return RETURN_OK;
8120 }
developere740c2a2023-05-23 18:34:32 +08008121 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status", interface_name);
8122 ret = system(cmd);
8123 if (ret == 0)
8124 *output_bool = 1;
developer7e4a2a62023-04-06 19:56:03 +08008125 }
developer72fb0bb2023-01-11 09:46:29 +08008126
developer7e4a2a62023-04-06 19:56:03 +08008127 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08008128}
8129
developer69b61b02023-03-07 17:17:44 +08008130// Outputs the AP "Enabled" "Disabled" status from driver
8131INT wifi_getApStatus(INT apIndex, CHAR *output_string)
developer72fb0bb2023-01-11 09:46:29 +08008132{
developer7e4a2a62023-04-06 19:56:03 +08008133 BOOL output_bool;
developer72fb0bb2023-01-11 09:46:29 +08008134
developer7e4a2a62023-04-06 19:56:03 +08008135 if (!output_string) {
8136 printf("%s: null pointer!", __func__);
8137 return RETURN_ERR;
8138 }
developer72fb0bb2023-01-11 09:46:29 +08008139
developer7e4a2a62023-04-06 19:56:03 +08008140 wifi_getApEnable(apIndex, &output_bool);
developer72fb0bb2023-01-11 09:46:29 +08008141
developer7e4a2a62023-04-06 19:56:03 +08008142 if(output_bool == 1)
8143 snprintf(output_string, 32, "Up");
8144 else
8145 snprintf(output_string, 32, "Disable");
8146
8147 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08008148}
8149
8150//Indicates whether or not beacons include the SSID name.
8151// outputs a 1 if SSID on the AP is enabled, else outputs 0
8152INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
8153{
8154 //get the running status
8155 char config_file[MAX_BUF_SIZE] = {0};
8156 char buf[16] = {0};
8157
8158 if (!output)
8159 return RETURN_ERR;
8160
8161 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8162 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
8163 // default is enable
8164 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
8165 *output = TRUE;
8166
8167 return RETURN_OK;
8168}
8169
8170// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
8171INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
8172{
8173 //store the config, apply instantly
8174 char config_file[MAX_BUF_SIZE] = {0};
8175 struct params list;
8176
8177 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8178 list.name = "ignore_broadcast_ssid";
8179 list.value = enable?"0":"1";
8180
8181 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8182 wifi_hostapdWrite(config_file, &list, 1);
8183 wifi_hostapdProcessUpdate(apIndex, &list, 1);
8184 //TODO: call hostapd_cli for dynamic_config_control
8185 wifi_reloadAp(apIndex);
8186 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8187
8188 return RETURN_OK;
8189}
8190
8191//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
8192INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
8193{
developer47cc27a2023-05-17 23:09:58 +08008194 /* get the running status */
8195 if(!output_uint)
8196 return RETURN_ERR;
8197
8198 *output_uint = 15;
8199 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08008200}
8201
developer47cc27a2023-05-17 23:09:58 +08008202/*Do not support AP retry limit fix*/
developer72fb0bb2023-01-11 09:46:29 +08008203INT wifi_setApRetryLimit(INT apIndex, UINT number)
8204{
developer47cc27a2023-05-17 23:09:58 +08008205 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08008206}
8207
developer95c045d2023-05-24 19:26:28 +08008208int get_wmm_cap_status_callback(struct nl_msg *msg, void *data)
8209{
8210 struct nlattr *tb[NL80211_ATTR_MAX + 1];
8211 struct nlattr *vndr_tb[MTK_NL80211_VENDOR_WMM_ATTR_MAX + 1];
8212 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
developer2f79c922023-06-02 17:33:42 +08008213 unsigned char *status = (unsigned char *)data;
developer95c045d2023-05-24 19:26:28 +08008214 int err = 0;
developer95c045d2023-05-24 19:26:28 +08008215
8216 err = nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
8217 genlmsg_attrlen(gnlh, 0), NULL);
8218 if (err < 0)
8219 return err;
8220
8221 if (tb[NL80211_ATTR_VENDOR_DATA]) {
8222 err = nla_parse_nested(vndr_tb, MTK_NL80211_VENDOR_WMM_ATTR_MAX,
8223 tb[NL80211_ATTR_VENDOR_DATA], NULL);
8224 if (err < 0)
8225 return err;
8226
8227 if (vndr_tb[MTK_NL80211_VENDOR_ATTR_WMM_AP_CAP_INFO]) {
developer95c045d2023-05-24 19:26:28 +08008228 *status = nla_get_u8(vndr_tb[MTK_NL80211_VENDOR_ATTR_WMM_AP_CAP_INFO]);
8229 }
8230 }
8231
8232 return 0;
8233}
8234
developer72fb0bb2023-01-11 09:46:29 +08008235//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
8236INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
8237{
developer95c045d2023-05-24 19:26:28 +08008238 int if_idx, ret = 0;
developer8e6583c2023-05-23 13:36:06 +08008239 char interface_name[16] = {0};
developer95c045d2023-05-24 19:26:28 +08008240 unsigned char status = 0;
8241 struct nl_msg *msg = NULL;
8242 struct nlattr * msg_data = NULL;
8243 struct mtk_nl80211_param param;
8244 struct unl unl_ins;
developer8e6583c2023-05-23 13:36:06 +08008245
8246 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08008247 if(!output)
developerdaf24792023-06-06 11:40:04 +08008248 return RETURN_ERR;
developer8e6583c2023-05-23 13:36:06 +08008249
developer95c045d2023-05-24 19:26:28 +08008250 if (apIndex > MAX_APS) {
8251 wifi_debug(DEBUG_ERROR, "Invalid apIndex %d\n", apIndex);
8252 return RETURN_ERR;
8253 }
8254
developer8e6583c2023-05-23 13:36:06 +08008255 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerdaf24792023-06-06 11:40:04 +08008256 return RETURN_ERR;
developer95c045d2023-05-24 19:26:28 +08008257
8258 if_idx = if_nametoindex(interface_name);
8259 /*init mtk nl80211 vendor cmd*/
8260 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_WMM;
8261 param.if_type = NL80211_ATTR_IFINDEX;
8262 param.if_idx = if_idx;
8263 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
8264
8265 if (ret) {
8266 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
8267 return RETURN_ERR;
8268 }
8269
8270 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_WMM_AP_CAP_INFO, 0xf)) {
8271 wifi_debug(DEBUG_ERROR, "Nla put attribute error\n");
8272 nlmsg_free(msg);
8273 goto err;
8274 }
8275
8276 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, get_wmm_cap_status_callback,
8277 (void *)&status);
8278 if (ret) {
8279 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vendor msg fails\n");
8280 goto err;
8281 }
8282 mtk_nl80211_deint(&unl_ins);
8283
8284 *output = status == 0 ? FALSE : TRUE;
8285 wifi_debug(DEBUG_NOTICE, "wmm cap (%u).\n", (unsigned int)(*output));
developer8e6583c2023-05-23 13:36:06 +08008286
8287 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08008288 return RETURN_OK;
developer95c045d2023-05-24 19:26:28 +08008289err:
8290 mtk_nl80211_deint(&unl_ins);
8291 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
8292 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08008293}
8294
8295//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
8296INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
8297{
8298 //get the running status from driver
8299 char cmd[128] = {0};
8300 char buf[128] = {0};
8301 int max_radio_num = 0, radioIndex = 0;
8302 int phyId = 0;
8303
8304 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8305
8306 wifi_getMaxRadioNumber(&max_radio_num);
8307 radioIndex = apIndex % max_radio_num;
8308 phyId = radio_index_to_phy(radioIndex);
8309 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", phyId);
8310 _syscmd(cmd,buf, sizeof(buf));
8311
8312 if (strlen(buf) > 0)
8313 *output = true;
8314
8315 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8316
8317 return RETURN_OK;
8318}
8319
8320//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
8321INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
8322{
developer95c045d2023-05-24 19:26:28 +08008323 return wifi_getApWMMCapability(apIndex, output);
developer72fb0bb2023-01-11 09:46:29 +08008324}
8325
8326// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
8327INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
8328{
developer95c045d2023-05-24 19:26:28 +08008329 int if_idx, ret = 0;
8330 char interface_name[16] = {0};
developer95c045d2023-05-24 19:26:28 +08008331 struct nl_msg *msg = NULL;
8332 struct nlattr * msg_data = NULL;
8333 struct mtk_nl80211_param param;
8334 struct unl unl_ins;
developer72fb0bb2023-01-11 09:46:29 +08008335
developer95c045d2023-05-24 19:26:28 +08008336 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08008337
developer95c045d2023-05-24 19:26:28 +08008338 if (apIndex > MAX_APS) {
8339 wifi_debug(DEBUG_ERROR, "Invalid apIndex %d\n", apIndex);
8340 return RETURN_ERR;
8341 }
developer72fb0bb2023-01-11 09:46:29 +08008342
developer95c045d2023-05-24 19:26:28 +08008343 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8344 return RETURN_ERR;
developer8e6583c2023-05-23 13:36:06 +08008345
developer95c045d2023-05-24 19:26:28 +08008346 if_idx = if_nametoindex(interface_name);
8347 /*init mtk nl80211 vendor cmd*/
8348 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_WMM;
8349 param.if_type = NL80211_ATTR_IFINDEX;
8350 param.if_idx = if_idx;
8351 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
8352
8353 if (ret) {
8354 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
8355 return RETURN_ERR;
8356 }
8357
8358 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_WMM_AP_CAP_INFO, enable ? 1 : 0)) {
8359 wifi_debug(DEBUG_ERROR, "Nla put attribute error\n");
8360 nlmsg_free(msg);
8361 goto err;
8362 }
8363
8364 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
8365 if (ret) {
8366 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vendor msg fails\n");
8367 goto err;
8368 }
8369 mtk_nl80211_deint(&unl_ins);
8370
8371 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8372 return RETURN_OK;
8373err:
8374 mtk_nl80211_deint(&unl_ins);
8375 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
8376 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08008377}
8378
developer95c045d2023-05-24 19:26:28 +08008379
developer72fb0bb2023-01-11 09:46:29 +08008380//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.
8381INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
8382{
8383 //get the running status from driver
8384 if(!output)
8385 return RETURN_ERR;
8386
8387 char config_file[128] = {0};
8388 char buf[16] = {0};
8389
8390 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8391 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
8392 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
8393 *output = TRUE;
8394 else
8395 *output = FALSE;
8396
8397 return RETURN_OK;
8398}
8399
8400// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
8401INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
8402{
8403 //save config and apply instantly.
8404 char config_file[MAX_BUF_SIZE] = {0};
8405 struct params list;
8406
8407 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8408 list.name = "uapsd_advertisement_enabled";
8409 list.value = enable?"1":"0";
8410
8411 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8412 wifi_hostapdWrite(config_file, &list, 1);
8413 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developere82c0ca2023-05-10 16:25:35 +08008414 wifi_quick_reload_ap(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08008415 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8416
8417 return RETURN_OK;
8418}
8419
8420// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
8421INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
8422{
8423 char interface_name[16] = {0};
8424 // assume class 0->BE, 1->BK, 2->VI, 3->VO
developerb149d9d2023-06-06 16:14:22 +08008425 char cmd[MAX_CMD_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08008426 char buf[128] = {0};
8427 char ack_filepath[128] = {0};
8428 uint16_t bitmap = 0;
8429 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
8430 FILE *f = NULL;
8431
8432 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
8433
8434 // Get current setting
8435 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
8436 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
8437 _syscmd(cmd, buf, sizeof(buf));
8438 if (strlen(buf) > 0)
8439 bitmap = strtoul(buf, NULL, 10);
8440
8441 bitmap = strtoul(buf, NULL, 10);
8442
8443 if (ackPolicy == TRUE) { // True, unset this class
8444 bitmap &= ~class_map[class];
8445 } else { // False, set this class
8446 bitmap |= class_map[class];
8447 }
8448
8449 f = fopen(ack_filepath, "w");
8450 if (f == NULL) {
8451 fprintf(stderr, "%s: fopen failed\n", __func__);
8452 return RETURN_ERR;
8453 }
8454 fprintf(f, "%hu", bitmap);
8455 fclose(f);
8456
8457 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8458 return RETURN_ERR;
8459 snprintf(cmd, sizeof(cmd), "iw dev %s set noack_map 0x%04x\n", interface_name, bitmap);
8460 _syscmd(cmd, buf, sizeof(buf));
8461
8462 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
8463 return RETURN_OK;
8464}
8465
8466//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.
8467INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
8468{
8469 //get the running status from driver
8470 if(!output_uint)
8471 return RETURN_ERR;
8472
8473 char output[16]={'\0'};
8474 char config_file[MAX_BUF_SIZE] = {0};
8475
8476 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8477 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
8478 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
8479 else {
8480 int device_num = atoi(output);
8481 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
8482 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
8483 return RETURN_ERR;
8484 }
8485 else {
8486 *output_uint = device_num;
8487 }
8488 }
8489
8490 return RETURN_OK;
8491}
8492
8493INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
8494{
8495 //store to wifi config, apply instantly
8496 char str[MAX_BUF_SIZE]={'\0'};
developer72fb0bb2023-01-11 09:46:29 +08008497 struct params params;
8498 char config_file[MAX_BUF_SIZE] = {0};
8499
8500 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8501 if (number > MAX_ASSOCIATED_STA_NUM) {
8502 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
8503 return RETURN_ERR;
8504 }
8505 sprintf(str, "%d", number);
8506 params.name = "max_num_sta";
8507 params.value = str;
8508
8509 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
8510 int ret = wifi_hostapdWrite(config_file, &params, 1);
8511 if (ret) {
8512 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
8513 ,__func__, ret);
8514 }
8515
8516 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
8517 if (ret) {
8518 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
8519 ,__func__, ret);
8520 }
8521 wifi_reloadAp(apIndex);
8522 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8523
8524 return RETURN_OK;
8525}
8526
8527//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.
8528INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
8529{
8530 //get the current threshold
8531 if(!output_uint)
8532 return RETURN_ERR;
8533 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
8534 if (*output_uint == 0)
8535 *output_uint = 50;
8536 return RETURN_OK;
8537}
8538
8539INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
8540{
8541 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
8542 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
8543 return RETURN_OK;
8544 return RETURN_ERR;
8545}
8546
8547//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.
8548INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
8549{
8550 if(!output_uint)
8551 return RETURN_ERR;
8552 *output_uint = 3;
8553 return RETURN_OK;
8554}
8555
8556//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
8557INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
8558{
8559 if(!output_uint)
8560 return RETURN_ERR;
8561 *output_uint = 3;
8562 return RETURN_OK;
8563}
8564
8565//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.
8566INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
8567{
8568 if(!output_in_seconds)
8569 return RETURN_ERR;
8570 *output_in_seconds = 0;
8571 return RETURN_OK;
8572}
8573
8574//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
8575INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
8576{
8577 if(!output || apIndex>=MAX_APS)
8578 return RETURN_ERR;
8579 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
8580 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
8581 return RETURN_OK;
developer69b61b02023-03-07 17:17:44 +08008582}
developer72fb0bb2023-01-11 09:46:29 +08008583
8584//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
8585INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
8586{
8587 char config_file[128] = {0};
8588 char wpa[16] = {0};
8589 char key_mgmt[64] = {0};
developer72fb0bb2023-01-11 09:46:29 +08008590 if (!output)
8591 return RETURN_ERR;
8592
8593 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8594 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
8595
8596 strcpy(output, "None");//Copying "None" to output string for default case
8597 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
8598 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
8599 if (!strcmp(wpa, "1"))
8600 snprintf(output, 32, "WPA-Personal");
8601 else if (!strcmp(wpa, "2"))
8602 snprintf(output, 32, "WPA2-Personal");
8603 else if (!strcmp(wpa, "3"))
8604 snprintf(output, 32, "WPA-WPA2-Personal");
8605
developere5750452023-05-15 16:46:42 +08008606 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
8607 snprintf(output, 32, "WPA3-Enterprise");
developer72fb0bb2023-01-11 09:46:29 +08008608 } else if (strstr(key_mgmt, "WPA-EAP")) {
8609 if (!strcmp(wpa, "1"))
8610 snprintf(output, 32, "WPA-Enterprise");
8611 else if (!strcmp(wpa, "2"))
8612 snprintf(output, 32, "WPA2-Enterprise");
8613 else if (!strcmp(wpa, "3"))
8614 snprintf(output, 32, "WPA-WPA2-Enterprise");
8615 } else if (strstr(key_mgmt, "SAE")) {
8616 if (strstr(key_mgmt, "WPA-PSK") == NULL)
8617 snprintf(output, 32, "WPA3-Personal");
8618 else
8619 snprintf(output, 32, "WPA3-Personal-Transition");
developer72fb0bb2023-01-11 09:46:29 +08008620 }
8621
8622 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
8623 return RETURN_OK;
8624#if 0
8625 //TODO: need to revisit below implementation
8626 char securityType[32], authMode[32];
8627 int enterpriseMode=0;
8628
8629 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8630 if(!output)
8631 return RETURN_ERR;
8632
8633 wifi_getApBeaconType(apIndex, securityType);
8634 strcpy(output,"None");//By default, copying "None" to output string
8635 if (strncmp(securityType,"None", strlen("None")) == 0)
8636 return RETURN_OK;
8637
8638 wifi_getApBasicAuthenticationMode(apIndex, authMode);
8639 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
8640
8641 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
8642 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
8643 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
8644 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
8645 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
8646 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
8647 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8648
8649 return RETURN_OK;
8650#endif
8651}
developer69b61b02023-03-07 17:17:44 +08008652
developer72fb0bb2023-01-11 09:46:29 +08008653INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
8654{
8655 char securityType[32];
8656 char authMode[32];
8657
8658 //store settings and wait for wifi up to apply
8659 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8660 if(!encMode)
8661 return RETURN_ERR;
8662
8663 if (strcmp(encMode, "None")==0)
8664 {
8665 strcpy(securityType,"None");
8666 strcpy(authMode,"None");
8667 }
8668 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
8669 {
8670 strcpy(securityType,"WPAand11i");
8671 strcpy(authMode,"PSKAuthentication");
8672 }
8673 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
8674 {
8675 strcpy(securityType,"WPAand11i");
8676 strcpy(authMode,"EAPAuthentication");
8677 }
8678 else if (strcmp(encMode, "WPA-Personal")==0)
8679 {
8680 strcpy(securityType,"WPA");
8681 strcpy(authMode,"PSKAuthentication");
8682 }
8683 else if (strcmp(encMode, "WPA-Enterprise")==0)
8684 {
8685 strcpy(securityType,"WPA");
8686 strcpy(authMode,"EAPAuthentication");
8687 }
8688 else if (strcmp(encMode, "WPA2-Personal")==0)
8689 {
8690 strcpy(securityType,"11i");
8691 strcpy(authMode,"PSKAuthentication");
8692 }
8693 else if (strcmp(encMode, "WPA2-Enterprise")==0)
8694 {
8695 strcpy(securityType,"11i");
8696 strcpy(authMode,"EAPAuthentication");
8697 }
8698 else if (strcmp(encMode, "WPA3-Personal") == 0)
8699 {
8700 strcpy(securityType,"11i");
8701 strcpy(authMode,"SAEAuthentication");
8702 }
8703 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
8704 {
8705 strcpy(securityType, "11i");
8706 strcpy(authMode, "PSK-SAEAuthentication");
8707 }
8708 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
8709 {
8710 strcpy(securityType,"11i");
8711 strcpy(authMode,"EAP_192-bit_Authentication");
8712 }
developer3086e2f2023-01-17 09:40:01 +08008713 else if (strcmp(encMode, "OWE") == 0)
8714 {
8715 strcpy(securityType,"11i");
8716 strcpy(authMode,"Enhanced_Open");
8717 }
developer72fb0bb2023-01-11 09:46:29 +08008718 else
8719 {
8720 strcpy(securityType,"None");
8721 strcpy(authMode,"None");
8722 }
8723 wifi_setApBeaconType(apIndex, securityType);
8724 wifi_setApBasicAuthenticationMode(apIndex, authMode);
8725 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8726
8727 return RETURN_OK;
developer69b61b02023-03-07 17:17:44 +08008728}
developer72fb0bb2023-01-11 09:46:29 +08008729
8730
8731//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
8732// output_string must be pre-allocated as 64 character string by caller
8733// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
8734INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
8735{
8736 char buf[16] = {0};
8737 char config_file[MAX_BUF_SIZE] = {0};
8738
8739 if(output_string==NULL)
8740 return RETURN_ERR;
8741
8742 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8743 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
8744
8745 if(strcmp(buf,"0")==0)
8746 {
8747 printf("wpa_mode is %s ......... \n",buf);
8748 return RETURN_ERR;
8749 }
8750
8751 wifi_dbg_printf("\nFunc=%s\n",__func__);
8752 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developere5750452023-05-15 16:46:42 +08008753 wifi_hostapdRead(config_file,"wpa_psk",output_string,65);
developer72fb0bb2023-01-11 09:46:29 +08008754 wifi_dbg_printf("\noutput_string=%s\n",output_string);
8755
8756 return RETURN_OK;
8757}
8758
8759// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
8760// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
8761INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
8762{
8763 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
8764 struct params params={'\0'};
8765 int ret;
8766 char config_file[MAX_BUF_SIZE] = {0};
8767
8768 if(NULL == preSharedKey)
8769 return RETURN_ERR;
8770
developere5750452023-05-15 16:46:42 +08008771 params.name = "wpa_psk";
developer72fb0bb2023-01-11 09:46:29 +08008772
developere5750452023-05-15 16:46:42 +08008773 if(strlen(preSharedKey) != 64)
developer72fb0bb2023-01-11 09:46:29 +08008774 {
developere5750452023-05-15 16:46:42 +08008775 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 64 chars\n");
developer72fb0bb2023-01-11 09:46:29 +08008776 return RETURN_ERR;
8777 }
8778 params.value = preSharedKey;
8779 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8780 ret = wifi_hostapdWrite(config_file, &params, 1);
developere5750452023-05-15 16:46:42 +08008781 if(!ret) {
developer72fb0bb2023-01-11 09:46:29 +08008782 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
developere5750452023-05-15 16:46:42 +08008783 wifi_reloadAp(apIndex);
8784 }
developer72fb0bb2023-01-11 09:46:29 +08008785 return ret;
8786 //TODO: call hostapd_cli for dynamic_config_control
8787}
8788
8789//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
8790// outputs the passphrase, maximum 63 characters
8791INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
8792{
8793 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
8794
8795 wifi_dbg_printf("\nFunc=%s\n",__func__);
8796 if (NULL == output_string)
8797 return RETURN_ERR;
8798
8799 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8800 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
8801 if(strcmp(buf,"0")==0)
8802 {
8803 printf("wpa_mode is %s ......... \n",buf);
8804 return RETURN_ERR;
8805 }
8806
8807 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
8808 wifi_dbg_printf("\noutput_string=%s\n",output_string);
8809
8810 return RETURN_OK;
8811}
8812
8813// sets the passphrase enviornment variable, max 63 characters
8814INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
8815{
8816 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
8817 struct params params={'\0'};
8818 char config_file[MAX_BUF_SIZE] = {0};
8819 int ret;
8820
8821 if(NULL == passPhrase)
8822 return RETURN_ERR;
8823
8824 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
8825 {
8826 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
8827 return RETURN_ERR;
8828 }
8829 params.name = "wpa_passphrase";
8830 params.value = passPhrase;
8831 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8832 ret=wifi_hostapdWrite(config_file,&params,1);
developere5750452023-05-15 16:46:42 +08008833 if(!ret) {
developer72fb0bb2023-01-11 09:46:29 +08008834 wifi_hostapdProcessUpdate(apIndex, &params, 1);
developere5750452023-05-15 16:46:42 +08008835 wifi_reloadAp(apIndex);
8836 }
developer72fb0bb2023-01-11 09:46:29 +08008837
8838 return ret;
8839}
8840
8841//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.
8842INT wifi_setApSecurityReset(INT apIndex)
8843{
8844 char original_config_file[64] = {0};
8845 char current_config_file[64] = {0};
8846 char buf[64] = {0};
8847 char cmd[64] = {0};
8848 char wpa[4] = {0};
8849 char wpa_psk[64] = {0};
8850 char wpa_passphrase[64] = {0};
8851 char wpa_psk_file[128] = {0};
8852 char wpa_key_mgmt[64] = {0};
8853 char wpa_pairwise[32] = {0};
8854 wifi_band band;
8855 struct params list[6];
8856
8857 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8858
8859 band = wifi_index_to_band(apIndex);
8860 if (band == band_2_4)
8861 sprintf(original_config_file, "/etc/hostapd-2G.conf");
8862 else if (band == band_5)
8863 sprintf(original_config_file, "/etc/hostapd-5G.conf");
8864 else if (band == band_6)
8865 sprintf(original_config_file, "/etc/hostapd-6G.conf");
8866 else
8867 return RETURN_ERR;
8868
8869 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
8870 list[0].name = "wpa";
8871 list[0].value = wpa;
developer69b61b02023-03-07 17:17:44 +08008872
developer72fb0bb2023-01-11 09:46:29 +08008873 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
8874 list[1].name = "wpa_psk";
8875 list[1].value = wpa_psk;
8876
8877 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
8878 list[2].name = "wpa_passphrase";
8879 list[2].value = wpa_passphrase;
8880
8881 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
8882
8883 if (strlen(wpa_psk_file) == 0)
8884 strcpy(wpa_psk_file, PSK_FILE);
8885
8886 if (access(wpa_psk_file, F_OK) != 0) {
developerdaf24792023-06-06 11:40:04 +08008887 snprintf(cmd, MAX_CMD_SIZE, "touch %s", wpa_psk_file);
developer72fb0bb2023-01-11 09:46:29 +08008888 _syscmd(cmd, buf, sizeof(buf));
8889 }
8890 list[3].name = "wpa_psk_file";
8891 list[3].value = wpa_psk_file;
8892
8893 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
8894 list[4].name = "wpa_key_mgmt";
8895 list[4].value = wpa_key_mgmt;
8896
8897 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
8898 list[5].name = "wpa_pairwise";
8899 list[5].value = wpa_pairwise;
8900
8901 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8902 wifi_hostapdWrite(current_config_file, list, 6);
8903
8904 wifi_setApEnable(apIndex, FALSE);
8905 wifi_setApEnable(apIndex, TRUE);
8906
8907 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8908 return RETURN_OK;
8909}
8910
8911//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).
8912INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
8913{
8914 char config_file[64] = {0};
8915 char buf[64] = {0};
8916 char cmd[256] = {0};
8917
8918 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8919
8920 if(!IP_output || !Port_output || !RadiusSecret_output)
8921 return RETURN_ERR;
8922
8923 // Read the first matched config
8924 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
8925 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
8926 _syscmd(cmd, buf, sizeof(buf));
8927 strncpy(IP_output, buf, 64);
8928
8929 memset(buf, 0, sizeof(buf));
8930 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
8931 _syscmd(cmd, buf, sizeof(buf));
8932 *Port_output = atoi(buf);
8933
8934 memset(buf, 0, sizeof(buf));
8935 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
8936 _syscmd(cmd, buf, sizeof(buf));
8937 strncpy(RadiusSecret_output, buf, 64);
8938
8939 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8940 return RETURN_OK;
8941}
8942
8943INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
8944{
8945 char config_file[64] = {0};
8946 char port_str[8] = {0};
8947 char cmd[256] = {0};
8948 char buf[128] = {0};
8949
8950 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8951
developere5750452023-05-15 16:46:42 +08008952 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
8953 return RETURN_ERR;
8954
8955 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
8956 return RETURN_ERR;
8957
developer72fb0bb2023-01-11 09:46:29 +08008958 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
8959
8960 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
8961 _syscmd(cmd, buf, sizeof(buf));
8962 memset(cmd, 0, sizeof(cmd));
8963
8964 snprintf(port_str, sizeof(port_str), "%d", port);
8965 if (strlen(buf) == 0)
8966 // Append
8967 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
8968 "auth_server_addr=%s\\n"
8969 "auth_server_port=%s\\n"
8970 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
8971 else {
8972 // Delete the three lines setting after the "# radius 1" comment
8973 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
8974 _syscmd(cmd, buf, sizeof(buf));
8975 memset(cmd, 0, sizeof(cmd));
8976 // Use "# radius 1" comment to find the location to insert the radius setting
8977 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
8978 "# radius 1\\n"
8979 "auth_server_addr=%s\\n"
8980 "auth_server_port=%s\\n"
8981 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
8982 }
8983 if(_syscmd(cmd, buf, sizeof(buf))) {
8984 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
8985 return RETURN_ERR;
8986 }
8987
8988 wifi_reloadAp(apIndex);
8989 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8990 return RETURN_OK;
8991}
8992
8993INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
8994{
8995 char config_file[64] = {0};
8996 char buf[64] = {0};
8997 char cmd[256] = {0};
8998
8999 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9000
9001 if(!IP_output || !Port_output || !RadiusSecret_output)
9002 return RETURN_ERR;
9003
9004 // Read the second matched config
9005 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9006 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
9007 _syscmd(cmd, buf, sizeof(buf));
9008 strncpy(IP_output, buf, 64);
9009
9010 memset(buf, 0, sizeof(buf));
9011 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
9012 _syscmd(cmd, buf, sizeof(buf));
9013 *Port_output = atoi(buf);
9014
9015 memset(buf, 0, sizeof(buf));
9016 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
9017 _syscmd(cmd, buf, sizeof(buf));
9018 strncpy(RadiusSecret_output, buf, 64);
9019
9020 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9021 return RETURN_OK;
9022}
9023
9024INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
9025{
9026 char config_file[64] = {0};
9027 char port_str[8] = {0};
9028 char cmd[256] = {0};
9029 char buf[128] = {0};
9030
9031 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9032
developere5750452023-05-15 16:46:42 +08009033 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
9034 return RETURN_ERR;
9035
9036 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
9037 return RETURN_ERR;
9038
developer72fb0bb2023-01-11 09:46:29 +08009039 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9040
9041 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
9042 _syscmd(cmd, buf, sizeof(buf));
9043 memset(cmd, 0, sizeof(cmd));
9044
9045 snprintf(port_str, sizeof(port_str), "%d", port);
9046 if (strlen(buf) == 0)
9047 // Append
9048 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
9049 "auth_server_addr=%s\\n"
9050 "auth_server_port=%s\\n"
9051 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
9052 else {
9053 // Delete the three lines setting after the "# radius 2" comment
9054 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
9055 _syscmd(cmd, buf, sizeof(buf));
9056 memset(cmd, 0, sizeof(cmd));
9057 // Use "# radius 2" comment to find the location to insert the radius setting
9058 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
9059 "# radius 2\\n"
9060 "auth_server_addr=%s\\n"
9061 "auth_server_port=%s\\n"
9062 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
9063 }
9064 if(_syscmd(cmd, buf, sizeof(buf))) {
9065 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
9066 return RETURN_ERR;
9067 }
9068
9069 wifi_reloadAp(apIndex);
9070 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9071 return RETURN_OK;
9072}
9073
9074//RadiusSettings
9075INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
9076{
9077 if(!output)
9078 return RETURN_ERR;
9079
9080 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
developer69b61b02023-03-07 17:17:44 +08009081 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
9082 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
9083 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
9084 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 +08009085 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 +08009086 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
9087 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
9088 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 +08009089 //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.
9090
9091 return RETURN_OK;
9092}
9093
9094INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
9095{
9096 //store the paramters, and apply instantly
9097 return RETURN_ERR;
9098}
9099
9100//Device.WiFi.AccessPoint.{i}.WPS.Enable
9101//Enables or disables WPS functionality for this access point.
9102// outputs the WPS enable state of this ap in output_bool
9103INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
9104{
9105 char interface_name[16] = {0};
developer2f79c922023-06-02 17:33:42 +08009106 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08009107 if(!output_bool)
9108 return RETURN_ERR;
9109 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9110 return RETURN_ERR;
9111 sprintf(cmd,"hostapd_cli -i %s get_config | grep wps_state | cut -d '=' -f2", interface_name);
9112 _syscmd(cmd, buf, sizeof(buf));
9113 if(strstr(buf, "configured"))
9114 *output_bool=TRUE;
9115 else
9116 *output_bool=FALSE;
9117
9118 return RETURN_OK;
developer69b61b02023-03-07 17:17:44 +08009119}
developer72fb0bb2023-01-11 09:46:29 +08009120
9121//Device.WiFi.AccessPoint.{i}.WPS.Enable
9122// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
9123INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
9124{
9125 char config_file[MAX_BUF_SIZE] = {0};
developere5750452023-05-15 16:46:42 +08009126 char buf[128] = {0};
developer72fb0bb2023-01-11 09:46:29 +08009127 struct params params;
9128
9129 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9130 //store the paramters, and wait for wifi up to apply
9131 params.name = "wps_state";
developere5750452023-05-15 16:46:42 +08009132 if (enable == TRUE) {
9133 wifi_getApBeaconType(apIndex, buf);
9134 if (strncmp(buf, "None", 4) == 0) // If ap didn't set encryption
9135 params.value = "1";
9136 else // If ap set encryption
9137 params.value = "2";
9138 } else {
9139 params.value = "0";
9140 }
developer72fb0bb2023-01-11 09:46:29 +08009141
9142 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9143 wifi_hostapdWrite(config_file, &params, 1);
9144 wifi_hostapdProcessUpdate(apIndex, &params, 1);
9145 wifi_reloadAp(apIndex);
9146
9147 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9148 return RETURN_OK;
9149}
9150
9151//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
9152INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
9153{
9154 if(!output)
9155 return RETURN_ERR;
9156 snprintf(output, 128, "PushButton,PIN");
9157 return RETURN_OK;
9158}
9159
9160//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
9161//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.
9162// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
9163INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
9164{
9165 if(!output)
9166 return RETURN_ERR;
9167 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
9168
9169 return RETURN_OK;
9170}
9171
9172//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
9173// 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
9174INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
9175{
9176 //apply instantly. No setting need to be stored.
9177 char methods[MAX_BUF_SIZE], *token, *next_token;
9178 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
9179 struct params params;
9180
9181 if(!methodString)
9182 return RETURN_ERR;
9183 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9184 //store the paramters, and wait for wifi up to apply
9185
9186 snprintf(methods, sizeof(methods), "%s", methodString);
9187 for(token=methods; *token; token=next_token)
9188 {
9189 strtok_r(token, ",", &next_token);
9190 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
9191 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
9192 else if(*token=='E')
9193 {
9194 if(!strcmp(methods, "Ethernet"))
9195 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
9196 else if(!strcmp(methods, "ExternalNFCToken"))
9197 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
9198 else
9199 printf("%s: Unknown WpsConfigMethod\n", __func__);
9200 }
9201 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
9202 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
9203 else if(*token=='N' && !strcmp(token, "NFCInterface"))
9204 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
9205 else if(*token=='P' )
9206 {
9207 if(!strcmp(token, "PushButton"))
developere5750452023-05-15 16:46:42 +08009208 snprintf(config_methods, sizeof(config_methods), "%s ", "push_button");
developer72fb0bb2023-01-11 09:46:29 +08009209 else if(!strcmp(token, "PIN"))
9210 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
9211 else
9212 printf("%s: Unknown WpsConfigMethod\n", __func__);
9213 }
9214 else
9215 printf("%s: Unknown WpsConfigMethod\n", __func__);
9216 }
9217 params.name = "config_methods";
9218 params.value = config_methods;
9219 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9220 wifi_hostapdWrite(config_file, &params, 1);
9221 wifi_hostapdProcessUpdate(apIndex, &params, 1);
9222 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9223
9224 return RETURN_OK;
9225}
9226
9227// outputs the pin value, ulong_pin must be allocated by the caller
9228INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
9229{
9230 char buf[MAX_BUF_SIZE] = {0};
9231 char cmd[MAX_CMD_SIZE] = {0};
9232
9233 if(!output_ulong)
9234 return RETURN_ERR;
9235 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
9236 _syscmd(cmd, buf, sizeof(buf));
9237 if(strlen(buf) > 0)
9238 *output_ulong=strtoul(buf, NULL, 10);
9239
9240 return RETURN_OK;
9241}
9242
9243// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
9244INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
9245{
9246 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
9247 char ap_pin[16] = {0};
developer72fb0bb2023-01-11 09:46:29 +08009248 char config_file[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08009249 struct params params;
9250
9251 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9252 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
9253 params.name = "ap_pin";
9254 params.value = ap_pin;
9255 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9256 wifi_hostapdWrite(config_file, &params, 1);
9257 wifi_hostapdProcessUpdate(apIndex, &params, 1);
9258 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9259
9260 return RETURN_OK;
9261}
9262
9263// Output string is either Not configured or Configured, max 32 characters
9264INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
9265{
9266 char interface_name[16] = {0};
9267 char cmd[MAX_CMD_SIZE];
9268 char buf[MAX_BUF_SIZE]={0};
9269
9270 if(!output_string)
9271 return RETURN_ERR;
9272 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9273 snprintf(output_string, 32, "Not configured");
9274 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9275 return RETURN_ERR;
9276 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep wps_state | cut -d'=' -f2", interface_name);
9277 _syscmd(cmd, buf, sizeof(buf));
9278
9279 if(!strncmp(buf, "configured", 10))
9280 snprintf(output_string, 32, "Configured");
9281 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9282
9283 return RETURN_OK;
9284}
9285
9286// sets the WPS pin for this AP
9287INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
9288{
9289 char interface_name[16] = {0};
9290 char cmd[MAX_CMD_SIZE];
9291 char buf[MAX_BUF_SIZE]={0};
9292 BOOL enable;
9293
9294 wifi_getApEnable(apIndex, &enable);
9295 if (!enable)
9296 return RETURN_ERR;
9297 wifi_getApWpsEnable(apIndex, &enable);
9298 if (!enable)
9299 return RETURN_ERR;
9300
9301 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9302 return RETURN_ERR;
9303 snprintf(cmd, 64, "hostapd_cli -i%s wps_pin any %s", interface_name, pin);
9304 _syscmd(cmd, buf, sizeof(buf));
9305 if((strstr(buf, "OK"))!=NULL)
9306 return RETURN_OK;
9307
9308 return RETURN_ERR;
9309}
9310
9311// This function is called when the WPS push button has been pressed for this AP
9312INT wifi_setApWpsButtonPush(INT apIndex)
9313{
9314 char cmd[MAX_CMD_SIZE];
9315 char buf[MAX_BUF_SIZE]={0};
9316 char interface_name[16] = {0};
9317 BOOL enable=FALSE;
9318
9319 wifi_getApEnable(apIndex, &enable);
9320 if (!enable)
9321 return RETURN_ERR;
9322
9323 wifi_getApWpsEnable(apIndex, &enable);
9324 if (!enable)
9325 return RETURN_ERR;
9326
9327 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9328 return RETURN_ERR;
9329
9330 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel; hostapd_cli -i%s wps_pbc", interface_name, interface_name);
9331 _syscmd(cmd, buf, sizeof(buf));
9332
9333 if((strstr(buf, "OK"))!=NULL)
9334 return RETURN_OK;
9335 return RETURN_ERR;
9336}
9337
9338// cancels WPS mode for this AP
9339INT wifi_cancelApWPS(INT apIndex)
9340{
9341 char interface_name[16] = {0};
9342 char cmd[MAX_CMD_SIZE];
9343 char buf[MAX_BUF_SIZE]={0};
9344
9345 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9346 return RETURN_ERR;
9347 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel", interface_name);
9348 _syscmd(cmd,buf, sizeof(buf));
9349
9350 if((strstr(buf, "OK"))!=NULL)
9351 return RETURN_OK;
9352 return RETURN_ERR;
9353}
9354
9355//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
9356//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
9357INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
9358{
9359 char interface_name[16] = {0};
9360 FILE *f = NULL;
developer2f79c922023-06-02 17:33:42 +08009361 int read_flag=0, auth_temp=0, mac_temp=0;
developer72fb0bb2023-01-11 09:46:29 +08009362 char cmd[256] = {0}, buf[2048] = {0};
9363 char *param = NULL, *value = NULL, *line=NULL;
9364 size_t len = 0;
developer72fb0bb2023-01-11 09:46:29 +08009365 wifi_associated_dev_t *dev=NULL;
9366
9367 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9368 *associated_dev_array = NULL;
9369 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9370 return RETURN_ERR;
9371 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
9372 _syscmd(cmd,buf,sizeof(buf));
9373 *output_array_size = atoi(buf);
9374
9375 if (*output_array_size <= 0)
9376 return RETURN_OK;
9377
9378 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
9379 *associated_dev_array = dev;
9380 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt" , interface_name);
9381 _syscmd(cmd,buf,sizeof(buf));
9382 f = fopen("/tmp/connected_devices.txt", "r");
9383 if (f==NULL)
9384 {
9385 *output_array_size=0;
9386 return RETURN_ERR;
9387 }
9388 while ((getline(&line, &len, f)) != -1)
9389 {
9390 param = strtok(line,"=");
9391 value = strtok(NULL,"=");
9392
9393 if( strcmp("flags",param) == 0 )
9394 {
9395 value[strlen(value)-1]='\0';
9396 if(strstr (value,"AUTHORIZED") != NULL )
9397 {
9398 dev[auth_temp].cli_AuthenticationState = 1;
9399 dev[auth_temp].cli_Active = 1;
9400 auth_temp++;
9401 read_flag=1;
9402 }
9403 }
9404 if(read_flag==1)
9405 {
9406 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
9407 {
9408 value[strlen(value)-1]='\0';
9409 sscanf(value, "%x:%x:%x:%x:%x:%x",
9410 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
9411 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
9412 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
9413 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
9414 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
9415 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
9416 mac_temp++;
9417 read_flag=0;
9418 }
9419 }
9420 }
9421 *output_array_size = auth_temp;
9422 auth_temp=0;
9423 mac_temp=0;
9424 free(line);
9425 fclose(f);
9426 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9427 return RETURN_OK;
9428}
9429
9430#define MACADDRESS_SIZE 6
9431
9432INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
9433{
9434 FILE *fp = NULL;
9435 char str[MAX_BUF_SIZE] = {0};
9436 int wificlientindex = 0 ;
9437 int count = 0;
9438 int signalstrength = 0;
9439 int arr[MACADDRESS_SIZE] = {0};
9440 unsigned char mac[MACADDRESS_SIZE] = {0};
9441 UINT wifi_count = 0;
developer72fb0bb2023-01-11 09:46:29 +08009442 char pipeCmd[MAX_CMD_SIZE] = {0};
9443
9444 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9445 *output_array_size = 0;
9446 *associated_dev_array = NULL;
9447
9448 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
9449 fp = popen(pipeCmd, "r");
developer69b61b02023-03-07 17:17:44 +08009450 if (fp == NULL)
developer72fb0bb2023-01-11 09:46:29 +08009451 {
9452 printf("Failed to run command inside function %s\n",__FUNCTION__ );
9453 return RETURN_ERR;
9454 }
9455
9456 /* Read the output a line at a time - output it. */
9457 fgets(str, sizeof(str)-1, fp);
9458 wifi_count = (unsigned int) atoi ( str );
9459 *output_array_size = wifi_count;
9460 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
9461 pclose(fp);
9462
9463 if(wifi_count == 0)
9464 {
9465 return RETURN_OK;
9466 }
9467 else
9468 {
9469 wifi_associated_dev3_t* temp = NULL;
9470 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
9471 if(temp == NULL)
9472 {
9473 printf("Error Statement. Insufficient memory \n");
9474 return RETURN_ERR;
9475 }
9476
9477 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
9478 system(pipeCmd);
9479 memset(pipeCmd,0,sizeof(pipeCmd));
9480 if(apIndex == 0)
9481 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
9482 else if(apIndex == 1)
9483 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
9484 system(pipeCmd);
9485
9486 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
9487 if(fp == NULL)
9488 {
9489 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
9490 free(temp);
9491 return RETURN_ERR;
9492 }
9493 fclose(fp);
9494
9495 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
9496 fp = popen(pipeCmd, "r");
9497 if(fp)
9498 {
9499 for(count =0 ; count < wifi_count; count++)
9500 {
9501 fgets(str, MAX_BUF_SIZE, fp);
9502 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
9503 {
9504 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
9505 {
9506 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
9507
9508 }
9509 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
9510 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]);
9511 }
9512 temp[count].cli_AuthenticationState = 1; //TODO
9513 temp[count].cli_Active = 1; //TODO
9514 }
9515 pclose(fp);
9516 }
9517
9518 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt");
9519 fp = popen(pipeCmd, "r");
9520 if(fp)
developer69b61b02023-03-07 17:17:44 +08009521 {
developer72fb0bb2023-01-11 09:46:29 +08009522 pclose(fp);
9523 }
9524 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
9525 if(fp)
9526 {
9527 for(count =0 ; count < wifi_count ;count++)
9528 {
9529 fgets(str, MAX_BUF_SIZE, fp);
9530 signalstrength = atoi(str);
9531 temp[count].cli_SignalStrength = signalstrength;
9532 temp[count].cli_RSSI = signalstrength;
9533 temp[count].cli_SNR = signalstrength + 95;
9534 }
9535 pclose(fp);
9536 }
9537
9538
9539 if((apIndex == 0) || (apIndex == 4))
9540 {
9541 for(count =0 ; count < wifi_count ;count++)
developer69b61b02023-03-07 17:17:44 +08009542 {
developer72fb0bb2023-01-11 09:46:29 +08009543 strcpy(temp[count].cli_OperatingStandard,"g");
9544 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
9545 }
9546
9547 //BytesSent
9548 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt");
9549 fp = popen(pipeCmd, "r");
9550 if(fp)
developer69b61b02023-03-07 17:17:44 +08009551 {
developer72fb0bb2023-01-11 09:46:29 +08009552 pclose(fp);
9553 }
9554 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
9555 if(fp)
9556 {
9557 for (count = 0; count < wifi_count; count++)
9558 {
9559 fgets(str, MAX_BUF_SIZE, fp);
9560 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
9561 }
9562 pclose(fp);
9563 }
9564
9565 //BytesReceived
9566 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt");
9567 fp = popen(pipeCmd, "r");
9568 if (fp)
9569 {
9570 pclose(fp);
9571 }
9572 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
9573 if (fp)
9574 {
9575 for (count = 0; count < wifi_count; count++)
9576 {
9577 fgets(str, MAX_BUF_SIZE, fp);
9578 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
9579 }
9580 pclose(fp);
9581 }
9582
9583 //PacketsSent
9584 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt");
9585 fp = popen(pipeCmd, "r");
9586 if (fp)
9587 {
9588 pclose(fp);
9589 }
9590
9591 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
9592 if (fp)
9593 {
9594 for (count = 0; count < wifi_count; count++)
9595 {
9596 fgets(str, MAX_BUF_SIZE, fp);
9597 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
9598 }
9599 pclose(fp);
9600 }
9601
9602 //PacketsReceived
9603 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt");
9604 fp = popen(pipeCmd, "r");
9605 if (fp)
9606 {
9607 pclose(fp);
9608 }
9609 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
9610 if (fp)
9611 {
9612 for (count = 0; count < wifi_count; count++)
9613 {
9614 fgets(str, MAX_BUF_SIZE, fp);
9615 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
9616 }
9617 pclose(fp);
9618 }
9619
9620 //ErrorsSent
9621 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt");
9622 fp = popen(pipeCmd, "r");
9623 if (fp)
9624 {
9625 pclose(fp);
9626 }
9627 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
9628 if (fp)
9629 {
9630 for (count = 0; count < wifi_count; count++)
9631 {
9632 fgets(str, MAX_BUF_SIZE, fp);
9633 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
9634 }
9635 pclose(fp);
9636 }
9637
9638 //ErrorsSent
9639 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt");
9640 fp = popen(pipeCmd, "r");
9641 if (fp)
9642 {
9643 pclose(fp);
9644 }
9645 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
9646 if (fp)
9647 {
9648 for (count = 0; count < wifi_count; count++)
9649 {
9650 fgets(str, MAX_BUF_SIZE, fp);
9651 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
9652 }
9653 pclose(fp);
9654 }
9655
9656 //LastDataDownlinkRate
9657 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt");
9658 fp = popen(pipeCmd, "r");
9659 if (fp)
9660 {
9661 pclose(fp);
9662 }
9663 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
9664 if (fp)
9665 {
9666 for (count = 0; count < wifi_count; count++)
9667 {
9668 fgets(str, MAX_BUF_SIZE, fp);
9669 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
9670 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
9671 }
9672 pclose(fp);
9673 }
9674
9675 //LastDataUplinkRate
9676 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt");
9677 fp = popen(pipeCmd, "r");
9678 if (fp)
9679 {
9680 pclose(fp);
9681 }
9682 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
9683 if (fp)
9684 {
9685 for (count = 0; count < wifi_count; count++)
9686 {
9687 fgets(str, MAX_BUF_SIZE, fp);
9688 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
9689 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
9690 }
9691 pclose(fp);
9692 }
9693
9694 }
9695 else if ((apIndex == 1) || (apIndex == 5))
9696 {
9697 for (count = 0; count < wifi_count; count++)
9698 {
9699 strcpy(temp[count].cli_OperatingStandard, "a");
9700 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
9701 temp[count].cli_BytesSent = 0;
9702 temp[count].cli_BytesReceived = 0;
9703 temp[count].cli_LastDataUplinkRate = 0;
9704 temp[count].cli_LastDataDownlinkRate = 0;
9705 temp[count].cli_PacketsSent = 0;
9706 temp[count].cli_PacketsReceived = 0;
9707 temp[count].cli_ErrorsSent = 0;
9708 }
9709 }
9710
9711 for (count = 0; count < wifi_count; count++)
9712 {
9713 temp[count].cli_Retransmissions = 0;
9714 temp[count].cli_DataFramesSentAck = 0;
9715 temp[count].cli_DataFramesSentNoAck = 0;
9716 temp[count].cli_MinRSSI = 0;
9717 temp[count].cli_MaxRSSI = 0;
9718 strncpy(temp[count].cli_InterferenceSources, "", 64);
9719 memset(temp[count].cli_IPAddress, 0, 64);
9720 temp[count].cli_RetransCount = 0;
9721 temp[count].cli_FailedRetransCount = 0;
9722 temp[count].cli_RetryCount = 0;
9723 temp[count].cli_MultipleRetryCount = 0;
9724 }
9725 *associated_dev_array = temp;
9726 }
9727 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9728 return RETURN_OK;
9729}
9730
developer7e4a2a62023-04-06 19:56:03 +08009731int wifihal_interfacestatus(CHAR *wifi_status, CHAR *interface_name)
developer72fb0bb2023-01-11 09:46:29 +08009732{
developer7e4a2a62023-04-06 19:56:03 +08009733 char cmd[MAX_CMD_SIZE] = {0};
9734 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08009735
developer7e4a2a62023-04-06 19:56:03 +08009736 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
9737
9738 snprintf(cmd, MAX_CMD_SIZE, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4 | tr -d '\\n'",
9739 interface_name);
9740 _syscmd(cmd, buf, MAX_BUF_SIZE);
9741
9742 strcpy(wifi_status, buf); /* TBD: check wifi_status mem lenth and replace with strcpy later */
9743
9744 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08009745 return RETURN_OK;
9746}
9747
9748/* #define HOSTAPD_STA_PARAM_ENTRIES 29
9749struct hostapd_sta_param {
9750 char key[50];
9751 char value[100];
9752}
9753
9754static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
9755 int i = 0;
9756
9757 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
9758 if (strncmp(params[i].key,key,50) == 0){
9759 return &params[i].value;
9760 }
9761 i++;
9762 }
9763 return NULL;
9764
9765} */
9766
developer72fb0bb2023-01-11 09:46:29 +08009767static const char *get_line_from_str_buf(const char *buf, char *line)
9768{
9769 int i;
9770 int n = strlen(buf);
9771
9772 for (i = 0; i < n; i++) {
9773 line[i] = buf[i];
9774 if (buf[i] == '\n') {
9775 line[i] = '\0';
9776 return &buf[i + 1];
9777 }
9778 }
9779
9780 return NULL;
9781}
9782
9783INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
9784{
developer0d26f2c2023-05-25 19:46:36 +08009785 char interface_name[16] = {0};
9786 FILE *f = NULL;
9787 int auth_temp= -1;
9788 char cmd[256] = {0}, buf[2048] = {0};
9789 char *param = NULL, *value = NULL, *line=NULL;
9790 size_t len = 0;
9791 wifi_associated_dev3_t *dev=NULL;
developer72fb0bb2023-01-11 09:46:29 +08009792
9793 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer0d26f2c2023-05-25 19:46:36 +08009794 *associated_dev_array = NULL;
9795 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72fb0bb2023-01-11 09:46:29 +08009796 return RETURN_ERR;
developer0d26f2c2023-05-25 19:46:36 +08009797 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
9798 _syscmd(cmd, buf, sizeof(buf));
9799 *output_array_size = atoi(buf);
developer72fb0bb2023-01-11 09:46:29 +08009800
developer0d26f2c2023-05-25 19:46:36 +08009801 if (*output_array_size <= 0)
9802 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08009803
developer0d26f2c2023-05-25 19:46:36 +08009804 dev=(wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
9805 *associated_dev_array = dev;
9806 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/diagnostic3_devices.txt" , interface_name);
9807 _syscmd(cmd,buf,sizeof(buf));
9808 f = fopen("/tmp/diagnostic3_devices.txt", "r");
9809 if (f == NULL)
9810 {
9811 *output_array_size=0;
developer72fb0bb2023-01-11 09:46:29 +08009812 return RETURN_ERR;
9813 }
developer0d26f2c2023-05-25 19:46:36 +08009814 while ((getline(&line, &len, f)) != -1)
9815 {
9816 param = strtok(line, "=");
9817 value = strtok(NULL, "=");
developer72fb0bb2023-01-11 09:46:29 +08009818
developer0d26f2c2023-05-25 19:46:36 +08009819 if( strcmp("flags",param) == 0 )
9820 {
9821 value[strlen(value)-1]='\0';
9822 if(strstr (value,"AUTHORIZED") != NULL )
9823 {
9824 auth_temp++;
9825 dev[auth_temp].cli_AuthenticationState = 1;
9826 dev[auth_temp].cli_Active = 1;
developer72fb0bb2023-01-11 09:46:29 +08009827 }
developer0d26f2c2023-05-25 19:46:36 +08009828 } else if (auth_temp < 0) {
9829 continue;
9830 } else if( strcmp("dot11RSNAStatsSTAAddress", param) == 0 )
9831 {
9832 value[strlen(value)-1]='\0';
9833 sscanf(value, "%x:%x:%x:%x:%x:%x",
9834 (unsigned int *)&dev[auth_temp].cli_MACAddress[0],
9835 (unsigned int *)&dev[auth_temp].cli_MACAddress[1],
9836 (unsigned int *)&dev[auth_temp].cli_MACAddress[2],
9837 (unsigned int *)&dev[auth_temp].cli_MACAddress[3],
9838 (unsigned int *)&dev[auth_temp].cli_MACAddress[4],
9839 (unsigned int *)&dev[auth_temp].cli_MACAddress[5]);
9840 } else if (strcmp("signal", param) == 0) {
9841 value[strlen(value)-1]='\0';
9842 sscanf(value, "%d", &dev[auth_temp].cli_RSSI);
9843 dev[auth_temp].cli_SNR = 95 + dev[auth_temp].cli_RSSI;
developer72fb0bb2023-01-11 09:46:29 +08009844 }
developer0d26f2c2023-05-25 19:46:36 +08009845 }
9846 if (line)
9847 free(line);
9848 fclose(f);
developer72fb0bb2023-01-11 09:46:29 +08009849 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08009850 return RETURN_OK;
9851}
9852
9853#if 0
9854//To-do
9855INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
9856{
9857 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9858
9859 //Using different approach to get required WiFi Parameters from system available commands
developer69b61b02023-03-07 17:17:44 +08009860#if 0
developer72fb0bb2023-01-11 09:46:29 +08009861 FILE *f;
9862 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
9863 char cmd[256], buf[2048];
9864 char *param , *value, *line=NULL;
9865 size_t len = 0;
9866 ssize_t nread;
9867 wifi_associated_dev3_t *dev=NULL;
9868 *associated_dev_array = NULL;
9869 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
9870 _syscmd(cmd,buf,sizeof(buf));
9871 *output_array_size = atoi(buf);
9872
9873 if (*output_array_size <= 0)
9874 return RETURN_OK;
9875
9876 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
9877 *associated_dev_array = dev;
9878 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt", interface_name);
9879 _syscmd(cmd,buf,sizeof(buf));
9880 f = fopen("/tmp/connected_devices.txt", "r");
9881 if (f==NULL)
9882 {
9883 *output_array_size=0;
9884 return RETURN_ERR;
9885 }
9886 while ((nread = getline(&line, &len, f)) != -1)
9887 {
9888 param = strtok(line,"=");
9889 value = strtok(NULL,"=");
9890
9891 if( strcmp("flags",param) == 0 )
9892 {
9893 value[strlen(value)-1]='\0';
9894 if(strstr (value,"AUTHORIZED") != NULL )
9895 {
9896 dev[auth_temp].cli_AuthenticationState = 1;
9897 dev[auth_temp].cli_Active = 1;
9898 auth_temp++;
9899 read_flag=1;
9900 }
9901 }
9902 if(read_flag==1)
9903 {
9904 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
9905 {
9906 value[strlen(value)-1]='\0';
9907 sscanf(value, "%x:%x:%x:%x:%x:%x",
9908 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
9909 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
9910 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
9911 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
9912 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
9913 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
9914
9915 }
9916 else if( strcmp("rx_packets",param) == 0 )
9917 {
9918 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
9919 }
9920
9921 else if( strcmp("tx_packets",param) == 0 )
9922 {
developer69b61b02023-03-07 17:17:44 +08009923 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
developer72fb0bb2023-01-11 09:46:29 +08009924 }
9925
9926 else if( strcmp("rx_bytes",param) == 0 )
9927 {
9928 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
9929 }
9930
9931 else if( strcmp("tx_bytes",param) == 0 )
9932 {
developer69b61b02023-03-07 17:17:44 +08009933 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
developer72fb0bb2023-01-11 09:46:29 +08009934 mac_temp++;
9935 read_flag=0;
developer69b61b02023-03-07 17:17:44 +08009936 }
developer72fb0bb2023-01-11 09:46:29 +08009937 }
9938 }
9939
9940 *output_array_size = auth_temp;
9941 auth_temp=0;
9942 mac_temp=0;
9943 free(line);
9944 fclose(f);
9945#endif
9946 char interface_name[MAX_BUF_SIZE] = {0};
9947 char wifi_status[MAX_BUF_SIZE] = {0};
9948 char hostapdconf[MAX_BUF_SIZE] = {0};
9949
9950 wifi_associated_dev3_t *dev_array = NULL;
9951 ULONG wifi_count = 0;
9952
9953 *associated_dev_array = NULL;
9954 *output_array_size = 0;
9955
9956 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
9957 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
9958 {
9959 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
9960
9961 wifi_GetInterfaceName(interface_name, hostapdconf);
9962
9963 if(strlen(interface_name) > 1)
9964 {
9965 wifihal_interfacestatus(wifi_status,interface_name);
9966 if(strcmp(wifi_status,"RUNNING") == 0)
9967 {
9968 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
9969
9970 *associated_dev_array = dev_array;
developer69b61b02023-03-07 17:17:44 +08009971 *output_array_size = wifi_count;
developer72fb0bb2023-01-11 09:46:29 +08009972 }
9973 else
9974 {
9975 *associated_dev_array = NULL;
9976 }
9977 }
9978 }
9979
9980 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9981 return RETURN_OK;
9982}
9983#endif
9984
9985/* getIPAddress function */
9986/**
9987* @description Returning IpAddress of the Matched String
9988*
developer69b61b02023-03-07 17:17:44 +08009989* @param
developer72fb0bb2023-01-11 09:46:29 +08009990* @str Having MacAddress
developer69b61b02023-03-07 17:17:44 +08009991* @ipaddr Having ipaddr
developer72fb0bb2023-01-11 09:46:29 +08009992* @return The status of the operation
9993* @retval RETURN_OK if successful
9994* @retval RETURN_ERR if any error is detected
9995*
9996*/
9997
9998INT getIPAddress(char *str,char *ipaddr)
9999{
10000 FILE *fp = NULL;
10001 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
10002 int LeaseTime = 0,ret = 0;
10003 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
10004 {
10005 return RETURN_ERR;
10006 }
10007
10008 while ( fgets(buf, sizeof(buf), fp)!= NULL )
10009 {
10010 /*
10011 Sample:sss
10012 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
10013 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
10014 */
10015 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
10016 &(LeaseTime),
10017 phyAddr,
10018 ipAddr,
10019 hostName
10020 );
10021 if(ret != 4)
10022 continue;
10023 if(strcmp(str,phyAddr) == 0)
10024 strcpy(ipaddr,ipAddr);
10025 }
10026 fclose(fp);
10027 return RETURN_OK;
10028}
10029
10030/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
10031/**
10032* @description Returning Inactive wireless connected clients informations
10033*
developer69b61b02023-03-07 17:17:44 +080010034* @param
developer72fb0bb2023-01-11 09:46:29 +080010035* @filename Holding private_wifi 2g/5g content files
10036* @associated_dev_array Having inactiv wireless clients informations
10037* @output_array_size Returning Inactive wireless counts
10038* @return The status of the operation
10039* @retval RETURN_OK if successful
10040* @retval RETURN_ERR if any error is detected
10041*
10042*/
10043
10044INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
10045{
10046 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10047 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
10048 FILE *fp = NULL;
10049 int arr[MACADDRESS_SIZE] = {0};
10050 unsigned char mac[MACADDRESS_SIZE] = {0};
10051 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
10052 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
10053 fp = popen(buf,"r");
10054 if(fp == NULL)
10055 return RETURN_ERR;
10056 else
10057 {
10058 fgets(path,sizeof(path),fp);
10059 maccount = atoi(path);
10060 }
10061 pclose(fp);
10062 *output_array_size = maccount;
10063 wifi_associated_dev3_t* temp = NULL;
10064 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
10065 *associated_dev_array = temp;
10066 if(temp == NULL)
10067 {
10068 printf("Error Statement. Insufficient memory \n");
10069 return RETURN_ERR;
10070 }
10071 memset(buf,0,sizeof(buf));
10072 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
10073 fp = popen(buf,"r");
10074 if (fp == NULL) {
10075 fprintf(stderr, "%s: failed pipe command %s.\n", __func__, buf);
10076 return RETURN_ERR;
10077 }
10078 for(count = 0; count < maccount ; count++)
10079 {
10080 fgets(path,sizeof(path),fp);
10081 for(i = 0; path[i]!='\n';i++)
10082 str[i]=path[i];
10083 str[i]='\0';
10084 getIPAddress(str,ipaddr);
10085 memset(buf,0,sizeof(buf));
10086 if(strlen(ipaddr) > 0)
10087 {
10088 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
10089 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
10090 {
10091 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
10092 {
10093 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
10094 {
10095 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
10096
10097 }
10098 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
10099 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]);
10100 }
10101 temp[count].cli_AuthenticationState = 0; //TODO
developer69b61b02023-03-07 17:17:44 +080010102 temp[count].cli_Active = 0; //TODO
developer72fb0bb2023-01-11 09:46:29 +080010103 temp[count].cli_SignalStrength = 0;
10104 }
10105 else //Active wireless clients info
10106 {
10107 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
10108 {
10109 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
10110 {
10111 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
10112
10113 }
10114 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
10115 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]);
10116 }
10117 temp[count].cli_Active = 1;
10118 }
10119 }
10120 memset(ipaddr,0,sizeof(ipaddr));
10121 }
10122 pclose(fp);
10123 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10124 return RETURN_OK;
10125}
10126//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
10127//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
10128//To get Band Steering Capability
10129INT wifi_getBandSteeringCapability(BOOL *support)
10130{
10131 *support = FALSE;
10132 return RETURN_OK;
10133}
10134
10135
10136//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
10137//To get Band Steering enable status
10138INT wifi_getBandSteeringEnable(BOOL *enable)
10139{
10140 *enable = FALSE;
10141 return RETURN_OK;
10142}
10143
10144//To turn on/off Band steering
10145INT wifi_setBandSteeringEnable(BOOL enable)
10146{
10147 return RETURN_OK;
10148}
10149
10150//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
10151//To get Band Steering AP group
10152INT wifi_getBandSteeringApGroup(char *output_ApGroup)
10153{
10154 if (NULL == output_ApGroup)
10155 return RETURN_ERR;
10156
10157 strcpy(output_ApGroup, "1,2");
10158 return RETURN_OK;
10159}
10160
10161//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
10162//to set and read the band steering BandUtilizationThreshold parameters
10163INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
10164{
10165 return RETURN_ERR;
10166}
10167
10168INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
10169{
10170 return RETURN_ERR;
10171}
10172
10173//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
10174//to set and read the band steering RSSIThreshold parameters
10175INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
10176{
10177 return RETURN_ERR;
10178}
10179
10180INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
10181{
10182 return RETURN_ERR;
10183}
10184
10185
10186//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
10187//to set and read the band steering physical modulation rate threshold parameters
10188INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
10189{
10190 //If chip is not support, return -1
10191 return RETURN_ERR;
10192}
10193
10194INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
10195{
10196 //If chip is not support, return -1
10197 return RETURN_ERR;
10198}
10199
10200//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
10201//to set and read the inactivity time (in seconds) for steering under overload condition
10202INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
10203{
10204 return RETURN_ERR;
10205}
10206
10207INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
10208{
10209 return RETURN_ERR;
10210}
10211
10212//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
10213//to set and read the inactivity time (in seconds) for steering under Idle condition
10214INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
10215{
10216 return RETURN_ERR;
10217}
10218
10219INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
10220{
10221 return RETURN_ERR;
10222}
10223
10224//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
10225//pClientMAC[64]
10226//pSourceSSIDIndex[64]
10227//pDestSSIDIndex[64]
10228//pSteeringReason[256]
10229INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
10230{
10231 //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
10232 *pSteeringTime=time(NULL);
10233 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
10234 return RETURN_OK;
10235}
10236
10237INT wifi_ifConfigDown(INT apIndex)
10238{
10239 INT status = RETURN_OK;
10240 char cmd[64];
10241
10242 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
10243 printf("%s: %s\n", __func__, cmd);
10244 system(cmd);
10245
10246 return status;
10247}
10248
10249INT wifi_ifConfigUp(INT apIndex)
10250{
10251 char interface_name[16] = {0};
10252 char cmd[128];
10253 char buf[1024];
10254
10255 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
10256 return RETURN_ERR;
10257 snprintf(cmd, sizeof(cmd), "ifconfig %s up 2>/dev/null", interface_name);
10258 _syscmd(cmd, buf, sizeof(buf));
10259 return 0;
10260}
10261
10262//>> Deprecated. Replace with wifi_applyRadioSettings
10263INT wifi_pushBridgeInfo(INT apIndex)
10264{
developerb2977562023-05-24 17:54:12 +080010265 char ip[32] = {0};
10266 char subnet[32] = {0};
10267 char bridge[32] = {0};
10268 char cmd[128] = {0};
10269 char buf[1024] = {0};
developer72fb0bb2023-01-11 09:46:29 +080010270
developerb2977562023-05-24 17:54:12 +080010271 wifi_getApBridgeInfo(apIndex, bridge, ip, subnet);
developer72fb0bb2023-01-11 09:46:29 +080010272
developerb2977562023-05-24 17:54:12 +080010273 snprintf(cmd, sizeof(cmd), "ifconfig %s %s netmask %s ", bridge, ip, subnet);
10274 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +080010275
developerb2977562023-05-24 17:54:12 +080010276 return 0;
developer72fb0bb2023-01-11 09:46:29 +080010277}
10278
10279INT wifi_pushChannel(INT radioIndex, UINT channel)
10280{
10281 char interface_name[16] = {0};
10282 char cmd[128];
10283 char buf[1024];
developer72fb0bb2023-01-11 09:46:29 +080010284
developer72fb0bb2023-01-11 09:46:29 +080010285 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
10286 return RETURN_ERR;
10287 snprintf(cmd, sizeof(cmd), "iwconfig %s freq %d",interface_name,channel);
10288 _syscmd(cmd,buf, sizeof(buf));
10289
10290 return 0;
10291}
10292
10293INT wifi_pushChannelMode(INT radioIndex)
10294{
10295 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
10296 return RETURN_ERR;
10297}
10298
10299INT wifi_pushDefaultValues(INT radioIndex)
10300{
10301 //Apply Comcast specified default radio settings instantly
10302 //AMPDU=1
10303 //AMPDUFrames=32
10304 //AMPDULim=50000
10305 //txqueuelen=1000
10306
10307 return RETURN_ERR;
10308}
10309
10310INT wifi_pushTxChainMask(INT radioIndex)
10311{
10312 //Apply default TxChainMask instantly
10313 return RETURN_ERR;
10314}
10315
10316INT wifi_pushRxChainMask(INT radioIndex)
10317{
10318 //Apply default RxChainMask instantly
10319 return RETURN_ERR;
10320}
10321
10322INT wifi_pushSSID(INT apIndex, CHAR *ssid)
10323{
developer7e4a2a62023-04-06 19:56:03 +080010324 INT status;
developer72fb0bb2023-01-11 09:46:29 +080010325
developer7e4a2a62023-04-06 19:56:03 +080010326 status = wifi_setSSIDName(apIndex, ssid);
10327 wifi_quick_reload_ap(apIndex);
developer72fb0bb2023-01-11 09:46:29 +080010328
developer7e4a2a62023-04-06 19:56:03 +080010329 return status;
developer72fb0bb2023-01-11 09:46:29 +080010330}
10331
10332INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
10333{
10334 //Apply default Ssid Advertisement instantly
10335 return RETURN_ERR;
10336}
10337
10338INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
10339{
developere82c0ca2023-05-10 16:25:35 +080010340 time_t now;
10341
10342 time(&now);
10343 if (now > radio_up_time[radioIndex])
10344 *output = now - radio_up_time[radioIndex];
10345 else {
10346 *output = 0;
10347 return RETURN_ERR;
10348 }
10349
10350 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +080010351}
10352
10353INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
10354{
10355 return RETURN_OK;
10356}
10357
10358INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
10359{
10360 return RETURN_OK;
10361}
10362
10363//To-do
10364INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
10365{
10366 char output[16]={'\0'};
10367 char config_file[MAX_BUF_SIZE] = {0};
10368
10369 if (!output_string)
10370 return RETURN_ERR;
10371
10372 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
10373 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
10374
10375 if (strlen(output) == 0)
10376 snprintf(output_string, 64, "Disabled");
10377 else if (strncmp(output, "0", 1) == 0)
10378 snprintf(output_string, 64, "Disabled");
10379 else if (strncmp(output, "1", 1) == 0)
10380 snprintf(output_string, 64, "Optional");
10381 else if (strncmp(output, "2", 1) == 0)
10382 snprintf(output_string, 64, "Required");
10383 else {
10384 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
10385 return RETURN_ERR;
10386 }
10387
10388 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
10389 return RETURN_OK;
10390}
10391INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
10392{
developer72fb0bb2023-01-11 09:46:29 +080010393 struct params params;
10394 char config_file[MAX_BUF_SIZE] = {0};
10395
10396 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10397 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
10398 return RETURN_ERR;
10399
10400 params.name = "ieee80211w";
10401 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
10402 params.value = "0";
10403 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
10404 params.value = "1";
10405 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
10406 params.value = "2";
10407 else{
10408 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
10409 return RETURN_ERR;
10410 }
10411 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
10412 wifi_hostapdWrite(config_file, &params, 1);
10413 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
10414 return RETURN_OK;
10415}
10416INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
10417{
10418 char output[16]={'\0'};
10419 char config_file[MAX_BUF_SIZE] = {0};
developer84c3d782023-05-31 16:08:21 +080010420 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +080010421
10422 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer84c3d782023-05-31 16:08:21 +080010423 band = wifi_index_to_band(radioIndex);
10424 snprintf(config_file, sizeof(config_file), "%s%d.dat", LOGAN_DAT_FILE, band);
developer262f4cb2023-05-24 12:22:04 +080010425 wifi_datfileRead(config_file, "AutoChannelSelect" , output, sizeof(output));
developer72fb0bb2023-01-11 09:46:29 +080010426
developer84c3d782023-05-31 16:08:21 +080010427 if (strncmp(output, "0", 1) == 0)
developer47a56bf2023-05-30 13:38:57 +080010428 *output_bool = FALSE;
developer262f4cb2023-05-24 12:22:04 +080010429 else if (strncmp(output, "1", 1) == 0)
10430 *output_bool = TRUE;
10431 else if (strncmp(output, "2", 1) == 0)
10432 *output_bool = TRUE;
10433 else if (strncmp(output, "3", 1) == 0)
10434 *output_bool = TRUE;
10435 else
10436 *output_bool = FALSE;
developer72fb0bb2023-01-11 09:46:29 +080010437 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
10438
10439 return RETURN_OK;
10440}
10441
10442INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
10443{
10444 return RETURN_OK;
10445}
10446
10447INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
10448{
10449 return RETURN_OK;
10450}
10451
10452INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
10453{
10454 return RETURN_OK;
10455}
10456
10457INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
10458{
10459 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10460 char config_file[MAX_BUF_SIZE] = {0};
10461
10462 if (NULL == output)
10463 return RETURN_ERR;
10464 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
10465 wifi_hostapdRead(config_file,"hw_mode",output,64);
10466
10467 if(strcmp(output,"b")==0)
10468 sprintf(output, "%s", "1,2,5.5,11");
10469 else if (strcmp(output,"a")==0)
10470 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
10471 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
10472 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
10473
10474 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10475 return RETURN_OK;
10476}
10477
10478INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
10479{
10480 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10481 char *temp;
10482 char temp_output[128];
10483 char temp_TransmitRates[128];
10484 char config_file[MAX_BUF_SIZE] = {0};
10485
10486 if (NULL == output)
10487 return RETURN_ERR;
10488
10489 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
10490 wifi_hostapdRead(config_file,"supported_rates",output,64);
10491
10492 if (strlen(output) == 0) {
10493 wifi_getRadioSupportedDataTransmitRates(wlanIndex, output);
10494 return RETURN_OK;
10495 }
10496 strcpy(temp_TransmitRates,output);
10497 strcpy(temp_output,"");
10498 temp = strtok(temp_TransmitRates," ");
10499 while(temp!=NULL)
10500 {
10501 temp[strlen(temp)-1]=0;
10502 if((temp[0]=='5') && (temp[1]=='\0'))
10503 {
10504 temp="5.5";
10505 }
10506 strcat(temp_output,temp);
10507 temp = strtok(NULL," ");
10508 if(temp!=NULL)
10509 {
10510 strcat(temp_output,",");
10511 }
10512 }
10513 strcpy(output,temp_output);
10514 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10515
10516 return RETURN_OK;
10517}
10518
10519INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
10520{
10521 return RETURN_OK;
10522}
10523
10524
10525INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
10526{
10527 int i=0;
10528 char *temp;
10529 char temp1[128] = {0};
10530 char temp_output[128] = {0};
10531 char temp_TransmitRates[128] = {0};
10532 struct params params={'\0'};
10533 char config_file[MAX_BUF_SIZE] = {0};
10534 wifi_band band = wifi_index_to_band(wlanIndex);
10535
10536 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10537 if(NULL == output)
10538 return RETURN_ERR;
10539 strcpy(temp_TransmitRates,output);
10540
10541 for(i=0;i<strlen(temp_TransmitRates);i++)
10542 {
10543 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
10544 {
10545 continue;
10546 }
10547 else
10548 {
10549 return RETURN_ERR;
10550 }
10551 }
10552 strcpy(temp_output,"");
10553 temp = strtok(temp_TransmitRates,",");
10554 while(temp!=NULL)
10555 {
10556 strcpy(temp1,temp);
10557 if(band == band_5)
10558 {
10559 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
10560 {
10561 return RETURN_ERR;
10562 }
10563 }
10564
10565 if(strcmp(temp,"5.5")==0)
10566 {
10567 strcpy(temp1,"55");
10568 }
10569 else
10570 {
10571 strcat(temp1,"0");
10572 }
10573 strcat(temp_output,temp1);
10574 temp = strtok(NULL,",");
10575 if(temp!=NULL)
10576 {
10577 strcat(temp_output," ");
10578 }
10579 }
10580 strcpy(output,temp_output);
10581
10582 params.name = "supported_rates";
10583 params.value = output;
10584
10585 wifi_dbg_printf("\n%s:",__func__);
10586 wifi_dbg_printf("params.value=%s\n",params.value);
10587 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
10588 wifi_hostapdWrite(config_file,&params,1);
10589 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10590
10591 return RETURN_OK;
10592}
10593
10594
10595static char *sncopy(char *dst, int dst_sz, const char *src)
10596{
10597 if (src && dst && dst_sz > 0) {
10598 strncpy(dst, src, dst_sz);
10599 dst[dst_sz - 1] = '\0';
10600 }
10601 return dst;
10602}
10603
10604static int util_get_sec_chan_offset(int channel, const char* ht_mode)
10605{
10606 if (0 == strcmp(ht_mode, "HT40") ||
10607 0 == strcmp(ht_mode, "HT80") ||
10608 0 == strcmp(ht_mode, "HT160")) {
10609 switch (channel) {
10610 case 1 ... 7:
10611 case 36:
10612 case 44:
10613 case 52:
10614 case 60:
10615 case 100:
10616 case 108:
10617 case 116:
10618 case 124:
10619 case 132:
10620 case 140:
10621 case 149:
10622 case 157:
10623 return 1;
10624 case 8 ... 13:
10625 case 40:
10626 case 48:
10627 case 56:
10628 case 64:
10629 case 104:
10630 case 112:
10631 case 120:
10632 case 128:
10633 case 136:
10634 case 144:
10635 case 153:
10636 case 161:
10637 return -1;
10638 default:
10639 return -EINVAL;
10640 }
10641 }
10642
10643 return -EINVAL;
10644}
10645
10646static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
10647{
10648 int idx = channel%8;
10649 if (0 == strcmp(ht_mode, "HT40") ||
10650 0 == strcmp(ht_mode, "HT80") ||
10651 0 == strcmp(ht_mode, "HT160")) {
10652 switch (idx) {
10653 case 1:
10654 return 1;
10655 case 5:
10656 return -1;
10657 default:
10658 return -EINVAL;
10659 }
10660 }
10661
10662 return -EINVAL;
10663}
10664static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
10665{
10666 if (NULL == hw_mode) return;
10667
10668 if (0 == strcmp(hw_mode, "ac"))
10669 sncopy(bw_mode, bw_mode_len, "ht vht");
10670
10671 if (0 == strcmp(hw_mode, "n"))
10672 sncopy(bw_mode, bw_mode_len, "ht");
10673
10674 return;
10675}
10676
10677static int util_chan_to_freq(int chan)
10678{
10679 if (chan == 14)
10680 return 2484;
10681 else if (chan < 14)
10682 return 2407 + chan * 5;
10683 else if (chan >= 182 && chan <= 196)
10684 return 4000 + chan * 5;
10685 else
10686 return 5000 + chan * 5;
10687 return 0;
10688}
10689
10690static int util_6G_chan_to_freq(int chan)
10691{
10692 if (chan)
10693 return 5950 + chan * 5;
10694 else
10695 return 0;
developer69b61b02023-03-07 17:17:44 +080010696
developer72fb0bb2023-01-11 09:46:29 +080010697}
10698const int *util_unii_5g_chan2list(int chan, int width)
10699{
10700 static const int lists[] = {
10701 // <width>, <chan1>, <chan2>..., 0,
10702 20, 36, 0,
10703 20, 40, 0,
10704 20, 44, 0,
10705 20, 48, 0,
10706 20, 52, 0,
10707 20, 56, 0,
10708 20, 60, 0,
10709 20, 64, 0,
10710 20, 100, 0,
10711 20, 104, 0,
10712 20, 108, 0,
10713 20, 112, 0,
10714 20, 116, 0,
10715 20, 120, 0,
10716 20, 124, 0,
10717 20, 128, 0,
10718 20, 132, 0,
10719 20, 136, 0,
10720 20, 140, 0,
10721 20, 144, 0,
10722 20, 149, 0,
10723 20, 153, 0,
10724 20, 157, 0,
10725 20, 161, 0,
10726 20, 165, 0,
10727 40, 36, 40, 0,
10728 40, 44, 48, 0,
10729 40, 52, 56, 0,
10730 40, 60, 64, 0,
10731 40, 100, 104, 0,
10732 40, 108, 112, 0,
10733 40, 116, 120, 0,
10734 40, 124, 128, 0,
10735 40, 132, 136, 0,
10736 40, 140, 144, 0,
10737 40, 149, 153, 0,
10738 40, 157, 161, 0,
10739 80, 36, 40, 44, 48, 0,
10740 80, 52, 56, 60, 64, 0,
10741 80, 100, 104, 108, 112, 0,
10742 80, 116, 120, 124, 128, 0,
10743 80, 132, 136, 140, 144, 0,
10744 80, 149, 153, 157, 161, 0,
10745 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
10746 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
10747 -1 // final delimiter
10748 };
10749 const int *start;
10750 const int *p;
10751
10752 for (p = lists; *p != -1; p++) {
10753 if (*p == width) {
10754 for (start = ++p; *p != 0; p++) {
10755 if (*p == chan)
10756 return start;
10757 }
10758 }
10759 // move to the end of channel list of given width
10760 while (*p != 0) {
10761 p++;
10762 }
10763 }
10764
10765 return NULL;
10766}
10767
10768static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
10769{
10770 if (NULL == ht_mode)
10771 return 0;
10772
10773 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
10774 const int *chans = util_unii_5g_chan2list(channel, width);
10775 int sum = 0;
10776 int cnt = 0;
10777
10778 if (NULL == chans)
10779 return 0;
10780
10781 while (*chans) {
10782 sum += *chans;
10783 cnt++;
10784 chans++;
10785 }
10786 if (cnt == 0)
10787 return 0;
10788 return sum / cnt;
10789}
10790
10791static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
10792{
10793 if (NULL == ht_mode)
10794 return 0;
10795
10796 int width = strtol((ht_mode + 2), NULL, 10);
10797
10798 int idx = 0 ;
10799 int centerchan = 0;
10800 int chan_ofs = 1;
10801
10802 if (width == 40){
10803 idx = ((channel/4) + chan_ofs)%2;
10804 switch (idx) {
10805 case 0:
10806 centerchan = (channel - 2);
10807 break;
10808 case 1:
10809 centerchan = (channel + 2);
developer69b61b02023-03-07 17:17:44 +080010810 break;
developer72fb0bb2023-01-11 09:46:29 +080010811 default:
10812 return -EINVAL;
10813 }
10814 }else if (width == 80){
developer69b61b02023-03-07 17:17:44 +080010815 idx = ((channel/4) + chan_ofs)%4;
developer72fb0bb2023-01-11 09:46:29 +080010816 switch (idx) {
10817 case 0:
10818 centerchan = (channel - 6);
10819 break;
10820 case 1:
10821 centerchan = (channel + 6);
10822 break;
10823 case 2:
10824 centerchan = (channel + 2);
10825 break;
10826 case 3:
10827 centerchan = (channel - 2);
10828 break;
10829 default:
10830 return -EINVAL;
developer69b61b02023-03-07 17:17:44 +080010831 }
developer72fb0bb2023-01-11 09:46:29 +080010832 }else if (width == 160){
10833 switch (channel) {
10834 case 1 ... 29:
10835 centerchan = 15;
10836 break;
10837 case 33 ... 61:
10838 centerchan = 47;
10839 break;
10840 case 65 ... 93:
10841 centerchan = 79;
10842 break;
10843 case 97 ... 125:
10844 centerchan = 111;
10845 break;
10846 case 129 ... 157:
10847 centerchan = 143;
10848 break;
10849 case 161 ... 189:
10850 centerchan = 175;
10851 break;
10852 case 193 ... 221:
10853 centerchan = 207;
10854 break;
10855 default:
10856 return -EINVAL;
developer69b61b02023-03-07 17:17:44 +080010857 }
developer72fb0bb2023-01-11 09:46:29 +080010858 }
10859 return centerchan;
10860}
10861static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
10862{
10863 BOOL onlyG, onlyN, onlyA;
10864 CHAR tmp[64];
10865 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
10866 if (ret == RETURN_OK) {
10867 sncopy(hw_mode, hw_mode_size, tmp);
10868 }
10869 return ret;
10870}
10871
10872INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
10873{
10874 // Sample commands:
10875 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
10876 // hostapd_cli -i wifi0 chan_switch 30 2437
developerc79e9172023-06-06 19:48:03 +080010877 int ret = 0;
developer72fb0bb2023-01-11 09:46:29 +080010878 char center_freq1_str[32] = ""; // center_freq1=%d
10879 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
10880 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
10881 char hw_mode[16] = ""; // n|ac
10882 char bw_mode[16] = ""; // ht|ht vht
10883 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
10884 char interface_name[16] = {0};
10885 int sec_chan_offset;
10886 int width;
10887 char config_file[64] = {0};
developer72fb0bb2023-01-11 09:46:29 +080010888 char *ext_str = "None";
10889 wifi_band band = band_invalid;
10890 int center_chan = 0;
10891 int center_freq1 = 0;
10892
10893 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
10894
10895 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
10896 return RETURN_ERR;
10897
10898 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10899
10900 band = wifi_index_to_band(radioIndex);
10901
10902 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
10903
10904 // Get radio mode HT20|HT40|HT80 etc.
10905 if (channel){
developer72fb0bb2023-01-11 09:46:29 +080010906 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
10907
10908 // Provide bandwith if specified
10909 if (channel_width_MHz > 20) {
10910 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
10911 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
10912 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
10913
10914 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
10915 }else if (channel_width_MHz == 20){
10916 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
10917 }
10918
10919
10920 if (channel_width_MHz > 20) {
10921 if (band == band_6){
10922 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
10923 if(center_chan){
10924 center_freq1 = util_6G_chan_to_freq(center_chan);
10925 }
10926 }else{
10927 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
10928 if(center_chan){
10929 center_freq1 = util_chan_to_freq(center_chan);
10930 }
10931 }
developer69b61b02023-03-07 17:17:44 +080010932
developer72fb0bb2023-01-11 09:46:29 +080010933 if (center_freq1)
10934 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
developer69b61b02023-03-07 17:17:44 +080010935
developer72fb0bb2023-01-11 09:46:29 +080010936 }
10937
10938 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
10939 if (band == band_6){
10940 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
10941 }else{
10942 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
10943 }
10944 if (sec_chan_offset != -EINVAL)
10945 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
10946
10947 // Only the first AP, other are hanging on the same radio
developerfead3972023-05-25 20:15:02 +080010948 ret = wifi_setChannel_netlink(radioIndex, &channel, NULL);
developerd1824452023-05-18 12:30:04 +080010949 if (ret != RETURN_OK) {
developerfead3972023-05-25 20:15:02 +080010950 fprintf(stderr, "%s: wifi_setChannel return error.\n", __func__);
developerd1824452023-05-18 12:30:04 +080010951 return RETURN_ERR;
10952 }
10953 /* wifi_dbg_printf("execute: '%s'\n", cmd);
developerf6a87542023-05-16 15:47:28 +080010954 ret = _syscmd(cmd, buf, sizeof(buf));
developerd1824452023-05-18 12:30:04 +080010955 wifi_reloadAp(radioIndex); */
developer72fb0bb2023-01-11 09:46:29 +080010956
10957 ret = wifi_setRadioChannel(radioIndex, channel);
10958 if (ret != RETURN_OK) {
10959 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
10960 return RETURN_ERR;
10961 }
10962
developer262f4cb2023-05-24 12:22:04 +080010963 if (sec_chan_offset == 1)
10964 ext_str = "Above";
10965 else if (sec_chan_offset == -1)
10966 ext_str = "Below";
developer72fb0bb2023-01-11 09:46:29 +080010967
developerd1824452023-05-18 12:30:04 +080010968 /*wifi_setRadioCenterChannel(radioIndex, center_chan); */
developer72fb0bb2023-01-11 09:46:29 +080010969
10970 } else {
10971 if (channel_width_MHz > 20)
10972 ext_str = "Above";
10973 }
10974
10975 wifi_setRadioExtChannel(radioIndex, ext_str);
10976
10977 char mhz_str[16];
10978 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
10979 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
10980
10981 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10982
10983 return RETURN_OK;
10984}
10985
10986INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
10987{
10988 int index = -1;
10989 wifi_neighbor_ap2_t *scan_array = NULL;
10990 char cmd[256]={0};
10991 char buf[128]={0};
10992 char file_name[32] = {0};
10993 char filter_SSID[32] = {0};
10994 char line[256] = {0};
10995 char interface_name[16] = {0};
10996 char *ret = NULL;
10997 int freq=0;
10998 FILE *f = NULL;
developer72fb0bb2023-01-11 09:46:29 +080010999 int channels_num = 0;
11000 int vht_channel_width = 0;
11001 int get_noise_ret = RETURN_ERR;
11002 bool filter_enable = false;
11003 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
11004 int phyId = 0;
11005
11006 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
11007
11008 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
11009 f = fopen(file_name, "r");
11010 if (f != NULL) {
11011 fgets(filter_SSID, sizeof(file_name), f);
11012 if (strlen(filter_SSID) != 0)
11013 filter_enable = true;
11014 fclose(f);
11015 }
11016
11017 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
11018 return RETURN_ERR;
11019
11020 phyId = radio_index_to_phy(radio_index);
11021
11022 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
11023 _syscmd(cmd, buf, sizeof(buf));
11024 channels_num = strtol(buf, NULL, 10);
11025
11026 sprintf(cmd, "iw dev %s scan dump | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
11027 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", interface_name, interface_name);
11028 fprintf(stderr, "cmd: %s\n", cmd);
11029 if ((f = popen(cmd, "r")) == NULL) {
11030 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
11031 return RETURN_ERR;
11032 }
developer69b61b02023-03-07 17:17:44 +080011033
developer72fb0bb2023-01-11 09:46:29 +080011034 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
11035 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
developer69b61b02023-03-07 17:17:44 +080011036
developer72fb0bb2023-01-11 09:46:29 +080011037 ret = fgets(line, sizeof(line), f);
11038 while (ret != NULL) {
11039 if(strstr(line, "BSS") != NULL) { // new neighbor info
developer69b61b02023-03-07 17:17:44 +080011040 // 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 +080011041 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
11042 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
11043
11044 if (!filter_BSS) {
11045 index++;
11046 wifi_neighbor_ap2_t *tmp;
11047 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
11048 if (tmp == NULL) { // no more memory to use
11049 index--;
11050 wifi_dbg_printf("%s: realloc failed\n", __func__);
11051 break;
11052 }
11053 scan_array = tmp;
11054 }
11055 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
11056
11057 filter_BSS = false;
11058 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
developerc79e9172023-06-06 19:48:03 +080011059 memset(scan_array[index].ap_Mode, 0, sizeof(scan_array[index].ap_Mode));
11060 memcpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
11061 memset(scan_array[index].ap_SecurityModeEnabled, 0, sizeof(scan_array[index].ap_SecurityModeEnabled));
11062 memcpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
11063 memset(scan_array[index].ap_EncryptionMode, 0, sizeof(scan_array[index].ap_EncryptionMode));
11064 memcpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
developer72fb0bb2023-01-11 09:46:29 +080011065 } else if (strstr(line, "freq") != NULL) {
11066 sscanf(line," freq: %d", &freq);
11067 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
11068
11069 if (freq >= 2412 && freq <= 2484) {
developerc79e9172023-06-06 19:48:03 +080011070 memset(scan_array[index].ap_OperatingFrequencyBand, 0, sizeof(scan_array[index].ap_OperatingFrequencyBand));
11071 memcpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
11072 memset(scan_array[index].ap_SupportedStandards, 0, sizeof(scan_array[index].ap_SupportedStandards));
11073 memcpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
11074 memset(scan_array[index].ap_OperatingStandards, 0, sizeof(scan_array[index].ap_OperatingStandards));
11075 memcpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
developer72fb0bb2023-01-11 09:46:29 +080011076 }
11077 else if (freq >= 5160 && freq <= 5805) {
developerc79e9172023-06-06 19:48:03 +080011078 memset(scan_array[index].ap_OperatingFrequencyBand, 0, sizeof(scan_array[index].ap_OperatingFrequencyBand));
11079 memcpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
11080 memset(scan_array[index].ap_SupportedStandards, 0, sizeof(scan_array[index].ap_SupportedStandards));
11081 memcpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
11082 memset(scan_array[index].ap_OperatingStandards, 0, sizeof(scan_array[index].ap_OperatingStandards));
11083 memcpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
developer72fb0bb2023-01-11 09:46:29 +080011084 }
11085
11086 scan_array[index].ap_Noise = 0;
11087 if (get_noise_ret == RETURN_OK) {
11088 for (int i = 0; i < channels_num; i++) {
11089 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
11090 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
11091 break;
11092 }
11093 }
11094 }
11095 } else if (strstr(line, "beacon interval") != NULL) {
11096 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
11097 } else if (strstr(line, "signal") != NULL) {
11098 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
11099 } else if (strstr(line,"SSID") != NULL) {
11100 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
11101 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
11102 filter_BSS = true;
11103 }
11104 } else if (strstr(line, "Supported rates") != NULL) {
11105 char SRate[80] = {0}, *tmp = NULL;
11106 memset(buf, 0, sizeof(buf));
11107 strcpy(SRate, line);
11108 tmp = strtok(SRate, ":");
11109 tmp = strtok(NULL, ":");
11110 strcpy(buf, tmp);
11111 memset(SRate, 0, sizeof(SRate));
11112
11113 tmp = strtok(buf, " \n");
11114 while (tmp != NULL) {
11115 strcat(SRate, tmp);
11116 if (SRate[strlen(SRate) - 1] == '*') {
11117 SRate[strlen(SRate) - 1] = '\0';
11118 }
11119 strcat(SRate, ",");
11120
11121 tmp = strtok(NULL, " \n");
11122 }
11123 SRate[strlen(SRate) - 1] = '\0';
11124 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
11125 } else if (strstr(line, "DTIM") != NULL) {
developer49c83812023-06-06 14:23:53 +080011126 sscanf(line,"DTIM Period %u", &(scan_array[index].ap_DTIMPeriod));
developer72fb0bb2023-01-11 09:46:29 +080011127 } else if (strstr(line, "VHT capabilities") != NULL) {
11128 strcat(scan_array[index].ap_SupportedStandards, ",ac");
11129 strcpy(scan_array[index].ap_OperatingStandards, "ac");
11130 } else if (strstr(line, "HT capabilities") != NULL) {
11131 strcat(scan_array[index].ap_SupportedStandards, ",n");
11132 strcpy(scan_array[index].ap_OperatingStandards, "n");
11133 } else if (strstr(line, "VHT operation") != NULL) {
11134 ret = fgets(line, sizeof(line), f);
11135 sscanf(line," * channel width: %d", &vht_channel_width);
11136 if(vht_channel_width == 1) {
11137 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
11138 } else {
11139 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
11140 }
11141 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
11142 continue;
11143 } else if (strstr(line, "HT operation") != NULL) {
11144 ret = fgets(line, sizeof(line), f);
developerdaf24792023-06-06 11:40:04 +080011145 sscanf(line," * secondary channel offset: %s", buf);
developer72fb0bb2023-01-11 09:46:29 +080011146 if (!strcmp(buf, "above")) {
11147 //40Mhz +
11148 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radio_index%1 ? "A": "G");
11149 }
11150 else if (!strcmp(buf, "below")) {
11151 //40Mhz -
11152 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
11153 } else {
11154 //20Mhz
11155 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radio_index%1 ? "A": "G");
11156 }
11157 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
11158 continue;
11159 } else if (strstr(line, "HE capabilities") != NULL) {
11160 strcat(scan_array[index].ap_SupportedStandards, ",ax");
11161 strcpy(scan_array[index].ap_OperatingStandards, "ax");
11162 ret = fgets(line, sizeof(line), f);
11163 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
11164 if (strstr(line, "HE40/2.4GHz") != NULL)
11165 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
11166 else
11167 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
11168 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
11169 if (strstr(line, "HE80/5GHz") != NULL) {
11170 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
11171 ret = fgets(line, sizeof(line), f);
11172 } else
11173 continue;
11174 if (strstr(line, "HE160/5GHz") != NULL)
11175 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
11176 }
11177 continue;
11178 } else if (strstr(line, "WPA") != NULL) {
11179 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
11180 } else if (strstr(line, "RSN") != NULL) {
11181 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
11182 } else if (strstr(line, "Group cipher") != NULL) {
11183 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
11184 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
11185 strcpy(scan_array[index].ap_EncryptionMode, "AES");
11186 }
11187 }
11188 ret = fgets(line, sizeof(line), f);
11189 }
11190
11191 if (!filter_BSS) {
11192 *output_array_size = index + 1;
11193 } else {
11194 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
11195 *output_array_size = index;
11196 }
11197 *neighbor_ap_array = scan_array;
11198 pclose(f);
11199 free(channels_noise_arr);
11200 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11201 return RETURN_OK;
11202}
11203
11204INT wifi_getApAssociatedDeviceStats(
11205 INT apIndex,
11206 mac_address_t *clientMacAddress,
11207 wifi_associated_dev_stats_t *associated_dev_stats,
11208 u64 *handle)
11209{
11210 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
11211 char interface_name[50] = {0};
11212 char cmd[1024] = {0};
11213 char mac_str[18] = {0};
11214 char *key = NULL;
11215 char *val = NULL;
11216 FILE *f = NULL;
11217 char *line = NULL;
11218 size_t len = 0;
11219
11220 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
11221 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
11222 return RETURN_ERR;
11223 }
11224
11225 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
11226 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
11227 if((f = popen(cmd, "r")) == NULL) {
11228 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
11229 return RETURN_ERR;
11230 }
11231
11232 while ((getline(&line, &len, f)) != -1) {
11233 key = strtok(line,":");
11234 val = strtok(NULL,":");
11235
11236 if(!strncmp(key,"rx bytes",8))
11237 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
11238 if(!strncmp(key,"tx bytes",8))
11239 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
11240 if(!strncmp(key,"rx packets",10))
11241 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
11242 if(!strncmp(key,"tx packets",10))
11243 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
11244 if(!strncmp(key,"tx retries",10))
11245 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
11246 if(!strncmp(key,"tx failed",9))
11247 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
11248 if(!strncmp(key,"rx drop misc",13))
11249 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
11250 if(!strncmp(key,"rx bitrate",10)) {
11251 val = strtok(val, " ");
11252 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
11253 }
11254 if(!strncmp(key,"tx bitrate",10)) {
11255 val = strtok(val, " ");
11256 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
11257 }
11258 }
11259 free(line);
11260 pclose(f);
11261 return RETURN_OK;
11262}
11263
11264INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
11265{
developer7e4a2a62023-04-06 19:56:03 +080011266 char interface_name[IF_NAME_SIZE] = {0};
developerb149d9d2023-06-06 16:14:22 +080011267 char cmd[MAX_CMD_SIZE] = {0}, buf[32] = {0};
developer72fb0bb2023-01-11 09:46:29 +080011268
developer7e4a2a62023-04-06 19:56:03 +080011269 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
11270
developer72fb0bb2023-01-11 09:46:29 +080011271 if (NULL == output_string)
11272 return RETURN_ERR;
11273
11274 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
11275 return RETURN_ERR;
developer7e4a2a62023-04-06 19:56:03 +080011276
11277 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 +080011278 _syscmd(cmd, buf, sizeof(buf));
11279
11280 //size of SSID name restricted to value less than 32 bytes
11281 snprintf(output_string, 32, "%s", buf);
developer7e4a2a62023-04-06 19:56:03 +080011282 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +080011283
11284 return RETURN_OK;
11285}
11286
11287INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
11288{
developer2edaf012023-05-24 14:24:53 +080011289 char *mac_arry_buf = NULL;
11290 INT policy = -1;
11291 INT buf_size = 1024;
developer72fb0bb2023-01-11 09:46:29 +080011292
developer2edaf012023-05-24 14:24:53 +080011293 mac_arry_buf = malloc(buf_size);
11294 if (!mac_arry_buf) {
11295 wifi_debug(DEBUG_ERROR,"malloc mac_arry_buf fails\n");
developer7e4a2a62023-04-06 19:56:03 +080011296 return RETURN_ERR;
developer2edaf012023-05-24 14:24:53 +080011297 }
11298 memset(mac_arry_buf, 0, buf_size);
11299 if (mtk_wifi_getApAclDevices(apIndex, mac_arry_buf, buf_size) != RETURN_OK) {
11300 wifi_debug(DEBUG_ERROR,"mtk_wifi_getApAclDevices get fails\n");
11301 goto err;
11302 }
11303 /*
11304 mtk format to get policy:
11305 "policy=1
11306 00:11:22:33:44:55
11307 00:11:22:33:44:66
11308 "
11309 */
11310 if (strlen(mac_arry_buf) < strlen("policy=1") || sscanf(mac_arry_buf, "policy=%01d", &policy) != 1) {
11311 wifi_debug(DEBUG_ERROR,"mac_arry_buf(%s) invalid\n", mac_arry_buf);
11312 goto err;
11313 }
11314 if (!(policy >=0 && policy <= 2)){
11315 wifi_debug(DEBUG_ERROR,"policy(%d) is invalid\n", policy);
11316 goto err;
11317 }
11318 *output_filterMode = policy;
11319 wifi_debug(DEBUG_NOTICE, "output_filterMode(%d), success\n", *output_filterMode);
11320 free(mac_arry_buf);
11321 mac_arry_buf = NULL;
11322 return RETURN_OK;
11323err:
11324 free(mac_arry_buf);
11325 mac_arry_buf = NULL;
11326 wifi_debug(DEBUG_NOTICE, "output_filterMode(%d), fails\n", *output_filterMode);
11327 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +080011328}
11329
developer2edaf012023-05-24 14:24:53 +080011330
developer72fb0bb2023-01-11 09:46:29 +080011331INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
11332{
11333 FILE *fp = NULL;
11334 char str[MAX_BUF_SIZE] = {0};
11335 int wificlientindex = 0 ;
11336 int count = 0;
11337 int signalstrength = 0;
11338 int arr[MACADDRESS_SIZE] = {0};
11339 unsigned char mac[MACADDRESS_SIZE] = {0};
11340 UINT wifi_count = 0;
developer72fb0bb2023-01-11 09:46:29 +080011341 char pipeCmd[MAX_CMD_SIZE] = {0};
11342
11343 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11344 *output_array_size = 0;
11345 *associated_dev_array = NULL;
11346 char interface_name[50] = {0};
11347
11348 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
11349 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
11350 return RETURN_ERR;
11351 }
11352
11353 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
11354 fp = popen(pipeCmd, "r");
11355 if (fp == NULL)
11356 {
11357 printf("Failed to run command inside function %s\n",__FUNCTION__ );
11358 return RETURN_ERR;
11359 }
11360
11361 /* Read the output a line at a time - output it. */
11362 fgets(str, sizeof(str)-1, fp);
11363 wifi_count = (unsigned int) atoi ( str );
11364 *output_array_size = wifi_count;
11365 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
11366 pclose(fp);
11367
11368 if(wifi_count == 0)
11369 {
11370 return RETURN_OK;
11371 }
11372 else
11373 {
11374 wifi_associated_dev2_t* temp = NULL;
11375 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
11376 *associated_dev_array = temp;
11377 if(temp == NULL)
11378 {
11379 printf("Error Statement. Insufficient memory \n");
11380 return RETURN_ERR;
11381 }
11382
11383 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
11384 system(pipeCmd);
11385
11386 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
11387 if(fp == NULL)
11388 {
11389 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
11390 return RETURN_ERR;
11391 }
11392 fclose(fp);
11393
11394 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
11395 fp = popen(pipeCmd, "r");
11396 if(fp)
11397 {
11398 for(count =0 ; count < wifi_count; count++)
11399 {
11400 fgets(str, MAX_BUF_SIZE, fp);
11401 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
11402 {
11403 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
11404 {
11405 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
11406
11407 }
11408 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
11409 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]);
11410 }
11411 temp[count].cli_AuthenticationState = 1; //TODO
11412 temp[count].cli_Active = 1; //TODO
11413 }
11414 pclose(fp);
11415 }
11416
11417 //Updating RSSI per client
11418 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt");
11419 fp = popen(pipeCmd, "r");
11420 if(fp)
11421 {
11422 pclose(fp);
11423 }
11424 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
11425 if(fp)
11426 {
11427 for(count =0 ; count < wifi_count ;count++)
11428 {
11429 fgets(str, MAX_BUF_SIZE, fp);
11430 signalstrength = atoi(str);
11431 temp[count].cli_RSSI = signalstrength;
11432 }
11433 pclose(fp);
11434 }
11435
11436
11437 //LastDataDownlinkRate
11438 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt");
11439 fp = popen(pipeCmd, "r");
11440 if (fp)
11441 {
11442 pclose(fp);
11443 }
11444 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
11445 if (fp)
11446 {
11447 for (count = 0; count < wifi_count; count++)
11448 {
11449 fgets(str, MAX_BUF_SIZE, fp);
11450 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
11451 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
11452 }
11453 pclose(fp);
11454 }
11455
11456 //LastDataUplinkRate
11457 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt");
11458 fp = popen(pipeCmd, "r");
11459 if (fp)
11460 {
11461 pclose(fp);
11462 }
11463 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
11464 if (fp)
11465 {
11466 for (count = 0; count < wifi_count; count++)
11467 {
11468 fgets(str, MAX_BUF_SIZE, fp);
11469 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
11470 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
11471 }
11472 pclose(fp);
11473 }
11474 }
11475 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11476 return RETURN_OK;
11477
11478}
11479
11480INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
11481{
11482#if 0
11483 /*char buf[1024] = {0};
11484 sprintf(cmd, "ifconfig %s ", interface_name);
11485 _syscmd(cmd, buf, sizeof(buf));*/
11486
11487 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
11488 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
11489 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
11490 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
11491
11492 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.
11493 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].
11494 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].
11495 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].
11496 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
11497 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
11498
11499 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
11500 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
11501 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
11502 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.
11503 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.
11504 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.
11505 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.
11506 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.
11507 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.
11508 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.
11509 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
11510#endif
11511
11512 FILE *fp = NULL;
11513 char interface_name[50] = {0};
11514 char pipeCmd[128] = {0};
11515 char str[256] = {0};
11516 wifi_ssidTrafficStats2_t *out = output_struct;
11517
11518 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
11519 if (!output_struct)
11520 return RETURN_ERR;
11521
11522 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
11523 if (wifi_GetInterfaceName(ssidIndex, interface_name) != RETURN_OK)
11524 return RETURN_ERR;
11525 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
11526
11527 fp = popen(pipeCmd, "r");
11528 if (fp == NULL) {
11529 fprintf(stderr, "%s: popen failed\n", __func__);
11530 return RETURN_ERR;
11531 }
11532 fgets(str, sizeof(str), fp);
11533 pclose(fp);
11534
11535 if (strlen(str) == 0) // interface not exist
11536 return RETURN_OK;
11537
developer5a333cf2023-06-06 18:18:50 +080011538 sscanf(str, "%*[^:]: %lu %lu %lu %lu %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
developer72fb0bb2023-01-11 09:46:29 +080011539 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
11540
11541 memset(str, 0, sizeof(str));
11542 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
11543 fp = popen(pipeCmd, "r");
11544 if (fp == NULL) {
11545 fprintf(stderr, "%s: popen failed\n", __func__);
11546 return RETURN_ERR;
11547 }
11548 fgets(str, sizeof(str), fp);
11549
developer5a333cf2023-06-06 18:18:50 +080011550 sscanf(str, "%*[^:]: %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
developer72fb0bb2023-01-11 09:46:29 +080011551 &out->ssid_BroadcastPacketsSent);
11552 pclose(fp);
11553
11554 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
11555 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
11556
11557 // Not supported
11558 output_struct->ssid_RetransCount = 0;
11559 output_struct->ssid_FailedRetransCount = 0;
11560 output_struct->ssid_RetryCount = 0;
11561 output_struct->ssid_MultipleRetryCount = 0;
11562 output_struct->ssid_ACKFailureCount = 0;
11563 output_struct->ssid_AggregatedPacketCount = 0;
11564
11565 return RETURN_OK;
11566}
11567
11568//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).
11569INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
11570{
11571 char output_val[16]={'\0'};
11572 char config_file[MAX_BUF_SIZE] = {0};
11573
11574 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11575 if (!output)
11576 return RETURN_ERR;
11577 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
11578 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
11579
11580 if( strcmp(output_val,"1") == 0 )
11581 *output = TRUE;
11582 else
11583 *output = FALSE;
11584 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11585
11586 return RETURN_OK;
11587}
11588
11589INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
11590{
11591 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +080011592 char string[MAX_BUF_SIZE]={'\0'};
developer72fb0bb2023-01-11 09:46:29 +080011593 char config_file[MAX_BUF_SIZE] = {0};
11594 struct params params;
11595
11596 if(enable == TRUE)
11597 strcpy(string,"1");
11598 else
11599 strcpy(string,"0");
11600
11601 params.name = "ap_isolate";
11602 params.value = string;
11603
11604 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
11605 wifi_hostapdWrite(config_file,&params,1);
11606 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11607
11608 return RETURN_OK;
11609}
11610
11611INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
11612{
developera1255e42023-05-13 17:45:02 +080011613 char mgmtpwr_file[32] = {0};
11614 char cmd[64] = {0};
11615 char buf[32]={0};
11616
developer72fb0bb2023-01-11 09:46:29 +080011617 if (NULL == output_dBm)
11618 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +080011619 snprintf(mgmtpwr_file, sizeof(mgmtpwr_file), "%s%d.txt", MGMT_POWER_CTRL, apIndex);
11620 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mgmtpwr_file);
11621 _syscmd(cmd, buf, sizeof(buf));
11622 if (strlen(buf) > 0)
11623 *output_dBm = strtol(buf, NULL, 10);
11624 else
11625 *output_dBm = 23;
developer72fb0bb2023-01-11 09:46:29 +080011626 return RETURN_OK;
11627}
11628
11629INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
11630{
developera1255e42023-05-13 17:45:02 +080011631 char interface_name[16] = {0};
developera1255e42023-05-13 17:45:02 +080011632 char mgmt_pwr_file[128]={0};
11633 FILE *f = NULL;
developerfead3972023-05-25 20:15:02 +080011634 int if_idx, ret = 0;
11635 struct nl_msg *msg = NULL;
11636 struct nlattr * msg_data = NULL;
11637 struct mtk_nl80211_param param;
11638 struct unl unl_ins;
11639 char power[16] = {0};
developera1255e42023-05-13 17:45:02 +080011640
11641 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11642
11643 if (wifi_GetInterfaceName(wlanIndex, interface_name) != RETURN_OK)
11644 return RETURN_ERR;
developerfead3972023-05-25 20:15:02 +080011645
11646 if_idx = if_nametoindex(interface_name);
11647 /*init mtk nl80211 vendor cmd*/
11648 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_TXPOWER;
11649 param.if_type = NL80211_ATTR_IFINDEX;
11650 param.if_idx = if_idx;
11651
11652 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
11653 if (ret) {
11654 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
11655 return RETURN_ERR;
11656 }
11657
11658 /*add mtk vendor cmd data*/
11659 snprintf(power, sizeof(power), "%d", dBm);
11660 if (nla_put(msg, MTK_NL80211_VENDOR_ATTR_TXPWR_MGMT, strlen(power), power)) {
11661 wifi_debug(DEBUG_ERROR, "Nla put attribute error\n");
11662 nlmsg_free(msg);
11663 goto err;
11664 }
11665
11666 /*send mtk nl80211 vendor msg*/
11667 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
11668 if (ret) {
11669 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
11670 goto err;
11671 }
11672
11673 /*deinit mtk nl80211 vendor msg*/
11674 mtk_nl80211_deint(&unl_ins);
11675 wifi_debug(DEBUG_NOTICE, "set cmd success.\n");
11676
developera1255e42023-05-13 17:45:02 +080011677 snprintf(mgmt_pwr_file, sizeof(mgmt_pwr_file), "%s%d.txt", MGMT_POWER_CTRL, wlanIndex);
11678 f = fopen(mgmt_pwr_file, "w");
11679 if (f == NULL) {
11680 fprintf(stderr, "%s: fopen failed\n", __func__);
11681 return RETURN_ERR;
11682 }
11683 fprintf(f, "%d", dBm);
11684 fclose(f);
developer72fb0bb2023-01-11 09:46:29 +080011685 return RETURN_OK;
developerfead3972023-05-25 20:15:02 +080011686err:
11687 mtk_nl80211_deint(&unl_ins);
11688 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
11689 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +080011690}
11691INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
11692{
11693 return RETURN_OK;
11694}
11695INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
11696{
11697 return RETURN_OK;
11698}
11699INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
11700{
11701 return RETURN_OK;
11702}
11703INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
11704{
11705 return RETURN_OK;
11706}
11707INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
11708{
11709 char config_file[MAX_BUF_SIZE] = {0};
11710 struct params list;
11711
11712 list.name = "bss_transition";
11713 list.value = activate?"1":"0";
11714 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
11715 wifi_hostapdWrite(config_file, &list, 1);
11716
11717 return RETURN_OK;
11718}
11719wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
11720
11721void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
11722{
11723 return;
11724}
11725
11726INT wifi_setApCsaDeauth(INT apIndex, INT mode)
11727{
11728 // TODO Implement me!
11729 return RETURN_OK;
11730}
11731
11732INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
11733{
11734 char file_name[128] = {0};
developer72fb0bb2023-01-11 09:46:29 +080011735 FILE *f = NULL;
11736 int max_num_radios = 0;
11737
11738 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11739
11740 wifi_getMaxRadioNumber(&max_num_radios);
11741 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
11742 for (int index = 0; index < max_num_radios; index++) {
11743 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
11744 f = fopen(file_name, "w");
11745 if (f == NULL)
11746 return RETURN_ERR;
11747 // For mode == 0 is to disable filter, just don't write to the file.
11748 if (mode)
11749 fprintf(f, "%s", essid);
11750
11751 fclose(f);
11752 }
11753 } else { // special case, need to set AP's SSID as filter for each radio.
11754 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
11755 f = fopen(file_name, "w");
11756 if (f == NULL)
11757 return RETURN_ERR;
11758
11759 // For mode == 0 is to disable filter, just don't write to the file.
11760 if (mode)
11761 fprintf(f, "%s", essid);
11762
11763 fclose(f);
11764 }
11765
11766 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11767 return RETURN_OK;
11768}
11769
11770INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
11771{
11772 // TODO Implement me!
11773 //Apply wifi_pushRadioChannel() instantly
11774 return RETURN_ERR;
11775}
11776
11777INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
11778{
11779 // TODO Implement me!
11780 return RETURN_OK;
11781}
11782
11783#ifdef HAL_NETLINK_IMPL
11784static int tidStats_callback(struct nl_msg *msg, void *arg) {
11785 struct nlattr *tb[NL80211_ATTR_MAX + 1];
11786 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
11787 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
11788 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
11789 int rem , tid_index = 0;
11790
11791 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
11792 wifi_associated_dev_tid_entry_t *stats_entry;
11793
11794 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
11795 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
11796 };
11797 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
11798 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
11799 };
11800
11801 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
11802 genlmsg_attrlen(gnlh, 0), NULL);
11803
11804
11805 if (!tb[NL80211_ATTR_STA_INFO]) {
11806 fprintf(stderr, "station stats missing!\n");
11807 return NL_SKIP;
11808 }
11809
11810 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
11811 tb[NL80211_ATTR_STA_INFO],
11812 stats_policy)) {
11813 fprintf(stderr, "failed to parse nested attributes!\n");
11814 return NL_SKIP;
11815 }
11816
developer386281b2023-05-20 15:43:13 +080011817 if (sinfo[NL80211_STA_INFO_TID_STATS]) {
11818 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
11819 {
11820 stats_entry = &out->tid_array[tid_index];
developer72fb0bb2023-01-11 09:46:29 +080011821
developer386281b2023-05-20 15:43:13 +080011822 stats_entry->tid = tid_index;
11823 stats_entry->ac = _tid_ac_index_get[tid_index];
developer72fb0bb2023-01-11 09:46:29 +080011824
developer386281b2023-05-20 15:43:13 +080011825 if(sinfo[NL80211_STA_INFO_TID_STATS])
11826 {
11827 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
11828 printf("failed to parse nested stats attributes!");
11829 return NL_SKIP;
11830 }
developer72fb0bb2023-01-11 09:46:29 +080011831 }
developer386281b2023-05-20 15:43:13 +080011832 if(stats_info[NL80211_TID_STATS_TX_MSDU])
11833 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
developer72fb0bb2023-01-11 09:46:29 +080011834
developer386281b2023-05-20 15:43:13 +080011835 if(tid_index < (PS_MAX_TID - 1))
11836 tid_index++;
11837 }
developer72fb0bb2023-01-11 09:46:29 +080011838 }
11839 //ToDo: sum_time_ms, ewma_time_ms
11840 return NL_SKIP;
11841}
11842#endif
11843
11844INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
11845{
11846#ifdef HAL_NETLINK_IMPL
11847 Netlink nl;
developerb149d9d2023-06-06 16:14:22 +080011848 char if_name[IF_NAME_SIZE];
11849 char interface_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +080011850
11851 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
11852 return RETURN_ERR;
11853
11854 snprintf(if_name, sizeof(if_name), "%s", interface_name);
11855
11856 nl.id = initSock80211(&nl);
11857
11858 if (nl.id < 0) {
11859 fprintf(stderr, "Error initializing netlink \n");
11860 return -1;
11861 }
11862
11863 struct nl_msg* msg = nlmsg_alloc();
11864
11865 if (!msg) {
11866 fprintf(stderr, "Failed to allocate netlink message.\n");
11867 nlfree(&nl);
11868 return -2;
11869 }
11870
11871 genlmsg_put(msg,
developer8dd72532023-05-17 19:58:35 +080011872 NL_AUTO_PID,
developer72fb0bb2023-01-11 09:46:29 +080011873 NL_AUTO_SEQ,
11874 nl.id,
11875 0,
11876 0,
11877 NL80211_CMD_GET_STATION,
11878 0);
11879
11880 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
11881 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
11882 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
developer8dd72532023-05-17 19:58:35 +080011883 nl_send_auto_complete(nl.socket, msg);
developer72fb0bb2023-01-11 09:46:29 +080011884 nl_recvmsgs(nl.socket, nl.cb);
11885 nlmsg_free(msg);
11886 nlfree(&nl);
11887 return RETURN_OK;
11888#else
11889//iw implementation
11890#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
11891#define TOTAL_MAX_LINES 50
11892
11893 char buf[256] = {'\0'}; /* or other suitable maximum line size */
11894 char if_name[32] = {0};
11895 FILE *fp=NULL;
11896 char pipeCmd[1024]= {'\0'};
11897 int lines,tid_index=0;
11898 char mac_addr[20] = {'\0'};
11899
11900 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
11901 return RETURN_ERR;
11902
11903 wifi_associated_dev_tid_entry_t *stats_entry;
11904
11905 strcpy(mac_addr,clientMacAddress);
11906
11907 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
11908 fp= popen(pipeCmd,"r");
11909 if(fp == NULL)
11910 {
11911 perror("popen for station dump failed\n");
11912 return RETURN_ERR;
11913 }
11914 pclose(fp);
11915
11916 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
11917 fp=popen(pipeCmd,"r");
11918 if(fp == NULL)
11919 {
11920 perror("popen for grep station failed\n");
11921 return RETURN_ERR;
11922 }
11923 else if(fgets(buf,sizeof(buf),fp) != NULL)
11924 lines=atoi(buf);
11925 else
11926 {
11927 pclose(fp);
11928 fprintf(stderr,"No devices are connected \n");
11929 return RETURN_ERR;
11930 }
11931 pclose(fp);
11932
11933 if(lines == 1)
11934 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
11935
11936 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
11937 {
11938 stats_entry = &tid_stats->tid_array[tid_index];
11939 stats_entry->tid = tid_index;
11940
11941 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);
11942
11943 fp=popen(pipeCmd,"r");
11944 if(fp ==NULL)
11945 {
11946 perror("Failed to read from tid file \n");
11947 return RETURN_ERR;
11948 }
11949 else if(fgets(buf,sizeof(buf),fp) != NULL)
11950 stats_entry->num_msdus = atol(buf);
11951
11952 pclose(fp);
11953 stats_entry->ac = _tid_ac_index_get[tid_index];
11954// TODO:
11955// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
11956// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
11957 }
11958 return RETURN_OK;
11959#endif
11960}
11961
11962
11963INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
11964{
11965 char interface_name[16] = {0};
11966 char cmd[128]={0};
11967 char buf[128]={0};
11968 int freq = 0;
11969
11970 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11971
11972 // full mode is used to scan all channels.
11973 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
11974 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
11975 ieee80211_channel_to_frequency(chan_list[0], &freq);
11976
11977 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
11978 return RETURN_ERR;
11979
11980 if (freq)
11981 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d freq %d", interface_name, dwell_time, freq);
11982 else
11983 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d", interface_name, dwell_time);
11984
11985 _syscmd(cmd, buf, sizeof(buf));
11986 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11987
11988 return RETURN_OK;
11989}
11990
11991
11992INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
11993{
11994 // TODO Implement me!
11995 return RETURN_ERR;
11996}
11997
11998INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
11999{
12000 // TODO Implement me!
12001 return RETURN_ERR;
12002}
12003
12004INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
12005{
12006 // TODO Implement me!
12007 return RETURN_ERR;
12008}
12009
12010INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
12011{
12012 // TODO Implement me!
12013 return RETURN_ERR;
12014}
12015
12016INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
12017{
12018 // TODO Implement me!
12019 return RETURN_ERR;
12020}
12021
12022INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
12023{
12024 // TODO Implement me!
12025 return RETURN_ERR;
12026}
12027
12028INT wifi_steering_eventUnregister(void)
12029{
12030 // TODO Implement me!
12031 return RETURN_ERR;
12032}
12033
12034INT wifi_delApAclDevices(INT apIndex)
12035{
developer7e4a2a62023-04-06 19:56:03 +080012036 char inf_name[IF_NAME_SIZE] = {0};
developer2edaf012023-05-24 14:24:53 +080012037 struct unl unl_ins;
12038 int if_idx = 0, ret = 0;
12039 struct nl_msg *msg = NULL;
12040 struct nlattr * msg_data = NULL;
12041 struct mtk_nl80211_param param;
developer72fb0bb2023-01-11 09:46:29 +080012042
developer7e4a2a62023-04-06 19:56:03 +080012043 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
12044 return RETURN_ERR;
developer2edaf012023-05-24 14:24:53 +080012045 if_idx = if_nametoindex(inf_name);
12046 if (!if_idx) {
12047 wifi_debug(DEBUG_ERROR,"can't finde ifname(%s) index,ERROR\n", inf_name);
12048 return RETURN_ERR;
12049 }
12050 /*init mtk nl80211 vendor cmd*/
12051 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_ACL;
12052 param.if_type = NL80211_ATTR_IFINDEX;
12053 param.if_idx = if_idx;
12054 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
12055 if (ret) {
12056 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
12057 return RETURN_ERR;
12058 }
12059 /*add mtk vendor cmd data*/
12060 if (nla_put_flag(msg, MTK_NL80211_VENDOR_ATTR_ACL_CLEAR_ALL)) {
12061 wifi_debug(DEBUG_ERROR, "Nla put attribute error\n");
12062 nlmsg_free(msg);
12063 goto err;
12064 }
12065 /*send mtk nl80211 vendor msg*/
12066 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
12067 if (ret) {
12068 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
12069 goto err;
12070 }
12071 /*deinit mtk nl80211 vendor msg*/
12072 mtk_nl80211_deint(&unl_ins);
12073 wifi_debug(DEBUG_NOTICE, "set cmd success.\n");
12074 return RETURN_OK;
12075err:
12076 mtk_nl80211_deint(&unl_ins);
12077 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
12078 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +080012079
12080 return RETURN_OK;
12081}
12082
12083#ifdef HAL_NETLINK_IMPL
12084static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
12085 struct nlattr *tb[NL80211_ATTR_MAX + 1];
12086 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
12087 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
12088 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
12089 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
12090 char mac_addr[20],dev[20];
12091
12092 nla_parse(tb,
12093 NL80211_ATTR_MAX,
12094 genlmsg_attrdata(gnlh, 0),
12095 genlmsg_attrlen(gnlh, 0),
12096 NULL);
12097
12098 if(!tb[NL80211_ATTR_STA_INFO]) {
12099 fprintf(stderr, "sta stats missing!\n");
12100 return NL_SKIP;
12101 }
12102
12103 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
12104 fprintf(stderr, "failed to parse nested attributes!\n");
12105 return NL_SKIP;
12106 }
12107 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
12108
12109 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
12110
developer386281b2023-05-20 15:43:13 +080012111 if (sinfo[NL80211_STA_INFO_RX_BITRATE]) {
12112 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
12113 fprintf(stderr, "failed to parse nested rate attributes!");
12114 return NL_SKIP;
12115 }
developer72fb0bb2023-01-11 09:46:29 +080012116 }
12117
12118 if(sinfo[NL80211_STA_INFO_TID_STATS])
12119 {
12120 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
12121 printf("failed to parse nested stats attributes!");
12122 return NL_SKIP;
12123 }
12124 }
developer5a1194f2023-05-24 16:00:03 +080012125 if (tb[NL80211_ATTR_VHT_CAPABILITY]) {
developer72fb0bb2023-01-11 09:46:29 +080012126
developereb1ea832023-05-24 14:46:27 +080012127 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
12128 {
12129 printf("Type is VHT\n");
12130 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
12131 ((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 +080012132
developereb1ea832023-05-24 14:46:27 +080012133 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
12134 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
12135 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
12136 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
12137 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
12138 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
12139 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
12140 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
12141 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
12142 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
12143 }
12144 else
12145 {
12146 printf(" OFDM or CCK \n");
12147 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
12148 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
12149 }
12150 }
developer72fb0bb2023-01-11 09:46:29 +080012151
developereff896f2023-05-29 14:52:55 +080012152 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
12153 if(rinfo[NL80211_RATE_INFO_MCS])
12154 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
12155 }
12156 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
12157 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
12158 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
12159 ((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 +080012160
developereff896f2023-05-29 14:52:55 +080012161 if(sinfo[NL80211_STA_INFO_TID_STATS]) {
12162 if(stats_info[NL80211_TID_STATS_RX_MSDU])
12163 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
12164 }
developer72fb0bb2023-01-11 09:46:29 +080012165
developereff896f2023-05-29 14:52:55 +080012166 if (sinfo[NL80211_STA_INFO_SIGNAL])
12167 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
12168 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
12169 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
12170 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
12171 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
12172 //rssi_array need to be filled
12173 return NL_SKIP;
developer72fb0bb2023-01-11 09:46:29 +080012174}
12175#endif
12176
12177INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
12178{
12179#ifdef HAL_NETLINK_IMPL
12180 Netlink nl;
12181 char if_name[32];
12182 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
12183 return RETURN_ERR;
12184
12185 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
12186
12187 if (*output_array_size <= 0)
12188 return RETURN_OK;
12189
12190 nl.id = initSock80211(&nl);
12191
12192 if (nl.id < 0) {
12193 fprintf(stderr, "Error initializing netlink \n");
12194 return 0;
12195 }
12196
12197 struct nl_msg* msg = nlmsg_alloc();
12198
12199 if (!msg) {
12200 fprintf(stderr, "Failed to allocate netlink message.\n");
12201 nlfree(&nl);
12202 return 0;
12203 }
12204
12205 genlmsg_put(msg,
developer8dd72532023-05-17 19:58:35 +080012206 NL_AUTO_PID,
developer72fb0bb2023-01-11 09:46:29 +080012207 NL_AUTO_SEQ,
12208 nl.id,
12209 0,
12210 0,
12211 NL80211_CMD_GET_STATION,
12212 0);
12213
12214 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
12215 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
12216 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
developer8dd72532023-05-17 19:58:35 +080012217 nl_send_auto_complete(nl.socket, msg);
developer72fb0bb2023-01-11 09:46:29 +080012218 nl_recvmsgs(nl.socket, nl.cb);
12219 nlmsg_free(msg);
12220 nlfree(&nl);
12221 return RETURN_OK;
12222#else
12223 //TODO Implement me
12224 return RETURN_OK;
12225#endif
12226}
12227
12228#ifdef HAL_NETLINK_IMPL
12229static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
12230 struct nlattr *tb[NL80211_ATTR_MAX + 1];
12231 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
12232 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
12233 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
12234 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
12235 char mac_addr[20],dev[20];
12236
12237 nla_parse(tb,
12238 NL80211_ATTR_MAX,
12239 genlmsg_attrdata(gnlh, 0),
12240 genlmsg_attrlen(gnlh, 0),
12241 NULL);
12242
12243 if(!tb[NL80211_ATTR_STA_INFO]) {
12244 fprintf(stderr, "sta stats missing!\n");
12245 return NL_SKIP;
12246 }
12247
12248 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
12249 fprintf(stderr, "failed to parse nested attributes!\n");
12250 return NL_SKIP;
12251 }
12252
12253 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
12254
12255 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
12256
developer386281b2023-05-20 15:43:13 +080012257 if (sinfo[NL80211_STA_INFO_TX_BITRATE]) {
12258 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
12259 fprintf(stderr, "failed to parse nested rate attributes!");
12260 return NL_SKIP;
12261 }
developer72fb0bb2023-01-11 09:46:29 +080012262 }
12263
12264 if(sinfo[NL80211_STA_INFO_TID_STATS])
12265 {
12266 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
12267 printf("failed to parse nested stats attributes!");
12268 return NL_SKIP;
12269 }
12270 }
developera6beea42023-05-24 16:44:05 +080012271 if (tb[NL80211_ATTR_VHT_CAPABILITY]) {
developereb1ea832023-05-24 14:46:27 +080012272 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
12273 {
12274 printf("Type is VHT\n");
12275 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
12276 ((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 +080012277
developereb1ea832023-05-24 14:46:27 +080012278 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
12279 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
12280 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
12281 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
12282 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
12283 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
12284 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
12285 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
12286 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
12287 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
12288 }
12289 else
12290 {
12291 printf(" OFDM or CCK \n");
developer72fb0bb2023-01-11 09:46:29 +080012292 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
developereb1ea832023-05-24 14:46:27 +080012293 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
12294 }
developer72fb0bb2023-01-11 09:46:29 +080012295 }
12296
12297 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
12298 if(rinfo[NL80211_RATE_INFO_MCS])
12299 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
12300 }
12301
12302 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
12303 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
12304 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
12305 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
12306
12307 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
developereff896f2023-05-29 14:52:55 +080012308 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
12309 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
developer72fb0bb2023-01-11 09:46:29 +080012310
developereff896f2023-05-29 14:52:55 +080012311 if(sinfo[NL80211_STA_INFO_TID_STATS]) {
12312 if(stats_info[NL80211_TID_STATS_TX_MSDU])
12313 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
12314 }
developer72fb0bb2023-01-11 09:46:29 +080012315
12316 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
12317 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
12318
developereff896f2023-05-29 14:52:55 +080012319 if(sinfo[NL80211_STA_INFO_TX_FAILED] && sinfo[NL80211_STA_INFO_TX_PACKETS])
12320 ((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 +080012321
12322 return NL_SKIP;
12323}
12324#endif
12325
12326INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
12327{
12328#ifdef HAL_NETLINK_IMPL
12329 Netlink nl;
developerb149d9d2023-06-06 16:14:22 +080012330 char if_name[IF_NAME_SIZE];
12331 char interface_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +080012332 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
12333 return RETURN_ERR;
12334
12335 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
12336
12337 if (*output_array_size <= 0)
12338 return RETURN_OK;
12339
12340 snprintf(if_name, sizeof(if_name), "%s", interface_name);
12341
12342 nl.id = initSock80211(&nl);
12343
12344 if(nl.id < 0) {
12345 fprintf(stderr, "Error initializing netlink \n");
12346 return 0;
12347 }
12348
12349 struct nl_msg* msg = nlmsg_alloc();
12350
12351 if(!msg) {
12352 fprintf(stderr, "Failed to allocate netlink message.\n");
12353 nlfree(&nl);
12354 return 0;
12355 }
12356
12357 genlmsg_put(msg,
developer8dd72532023-05-17 19:58:35 +080012358 NL_AUTO_PID,
developer72fb0bb2023-01-11 09:46:29 +080012359 NL_AUTO_SEQ,
12360 nl.id,
12361 0,
12362 0,
12363 NL80211_CMD_GET_STATION,
12364 0);
12365
12366 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
12367 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
12368 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
developer8dd72532023-05-17 19:58:35 +080012369 nl_send_auto_complete(nl.socket, msg);
developer72fb0bb2023-01-11 09:46:29 +080012370 nl_recvmsgs(nl.socket, nl.cb);
12371 nlmsg_free(msg);
12372 nlfree(&nl);
12373 return RETURN_OK;
12374#else
12375 //TODO Implement me
12376 return RETURN_OK;
12377#endif
12378}
12379
12380INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
12381{
12382 // TODO Implement me!
12383 char buf[MAX_BUF_SIZE] = {0};
12384 char config_file[MAX_BUF_SIZE] = {0};
12385
12386 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
12387 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
12388 *activate = (strncmp("1",buf,1) == 0);
12389
12390 return RETURN_OK;
12391}
12392
12393INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
12394{
12395 char config_file[MAX_BUF_SIZE] = {0};
12396 struct params list;
12397
12398 list.name = "rrm_neighbor_report";
12399 list.value = activate?"1":"0";
12400 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
12401 wifi_hostapdWrite(config_file, &list, 1);
12402
12403 return RETURN_OK;
12404}
12405
12406INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
12407{
12408 char buf[32] = {0};
12409 char config_file[MAX_BUF_SIZE] = {0};
12410
12411 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
12412 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
12413 *activate = (strncmp("1",buf,1) == 0);
12414
12415 return RETURN_OK;
12416}
12417#undef HAL_NETLINK_IMPL
12418#ifdef HAL_NETLINK_IMPL
12419static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
12420 struct nlattr *tb[NL80211_ATTR_MAX + 1];
12421 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
12422 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
12423 char dev[20];
12424 int freq =0 ;
12425 static int i=0;
12426
12427 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
12428
12429 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
12430 };
12431
12432 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
12433
12434 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
12435
12436 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
12437 fprintf(stderr, "survey data missing!\n");
12438 return NL_SKIP;
12439 }
12440
12441 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
12442 {
12443 fprintf(stderr, "failed to parse nested attributes!\n");
12444 return NL_SKIP;
12445 }
12446
12447
12448 if(out[0].array_size == 1 )
12449 {
12450 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
12451 {
12452 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
12453 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
12454 out[0].ch_number = ieee80211_frequency_to_channel(freq);
12455
12456 if (sinfo[NL80211_SURVEY_INFO_NOISE])
12457 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
12458 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
12459 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
12460 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
12461 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
12462 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
12463 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
12464 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
12465 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
12466 if (sinfo[NL80211_SURVEY_INFO_TIME])
12467 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
12468 return NL_STOP;
12469 }
12470 }
12471 else
12472 {
12473 if ( i <= out[0].array_size )
12474 {
12475 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
12476 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
12477 out[i].ch_number = ieee80211_frequency_to_channel(freq);
12478
12479 if (sinfo[NL80211_SURVEY_INFO_NOISE])
12480 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
12481 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
12482 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
12483 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
12484 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
12485 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
12486 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
12487 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
12488 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
12489 if (sinfo[NL80211_SURVEY_INFO_TIME])
12490 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
12491 }
12492 }
12493
12494 i++;
12495 return NL_SKIP;
12496}
12497#endif
12498
12499static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
12500{
12501 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
12502 FILE *fp;
12503
12504 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
12505 {
12506 printf("Creating Frequency-Channel Map\n");
12507 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
12508 }
12509 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
12510 if((fp = popen(command, "r")))
12511 {
12512 fgets(output, sizeof(output), fp);
12513 *freqMHz = atoi(output);
12514 pclose(fp);
12515 }
12516
12517 return 0;
12518}
12519
developer2f79c922023-06-02 17:33:42 +080012520static int get_survey_dump_buf(INT radioIndex, int channel, char *buf, size_t bufsz)
developer72fb0bb2023-01-11 09:46:29 +080012521{
12522 int freqMHz = -1;
12523 char cmd[MAX_CMD_SIZE] = {'\0'};
12524 char interface_name[16] = {0};
12525
12526 ieee80211_channel_to_frequency(channel, &freqMHz);
12527 if (freqMHz == -1) {
12528 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
12529 return -1;
12530 }
12531
12532 wifi_GetInterfaceName(radioIndex, interface_name);
12533 if (sprintf(cmd,"iw dev %s survey dump | grep -A5 %d | tr -d '\\t'", interface_name, freqMHz) < 0) {
12534 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
12535 radioIndex, freqMHz);
12536 return -1;
12537 }
12538
12539 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
12540 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
12541 return -1;
12542 }
12543
12544 return 0;
12545}
12546
12547static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
12548{
12549 const char *ptr = buf;
12550 char *key = NULL;
12551 char *val = NULL;
12552 char line[256] = { '\0' };
12553
developerdaf24792023-06-06 11:40:04 +080012554 while ((ptr = get_line_from_str_buf(ptr, line))) {
developer72fb0bb2023-01-11 09:46:29 +080012555 if (strstr(line, "Frequency")) continue;
12556
12557 key = strtok(line, ":");
12558 val = strtok(NULL, " ");
12559 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
12560
12561 if (!strcmp(key, "noise")) {
12562 sscanf(val, "%d", &stats->ch_noise);
12563 if (stats->ch_noise == 0) {
12564 // Workaround for missing noise information.
12565 // Assume -95 for 2.4G and -103 for 5G
12566 if (radioIndex == 0) stats->ch_noise = -95;
12567 if (radioIndex == 1) stats->ch_noise = -103;
12568 }
12569 }
12570 else if (!strcmp(key, "channel active time")) {
12571 sscanf(val, "%llu", &stats->ch_utilization_total);
12572 }
12573 else if (!strcmp(key, "channel busy time")) {
12574 sscanf(val, "%llu", &stats->ch_utilization_busy);
12575 }
12576 else if (!strcmp(key, "channel receive time")) {
12577 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
12578 }
12579 else if (!strcmp(key, "channel transmit time")) {
12580 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
12581 }
12582 };
12583
12584 return 0;
12585}
12586
12587INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
12588{
12589 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12590#ifdef HAL_NETLINK_IMPL
12591 Netlink nl;
12592 wifi_channelStats_t_loc local[array_size];
12593 char if_name[32];
12594
12595 local[0].array_size = array_size;
12596
12597 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
12598 return RETURN_ERR;
12599
12600 nl.id = initSock80211(&nl);
12601
12602 if (nl.id < 0) {
12603 fprintf(stderr, "Error initializing netlink \n");
12604 return -1;
12605 }
12606
12607 struct nl_msg* msg = nlmsg_alloc();
12608
12609 if (!msg) {
12610 fprintf(stderr, "Failed to allocate netlink message.\n");
12611 nlfree(&nl);
12612 return -2;
12613 }
12614
12615 genlmsg_put(msg,
developer8dd72532023-05-17 19:58:35 +080012616 NL_AUTO_PID,
developer72fb0bb2023-01-11 09:46:29 +080012617 NL_AUTO_SEQ,
12618 nl.id,
12619 0,
12620 NLM_F_DUMP,
12621 NL80211_CMD_GET_SURVEY,
12622 0);
12623
12624 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
developer8dd72532023-05-17 19:58:35 +080012625 nl_send_auto_complete(nl.socket, msg);
developer72fb0bb2023-01-11 09:46:29 +080012626 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
12627 nl_recvmsgs(nl.socket, nl.cb);
12628 nlmsg_free(msg);
12629 nlfree(&nl);
12630 //Copying the Values
12631 for(int i=0;i<array_size;i++)
12632 {
12633 input_output_channelStats_array[i].ch_number = local[i].ch_number;
12634 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
12635 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
12636 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
12637 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
12638 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
12639 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
12640 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
12641 }
12642#else
12643 ULONG channel = 0;
12644 int i;
12645 int number_of_channels = array_size;
12646 char buf[512];
developer72fb0bb2023-01-11 09:46:29 +080012647
12648 if (number_of_channels == 0) {
12649 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
12650 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
12651 return RETURN_ERR;
12652 }
12653 number_of_channels = 1;
12654 input_output_channelStats_array[0].ch_number = channel;
12655 }
12656
12657 for (i = 0; i < number_of_channels; i++) {
12658
12659 input_output_channelStats_array[i].ch_noise = 0;
12660 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
12661 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
12662 input_output_channelStats_array[i].ch_utilization_busy = 0;
12663 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
12664 input_output_channelStats_array[i].ch_utilization_total = 0;
12665
12666 memset(buf, 0, sizeof(buf));
12667 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
12668 return RETURN_ERR;
12669 }
12670 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
12671 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
12672 return RETURN_ERR;
12673 }
12674
12675 // XXX: fake missing 'self' counter which is not available in iw survey output
12676 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
12677 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
12678
12679 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
12680 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
12681 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
12682 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
12683 input_output_channelStats_array[i].ch_utilization_total *= 1000;
12684
12685 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",
12686 __func__,
12687 input_output_channelStats_array[i].ch_number,
12688 input_output_channelStats_array[i].ch_noise,
12689 input_output_channelStats_array[i].ch_utilization_total,
12690 input_output_channelStats_array[i].ch_utilization_busy,
12691 input_output_channelStats_array[i].ch_utilization_busy_rx,
12692 input_output_channelStats_array[i].ch_utilization_busy_tx,
12693 input_output_channelStats_array[i].ch_utilization_busy_self,
12694 input_output_channelStats_array[i].ch_utilization_busy_ext);
12695 }
12696#endif
12697 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12698 return RETURN_OK;
12699}
12700#define HAL_NETLINK_IMPL
12701
12702/* Hostapd events */
12703
12704#ifndef container_of
12705#define offset_of(st, m) ((size_t)&(((st *)0)->m))
12706#define container_of(ptr, type, member) \
12707 ((type *)((char *)ptr - offset_of(type, member)))
12708#endif /* container_of */
12709
12710struct ctrl {
12711 char sockpath[128];
12712 char sockdir[128];
12713 char bss[IFNAMSIZ];
12714 char reply[4096];
12715 int ssid_index;
12716 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
12717 void (*overrun)(struct ctrl *ctrl);
12718 struct wpa_ctrl *wpa;
12719 unsigned int ovfl;
12720 size_t reply_len;
12721 int initialized;
12722 ev_timer retry;
12723 ev_timer watchdog;
12724 ev_stat stat;
12725 ev_io io;
12726};
12727static wifi_newApAssociatedDevice_callback clients_connect_cb;
12728static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
12729static struct ctrl wpa_ctrl[MAX_APS];
12730static int initialized;
12731
12732static unsigned int ctrl_get_drops(struct ctrl *ctrl)
12733{
12734 char cbuf[256] = {};
12735 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
12736 struct cmsghdr *cmsg;
12737 unsigned int ovfl = ctrl->ovfl;
12738 unsigned int drop;
12739
12740 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
12741 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
12742 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
12743 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
12744
12745 drop = ovfl - ctrl->ovfl;
12746 ctrl->ovfl = ovfl;
12747
12748 return drop;
12749}
12750
12751static void ctrl_close(struct ctrl *ctrl)
12752{
12753 if (ctrl->io.cb)
12754 ev_io_stop(EV_DEFAULT_ &ctrl->io);
12755 if (ctrl->retry.cb)
12756 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
12757 if (!ctrl->wpa)
12758 return;
12759
12760 wpa_ctrl_detach(ctrl->wpa);
12761 wpa_ctrl_close(ctrl->wpa);
12762 ctrl->wpa = NULL;
12763 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
12764}
12765
12766static void ctrl_process(struct ctrl *ctrl)
12767{
12768 const char *str;
12769 int drops;
12770 int level;
developer72fb0bb2023-01-11 09:46:29 +080012771
12772 /* Example events:
12773 *
12774 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
12775 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
12776 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
12777 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
12778 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
12779 */
12780 if (!(str = index(ctrl->reply, '>')))
12781 return;
12782 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
12783 return;
12784
12785 str++;
12786
12787 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
12788 if (!(str = index(ctrl->reply, ' ')))
12789 return;
12790 wifi_associated_dev_t sta;
12791 memset(&sta, 0, sizeof(sta));
12792
12793 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
12794 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
12795 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
12796
12797 sta.cli_Active=true;
12798
12799 (clients_connect_cb)(ctrl->ssid_index, &sta);
12800 goto handled;
12801 }
12802
12803 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
12804 if (!(str = index(ctrl->reply, ' ')))
12805 return;
12806
12807 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
12808 goto handled;
12809 }
12810
12811 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
12812 printf("CTRL_WPA: handle TERMINATING event\n");
12813 goto retry;
12814 }
12815
12816 if (strncmp("AP-DISABLED", str, 11) == 0) {
12817 printf("CTRL_WPA: handle AP-DISABLED\n");
12818 goto retry;
12819 }
12820
12821 printf("Event not supported!!\n");
12822
12823handled:
12824
12825 if ((drops = ctrl_get_drops(ctrl))) {
12826 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
12827 if (ctrl->overrun)
12828 ctrl->overrun(ctrl);
12829 }
12830
12831 return;
12832
12833retry:
12834 printf("WPA_CTRL: closing\n");
12835 ctrl_close(ctrl);
12836 printf("WPA_CTRL: retrying from ctrl prcoess\n");
12837 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
12838}
12839
12840static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
12841{
12842 struct ctrl *ctrl = container_of(io, struct ctrl, io);
12843 int err;
12844
12845 memset(ctrl->reply, 0, sizeof(ctrl->reply));
12846 ctrl->reply_len = sizeof(ctrl->reply) - 1;
12847 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
12848 ctrl->reply[ctrl->reply_len] = 0;
12849 if (err < 0) {
12850 if (errno == EAGAIN || errno == EWOULDBLOCK)
12851 return;
12852 ctrl_close(ctrl);
12853 ev_timer_again(EV_A_ &ctrl->retry);
12854 return;
12855 }
12856
12857 ctrl_process(ctrl);
12858}
12859
12860static int ctrl_open(struct ctrl *ctrl)
12861{
12862 int fd;
12863
12864 if (ctrl->wpa)
12865 return 0;
12866
12867 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
12868 if (!ctrl->wpa)
12869 goto err;
12870
12871 if (wpa_ctrl_attach(ctrl->wpa) < 0)
12872 goto err_close;
12873
12874 fd = wpa_ctrl_get_fd(ctrl->wpa);
12875 if (fd < 0)
12876 goto err_detach;
12877
12878 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
12879 goto err_detach;
12880
12881 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
12882 ev_io_start(EV_DEFAULT_ &ctrl->io);
12883
12884 return 0;
12885
12886err_detach:
12887 wpa_ctrl_detach(ctrl->wpa);
12888err_close:
12889 wpa_ctrl_close(ctrl->wpa);
12890err:
12891 ctrl->wpa = NULL;
12892 return -1;
12893}
12894
12895static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
12896{
12897 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
12898
12899 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
12900 ctrl_open(ctrl);
12901}
12902
12903static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
12904{
12905 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
12906
12907 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
12908 if (ctrl_open(ctrl) == 0) {
12909 printf("WPA_CTRL: retry successful\n");
12910 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
12911 }
12912}
12913
12914int ctrl_enable(struct ctrl *ctrl)
12915{
12916 if (ctrl->wpa)
12917 return 0;
12918
12919 if (!ctrl->stat.cb) {
12920 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
12921 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
12922 }
12923
12924 if (!ctrl->retry.cb) {
12925 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
12926 }
12927
12928 return ctrl_open(ctrl);
12929}
12930
12931static void
12932ctrl_msg_cb(char *buf, size_t len)
12933{
12934 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
12935
12936 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
12937 ctrl_process(ctrl);
12938}
12939
12940static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
12941{
12942 int err;
12943
12944 if (!ctrl->wpa)
12945 return -1;
12946 if (*reply_len < 2)
12947 return -1;
12948
12949 (*reply_len)--;
12950 ctrl->reply_len = sizeof(ctrl->reply);
12951 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
12952 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
12953 if (err < 0)
12954 return err;
12955
12956 if (ctrl->reply_len > *reply_len)
12957 ctrl->reply_len = *reply_len;
12958
12959 *reply_len = ctrl->reply_len;
12960 memcpy(reply, ctrl->reply, *reply_len);
12961 reply[*reply_len - 1] = 0;
12962 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
12963 return 0;
12964}
12965
12966static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
12967{
12968 const char *pong = "PONG";
12969 const char *ping = "PING";
12970 char reply[1024];
12971 size_t len = sizeof(reply);
12972 int err;
12973 ULONG s, snum;
12974 INT ret;
12975 BOOL status;
12976
12977 printf("WPA_CTRL: watchdog cb\n");
12978
12979 ret = wifi_getSSIDNumberOfEntries(&snum);
12980 if (ret != RETURN_OK) {
12981 printf("%s: failed to get SSID count", __func__);
12982 return;
12983 }
12984
12985 if (snum > MAX_APS) {
12986 printf("more ssid than supported! %lu\n", snum);
12987 return;
12988 }
12989
12990 for (s = 0; s < snum; s++) {
12991 if (wifi_getApEnable(s, &status) != RETURN_OK) {
12992 printf("%s: failed to get AP Enable for index: %lu\n", __func__, s);
12993 continue;
12994 }
12995 if (status == false) continue;
12996
12997 memset(reply, 0, sizeof(reply));
12998 len = sizeof(reply);
12999 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
13000 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
13001 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
13002 continue;
13003
13004 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
13005 ctrl_close(&wpa_ctrl[s]);
13006 printf("WPA_CTRL: ev_timer_again %lu\n", s);
13007 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
13008 }
13009}
13010
13011static int init_wpa()
13012{
developer2f79c922023-06-02 17:33:42 +080013013 int ret = 0;
developer72fb0bb2023-01-11 09:46:29 +080013014 ULONG s, snum;
13015
13016 ret = wifi_getSSIDNumberOfEntries(&snum);
13017 if (ret != RETURN_OK) {
13018 printf("%s: failed to get SSID count", __func__);
13019 return RETURN_ERR;
13020 }
13021
13022 if (snum > MAX_APS) {
13023 printf("more ssid than supported! %lu\n", snum);
13024 return RETURN_ERR;
13025 }
13026
13027 for (s = 0; s < snum; s++) {
13028 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
13029 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
13030 wpa_ctrl[s].ssid_index = s;
13031 ctrl_enable(&wpa_ctrl[s]);
13032 }
13033
13034 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
13035 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
13036
13037 initialized = 1;
13038 printf("WPA_CTRL: initialized\n");
13039
13040 return RETURN_OK;
13041}
13042
13043void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
13044{
13045 clients_connect_cb = callback_proc;
13046 if (!initialized)
13047 init_wpa();
13048}
13049
13050void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
13051{
13052 clients_disconnect_cb = callback_proc;
13053 if (!initialized)
13054 init_wpa();
13055}
13056
13057INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
13058{
13059 // TODO Implement me!
13060 return RETURN_ERR;
13061}
13062
13063INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
13064{
13065 // TODO Implement me!
13066 return RETURN_ERR;
13067}
13068
13069INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
13070{
13071 int i;
developerd1824452023-05-18 12:30:04 +080013072 int phyId = -1;
13073 char cmd[256] = {0};
13074 char channel_numbers_buf[256] = {0};
13075 char dfs_state_buf[256] = {0};
13076 char line[256] = {0};
developer72fb0bb2023-01-11 09:46:29 +080013077 const char *ptr;
developerd1824452023-05-18 12:30:04 +080013078 BOOL dfs_enable = false;
developer72fb0bb2023-01-11 09:46:29 +080013079
developerd1824452023-05-18 12:30:04 +080013080 memset(outputMap, 0, outputMapSize*sizeof(wifi_channelMap_t)); // all unused entries should be zero
developer72fb0bb2023-01-11 09:46:29 +080013081
developerd1824452023-05-18 12:30:04 +080013082 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
13083 phyId = radio_index_to_phy(radioIndex);
developer72fb0bb2023-01-11 09:46:29 +080013084
developerd1824452023-05-18 12:30:04 +080013085 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 +080013086
developerd1824452023-05-18 12:30:04 +080013087 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
13088 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
13089 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +080013090 }
13091
developerd1824452023-05-18 12:30:04 +080013092 ptr = channel_numbers_buf;
13093 i = 0;
developerdaf24792023-06-06 11:40:04 +080013094 while ((ptr = get_line_from_str_buf(ptr, line))) {
developerd1824452023-05-18 12:30:04 +080013095 if (i >= outputMapSize) {
13096 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
13097 return RETURN_ERR;
13098 }
13099 sscanf(line, "%d", &outputMap[i].ch_number);
13100
13101 memset(cmd, 0, sizeof(cmd));
13102 // Below command should fetch string for DFS state (usable, available or unavailable)
13103 // Example line: "DFS state: usable (for 78930 sec)"
13104 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) {
13105 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
developer72fb0bb2023-01-11 09:46:29 +080013106 return RETURN_ERR;
13107 }
13108
developerd1824452023-05-18 12:30:04 +080013109 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
13110 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
developer72fb0bb2023-01-11 09:46:29 +080013111 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
13112 return RETURN_ERR;
13113 }
13114
developerd1824452023-05-18 12:30:04 +080013115 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
developer59fda4f2023-05-16 15:47:38 +080013116
developerd1824452023-05-18 12:30:04 +080013117 if (!strcmp(dfs_state_buf, "usable")) {
13118 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
13119 } else if (!strcmp(dfs_state_buf, "available")) {
13120 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
13121 } else if (!strcmp(dfs_state_buf, "unavailable")) {
13122 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
13123 } else {
13124 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
developer72fb0bb2023-01-11 09:46:29 +080013125 }
developerd1824452023-05-18 12:30:04 +080013126 i++;
developer59fda4f2023-05-16 15:47:38 +080013127 }
developer40ba1762023-05-13 11:03:49 +080013128
developerd1824452023-05-18 12:30:04 +080013129 return RETURN_OK;
13130
developer72fb0bb2023-01-11 09:46:29 +080013131 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
13132 return RETURN_ERR;
13133}
13134
13135INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
13136{
13137 // TODO Implement me!
13138 return RETURN_ERR;
13139}
13140
13141INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
13142{
13143 return RETURN_OK;
13144}
13145
13146INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
13147{
13148 // TODO Implement me!
13149 return RETURN_ERR;
13150}
13151
13152INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
13153{
13154 // TODO API refrence Implementaion is present on RPI hal
13155 return RETURN_ERR;
13156}
13157
13158INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
13159{
developera1255e42023-05-13 17:45:02 +080013160/*
developer72fb0bb2023-01-11 09:46:29 +080013161 char interface_name[16] = {0};
13162 char cmd[128]={'\0'};
13163 char buf[128]={'\0'};
13164 char *support;
13165 int maximum_tx = 0, current_tx = 0;
developera1255e42023-05-13 17:45:02 +080013166*/ ULONG pwr_percentage = 0;
developer72fb0bb2023-01-11 09:46:29 +080013167
13168 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13169 if(txpwr_pcntg == NULL)
developerdaf24792023-06-06 11:40:04 +080013170 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +080013171
developera1255e42023-05-13 17:45:02 +080013172 wifi_getRadioTransmitPower(apIndex, &pwr_percentage);
13173 *txpwr_pcntg = pwr_percentage;
13174/* if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72fb0bb2023-01-11 09:46:29 +080013175 return RETURN_ERR;
13176
13177 // Get the maximum tx power of the device
13178 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", interface_name);
13179 _syscmd(cmd, buf, sizeof(buf));
13180 maximum_tx = strtol(buf, NULL, 10);
13181
13182 // Get the current tx power
13183 memset(cmd, 0, sizeof(cmd));
13184 memset(buf, 0, sizeof(buf));
13185 snprintf(cmd, sizeof(cmd), "iw %s info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", interface_name);
13186 _syscmd(cmd, buf, sizeof(buf));
13187 current_tx = strtol(buf, NULL, 10);
13188
13189 // Get the power supported list and find the current power percentage in supported list
13190 memset(buf, 0, sizeof(buf));
13191 wifi_getRadioTransmitPowerSupported(apIndex, buf);
13192 support = strtok(buf, ",");
13193 while(true)
13194 {
13195 if(support == NULL) { // current power is not in supported list, this should not happen if the power is set by hal.
13196 *txpwr_pcntg = 100;
13197 wifi_dbg_printf("current power is not in supported list\n");
13198 return RETURN_OK;
13199 }
13200 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
13201 if (tmp == current_tx) {
13202 *txpwr_pcntg = strtol(support, NULL, 10);
13203 break;
13204 }
13205 support = strtok(NULL, ",");
13206 }
developera1255e42023-05-13 17:45:02 +080013207*/
developer72fb0bb2023-01-11 09:46:29 +080013208 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13209 return RETURN_OK;
13210}
13211
13212INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
13213{
13214 // TODO precac feature.
developerd1824452023-05-18 12:30:04 +080013215 struct params params[2] = {0};
developer72fb0bb2023-01-11 09:46:29 +080013216 char config_file[128] = {0};
developerd1824452023-05-18 12:30:04 +080013217 BOOL dfs_enable = false;
13218 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +080013219
13220 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developerd1824452023-05-18 12:30:04 +080013221 band = wifi_index_to_band(radioIndex);
13222 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
developer72fb0bb2023-01-11 09:46:29 +080013223
developerd1824452023-05-18 12:30:04 +080013224 if (dfs_enable == false) {
13225 WIFI_ENTRY_EXIT_DEBUG("Please enable DFS firstly!: %s\n", __func__);
13226 return RETURN_ERR;
13227 }
13228 params[0].name = "DfsZeroWaitDefault";
13229 params[0].value = enable?"1":"0";
13230 params[1].name = "DfsDedicatedZeroWait";
13231 params[1].value = enable?"1":"0";
13232 snprintf(config_file, sizeof(config_file), "%s%d.dat", LOGAN_DAT_FILE, band);
13233 wifi_datfileWrite(config_file, params, 2);
developerc0772e62023-05-18 15:10:48 +080013234 wifi_reloadAp(radioIndex);
developer72fb0bb2023-01-11 09:46:29 +080013235 /* TODO precac feature */
13236
13237 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13238 return RETURN_OK;
13239}
13240
13241INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
13242{
13243 char config_file[128] = {0};
developerd1824452023-05-18 12:30:04 +080013244 char buf1[32] = {0};
13245 char buf2[32] = {0};
13246 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +080013247
13248 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13249 if (NULL == enable || NULL == precac)
13250 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +080013251 band = wifi_index_to_band(radioIndex);
13252 snprintf(config_file, sizeof(config_file), "%s%d.dat", LOGAN_DAT_FILE, band);
13253 wifi_datfileRead(config_file, "DfsZeroWaitDefault", buf1, sizeof(buf1));
13254 wifi_datfileRead(config_file, "DfsDedicatedZeroWait", buf2, sizeof(buf2));
13255 if ((strncmp(buf1, "1", 1) == 0) && (strncmp(buf2, "1", 1) == 0))
developer72fb0bb2023-01-11 09:46:29 +080013256 *enable = true;
13257 else
13258 *enable = false;
13259
13260 /* TODO precac feature */
13261
13262 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13263 return RETURN_OK;
13264}
13265
13266INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
13267{
13268 *supported = TRUE;
13269 return RETURN_OK;
13270}
13271
13272INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
13273{
developer863a4a62023-06-06 16:55:59 +080013274 CHAR dat_file[64] = {0};
developera1255e42023-05-13 17:45:02 +080013275 wifi_band band = band_invalid;
developera1255e42023-05-13 17:45:02 +080013276 char ofdmabuf[32] = {'\0'};
13277 char mimobuf[32] = {'\0'};
13278 char new_ofdmabuf[32] = {'\0'};
13279 char new_mimobuf[32] = {'\0'};
13280 struct params params[2];
13281 char *str_zero = "0;0;0;0;0;0;0;0;0;0;0;0;0;0;0";/*default 15bss per band.*/
13282 char *str_one = "1;1;1;1;1;1;1;1;1;1;1;1;1;1;1";
13283 UCHAR bss_cnt = 0;
13284 UCHAR val_cnt = 0;
developer72fb0bb2023-01-11 09:46:29 +080013285
developera1255e42023-05-13 17:45:02 +080013286 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13287 if ((mu_type < WIFI_DL_MU_TYPE_NONE)
13288 || (mu_type > WIFI_DL_MU_TYPE_OFDMA_MIMO)) {
13289 printf("%s:mu_type input Error", __func__);
13290 return RETURN_ERR;
13291 }
13292 band = wifi_index_to_band(radio_index);
13293 if (band == band_invalid) {
13294 printf("%s:Band Error\n", __func__);
13295 return RETURN_ERR;
13296 }
13297 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
13298 /*get current value in dat file*/
13299 wifi_datfileRead(dat_file, "MuOfdmaDlEnable", ofdmabuf, sizeof(ofdmabuf));
13300 wifi_datfileRead(dat_file, "MuMimoDlEnable", mimobuf, sizeof(mimobuf));
13301 WIFI_ENTRY_EXIT_DEBUG("%s:ofdma-%s, mimo-%s\n", __func__, ofdmabuf, mimobuf);
13302 get_bssnum_byindex(radio_index, &bss_cnt);
13303 val_cnt = 2*bss_cnt - 1;
13304 WIFI_ENTRY_EXIT_DEBUG("bss number: %d\n", bss_cnt);
13305 if ((val_cnt >= sizeof(new_ofdmabuf))
13306 || (val_cnt >= sizeof(new_mimobuf))) {
developer49c83812023-06-06 14:23:53 +080013307 printf("%s:bss cnt Error", __func__);
developera1255e42023-05-13 17:45:02 +080013308 return RETURN_ERR;
13309 }
13310 /*translate set value*/
13311 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
13312 strncpy(new_ofdmabuf, str_zero, val_cnt);
13313 strncpy(new_mimobuf, str_zero, val_cnt);
developer72fb0bb2023-01-11 09:46:29 +080013314 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
developera1255e42023-05-13 17:45:02 +080013315 strncpy(new_ofdmabuf, str_one, val_cnt);
13316 strncpy(new_mimobuf, str_zero, val_cnt);
developer72fb0bb2023-01-11 09:46:29 +080013317 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
developera1255e42023-05-13 17:45:02 +080013318 strncpy(new_ofdmabuf, str_zero, val_cnt);
13319 strncpy(new_mimobuf, str_one, val_cnt);
13320 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO) {
13321 strncpy(new_ofdmabuf, str_one, val_cnt);
13322 strncpy(new_mimobuf, str_one, val_cnt);
developer72fb0bb2023-01-11 09:46:29 +080013323 }
developera1255e42023-05-13 17:45:02 +080013324 WIFI_ENTRY_EXIT_DEBUG("%s:new_ofdmabuf-%s, new_mimobuf-%s\n", __func__, new_ofdmabuf, new_mimobuf);
13325 /*same value, not operation*/
13326 if ((strncmp(new_mimobuf, mimobuf, 1) ==0)
13327 && (strncmp(new_ofdmabuf, ofdmabuf, 1) ==0)) {
13328 printf("%s:Reduntant value\n", __func__);
13329 return RETURN_OK;
13330 }
13331 /*modify dat file to new file*/
13332 params[0].name="MuOfdmaDlEnable";
13333 params[0].value=new_ofdmabuf;
13334 params[1].name="MuMimoDlEnable";
13335 params[1].value=new_mimobuf;
13336 wifi_datfileWrite(dat_file, params, 2);
13337 /*hostapd control restarp ap to take effect on these new value*/
13338 wifi_reloadAp(radio_index);
developer72fb0bb2023-01-11 09:46:29 +080013339 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13340 return RETURN_OK;
13341}
13342
13343INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
13344{
developer5a333cf2023-06-06 18:18:50 +080013345 CHAR dat_file[64] = {0};
developera1255e42023-05-13 17:45:02 +080013346 wifi_band band = band_invalid;
13347 char ofdmabuf[32] = {'\0'};
13348 char mimobuf[32] = {'\0'};
13349 char *token = NULL;
13350 UCHAR ofdma = 0;
13351 UCHAR mimo = 0;
developer72fb0bb2023-01-11 09:46:29 +080013352
13353 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13354
13355 if (mu_type == NULL)
13356 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +080013357 band = wifi_index_to_band(radio_index);
13358 if (band == band_invalid) {
13359 printf("%s:Band Error\n", __func__);
13360 return RETURN_ERR;
13361 }
13362 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
13363 /*get current value in dat file*/
13364 wifi_datfileRead(dat_file, "MuOfdmaDlEnable", ofdmabuf, sizeof(ofdmabuf));
13365 wifi_datfileRead(dat_file, "MuMimoDlEnable", mimobuf, sizeof(mimobuf));
developer72fb0bb2023-01-11 09:46:29 +080013366
developera1255e42023-05-13 17:45:02 +080013367 token = strtok(ofdmabuf, ";");
13368 ofdma = strtol(token, NULL, 10);
13369 token = strtok(mimobuf, ";");
13370 mimo = strtol(token, NULL, 10);
13371 WIFI_ENTRY_EXIT_DEBUG("%s:ofdma=%d,mimo=%d\n", __func__, ofdma, mimo);
13372 if ((ofdma == 1) && (mimo == 1))
13373 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
13374 else if ((ofdma == 0) && (mimo == 1))
13375 *mu_type = WIFI_DL_MU_TYPE_MIMO;
13376 else if ((ofdma == 1) && (mimo == 0))
13377 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
13378 else
13379 *mu_type = WIFI_DL_MU_TYPE_NONE;
developer72fb0bb2023-01-11 09:46:29 +080013380 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13381 return RETURN_OK;
13382}
13383
13384INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
13385{
13386 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
developer863a4a62023-06-06 16:55:59 +080013387 CHAR dat_file[64] = {0};
developera1255e42023-05-13 17:45:02 +080013388 wifi_band band = band_invalid;
developera1255e42023-05-13 17:45:02 +080013389 char ofdmabuf[32] = {'\0'};
13390 char mimobuf[32] = {'\0'};
13391 char new_ofdmabuf[32] = {'\0'};
13392 char new_mimobuf[32] = {'\0'};
13393 struct params params[2];
13394 char *str_zero = "0;0;0;0;0;0;0;0;0;0;0;0;0;0;0";/*default 15bss per band.*/
13395 char *str_one = "1;1;1;1;1;1;1;1;1;1;1;1;1;1;1";
13396 UCHAR bss_cnt = 0;
13397 UCHAR val_cnt = 0;
developer72fb0bb2023-01-11 09:46:29 +080013398
developera1255e42023-05-13 17:45:02 +080013399 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13400 band = wifi_index_to_band(radio_index);
13401 if (band == band_invalid) {
13402 printf("%s:Band Error\n", __func__);
13403 return RETURN_ERR;
13404 }
13405 if ((mu_type < WIFI_UL_MU_TYPE_NONE)
13406 || (mu_type > WIFI_UL_MU_TYPE_OFDMA)) {
13407 printf("%s:mu_type input Error\n", __func__);
13408 return RETURN_ERR;
13409 }
13410 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
13411 /*get current value in dat file*/
13412 wifi_datfileRead(dat_file, "MuOfdmaUlEnable", ofdmabuf, sizeof(ofdmabuf));
13413 wifi_datfileRead(dat_file, "MuMimoUlEnable", mimobuf, sizeof(mimobuf));
13414 WIFI_ENTRY_EXIT_DEBUG("%s:ofdma-%s, mimo-%s\n", __func__, ofdmabuf, mimobuf);
13415 get_bssnum_byindex(radio_index, &bss_cnt);
13416 val_cnt = 2*bss_cnt - 1;
13417 printf("bssNumber:%d,ValCnt:%d\n", bss_cnt, val_cnt);
13418 if ((val_cnt >= sizeof(new_ofdmabuf))
13419 || (val_cnt >= sizeof(new_mimobuf))) {
developer49c83812023-06-06 14:23:53 +080013420 printf("%s:bss cnt Error\n", __func__);
developera1255e42023-05-13 17:45:02 +080013421 return RETURN_ERR;
13422 }
13423 /*translate set value*/
13424 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
13425 strncpy(new_ofdmabuf, str_zero, val_cnt);
13426 strncpy(new_mimobuf, str_zero, val_cnt);
developer72fb0bb2023-01-11 09:46:29 +080013427 }
developera1255e42023-05-13 17:45:02 +080013428 if (mu_type == WIFI_UL_MU_TYPE_OFDMA) {
13429 strncpy(new_ofdmabuf, str_one, val_cnt);
13430 strncpy(new_mimobuf, str_zero, val_cnt);
13431 }
13432 printf("%s:new_ofdmabuf-%s, new_mimobuf-%s\n", __func__, new_ofdmabuf, new_mimobuf);
13433 /*same value, not operation*/
13434 if ((strncmp(new_mimobuf, mimobuf, 1) ==0)
13435 && (strncmp(new_ofdmabuf, ofdmabuf, 1) ==0)) {
13436 printf("%s:Reduntant value\n", __func__);
13437 return RETURN_OK;
13438 }
13439 /*modify dat file to new file*/
13440 params[0].name="MuOfdmaUlEnable";
13441 params[0].value=new_ofdmabuf;
13442 params[1].name="MuMimoUlEnable";
13443 params[1].value=new_mimobuf;
13444 wifi_datfileWrite(dat_file, params, 2);
13445 wifi_reloadAp(radio_index);
developer72fb0bb2023-01-11 09:46:29 +080013446 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13447 return RETURN_OK;
13448}
13449
13450INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
13451{
developer863a4a62023-06-06 16:55:59 +080013452 CHAR dat_file[64] = {0};
developera1255e42023-05-13 17:45:02 +080013453 wifi_band band = band_invalid;
13454 char ofdmabuf[32] = {'\0'};
13455 char mimobuf[32] = {'\0'};
13456 char *token = NULL;
13457 UCHAR ofdma = 0;
13458 UCHAR mimo = 0;
developer72fb0bb2023-01-11 09:46:29 +080013459
13460 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13461
13462 if (mu_type == NULL)
13463 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +080013464 band = wifi_index_to_band(radio_index);
13465 if (band == band_invalid) {
13466 printf("%s:Band Error", __func__);
13467 return RETURN_ERR;
13468 }
13469 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
13470 /*get current value in dat file*/
13471 wifi_datfileRead(dat_file, "MuOfdmaUlEnable", ofdmabuf, sizeof(ofdmabuf));
13472 wifi_datfileRead(dat_file, "MuMimoUlEnable", mimobuf, sizeof(mimobuf));
developer72fb0bb2023-01-11 09:46:29 +080013473
developera1255e42023-05-13 17:45:02 +080013474 token = strtok(ofdmabuf, ";");
13475 ofdma = strtol(token, NULL, 10);
13476 token = strtok(mimobuf, ";");
13477 mimo = strtol(token, NULL, 10);
13478 WIFI_ENTRY_EXIT_DEBUG("%s:ofdma=%d, mimo=%d\n", __func__, ofdma, mimo);
13479 if ((ofdma == 1) && (mimo == 0))
13480 *mu_type = WIFI_UL_MU_TYPE_OFDMA;
13481 else
13482 *mu_type = WIFI_UL_MU_TYPE_NONE;
developer72fb0bb2023-01-11 09:46:29 +080013483 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13484 return RETURN_OK;
13485}
13486
13487
13488INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
13489{
13490 char cmd[128] = {0};
13491 char buf[256] = {0};
13492 char config_file[64] = {0};
13493 char GI[8] = {0};
developer863a4a62023-06-06 16:55:59 +080013494 UINT mode_map = 0;
developer72fb0bb2023-01-11 09:46:29 +080013495 FILE *f = NULL;
13496 wifi_band band = band_invalid;
developera1255e42023-05-13 17:45:02 +080013497 char dat_file[64] = {'\0'};
13498 struct params params[3];
developer72fb0bb2023-01-11 09:46:29 +080013499
13500 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13501
13502 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
13503 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
13504 return RETURN_ERR;
13505 }
developera1255e42023-05-13 17:45:02 +080013506 /*sanity check*/
13507 if (((guard_interval == wifi_guard_interval_1600)
13508 || (guard_interval == wifi_guard_interval_3200))
developerdaf24792023-06-06 11:40:04 +080013509 && ((mode_map & (WIFI_MODE_BE | WIFI_MODE_AX)) == 0)) {
developera1255e42023-05-13 17:45:02 +080013510 wifi_dbg_printf("%s: N/AC Mode not support 1600/3200ns GI\n", __func__);
13511 return RETURN_ERR;
13512 }
developer72fb0bb2023-01-11 09:46:29 +080013513 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
13514 band = wifi_index_to_band(radio_index);
13515
13516 // Hostapd are not supported HE mode GI 1600, 3200 ns.
13517 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
13518 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
13519 _syscmd(cmd, buf, sizeof(buf));
13520 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
13521 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
13522 if (strstr(buf, "[SHORT-GI-") == NULL) {
13523 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[SHORT-GI-20][SHORT-GI-40]/' %s", config_file);
13524 _syscmd(cmd, buf, sizeof(buf));
13525 }
13526 if (band == band_5) {
13527 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
13528 if (strstr(buf, "[SHORT-GI-") == NULL) {
13529 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SHORT-GI-80][SHORT-GI-160]/' %s", config_file);
13530 _syscmd(cmd, buf, sizeof(buf));
13531 }
13532 }
13533 }
developera1255e42023-05-13 17:45:02 +080013534 /*wifi_reloadAp(radio_index);
13535 caller "wifi_setRadioOperatingParameters" have done this step.
13536 */
13537 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
13538 if (guard_interval == wifi_guard_interval_400) {
13539 params[0].name = "HT_GI";
13540 params[0].value = "1";
13541 params[1].name = "VHT_SGI";
13542 params[1].value = "1";
13543 wifi_datfileWrite(dat_file, params, 2);
developer72fb0bb2023-01-11 09:46:29 +080013544 strcpy(GI, "0.4");
developera1255e42023-05-13 17:45:02 +080013545 } else {
13546 params[0].name = "HT_GI";
13547 params[0].value = "0";
13548 params[1].name = "VHT_SGI";
13549 params[1].value = "0";
13550 /*should enable FIXED_HE_GI_SUPPORT in driver*/
13551 params[2].name = "FgiFltf";
13552 if (guard_interval == wifi_guard_interval_800) {
13553 params[2].value = "800";
13554 strcpy(GI, "0.8");
13555 } else if (guard_interval == wifi_guard_interval_1600) {
13556 params[2].value = "1600";
13557 strcpy(GI, "1.6");
13558 } else if (guard_interval == wifi_guard_interval_3200) {
13559 params[2].value = "3200";
13560 strcpy(GI, "3.2");
13561 } else if (guard_interval == wifi_guard_interval_auto) {
13562 params[2].value = "0";
13563 strcpy(GI, "auto");
13564 }
13565 wifi_datfileWrite(dat_file, params, 3);
13566 }
developer72fb0bb2023-01-11 09:46:29 +080013567 // Record GI for get GI function
13568 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
13569 f = fopen(buf, "w");
13570 if (f == NULL)
13571 return RETURN_ERR;
13572 fprintf(f, "%s", GI);
13573 fclose(f);
13574 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13575 return RETURN_OK;
13576}
13577
13578INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
13579{
13580 char buf[32] = {0};
13581 char cmd[64] = {0};
13582
13583 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13584
13585 if (guard_interval == NULL)
13586 return RETURN_ERR;
13587
developera1255e42023-05-13 17:45:02 +080013588 snprintf(cmd, sizeof(cmd), "cat %s%d.txt 2> /dev/null", GUARD_INTERVAL_FILE, radio_index);
developer72fb0bb2023-01-11 09:46:29 +080013589 _syscmd(cmd, buf, sizeof(buf));
13590
13591 if (strncmp(buf, "0.4", 3) == 0)
13592 *guard_interval = wifi_guard_interval_400;
13593 else if (strncmp(buf, "0.8", 3) == 0)
13594 *guard_interval = wifi_guard_interval_800;
13595 else if (strncmp(buf, "1.6", 3) == 0)
13596 *guard_interval = wifi_guard_interval_1600;
13597 else if (strncmp(buf, "3.2", 3) == 0)
13598 *guard_interval = wifi_guard_interval_3200;
13599 else
13600 *guard_interval = wifi_guard_interval_auto;
13601
13602 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13603 return RETURN_OK;
13604}
13605
13606INT wifi_setBSSColor(INT radio_index, UCHAR color)
13607{
13608 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13609 struct params params = {0};
13610 char config_file[128] = {0};
13611 char bss_color[4] ={0};
13612
developera1255e42023-05-13 17:45:02 +080013613 if (color < 1 || color > 63) {
13614 wifi_dbg_printf("color value is err:%d.\n", color);
13615 return RETURN_ERR;
13616 }
developer72fb0bb2023-01-11 09:46:29 +080013617 params.name = "he_bss_color";
13618 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
13619 params.value = bss_color;
13620 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
13621 wifi_hostapdWrite(config_file, &params, 1);
developera1255e42023-05-13 17:45:02 +080013622 //wifi_hostapdProcessUpdate(radio_index, &params, 1);
13623 wifi_reloadAp(radio_index);
developer69b61b02023-03-07 17:17:44 +080013624
developer72fb0bb2023-01-11 09:46:29 +080013625 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13626 return RETURN_OK;
13627}
13628
13629INT wifi_getBSSColor(INT radio_index, UCHAR *color)
13630{
13631 char config_file[128] = {0};
13632 char buf[64] = {0};
13633 char temp_output[128] = {'\0'};
13634
13635 wifi_dbg_printf("\nFunc=%s\n", __func__);
13636 if (NULL == color)
13637 return RETURN_ERR;
13638
13639 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
13640 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
13641
13642 if(strlen(buf) > 0) {
13643 snprintf(temp_output, sizeof(temp_output), "%s", buf);
13644 } else {
13645 snprintf(temp_output, sizeof(temp_output), "1"); // default value
13646 }
13647
13648 *color = (UCHAR)strtoul(temp_output, NULL, 10);
13649 wifi_dbg_printf("\noutput_string=%s\n", color);
13650
13651 return RETURN_OK;
13652}
13653
13654/* multi-psk support */
13655INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
13656{
13657 char cmd[256];
13658 char interface_name[16] = {0};
13659
13660 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
13661 return RETURN_ERR;
13662
13663 sprintf(cmd, "hostapd_cli -i %s sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
13664 interface_name,
13665 mac[0],
13666 mac[1],
13667 mac[2],
13668 mac[3],
13669 mac[4],
13670 mac[5]
13671 );
13672 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
13673 _syscmd(cmd, key->wifi_keyId, 64);
13674
13675
13676 return RETURN_OK;
13677}
13678
13679INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
13680{
13681 char interface_name[16] = {0};
13682 FILE *fd = NULL;
13683 char fname[100];
13684 char cmd[128] = {0};
13685 char out[64] = {0};
13686 wifi_key_multi_psk_t * key = NULL;
13687 if(keysNumber < 0)
13688 return RETURN_ERR;
13689
13690 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
13691 fd = fopen(fname, "w");
13692 if (!fd) {
13693 return RETURN_ERR;
13694 }
13695 key= (wifi_key_multi_psk_t *) keys;
13696 for(int i=0; i<keysNumber; ++i, key++) {
13697 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
13698 }
13699 fclose(fd);
13700
13701 //reload file
13702 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
13703 return RETURN_ERR;
13704 sprintf(cmd, "hostapd_cli -i%s raw RELOAD_WPA_PSK", interface_name);
13705 _syscmd(cmd, out, 64);
13706 return RETURN_OK;
13707}
13708
13709INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
13710{
13711 FILE *fd = NULL;
13712 char fname[100];
13713 char * line = NULL;
13714 char * pos = NULL;
13715 size_t len = 0;
13716 ssize_t read = 0;
13717 INT ret = RETURN_OK;
13718 wifi_key_multi_psk_t *keys_it = NULL;
13719
13720 if (keysNumber < 1) {
13721 return RETURN_ERR;
13722 }
13723
13724 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
13725 fd = fopen(fname, "r");
13726 if (!fd) {
13727 return RETURN_ERR;
13728 }
13729
13730 if (keys == NULL) {
13731 ret = RETURN_ERR;
13732 goto close;
13733 }
13734
13735 keys_it = keys;
13736 while ((read = getline(&line, &len, fd)) != -1) {
13737 //Strip trailing new line if present
13738 if (read > 0 && line[read-1] == '\n') {
13739 line[read-1] = '\0';
13740 }
13741
13742 if(strcmp(line,"keyid=")) {
developerdaf24792023-06-06 11:40:04 +080013743 sscanf(line, "keyid=%s", keys_it->wifi_keyId);
developer72fb0bb2023-01-11 09:46:29 +080013744 if (!(pos = index(line, ' '))) {
13745 ret = RETURN_ERR;
13746 goto close;
13747 }
13748 pos++;
13749 //Here should be 00:00:00:00:00:00
13750 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
13751 printf("Not supported MAC: %s\n", pos);
13752 }
13753 if (!(pos = index(pos, ' '))) {
13754 ret = RETURN_ERR;
13755 goto close;
13756 }
13757 pos++;
13758
13759 //The rest is PSK
13760 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
13761 keys_it++;
13762
13763 if(--keysNumber <= 0)
13764 break;
13765 }
13766 }
13767
13768close:
13769 free(line);
13770 fclose(fd);
13771 return ret;
13772}
13773/* end of multi-psk support */
13774
13775INT wifi_setNeighborReports(UINT apIndex,
13776 UINT numNeighborReports,
13777 wifi_NeighborReport_t *neighborReports)
13778{
13779 char cmd[256] = { 0 };
13780 char hex_bssid[13] = { 0 };
13781 char bssid[18] = { 0 };
developerb149d9d2023-06-06 16:14:22 +080013782 char nr[100] = { 0 };
13783 char ssid[32];
13784 char hex_ssid[32];
developer72fb0bb2023-01-11 09:46:29 +080013785 char interface_name[16] = {0};
13786 INT ret;
13787
13788 /*rmeove all neighbors*/
13789 wifi_dbg_printf("\n[%s]: removing all neighbors from %s\n", __func__, interface_name);
13790 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
13791 return RETURN_ERR;
13792 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);
13793 system(cmd);
13794
13795 for(unsigned int i = 0; i < numNeighborReports; i++)
13796 {
13797 memset(ssid, 0, sizeof(ssid));
13798 ret = wifi_getSSIDName(apIndex, ssid);
13799 if (ret != RETURN_OK)
13800 return RETURN_ERR;
13801
13802 memset(hex_ssid, 0, sizeof(hex_ssid));
13803 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
13804 sprintf(hex_ssid + k,"%02x", ssid[j]);
13805
13806 snprintf(hex_bssid, sizeof(hex_bssid),
13807 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
13808 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
13809 snprintf(bssid, sizeof(bssid),
13810 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
13811 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
13812
13813 snprintf(nr, sizeof(nr),
13814 "%s" // bssid
13815 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
13816 "%02hhx" // operclass
13817 "%02hhx" // channel
13818 "%02hhx", // phy_mode
13819 hex_bssid,
13820 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
13821 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
13822 neighborReports[i].opClass,
13823 neighborReports[i].channel,
13824 neighborReports[i].phyTable);
13825
13826 snprintf(cmd, sizeof(cmd),
13827 "hostapd_cli set_neighbor "
13828 "%s " // bssid
13829 "ssid=%s " // ssid
13830 "nr=%s " // nr
13831 "-i %s",
13832 bssid,hex_ssid,nr, interface_name);
13833
13834 if (WEXITSTATUS(system(cmd)) != 0)
13835 {
13836 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
13837 }
13838 }
13839
13840 return RETURN_OK;
13841}
13842
13843INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
13844{
13845 return RETURN_OK;
13846}
13847
13848#ifdef _WIFI_HAL_TEST_
13849int main(int argc,char **argv)
13850{
13851 int index;
13852 INT ret=0;
13853 char buf[1024]="";
13854
13855 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13856 if(argc<3)
13857 {
13858 if(argc==2)
13859 {
13860 if(!strcmp(argv[1], "init"))
13861 return wifi_init();
13862 if(!strcmp(argv[1], "reset"))
13863 return wifi_reset();
13864 if(!strcmp(argv[1], "wifi_getHalVersion"))
13865 {
13866 char buffer[64];
13867 if(wifi_getHalVersion(buffer)==RETURN_OK)
13868 printf("Version: %s\n", buffer);
13869 else
13870 printf("Error in wifi_getHalVersion\n");
13871 return RETURN_OK;
13872 }
13873 }
13874 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
13875 exit(-1);
13876 }
13877
13878 index = atoi(argv[2]);
13879 if(strstr(argv[1], "wifi_getApName")!=NULL)
13880 {
13881 wifi_getApName(index,buf);
13882 printf("Ap name is %s \n",buf);
13883 return 0;
13884 }
developerfead3972023-05-25 20:15:02 +080013885 if(strstr(argv[1], "wifi_setRadioMode")!=NULL)
13886 {
13887 UINT pureMode = atoi(argv[3]);
13888
13889 wifi_setRadioMode(index, NULL, pureMode);
13890 printf("Ap SET Radio mode 0x%x\n", pureMode);
13891 return 0;
13892 }
13893 if(strstr(argv[1], "wifi_setRadioTransmitPower")!=NULL)
13894 {
13895 ULONG TransmitPower = atoi(argv[3]);
13896
13897 wifi_setRadioTransmitPower(index, TransmitPower);
13898 printf("Ap SET TransmitPower %lu\n", TransmitPower);
13899 return 0;
13900 }
13901 if(strstr(argv[1], "wifi_setApManagementFramePowerControl")!=NULL)
13902 {
13903 INT TransmitPower = atoi(argv[3]);
13904
13905 wifi_setApManagementFramePowerControl(index, TransmitPower);
13906 printf("Ap SET Mgnt TransmitPower %d\n", TransmitPower);
13907 return 0;
13908 }
13909 if(strstr(argv[1], "wifi_setRadioBW")!=NULL)
13910 {
13911 CHAR *bandwith = argv[3];
13912
13913 wifi_setRadioOperatingChannelBandwidth(index, bandwith);
13914 printf("Ap SET bw %s\n", bandwith);
13915 return 0;
13916 }
13917 if(strstr(argv[1], "wifi_factoryResetRadio")!=NULL)
13918 {
13919 wifi_factoryResetRadio(index);
13920 printf("wifi_factoryResetRadio ok!\n");
13921 return 0;
13922 }
13923 if(strstr(argv[1], "wifi_getRadioResetCount")!=NULL)
13924 {
13925 ULONG rst_cnt;
13926 wifi_getRadioResetCount(index, &rst_cnt);
13927 printf("wifi_factoryResetRadio rst_cnt = %lu\n", rst_cnt);
13928 return 0;
13929 }
developer2edaf012023-05-24 14:24:53 +080013930 if (strncmp(argv[1], "wifi_addApAclDevice", strlen(argv[1])) == 0) {
developer49b17232023-05-19 16:35:19 +080013931 if(argc <= 3 )
13932 {
developer2edaf012023-05-24 14:24:53 +080013933 wifi_debug(DEBUG_ERROR, "Insufficient arguments \n");
developer49b17232023-05-19 16:35:19 +080013934 exit(-1);
13935 }
13936 wifi_addApAclDevice(index, argv[3]);
13937 return 0;
13938 }
developer2edaf012023-05-24 14:24:53 +080013939 if (strncmp(argv[1], "wifi_getApAclDevices", strlen(argv[1])) == 0) {
13940 wifi_getApAclDevices(index, buf, 1024);
13941 wifi_debug(DEBUG_NOTICE, "Ap acl Devices: %s\n", buf);
developer121a8e72023-05-22 09:19:39 +080013942 return 0;
13943 }
developer2edaf012023-05-24 14:24:53 +080013944 if (strncmp(argv[1], "wifi_delApAclDevice", strlen(argv[1])) == 0) {
13945 if(argc <= 3 )
13946 {
13947 wifi_debug(DEBUG_ERROR, "Insufficient arguments \n");
13948 exit(-1);
13949 }
13950 wifi_delApAclDevice(index, argv[3]);
13951 return 0;
13952 }
13953 if (strncmp(argv[1], "wifi_delApAclDevices", strlen(argv[1])) == 0) {
13954 wifi_delApAclDevices(index);
13955 return 0;
13956 }
13957 if (strncmp(argv[1], "wifi_getApAclDeviceNum", strlen(argv[1])) == 0) {
developer863a4a62023-06-06 16:55:59 +080013958 UINT acl_num = 0;
developer2edaf012023-05-24 14:24:53 +080013959 wifi_getApAclDeviceNum(index, &acl_num);
13960 wifi_debug(DEBUG_NOTICE, "Ap acl numbers: %d\n", acl_num);
13961 return 0;
13962 }
13963 if (strncmp(argv[1], "wifi_getApDenyAclDevices", strlen(argv[1])) == 0) {
13964 wifi_getApDenyAclDevices(index, buf, 1024);
13965 wifi_debug(DEBUG_NOTICE, "Ap Deny Acl Devices: %s\n", buf);
13966 return 0;
13967 }
13968 if (strncmp(argv[1], "wifi_setApMacAddressControlMode", strlen(argv[1])) == 0) {
13969 int filter_mode = 0;
13970 if(argc <= 3 )
13971 {
13972 wifi_debug(DEBUG_ERROR, "Insufficient arguments \n");
13973 exit(-1);
13974 }
13975 filter_mode = atoi(argv[3]);
13976 wifi_setApMacAddressControlMode(index,filter_mode);
13977 return 0;
13978 }
developer5cd4c862023-05-26 09:34:42 +080013979 if (strncmp(argv[1], "wifi_getRadioDeclineBARequestEnable", strlen(argv[1])) == 0) {
13980 BOOL output_bool = 0;
13981 wifi_getRadioDeclineBARequestEnable(index, &output_bool);
13982 wifi_debug(DEBUG_NOTICE, "Ap get radio ba decline enable: %d\n", output_bool);
13983 return 0;
13984 }
13985 if (strncmp(argv[1], "wifi_getRadioAutoBlockAckEnable", strlen(argv[1])) == 0) {
13986 BOOL output_bool = 0;
13987 wifi_getRadioAutoBlockAckEnable(index, &output_bool);
13988 wifi_debug(DEBUG_NOTICE, "Ap get radio auto_ba enable: %d\n", output_bool);
13989 return 0;
13990 }
13991
13992 if (strncmp(argv[1], "wifi_getApMacAddressControlMode", strlen(argv[1])) == 0) {
13993 int filter_mode = 0;
13994 wifi_getApMacAddressControlMode(index, &filter_mode);
13995 wifi_debug(DEBUG_NOTICE, "Ap MacAddress Control Mode: %d\n", filter_mode);
13996 return 0;
13997 }
13998 if (strncmp(argv[1], "wifi_setRadioIGMPSnoopingEnable", strlen(argv[1])) == 0) {
13999 int enable = 0;
14000 if(argc <= 3 )
14001 {
14002 wifi_debug(DEBUG_ERROR, "Insufficient arguments \n");
14003 exit(-1);
14004 }
14005 enable = (BOOL)atoi(argv[3]);
14006 wifi_setRadioIGMPSnoopingEnable(index, enable);
14007 wifi_debug(DEBUG_NOTICE, "Ap set IGMP Snooping Enable: %d\n", enable);
14008 return 0;
14009 }
14010
14011 if (strncmp(argv[1], "wifi_getRadioIGMPSnoopingEnable", strlen(argv[1])) == 0) {
14012 BOOL out_status = 0;
14013 wifi_getRadioIGMPSnoopingEnable(index, &out_status);
14014 wifi_debug(DEBUG_NOTICE, "Ap get IGMP Snooping Enable: %d\n", out_status);
14015 return 0;
14016 }
developer121a8e72023-05-22 09:19:39 +080014017
developer95c045d2023-05-24 19:26:28 +080014018 if (strncmp(argv[1], "wifi_setApWmmEnable", strlen(argv[1])) == 0) {
14019 int enable = 0;
14020 if(argc <= 3)
14021 {
14022 wifi_debug(DEBUG_ERROR, "Insufficient arguments \n");
14023 exit(-1);
14024 }
14025 enable = atoi(argv[3]);
14026 wifi_setApWmmEnable(index,enable);
14027 return 0;
14028 }
developer56fbedb2023-05-30 16:47:05 +080014029 if (strncmp(argv[1], "wifi_down", strlen(argv[1])) == 0) {
14030 wifi_down();
14031 return 0;
14032 }
developer95c045d2023-05-24 19:26:28 +080014033
developer56fbedb2023-05-30 16:47:05 +080014034 if (strncmp(argv[1], "wifi_getRadioStatus", strlen(argv[1])) == 0) {
14035 BOOL enable = 0;
14036
14037 wifi_getRadioStatus(index, &enable);
14038 wifi_debug(DEBUG_NOTICE, "wifi_getRadioStatus enable: %d\n", (int)enable);
14039 return 0;
14040 }
developer333c1eb2023-05-31 14:59:39 +080014041
developer95c045d2023-05-24 19:26:28 +080014042 if (strncmp(argv[1], "wifi_getApWMMCapability", strlen(argv[1])) == 0) {
14043 BOOL enable = 0;
14044
14045 wifi_getApWMMCapability(index, &enable);
14046 wifi_debug(DEBUG_NOTICE, "wifi_getApWMMCapability enable: %d\n", (int)enable);
14047 return 0;
14048 }
14049
14050 if (strncmp(argv[1], "wifi_getApWmmEnable", strlen(argv[1])) == 0) {
14051 BOOL enable = 0;
14052
14053 wifi_getApWmmEnable(index, &enable);
14054 wifi_debug(DEBUG_NOTICE, "wifi_getApWmmEnable enable: %d\n", (int)enable);
14055 return 0;
14056 }
14057
developer2edaf012023-05-24 14:24:53 +080014058 if (strncmp(argv[1], "wifi_getApMacAddressControlMode", strlen(argv[1])) == 0) {
14059 int filter_mode = 0;
14060 wifi_getApMacAddressControlMode(index, &filter_mode);
14061 wifi_debug(DEBUG_NOTICE, "Ap MacAddress Control Mode: %d\n", filter_mode);
14062 return 0;
14063 }
developer0f10c772023-05-16 21:43:39 +080014064 if(strstr(argv[1], "wifi_getRadioMode")!=NULL)
14065 {
developer863a4a62023-06-06 16:55:59 +080014066 UINT mode = 0;
developer0f10c772023-05-16 21:43:39 +080014067
14068 wifi_getRadioMode(index, buf, &mode);
14069 printf("Ap Radio mode is %s , mode = 0x%x\n", buf, mode);
14070 return 0;
14071 }
developer72fb0bb2023-01-11 09:46:29 +080014072 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
14073 {
14074 BOOL b = FALSE;
14075 BOOL *output_bool = &b;
14076 wifi_getRadioAutoChannelEnable(index,output_bool);
14077 printf("Channel enabled = %d \n",b);
14078 return 0;
14079 }
14080 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
14081 {
14082 wifi_getApWpaEncryptionMode(index,buf);
14083 printf("encryption enabled = %s\n",buf);
14084 return 0;
14085 }
14086 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
14087 {
14088 BOOL b = FALSE;
14089 BOOL *output_bool = &b;
14090 wifi_getApSsidAdvertisementEnable(index,output_bool);
14091 printf("advertisment enabled = %d\n",b);
14092 return 0;
14093 }
14094 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
14095 {
14096 if(argc <= 3 )
14097 {
14098 printf("Insufficient arguments \n");
14099 exit(-1);
14100 }
14101
14102 char sta[20] = {'\0'};
14103 ULLONG handle= 0;
14104 strcpy(sta,argv[3]);
14105 mac_address_t st;
14106 mac_addr_aton(st,sta);
14107
14108 wifi_associated_dev_tid_stats_t tid_stats;
14109 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
14110 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
14111 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);
14112 }
14113
14114 if(strstr(argv[1], "getApEnable")!=NULL) {
14115 BOOL enable;
14116 ret=wifi_getApEnable(index, &enable);
14117 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
14118 }
14119 else if(strstr(argv[1], "setApEnable")!=NULL) {
14120 BOOL enable = atoi(argv[3]);
14121 ret=wifi_setApEnable(index, enable);
14122 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
14123 }
14124 else if(strstr(argv[1], "getApStatus")!=NULL) {
developer69b61b02023-03-07 17:17:44 +080014125 char status[64];
developer72fb0bb2023-01-11 09:46:29 +080014126 ret=wifi_getApStatus(index, status);
14127 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
14128 }
14129 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
14130 {
14131 wifi_getSSIDNameStatus(index,buf);
14132 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
14133 return 0;
developer2202b332023-05-24 16:23:22 +080014134 } else if(strstr(argv[1], "wifi_resetApVlanCfg")!=NULL) {
14135 wifi_resetApVlanCfg(index);
14136 printf("%s %d: wifi_resetApVlanCfg : %s\n",argv[1], index,buf);
14137 return 0;
developer72fb0bb2023-01-11 09:46:29 +080014138 }
14139 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
14140 wifi_ssidTrafficStats2_t stats={0};
14141 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
14142 printf("%s %d: returns %d\n", argv[1], index, ret);
14143 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
14144 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
14145 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
14146 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
14147 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
14148 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
14149 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
14150 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
14151 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
14152 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
14153 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
14154 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
14155 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
14156 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
14157 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
14158 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
14159 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
14160 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
14161 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
14162 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
14163 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
14164 }
14165 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
14166 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
14167 UINT array_size=0;
14168 UINT i=0;
14169 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
14170 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
developer69b61b02023-03-07 17:17:44 +080014171 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
developer72fb0bb2023-01-11 09:46:29 +080014172 printf(" neighbor %d:\n", i);
14173 printf(" ap_SSID =%s\n", pt->ap_SSID);
14174 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
14175 printf(" ap_Mode =%s\n", pt->ap_Mode);
14176 printf(" ap_Channel =%d\n", pt->ap_Channel);
14177 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
14178 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
14179 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
14180 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
14181 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
14182 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
14183 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
14184 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
14185 printf(" ap_Noise =%d\n", pt->ap_Noise);
14186 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
14187 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
14188 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
developer69b61b02023-03-07 17:17:44 +080014189 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
developer72fb0bb2023-01-11 09:46:29 +080014190 }
14191 if(neighbor_ap_array)
14192 free(neighbor_ap_array); //make sure to free the list
14193 }
14194 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
14195 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
14196 UINT array_size=0;
14197 UINT i=0;
14198 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
14199 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
developer69b61b02023-03-07 17:17:44 +080014200 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
developer72fb0bb2023-01-11 09:46:29 +080014201 printf(" associated_dev %d:\n", i);
14202 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
14203 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
14204 printf(" cli_SNR =%d\n", pt->cli_SNR);
14205 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
14206 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
14207 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
14208 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
14209 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
14210 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
14211 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
14212 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
14213 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
14214 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
14215 }
14216 if(associated_dev_array)
14217 free(associated_dev_array); //make sure to free the list
14218 }
14219
14220 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
14221 {
14222#define MAX_ARRAY_SIZE 64
14223 int i, array_size;
14224 char *p, *ch_str;
14225 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
14226
14227 if(argc != 5)
14228 {
14229 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
14230 exit(-1);
14231 }
14232 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
14233
14234 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
14235 {
14236 strtok_r(ch_str, ",", &p);
14237 input_output_channelStats_array[i].ch_number = atoi(ch_str);
14238 }
14239 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
14240 if(!array_size)
14241 array_size=1;//Need to print current channel statistics
14242 for(i=0; i<array_size; i++)
14243 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
14244 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
14245 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
14246 input_output_channelStats_array[i].ch_number,\
14247 input_output_channelStats_array[i].ch_noise,\
14248 input_output_channelStats_array[i].ch_utilization_busy_rx,\
14249 input_output_channelStats_array[i].ch_utilization_busy_tx,\
14250 input_output_channelStats_array[i].ch_utilization_busy,\
14251 input_output_channelStats_array[i].ch_utilization_busy_ext,\
14252 input_output_channelStats_array[i].ch_utilization_total);
14253 }
14254
14255 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
14256 {
14257 if(argc <= 3 )
14258 {
14259 printf("Insufficient arguments \n");
14260 exit(-1);
14261 }
14262 char mac_addr[20] = {'\0'};
14263 wifi_device_t output_struct;
14264 int dev_index = atoi(argv[3]);
14265
14266 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
14267 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
14268 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);
14269 }
14270
14271 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
14272 {
14273 if (argc <= 3)
14274 {
14275 printf("Insufficient arguments\n");
14276 exit(-1);
14277 }
14278 char args[256];
14279 wifi_NeighborReport_t *neighborReports;
14280
14281 neighborReports = calloc(argc - 2, sizeof(neighborReports));
14282 if (!neighborReports)
14283 {
14284 printf("Failed to allocate memory");
14285 exit(-1);
14286 }
14287
14288 for (int i = 3; i < argc; ++i)
14289 {
14290 char *val;
14291 int j = 0;
14292 memset(args, 0, sizeof(args));
14293 strncpy(args, argv[i], sizeof(args));
14294 val = strtok(args, ";");
14295 while (val != NULL)
14296 {
14297 if (j == 0)
14298 {
14299 mac_addr_aton(neighborReports[i - 3].bssid, val);
14300 } else if (j == 1)
14301 {
14302 neighborReports[i - 3].info = strtol(val, NULL, 16);
14303 } else if (j == 2)
14304 {
14305 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
14306 } else if (j == 3)
14307 {
14308 neighborReports[i - 3].channel = strtol(val, NULL, 16);
14309 } else if (j == 4)
14310 {
14311 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
14312 } else {
14313 printf("Insufficient arguments]n\n");
14314 exit(-1);
14315 }
14316 val = strtok(NULL, ";");
14317 j++;
14318 }
14319 }
14320
14321 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
14322 if (ret != RETURN_OK)
14323 {
14324 printf("wifi_setNeighborReports ret = %d", ret);
14325 exit(-1);
14326 }
14327 }
14328 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
14329 {
14330 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
14331 printf("%s.\n", buf);
14332 else
14333 printf("Error returned\n");
14334 }
14335 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
14336 {
14337 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
14338 printf("%s.\n", buf);
14339 else
14340 printf("Error returned\n");
14341 }
14342 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
14343 {
14344 if (argc <= 2)
14345 {
14346 printf("Insufficient arguments\n");
14347 exit(-1);
14348 }
14349 char buf[64]= {'\0'};
14350 wifi_getRadioOperatingChannelBandwidth(index,buf);
14351 printf("Current bandwidth is %s \n",buf);
14352 return 0;
14353 }
14354 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
14355 {
14356 if (argc <= 5)
14357 {
14358 printf("Insufficient arguments\n");
14359 exit(-1);
14360 }
14361 UINT channel = atoi(argv[3]);
14362 UINT width = atoi(argv[4]);
14363 UINT beacon = atoi(argv[5]);
14364 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
14365 printf("Result = %d", ret);
14366 }
developercc5cbfb2023-06-13 18:29:52 +080014367 if(strstr(argv[1],"wifi_getApBridgeInfo")!=NULL)
14368 {
14369 char br_name[64], ip[64], subset[64] = {0};
14370 wifi_getApBridgeInfo(0, br_name, ip, subset);
14371 printf("wifi_getApBridgeInfo br_name = %s, ip = %s, subset = %s\n", br_name, ip, subset);
14372 }
14373 if(strstr(argv[1],"wifi_enableGreylistAccessControl")!=NULL)
14374 {
14375 int enable = atoi(argv[3]);
14376 wifi_enableGreylistAccessControl(enable == 0 ? FALSE : TRUE);
14377 printf("wifi_enableGreylistAccessControl enable=%d\n", enable);
14378 }
14379 if(strstr(argv[1],"wifi_setApBridgeInfo")!=NULL)
14380 {
14381 wifi_setApBridgeInfo(0, argv[3], argv[4], argv[5]);
14382 printf("wifi_setApBridgeInfo br_name = %s, ip = %s, subset = %s\n", argv[3], argv[4], argv[5]);
14383 }
developer72fb0bb2023-01-11 09:46:29 +080014384
14385 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
14386 return 0;
14387}
14388
14389#endif
14390
14391#ifdef WIFI_HAL_VERSION_3
14392
14393INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
14394{
14395 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
14396 if (bitMap & WIFI_BITRATE_1MBPS)
14397 strcat(BasicRate, "1,");
14398 if (bitMap & WIFI_BITRATE_2MBPS)
14399 strcat(BasicRate, "2,");
14400 if (bitMap & WIFI_BITRATE_5_5MBPS)
14401 strcat(BasicRate, "5.5,");
14402 if (bitMap & WIFI_BITRATE_6MBPS)
14403 strcat(BasicRate, "6,");
14404 if (bitMap & WIFI_BITRATE_9MBPS)
14405 strcat(BasicRate, "9,");
14406 if (bitMap & WIFI_BITRATE_11MBPS)
14407 strcat(BasicRate, "11,");
14408 if (bitMap & WIFI_BITRATE_12MBPS)
14409 strcat(BasicRate, "12,");
14410 if (bitMap & WIFI_BITRATE_18MBPS)
14411 strcat(BasicRate, "18,");
14412 if (bitMap & WIFI_BITRATE_24MBPS)
14413 strcat(BasicRate, "24,");
14414 if (bitMap & WIFI_BITRATE_36MBPS)
14415 strcat(BasicRate, "36,");
14416 if (bitMap & WIFI_BITRATE_48MBPS)
14417 strcat(BasicRate, "48,");
14418 if (bitMap & WIFI_BITRATE_54MBPS)
14419 strcat(BasicRate, "54,");
14420 if (strlen(BasicRate) != 0) // remove last comma
14421 BasicRate[strlen(BasicRate) - 1] = '\0';
14422 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
14423 return RETURN_OK;
14424}
14425
14426INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
14427{
14428 UINT BitMap = 0;
14429 char *rate;
14430
14431 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
14432 rate = strtok(BasicRatesList, ",");
14433 while(rate != NULL)
14434 {
14435 if (strcmp(rate, "1") == 0)
14436 BitMap |= WIFI_BITRATE_1MBPS;
14437 else if (strcmp(rate, "2") == 0)
14438 BitMap |= WIFI_BITRATE_2MBPS;
14439 else if (strcmp(rate, "5.5") == 0)
14440 BitMap |= WIFI_BITRATE_5_5MBPS;
14441 else if (strcmp(rate, "6") == 0)
14442 BitMap |= WIFI_BITRATE_6MBPS;
14443 else if (strcmp(rate, "9") == 0)
14444 BitMap |= WIFI_BITRATE_9MBPS;
14445 else if (strcmp(rate, "11") == 0)
14446 BitMap |= WIFI_BITRATE_11MBPS;
14447 else if (strcmp(rate, "12") == 0)
14448 BitMap |= WIFI_BITRATE_12MBPS;
14449 else if (strcmp(rate, "18") == 0)
14450 BitMap |= WIFI_BITRATE_18MBPS;
14451 else if (strcmp(rate, "24") == 0)
14452 BitMap |= WIFI_BITRATE_24MBPS;
14453 else if (strcmp(rate, "36") == 0)
14454 BitMap |= WIFI_BITRATE_36MBPS;
14455 else if (strcmp(rate, "48") == 0)
14456 BitMap |= WIFI_BITRATE_48MBPS;
14457 else if (strcmp(rate, "54") == 0)
14458 BitMap |= WIFI_BITRATE_54MBPS;
14459 rate = strtok(NULL, ",");
14460 }
14461 *basicRateBitMap = BitMap;
14462 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
14463 return RETURN_OK;
14464}
14465
14466// This API is used to configured all radio operation parameter in a single set. it includes channel number, channelWidth, mode and auto chammel configuration.
14467INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
14468{
14469 char buf[128] = {0};
developerdaf24792023-06-06 11:40:04 +080014470 int bandwidth = 20;
developer72fb0bb2023-01-11 09:46:29 +080014471 int set_mode = 0;
developer56fbedb2023-05-30 16:47:05 +080014472 BOOL drv_dat_change = 0, hapd_conf_change = 0;
developer72fb0bb2023-01-11 09:46:29 +080014473 wifi_radio_operationParam_t current_param;
14474
14475 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
14476
14477 multiple_set = TRUE;
14478 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
14479 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
14480 return RETURN_ERR;
14481 }
14482 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
14483 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
14484 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
14485 return RETURN_ERR;
14486 }
developer333c1eb2023-05-31 14:59:39 +080014487 drv_dat_change = TRUE;
developer72fb0bb2023-01-11 09:46:29 +080014488 }
developer333c1eb2023-05-31 14:59:39 +080014489 if (current_param.channelWidth != operationParam->channelWidth ||
14490 current_param.channel != operationParam->channel ||
14491 current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
14492 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
14493 bandwidth = 20;
14494 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
14495 bandwidth = 40;
14496 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
14497 bandwidth = 80;
14498 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
14499 bandwidth = 160;
developer72fb0bb2023-01-11 09:46:29 +080014500
developer333c1eb2023-05-31 14:59:39 +080014501 if (operationParam->autoChannelEnabled) {
14502 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
14503 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
14504 return RETURN_ERR;
14505 }
14506 } else {
14507 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
14508 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
14509 return RETURN_ERR;
14510 }
developer72fb0bb2023-01-11 09:46:29 +080014511 }
developer333c1eb2023-05-31 14:59:39 +080014512 drv_dat_change = TRUE;
developer72fb0bb2023-01-11 09:46:29 +080014513 }
developer72fb0bb2023-01-11 09:46:29 +080014514 if (current_param.variant != operationParam->variant) {
14515 // Two different definition bit map, so need to check every bit.
14516 if (operationParam->variant & WIFI_80211_VARIANT_A)
14517 set_mode |= WIFI_MODE_A;
14518 if (operationParam->variant & WIFI_80211_VARIANT_B)
14519 set_mode |= WIFI_MODE_B;
14520 if (operationParam->variant & WIFI_80211_VARIANT_G)
14521 set_mode |= WIFI_MODE_G;
14522 if (operationParam->variant & WIFI_80211_VARIANT_N)
14523 set_mode |= WIFI_MODE_N;
14524 if (operationParam->variant & WIFI_80211_VARIANT_AC)
14525 set_mode |= WIFI_MODE_AC;
14526 if (operationParam->variant & WIFI_80211_VARIANT_AX)
14527 set_mode |= WIFI_MODE_AX;
14528 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
14529 memset(buf, 0, sizeof(buf));
developer56fbedb2023-05-30 16:47:05 +080014530 drv_dat_change = TRUE;
developer0f10c772023-05-16 21:43:39 +080014531 if (wifi_setRadioMode_by_dat(index, set_mode) != RETURN_OK) {
developer72fb0bb2023-01-11 09:46:29 +080014532 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
14533 return RETURN_ERR;
14534 }
14535 }
14536 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
developer56fbedb2023-05-30 16:47:05 +080014537 hapd_conf_change = TRUE;
developer72fb0bb2023-01-11 09:46:29 +080014538 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
14539 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
14540 return RETURN_ERR;
14541 }
14542 }
14543 if (current_param.beaconInterval != operationParam->beaconInterval) {
developer56fbedb2023-05-30 16:47:05 +080014544 hapd_conf_change = TRUE;
developer72fb0bb2023-01-11 09:46:29 +080014545 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
14546 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
14547 return RETURN_ERR;
14548 }
14549 }
14550 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
developer56fbedb2023-05-30 16:47:05 +080014551 hapd_conf_change = TRUE;
developer72fb0bb2023-01-11 09:46:29 +080014552 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
14553 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
14554 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
14555 return RETURN_ERR;
14556 }
14557 }
14558 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
developer56fbedb2023-05-30 16:47:05 +080014559 hapd_conf_change = TRUE;
developer72fb0bb2023-01-11 09:46:29 +080014560 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
14561 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
14562 return RETURN_ERR;
14563 }
14564 }
14565 if (current_param.guardInterval != operationParam->guardInterval) {
developer56fbedb2023-05-30 16:47:05 +080014566 hapd_conf_change = TRUE;
14567 drv_dat_change = TRUE;
14568 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
developer72fb0bb2023-01-11 09:46:29 +080014569 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
14570 return RETURN_ERR;
14571 }
14572 }
14573 if (current_param.transmitPower != operationParam->transmitPower) {
developer56fbedb2023-05-30 16:47:05 +080014574 drv_dat_change = TRUE;
developer72fb0bb2023-01-11 09:46:29 +080014575 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
14576 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
14577 return RETURN_ERR;
14578 }
14579 }
14580 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
developer56fbedb2023-05-30 16:47:05 +080014581 hapd_conf_change = TRUE;
developer72fb0bb2023-01-11 09:46:29 +080014582 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
14583 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
14584 return RETURN_ERR;
14585 }
14586 }
14587 if (current_param.obssCoex != operationParam->obssCoex) {
developer56fbedb2023-05-30 16:47:05 +080014588 hapd_conf_change = TRUE;
developer72fb0bb2023-01-11 09:46:29 +080014589 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
14590 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
14591 return RETURN_ERR;
14592 }
14593 }
14594 if (current_param.stbcEnable != operationParam->stbcEnable) {
developer56fbedb2023-05-30 16:47:05 +080014595 hapd_conf_change = TRUE;
14596 drv_dat_change = TRUE;
developer72fb0bb2023-01-11 09:46:29 +080014597 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
14598 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
14599 return RETURN_ERR;
14600 }
14601 }
14602 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
14603 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
14604 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
14605 return RETURN_ERR;
14606 }
14607 }
14608
developer56fbedb2023-05-30 16:47:05 +080014609 /* only down/up interface when dat file has been changed,
14610 * if enable is true, then restart the radio.
14611 */
14612 if (drv_dat_change == TRUE) {
14613 wifi_setRadioEnable(index, FALSE);
14614 if (operationParam->enable == TRUE)
14615 wifi_setRadioEnable(index, TRUE);
14616 } else if (hapd_conf_change == TRUE) {
14617 hostapd_raw_remove_bss(index);
14618 if (operationParam->enable == TRUE)
14619 hostapd_raw_add_bss(index);
14620 }
14621
developer72fb0bb2023-01-11 09:46:29 +080014622 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
14623
14624 return RETURN_OK;
14625}
14626
14627INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
14628{
14629 char band[64] = {0};
14630 char buf[256] = {0};
14631 char config_file[64] = {0};
14632 char cmd[128] = {0};
developer863a4a62023-06-06 16:55:59 +080014633 UINT mode = 0;
developer72fb0bb2023-01-11 09:46:29 +080014634 BOOL enabled = FALSE;
developer863a4a62023-06-06 16:55:59 +080014635 int dtimPeriod;
developer2f79c922023-06-02 17:33:42 +080014636 UINT beaconInterval;
14637 UINT basicDataTransmitRates;
14638 UINT operationalDataTransmitRates;
14639 wifi_guard_interval_t guardInterval;
14640 UINT transmitPower;
developer72fb0bb2023-01-11 09:46:29 +080014641
14642 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
14643 printf("Entering %s index = %d\n", __func__, (int)index);
14644
14645 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
14646 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
14647 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
14648 {
14649 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
14650 return RETURN_ERR;
14651 }
14652 operationParam->enable = enabled;
14653
14654 memset(band, 0, sizeof(band));
14655 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
14656 {
14657 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
14658 return RETURN_ERR;
14659 }
14660
14661 if (!strcmp(band, "2.4GHz"))
14662 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
14663 else if (!strcmp(band, "5GHz"))
14664 operationParam->band = WIFI_FREQUENCY_5_BAND;
14665 else if (!strcmp(band, "6GHz"))
14666 operationParam->band = WIFI_FREQUENCY_6_BAND;
14667 else
14668 {
14669 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
14670 band);
14671 }
14672
14673 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
14674 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
14675 operationParam->channel = 0;
14676 operationParam->autoChannelEnabled = TRUE;
14677 } else {
14678 operationParam->channel = strtol(buf, NULL, 10);
14679 operationParam->autoChannelEnabled = FALSE;
14680 }
14681
14682 memset(buf, 0, sizeof(buf));
14683 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
14684 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
14685 return RETURN_ERR;
14686 }
14687 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
14688 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
14689 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
14690 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
14691 else
14692 {
14693 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
14694 return false;
14695 }
14696
14697 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
14698 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
14699 return RETURN_ERR;
14700 }
14701 // Two different definition bit map, so need to check every bit.
14702 if (mode & WIFI_MODE_A)
14703 operationParam->variant |= WIFI_80211_VARIANT_A;
14704 if (mode & WIFI_MODE_B)
14705 operationParam->variant |= WIFI_80211_VARIANT_B;
14706 if (mode & WIFI_MODE_G)
14707 operationParam->variant |= WIFI_80211_VARIANT_G;
14708 if (mode & WIFI_MODE_N)
14709 operationParam->variant |= WIFI_80211_VARIANT_N;
14710 if (mode & WIFI_MODE_AC)
14711 operationParam->variant |= WIFI_80211_VARIANT_AC;
14712 if (mode & WIFI_MODE_AX)
14713 operationParam->variant |= WIFI_80211_VARIANT_AX;
14714 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
14715 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
14716 return RETURN_ERR;
14717 }
developer2f79c922023-06-02 17:33:42 +080014718 if (wifi_getApDTIMInterval(index, &dtimPeriod) != RETURN_OK) {
developer72fb0bb2023-01-11 09:46:29 +080014719 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
14720 return RETURN_ERR;
14721 }
developer2f79c922023-06-02 17:33:42 +080014722 operationParam->dtimPeriod = dtimPeriod;
14723 if (wifi_getRadioBeaconPeriod(index, &beaconInterval) != RETURN_OK) {
developer72fb0bb2023-01-11 09:46:29 +080014724 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
14725 return RETURN_ERR;
14726 }
developer2f79c922023-06-02 17:33:42 +080014727 operationParam->beaconInterval = beaconInterval;
developer72fb0bb2023-01-11 09:46:29 +080014728
14729 memset(buf, 0, sizeof(buf));
14730 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
14731 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
14732 return RETURN_ERR;
14733 }
developer2f79c922023-06-02 17:33:42 +080014734 TransmitRatesToBitMap(buf, &basicDataTransmitRates);
14735 operationParam->basicDataTransmitRates = basicDataTransmitRates;
developer72fb0bb2023-01-11 09:46:29 +080014736
14737 memset(buf, 0, sizeof(buf));
14738 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
14739 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
14740 return RETURN_ERR;
14741 }
developer2f79c922023-06-02 17:33:42 +080014742 TransmitRatesToBitMap(buf, &operationalDataTransmitRates);
14743 operationParam->operationalDataTransmitRates = operationalDataTransmitRates;
developer72fb0bb2023-01-11 09:46:29 +080014744
14745 memset(buf, 0, sizeof(buf));
14746 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
14747 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
14748
developer2f79c922023-06-02 17:33:42 +080014749 if (wifi_getGuardInterval(index, &guardInterval) != RETURN_OK) {
developer72fb0bb2023-01-11 09:46:29 +080014750 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
14751 return RETURN_ERR;
14752 }
developer2f79c922023-06-02 17:33:42 +080014753 operationParam->guardInterval = guardInterval;
14754
14755 if (wifi_getRadioPercentageTransmitPower(index, (ULONG *)&transmitPower) != RETURN_OK) {
developer72fb0bb2023-01-11 09:46:29 +080014756 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
14757 return RETURN_ERR;
14758 }
developer2f79c922023-06-02 17:33:42 +080014759 operationParam->transmitPower = transmitPower;
developer72fb0bb2023-01-11 09:46:29 +080014760
14761 memset(buf, 0, sizeof(buf));
14762 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
14763 if (strcmp(buf, "-1") == 0) {
14764 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
14765 operationParam->ctsProtection = FALSE;
14766 } else {
14767 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
14768 operationParam->ctsProtection = TRUE;
14769 }
14770
14771 memset(buf, 0, sizeof(buf));
14772 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
14773 if (strcmp(buf, "0") == 0)
14774 operationParam->obssCoex = FALSE;
14775 else
14776 operationParam->obssCoex = TRUE;
14777
14778 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
14779 _syscmd(cmd, buf, sizeof(buf));
14780 if (strlen(buf) != 0)
14781 operationParam->stbcEnable = TRUE;
14782 else
14783 operationParam->stbcEnable = FALSE;
14784
14785 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
14786 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
14787 return RETURN_ERR;
14788 }
14789
14790 // Below value is hardcoded
14791
14792 operationParam->numSecondaryChannels = 0;
14793 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
14794 operationParam->channelSecondary[i] = 0;
14795 }
14796 operationParam->csa_beacon_count = 15;
14797 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
14798
14799 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
14800 return RETURN_OK;
14801}
14802
14803static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
14804{
14805 int max_radio_num = 0;
14806
14807 wifi_getMaxRadioNumber(&max_radio_num);
14808 if (radioIndex >= max_radio_num) {
14809 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
14810 return RETURN_ERR;
14811 }
14812
14813 return (arrayIndex * max_radio_num) + radioIndex;
14814}
14815
developer96b38512023-02-22 11:17:45 +080014816static int vap_index_to_array_index(int vapIndex, int *radioIndex, int *arrayIndex)
14817{
14818 int max_radio_num = 0;
14819
14820 if ((vapIndex < 0) || (vapIndex > MAX_NUM_VAP_PER_RADIO*MAX_NUM_RADIOS))
14821 return -1;
14822
14823 wifi_getMaxRadioNumber(&max_radio_num);
14824
14825 (*radioIndex) = vapIndex % max_radio_num;
14826 (*arrayIndex) = vapIndex / max_radio_num;
14827
14828 return 0;
14829}
14830
14831
developer72fb0bb2023-01-11 09:46:29 +080014832wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
14833 if (strncmp(beaconRate, "1Mbps", 5) == 0)
14834 return WIFI_BITRATE_1MBPS;
14835 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
14836 return WIFI_BITRATE_2MBPS;
14837 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
14838 return WIFI_BITRATE_5_5MBPS;
14839 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
14840 return WIFI_BITRATE_6MBPS;
14841 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
14842 return WIFI_BITRATE_9MBPS;
14843 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
14844 return WIFI_BITRATE_11MBPS;
14845 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
14846 return WIFI_BITRATE_12MBPS;
14847 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
14848 return WIFI_BITRATE_18MBPS;
14849 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
14850 return WIFI_BITRATE_24MBPS;
14851 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
14852 return WIFI_BITRATE_36MBPS;
14853 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
14854 return WIFI_BITRATE_48MBPS;
14855 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
14856 return WIFI_BITRATE_54MBPS;
14857 return WIFI_BITRATE_DEFAULT;
14858}
14859
14860INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
14861{
14862 if (beacon == WIFI_BITRATE_1MBPS)
14863 strcpy(beacon_str, "1Mbps");
14864 else if (beacon == WIFI_BITRATE_2MBPS)
14865 strcpy(beacon_str, "2Mbps");
14866 else if (beacon == WIFI_BITRATE_5_5MBPS)
14867 strcpy(beacon_str, "5.5Mbps");
14868 else if (beacon == WIFI_BITRATE_6MBPS)
14869 strcpy(beacon_str, "6Mbps");
14870 else if (beacon == WIFI_BITRATE_9MBPS)
14871 strcpy(beacon_str, "9Mbps");
14872 else if (beacon == WIFI_BITRATE_11MBPS)
14873 strcpy(beacon_str, "11Mbps");
14874 else if (beacon == WIFI_BITRATE_12MBPS)
14875 strcpy(beacon_str, "12Mbps");
14876 else if (beacon == WIFI_BITRATE_18MBPS)
14877 strcpy(beacon_str, "18Mbps");
14878 else if (beacon == WIFI_BITRATE_24MBPS)
14879 strcpy(beacon_str, "24Mbps");
14880 else if (beacon == WIFI_BITRATE_36MBPS)
14881 strcpy(beacon_str, "36Mbps");
14882 else if (beacon == WIFI_BITRATE_48MBPS)
14883 strcpy(beacon_str, "48Mbps");
14884 else if (beacon == WIFI_BITRATE_54MBPS)
14885 strcpy(beacon_str, "54Mbps");
14886 return RETURN_OK;
14887}
14888
14889INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
14890{
14891 INT mode = 0;
14892 INT ret = -1;
developer863a4a62023-06-06 16:55:59 +080014893 UINT output = 0;
developer72fb0bb2023-01-11 09:46:29 +080014894 int i = 0;
14895 int vap_index = 0;
14896 BOOL enabled = FALSE;
developerb149d9d2023-06-06 16:14:22 +080014897 char buf[32] = {0};
developer72fb0bb2023-01-11 09:46:29 +080014898 wifi_vap_security_t security = {0};
developer72fb0bb2023-01-11 09:46:29 +080014899
14900 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
14901 printf("Entering %s index = %d\n", __func__, (int)index);
14902
developerfde01262023-05-22 15:15:24 +080014903 ret = wifi_BandProfileRead(0, index, "BssidNum", buf, sizeof(buf), "0");
14904 if (ret != 0) {
14905 fprintf(stderr, "%s: wifi_BandProfileRead BssidNum failed\n", __func__);
14906 return RETURN_ERR;
14907 }
14908
14909 map->num_vaps = atoi(buf);
14910 if (map->num_vaps <= 0) {
14911 fprintf(stderr, "%s: invalid BssidNum %s\n", __func__, buf);
14912 return RETURN_ERR;
14913 }
14914
14915 for (i = 0; i < map->num_vaps; i++)
developer72fb0bb2023-01-11 09:46:29 +080014916 {
14917 map->vap_array[i].radio_index = index;
14918
14919 vap_index = array_index_to_vap_index(index, i);
14920 if (vap_index < 0)
14921 return RETURN_ERR;
14922
14923 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
14924
14925 map->vap_array[i].vap_index = vap_index;
14926
14927 memset(buf, 0, sizeof(buf));
14928 ret = wifi_getApName(vap_index, buf);
14929 if (ret != RETURN_OK) {
14930 printf("%s: wifi_getApName return error\n", __func__);
14931 return RETURN_ERR;
14932 }
14933 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
14934
14935 memset(buf, 0, sizeof(buf));
14936 ret = wifi_getSSIDName(vap_index, buf);
14937 if (ret != RETURN_OK) {
14938 printf("%s: wifi_getSSIDName return error\n", __func__);
14939 return RETURN_ERR;
14940 }
14941 snprintf(map->vap_array[i].u.bss_info.ssid, sizeof(map->vap_array[i].u.bss_info.ssid), "%s", buf);
14942
developere740c2a2023-05-23 18:34:32 +080014943#if 0
developer72fb0bb2023-01-11 09:46:29 +080014944 ret = wifi_getSSIDEnable(vap_index, &enabled);
14945 if (ret != RETURN_OK) {
14946 printf("%s: wifi_getSSIDEnable return error\n", __func__);
14947 return RETURN_ERR;
14948 }
developere740c2a2023-05-23 18:34:32 +080014949#endif
14950 map->vap_array[i].u.bss_info.enabled = true;
developer72fb0bb2023-01-11 09:46:29 +080014951
14952 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
14953 if (ret != RETURN_OK) {
14954 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
14955 return RETURN_ERR;
14956 }
14957 map->vap_array[i].u.bss_info.showSsid = enabled;
developer69b61b02023-03-07 17:17:44 +080014958
developer72fb0bb2023-01-11 09:46:29 +080014959 ret = wifi_getApIsolationEnable(vap_index, &enabled);
14960 if (ret != RETURN_OK) {
14961 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
14962 return RETURN_ERR;
14963 }
14964 map->vap_array[i].u.bss_info.isolation = enabled;
14965
14966 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
14967 if (ret != RETURN_OK) {
14968 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
14969 return RETURN_ERR;
14970 }
14971 map->vap_array[i].u.bss_info.bssMaxSta = output;
14972
14973 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
14974 if (ret != RETURN_OK) {
14975 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
14976 return RETURN_ERR;
14977 }
14978 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
14979
14980 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
14981 if (ret != RETURN_OK) {
14982 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
14983 return RETURN_ERR;
14984 }
14985 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
14986
14987 ret = wifi_getApSecurity(vap_index, &security);
14988 if (ret != RETURN_OK) {
14989 printf("%s: wifi_getApSecurity return error\n", __func__);
14990 return RETURN_ERR;
14991 }
14992 map->vap_array[i].u.bss_info.security = security;
14993
14994 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
14995 if (ret != RETURN_OK) {
14996 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
14997 return RETURN_ERR;
14998 }
developer69b61b02023-03-07 17:17:44 +080014999 if (mode == 0)
developer72fb0bb2023-01-11 09:46:29 +080015000 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
developer69b61b02023-03-07 17:17:44 +080015001 else
developer72fb0bb2023-01-11 09:46:29 +080015002 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
developer69b61b02023-03-07 17:17:44 +080015003 if (mode == 1)
developer72fb0bb2023-01-11 09:46:29 +080015004 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
developer69b61b02023-03-07 17:17:44 +080015005 else if (mode == 2)
developer72fb0bb2023-01-11 09:46:29 +080015006 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
15007
15008 ret = wifi_getApWmmEnable(vap_index, &enabled);
15009 if (ret != RETURN_OK) {
15010 printf("%s: wifi_getApWmmEnable return error\n", __func__);
15011 return RETURN_ERR;
15012 }
15013 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
15014
15015 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
15016 if (ret != RETURN_OK) {
15017 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
15018 return RETURN_ERR;
15019 }
15020 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
15021
15022 memset(buf, 0, sizeof(buf));
15023 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
15024 if (ret != RETURN_OK) {
15025 printf("%s: wifi_getApBeaconRate return error\n", __func__);
15026 return RETURN_ERR;
15027 }
15028 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
15029
15030 memset(buf, 0, sizeof(buf));
15031 ret = wifi_getBaseBSSID(vap_index, buf);
15032 if (ret != RETURN_OK) {
15033 printf("%s: wifi_getBaseBSSID return error\n", __func__);
15034 return RETURN_ERR;
15035 }
developer5b2f10c2023-05-25 17:02:21 +080015036 if (hwaddr_aton2(buf, map->vap_array[i].u.bss_info.bssid) < 0) {
15037 printf("%s: hwaddr_aton2 fail\n", __func__);
15038 return RETURN_ERR;
15039 }
developer72fb0bb2023-01-11 09:46:29 +080015040
15041 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
15042 if (ret != RETURN_OK) {
15043 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
15044 return RETURN_ERR;
15045 }
15046 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
15047
15048 // TODO: wps, noack
15049 }
15050 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
15051 return RETURN_OK;
15052}
15053
developer47cc27a2023-05-17 23:09:58 +080015054void checkVapStatus(int apIndex, BOOL *enable)
developer72fb0bb2023-01-11 09:46:29 +080015055{
15056 char if_name[16] = {0};
15057 char cmd[128] = {0};
15058 char buf[128] = {0};
15059
15060 *enable = FALSE;
15061 if (wifi_GetInterfaceName(apIndex, if_name) != RETURN_OK)
15062 return;
15063
15064 snprintf(cmd, sizeof(cmd), "cat %s | grep ^%s=1", VAP_STATUS_FILE, if_name);
15065 _syscmd(cmd, buf, sizeof(buf));
15066 if (strlen(buf) > 0)
15067 *enable = TRUE;
15068 return;
15069}
15070
developer56fbedb2023-05-30 16:47:05 +080015071int hostapd_manage_bss(INT apIndex, BOOL enable)
15072{
15073 char interface_name[16] = {0};
developerb149d9d2023-06-06 16:14:22 +080015074 char config_file[MAX_SUB_CMD_SIZE] = {0};
developer56fbedb2023-05-30 16:47:05 +080015075 char cmd[MAX_CMD_SIZE] = {0};
15076 char buf[MAX_BUF_SIZE] = {0};
15077 BOOL status = FALSE;
15078 int max_radio_num = 0;
15079 int phyId = 0;
15080
15081 wifi_getApEnable(apIndex, &status);
15082
15083 wifi_getMaxRadioNumber(&max_radio_num);
15084 if (enable == status)
15085 return RETURN_OK;
15086
15087 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
15088 return RETURN_ERR;
15089
15090 if (enable == TRUE) {
15091 int radioIndex = apIndex % max_radio_num;
15092 phyId = radio_index_to_phy(radioIndex);
15093 fprintf(stderr, "%s %d\n", __func__, __LINE__);
15094 snprintf(config_file, MAX_BUF_SIZE, "%s%d.conf", CONFIG_PREFIX, apIndex);
15095 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyId, config_file);
15096 _syscmd(cmd, buf, sizeof(buf));
15097 } else {
15098 fprintf(stderr, "%s %d\n", __func__, __LINE__);
15099 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw REMOVE %s", interface_name);
15100 _syscmd(cmd, buf, sizeof(buf));
15101 }
15102 snprintf(cmd, MAX_CMD_SIZE, "sed -i -n -e '/^%s=/!p' -e '$a%s=%d' %s",
15103 interface_name, interface_name, enable, VAP_STATUS_FILE);
15104 _syscmd(cmd, buf, sizeof(buf));
15105 //Wait for wifi up/down to apply
15106 return RETURN_OK;
15107}
15108
15109int hostapd_raw_add_bss(int apIndex)
15110{
15111 return hostapd_manage_bss(apIndex, TRUE);
15112}
15113
15114int hostapd_raw_remove_bss(int apIndex)
15115{
15116 return hostapd_manage_bss(apIndex, FALSE);
15117}
15118
15119int hostapd_raw_restart_bss(int apIndex)
developer333c1eb2023-05-31 14:59:39 +080015120{
developerdaf24792023-06-06 11:40:04 +080015121 int ret = 0;
15122
15123 ret = hostapd_raw_remove_bss(apIndex);
15124 if(ret != RETURN_OK)
15125 return RETURN_ERR;
15126
15127 ret = hostapd_raw_add_bss(apIndex);
15128 if(ret != RETURN_OK)
15129 return RETURN_ERR;
15130
15131 return RETURN_OK;
developer56fbedb2023-05-30 16:47:05 +080015132}
15133
developer72fb0bb2023-01-11 09:46:29 +080015134INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
15135{
developer72fb0bb2023-01-11 09:46:29 +080015136 unsigned int i;
15137 wifi_vap_info_t *vap_info = NULL;
15138 int acl_mode;
15139 int ret = 0;
developer72fb0bb2023-01-11 09:46:29 +080015140 char buf[256] = {0};
15141 char cmd[128] = {0};
15142 char config_file[64] = {0};
developer72fb0bb2023-01-11 09:46:29 +080015143 char psk_file[64] = {0};
developer47cc27a2023-05-17 23:09:58 +080015144 BOOL enable = FALSE;
developere740c2a2023-05-23 18:34:32 +080015145 int band_idx;
15146
developer72fb0bb2023-01-11 09:46:29 +080015147
15148 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
15149 printf("Entering %s index = %d\n", __func__, (int)index);
15150 for (i = 0; i < map->num_vaps; i++)
15151 {
15152 multiple_set = TRUE;
15153 vap_info = &map->vap_array[i];
15154
15155 // Check vap status file to enable multiple ap if the system boot.
15156 checkVapStatus(vap_info->vap_index, &enable);
15157 if (vap_info->u.bss_info.enabled == FALSE && enable == FALSE)
15158 continue;
15159
15160 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
15161
developere740c2a2023-05-23 18:34:32 +080015162 band_idx = radio_index_to_band(index);
15163 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
15164 snprintf(cmd, sizeof(cmd), "cp /etc/hostapd-%s.conf %s", wifi_band_str[band_idx], config_file);
15165 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +080015166
developer56fbedb2023-05-30 16:47:05 +080015167 struct params params[3];
developer72fb0bb2023-01-11 09:46:29 +080015168 params[0].name = "interface";
15169 params[0].value = vap_info->vap_name;
developer72fb0bb2023-01-11 09:46:29 +080015170 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", vap_info->vap_index);
developer56fbedb2023-05-30 16:47:05 +080015171 params[1].name = "wpa_psk_file";
15172 params[1].value = psk_file;
15173 params[2].name = "ssid";
15174 params[2].value = vap_info->u.bss_info.ssid;
developer72fb0bb2023-01-11 09:46:29 +080015175
15176 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
developer56fbedb2023-05-30 16:47:05 +080015177 wifi_hostapdWrite(config_file, params, 3);
developer72fb0bb2023-01-11 09:46:29 +080015178
15179 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
15180 _syscmd(cmd, buf, sizeof(buf));
15181
15182 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
15183 if (ret != RETURN_OK) {
15184 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
15185 return RETURN_ERR;
15186 }
15187
15188 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
15189 if (ret != RETURN_OK) {
15190 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
15191 return RETURN_ERR;
15192 }
15193
15194 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
15195 if (ret != RETURN_OK) {
15196 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
15197 return RETURN_ERR;
15198 }
15199
15200 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
15201 if (ret != RETURN_OK) {
15202 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
15203 return RETURN_ERR;
15204 }
15205
15206 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
15207 if (ret != RETURN_OK) {
15208 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
15209 return RETURN_ERR;
15210 }
15211
15212 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
15213 if (ret != RETURN_OK) {
15214 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
15215 return RETURN_ERR;
15216 }
15217
15218 if (vap_info->u.bss_info.mac_filter_enable == false){
15219 acl_mode = 0;
15220 }else {
15221 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
15222 acl_mode = 2;
15223 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
15224 _syscmd(cmd, buf, sizeof(buf));
15225 }else{
15226 acl_mode = 1;
15227 }
15228 }
15229
15230 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
15231 if (ret != RETURN_OK) {
15232 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
15233 return RETURN_ERR;
15234 }
15235
15236 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
15237 if (ret != RETURN_OK) {
15238 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
15239 return RETURN_ERR;
15240 }
15241
developer0f10c772023-05-16 21:43:39 +080015242 memset(buf, 0, sizeof(buf));
15243 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
15244 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
15245 if (ret != RETURN_OK) {
15246 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
15247 return RETURN_ERR;
15248 }
developer72fb0bb2023-01-11 09:46:29 +080015249
15250 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
15251 if (ret != RETURN_OK) {
15252 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable\n", __func__);
15253 return RETURN_ERR;
15254 }
15255
developer72fb0bb2023-01-11 09:46:29 +080015256 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
15257 if (ret != RETURN_OK) {
15258 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
15259 return RETURN_ERR;
15260 }
developer333c1eb2023-05-31 14:59:39 +080015261
developer56fbedb2023-05-30 16:47:05 +080015262 hostapd_raw_restart_bss(vap_info->vap_index);
developer72fb0bb2023-01-11 09:46:29 +080015263
developer23e71282023-01-18 10:25:19 +080015264 multiple_set = FALSE;
15265
15266 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
developer72fb0bb2023-01-11 09:46:29 +080015267 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
15268 if (ret != RETURN_OK) {
15269 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
15270 return RETURN_ERR;
15271 }
15272
15273 // TODO mgmtPowerControl, interworking, wps
15274 }
15275 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
15276 return RETURN_OK;
15277}
15278
15279int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
15280{
15281 char *token, *next;
15282 const char s[2] = ",";
15283 int count =0;
15284
15285 /* get the first token */
15286 token = strtok_r(pchannels, s, &next);
15287
15288 /* walk through other tokens */
15289 while( token != NULL && count < MAX_CHANNELS) {
15290 chlistptr->channels_list[count++] = atoi(token);
15291 token = strtok_r(NULL, s, &next);
15292 }
15293
15294 return count;
15295}
15296
15297static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
15298{
15299 INT status;
15300 wifi_channels_list_t *chlistp;
15301 CHAR output_string[64];
15302 CHAR pchannels[128];
15303 CHAR interface_name[16] = {0};
15304 wifi_band band;
15305
15306 if(rcap == NULL)
15307 {
15308 return RETURN_ERR;
15309 }
15310
15311 rcap->numSupportedFreqBand = 1;
15312 band = wifi_index_to_band(radioIndex);
15313
15314 if (band == band_2_4)
15315 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
15316 else if (band == band_5)
15317 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
15318 else if (band == band_6)
15319 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
15320
15321 chlistp = &(rcap->channel_list[0]);
15322 memset(pchannels, 0, sizeof(pchannels));
15323
15324 /* possible number of radio channels */
15325 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
15326 {
15327 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
15328 }
15329 /* Number of channels and list*/
15330 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
15331
15332 /* autoChannelSupported */
15333 /* always ON with wifi_getRadioAutoChannelSupported */
15334 rcap->autoChannelSupported = TRUE;
15335
15336 /* DCSSupported */
15337 /* always ON with wifi_getRadioDCSSupported */
15338 rcap->DCSSupported = TRUE;
15339
15340 /* zeroDFSSupported - TBD */
15341 rcap->zeroDFSSupported = FALSE;
15342
15343 /* Supported Country List*/
15344 memset(output_string, 0, sizeof(output_string));
15345 status = wifi_getRadioCountryCode(radioIndex, output_string);
15346 if( status != 0 ) {
15347 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
15348 return RETURN_ERR;
15349 } else {
15350 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
15351 }
15352 if(!strcmp(output_string,"US")){
15353 rcap->countrySupported[0] = wifi_countrycode_US;
15354 rcap->countrySupported[1] = wifi_countrycode_CA;
15355 } else if (!strcmp(output_string,"CA")) {
15356 rcap->countrySupported[0] = wifi_countrycode_CA;
15357 rcap->countrySupported[1] = wifi_countrycode_US;
15358 } else {
15359 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
15360 }
15361
15362 rcap->numcountrySupported = 2;
15363
15364 /* csi */
15365 rcap->csi.maxDevices = 8;
15366 rcap->csi.soudingFrameSupported = TRUE;
15367
15368 wifi_GetInterfaceName(radioIndex, interface_name);
15369 snprintf(rcap->ifaceName, sizeof(interface_name), "%s",interface_name);
15370
15371 /* channelWidth - all supported bandwidths */
15372 int i=0;
15373 rcap->channelWidth[i] = 0;
15374 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
15375 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
15376 WIFI_CHANNELBANDWIDTH_40MHZ);
15377
15378 }
15379 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
15380 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
15381 WIFI_CHANNELBANDWIDTH_40MHZ |
15382 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
15383 }
15384
15385
15386 /* mode - all supported variants */
15387 // rcap->mode[i] = WIFI_80211_VARIANT_H;
15388 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
15389 rcap->mode[i] = ( WIFI_80211_VARIANT_B | WIFI_80211_VARIANT_G | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AX );
15390 }
15391 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
15392 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
15393 }
15394 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
15395 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
15396 }
15397 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
15398 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
15399
15400 /* supportedBitRate - all supported bitrates */
15401 rcap->supportedBitRate[i] = 0;
15402 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
15403 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
15404 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
15405 }
developerdaf24792023-06-06 11:40:04 +080015406 else if ((rcap->band[i] & (WIFI_FREQUENCY_5_BAND )) || (rcap->band[i] & (WIFI_FREQUENCY_6_BAND))) {
developer72fb0bb2023-01-11 09:46:29 +080015407 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
15408 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
15409 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
15410 }
15411
15412
15413 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
15414 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
15415 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
15416 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
15417 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
15418 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
15419 rcap->cipherSupported = 0;
15420 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
15421 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
15422
15423 return RETURN_OK;
15424}
15425
15426INT wifi_getHalCapability(wifi_hal_capability_t *cap)
15427{
15428 INT status = 0, radioIndex = 0;
developer2f79c922023-06-02 17:33:42 +080015429 char output[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +080015430 int iter = 0;
15431 unsigned int j = 0;
15432 int max_num_radios;
15433 wifi_interface_name_idex_map_t *iface_info = NULL;
15434
15435 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
15436
15437 memset(cap, 0, sizeof(wifi_hal_capability_t));
15438
15439 /* version */
15440 cap->version.major = WIFI_HAL_MAJOR_VERSION;
15441 cap->version.minor = WIFI_HAL_MINOR_VERSION;
15442
15443 /* number of radios platform property */
15444 wifi_getMaxRadioNumber(&max_num_radios);
15445 cap->wifi_prop.numRadios = max_num_radios;
15446
15447 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
15448 {
15449 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
15450 if (status != 0) {
15451 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
15452 return RETURN_ERR;
15453 }
15454
15455 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
15456 {
15457 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
15458 {
15459 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
15460 return RETURN_ERR;
15461 }
15462 iface_info = &cap->wifi_prop.interface_map[iter];
15463 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
15464 iface_info->rdk_radio_index = radioIndex;
15465 memset(output, 0, sizeof(output));
15466 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
15467 {
15468 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
15469 }
15470 // TODO: bridge name
15471 // TODO: vlan id
15472 // TODO: primary
15473 iface_info->index = array_index_to_vap_index(radioIndex, j);
15474 memset(output, 0, sizeof(output));
15475 if (wifi_getApName(iface_info->index, output) == RETURN_OK)
15476 {
15477 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
15478 }
15479 iter++;
15480 }
15481 }
15482
15483 cap->BandSteeringSupported = FALSE;
15484 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
15485 return RETURN_OK;
15486}
15487
15488INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
15489{
15490 struct params h_config={0};
15491 char config_file[64] = {0};
15492
15493 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
15494
15495 h_config.name = "okc";
15496 h_config.value = okc_enable?"1":"0";
15497
15498 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
15499 wifi_hostapdWrite(config_file, &h_config, 1);
15500 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
15501
15502 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
15503 return RETURN_OK;
15504}
15505
15506INT wifi_setSAEMFP(int ap_index, BOOL enable)
15507{
15508 struct params h_config={0};
15509 char config_file[64] = {0};
developer72fb0bb2023-01-11 09:46:29 +080015510
15511 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
15512
15513 h_config.name = "sae_require_mfp";
15514 h_config.value = enable?"1":"0";
15515
15516 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
15517 wifi_hostapdWrite(config_file, &h_config, 1);
15518 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
15519
15520 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
15521 return RETURN_OK;
15522}
15523
15524INT wifi_setSAEpwe(int ap_index, int sae_pwe)
15525{
15526 struct params h_config={0};
15527 char config_file[64] = {0};
15528 char buf[128] = {0};
15529
15530 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
15531
15532 h_config.name = "sae_pwe";
15533 snprintf(buf, sizeof(buf), "%d", sae_pwe);
15534 h_config.value = buf;
15535
15536 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
15537 wifi_hostapdWrite(config_file, &h_config, 1);
15538 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
15539
15540 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
15541 return RETURN_OK;
15542}
15543
15544INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
15545{
15546 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
15547 struct params h_config={0};
15548 char config_file[64] = {0};
15549
15550 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
15551
15552 h_config.name = "wpa_disable_eapol_key_retries";
15553 h_config.value = disable_EAPOL_retries?"1":"0";
15554
15555 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
15556 wifi_hostapdWrite(config_file, &h_config, 1);
15557 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
15558
15559 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
15560 return RETURN_OK;
15561}
15562
15563INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
15564{
15565 char buf[128] = {0};
15566 char config_file[128] = {0};
developerb149d9d2023-06-06 16:14:22 +080015567 char cmd[MAX_CMD_SIZE] = {0};
developer863a4a62023-06-06 16:55:59 +080015568 char password[65] = {0};
developer72fb0bb2023-01-11 09:46:29 +080015569 char mfp[32] = {0};
15570 char wpa_mode[32] = {0};
15571 BOOL okc_enable = FALSE;
15572 BOOL sae_MFP = FALSE;
15573 BOOL disable_EAPOL_retries = TRUE;
15574 int sae_pwe = 0;
15575 struct params params = {0};
15576 wifi_band band = band_invalid;
15577
15578 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
15579
15580 multiple_set = TRUE;
15581 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
15582 if (security->mode == wifi_security_mode_none) {
15583 strcpy(wpa_mode, "None");
15584 } else if (security->mode == wifi_security_mode_wpa_personal)
15585 strcpy(wpa_mode, "WPA-Personal");
15586 else if (security->mode == wifi_security_mode_wpa2_personal)
15587 strcpy(wpa_mode, "WPA2-Personal");
15588 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
15589 strcpy(wpa_mode, "WPA-WPA2-Personal");
15590 else if (security->mode == wifi_security_mode_wpa_enterprise)
15591 strcpy(wpa_mode, "WPA-Enterprise");
15592 else if (security->mode == wifi_security_mode_wpa2_enterprise)
15593 strcpy(wpa_mode, "WPA2-Enterprise");
15594 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
15595 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
15596 else if (security->mode == wifi_security_mode_wpa3_personal) {
15597 strcpy(wpa_mode, "WPA3-Personal");
15598 okc_enable = TRUE;
15599 sae_MFP = TRUE;
15600 sae_pwe = 2;
15601 disable_EAPOL_retries = FALSE;
15602 } else if (security->mode == wifi_security_mode_wpa3_transition) {
15603 strcpy(wpa_mode, "WPA3-Personal-Transition");
15604 okc_enable = TRUE;
15605 sae_MFP = TRUE;
15606 sae_pwe = 2;
15607 disable_EAPOL_retries = FALSE;
15608 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
15609 strcpy(wpa_mode, "WPA3-Enterprise");
15610 sae_MFP = TRUE;
15611 sae_pwe = 2;
15612 disable_EAPOL_retries = FALSE;
developerd01e3e82023-04-26 19:10:38 +080015613 } else if (security->mode == wifi_security_mode_enhanced_open) {
developer3086e2f2023-01-17 09:40:01 +080015614 strcpy(wpa_mode, "OWE");
15615 sae_MFP = TRUE;
15616 sae_pwe = 2;
15617 disable_EAPOL_retries = FALSE;
developer72fb0bb2023-01-11 09:46:29 +080015618 }
15619
15620 band = wifi_index_to_band(ap_index);
15621 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
15622 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
15623 return RETURN_ERR;
15624 }
15625
15626 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
15627 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
15628 wifi_setSAEMFP(ap_index, sae_MFP);
15629 wifi_setSAEpwe(ap_index, sae_pwe);
15630 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
15631
developerd01e3e82023-04-26 19:10:38 +080015632 if (security->mode != wifi_security_mode_none && security->mode != wifi_security_mode_enhanced_open) {
developere5750452023-05-15 16:46:42 +080015633 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) {
15634 int key_len = strlen(security->u.key.key);
15635 // wpa_psk and wpa_passphrase cann;t use at the same time, the command replace one with the other.
15636 if (key_len == 64) { // set wpa_psk
15637 strncpy(password, security->u.key.key, 64); // 64 characters
15638 password[64] = '\0';
15639 wifi_setApSecurityPreSharedKey(ap_index, password);
15640 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_passphrase=/!p' %s", config_file);
15641 } else if (key_len >= 8 && key_len < 64) { // set wpa_passphrase
15642 strncpy(password, security->u.key.key, 63);
15643 password[63] = '\0';
15644 wifi_setApSecurityKeyPassphrase(ap_index, password);
15645 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_psk=/!p' %s", config_file);
15646 } else
15647 return RETURN_ERR;
15648 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +080015649 }
15650 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
15651 params.name = "sae_password";
15652 params.value = security->u.key.key;
15653 wifi_hostapdWrite(config_file, &params, 1);
developere5750452023-05-15 16:46:42 +080015654 } else { // remove sae_password
15655 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^sae_password=/!p' %s", config_file);
15656 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +080015657 }
15658 }
15659
15660 if (security->mode != wifi_security_mode_none) {
15661 memset(&params, 0, sizeof(params));
15662 params.name = "wpa_pairwise";
15663 if (security->encr == wifi_encryption_tkip)
15664 params.value = "TKIP";
15665 else if (security->encr == wifi_encryption_aes)
15666 params.value = "CCMP";
15667 else if (security->encr == wifi_encryption_aes_tkip)
15668 params.value = "TKIP CCMP";
15669 wifi_hostapdWrite(config_file, &params, 1);
15670 }
15671
15672 if (security->mfp == wifi_mfp_cfg_disabled)
15673 strcpy(mfp, "Disabled");
15674 else if (security->mfp == wifi_mfp_cfg_optional)
15675 strcpy(mfp, "Optional");
15676 else if (security->mfp == wifi_mfp_cfg_required)
15677 strcpy(mfp, "Required");
15678 wifi_setApSecurityMFPConfig(ap_index, mfp);
15679
15680 memset(&params, 0, sizeof(params));
15681 params.name = "transition_disable";
15682 if (security->wpa3_transition_disable == TRUE)
15683 params.value = "0x01";
15684 else
15685 params.value = "0x00";
15686 wifi_hostapdWrite(config_file, &params, 1);
15687
15688 memset(&params, 0, sizeof(params));
15689 params.name = "wpa_group_rekey";
15690 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
15691 params.value = buf;
15692 wifi_hostapdWrite(config_file, &params, 1);
15693
15694 memset(&params, 0, sizeof(params));
15695 params.name = "wpa_strict_rekey";
15696 params.value = security->strict_rekey?"1":"0";
15697 wifi_hostapdWrite(config_file, &params, 1);
15698
15699 memset(&params, 0, sizeof(params));
15700 params.name = "wpa_pairwise_update_count";
developere5750452023-05-15 16:46:42 +080015701 if (security->eapol_key_retries == 0)
15702 security->eapol_key_retries = 4; // 0 is invalid, set to default value.
developer72fb0bb2023-01-11 09:46:29 +080015703 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
15704 params.value = buf;
15705 wifi_hostapdWrite(config_file, &params, 1);
15706
15707 memset(&params, 0, sizeof(params));
15708 params.name = "disable_pmksa_caching";
15709 params.value = security->disable_pmksa_caching?"1":"0";
15710 wifi_hostapdWrite(config_file, &params, 1);
15711
developer23e71282023-01-18 10:25:19 +080015712 if (multiple_set == FALSE) {
15713 wifi_setApEnable(ap_index, FALSE);
15714 wifi_setApEnable(ap_index, TRUE);
15715 }
developer72fb0bb2023-01-11 09:46:29 +080015716
15717 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
15718
15719 return RETURN_OK;
15720}
15721
15722INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
15723{
15724 char buf[256] = {0};
15725 char config_file[128] = {0};
15726 int disable = 0;
developere5750452023-05-15 16:46:42 +080015727 bool set_sae = FALSE;
developer72fb0bb2023-01-11 09:46:29 +080015728
15729 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
15730 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
15731 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
15732 security->mode = wifi_security_mode_none;
15733 if (strlen(buf) != 0) {
15734 if (!strcmp(buf, "WPA-Personal"))
15735 security->mode = wifi_security_mode_wpa_personal;
15736 else if (!strcmp(buf, "WPA2-Personal"))
15737 security->mode = wifi_security_mode_wpa2_personal;
15738 else if (!strcmp(buf, "WPA-WPA2-Personal"))
15739 security->mode = wifi_security_mode_wpa_wpa2_personal;
15740 else if (!strcmp(buf, "WPA-Enterprise"))
15741 security->mode = wifi_security_mode_wpa_enterprise;
15742 else if (!strcmp(buf, "WPA2-Enterprise"))
15743 security->mode = wifi_security_mode_wpa2_enterprise;
15744 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
15745 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
15746 else if (!strcmp(buf, "WPA3-Personal"))
15747 security->mode = wifi_security_mode_wpa3_personal;
15748 else if (!strcmp(buf, "WPA3-Personal-Transition"))
15749 security->mode = wifi_security_mode_wpa3_transition;
15750 else if (!strcmp(buf, "WPA3-Enterprise"))
15751 security->mode = wifi_security_mode_wpa3_enterprise;
developer3086e2f2023-01-17 09:40:01 +080015752 else if (!strcmp(buf, "OWE"))
developerd01e3e82023-04-26 19:10:38 +080015753 security->mode = wifi_security_mode_enhanced_open;
developer72fb0bb2023-01-11 09:46:29 +080015754 }
15755
15756 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
15757 if (security->mode == wifi_security_mode_none)
15758 security->encr = wifi_encryption_none;
15759 else {
15760 if (strcmp(buf, "TKIP") == 0)
15761 security->encr = wifi_encryption_tkip;
15762 else if (strcmp(buf, "CCMP") == 0)
15763 security->encr = wifi_encryption_aes;
15764 else
15765 security->encr = wifi_encryption_aes_tkip;
15766 }
15767
developerdaf24792023-06-06 11:40:04 +080015768 if (security->mode != wifi_security_mode_none) {
developer72fb0bb2023-01-11 09:46:29 +080015769 memset(buf, 0, sizeof(buf));
15770 // wpa3 can use one or both configs as password, so we check sae_password first.
15771 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
developere5750452023-05-15 16:46:42 +080015772 if (strlen(buf) != 0) {
15773 if (security->mode == wifi_security_mode_wpa3_personal || security->mode == wifi_security_mode_wpa3_transition)
15774 security->u.key.type = wifi_security_key_type_sae;
15775 set_sae = TRUE;
15776 strncpy(security->u.key.key, buf, sizeof(buf));
15777 }
15778 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
15779 if (strlen(buf) != 0){
15780 if (set_sae == TRUE)
15781 security->u.key.type = wifi_security_key_type_psk_sae;
15782 else if (strlen(buf) == 64)
15783 security->u.key.type = wifi_security_key_type_psk;
15784 else
15785 security->u.key.type = wifi_security_key_type_pass;
15786 strncpy(security->u.key.key, buf, sizeof(security->u.key.key));
developer72fb0bb2023-01-11 09:46:29 +080015787 }
developer72fb0bb2023-01-11 09:46:29 +080015788 security->u.key.key[255] = '\0';
15789 }
15790
15791 memset(buf, 0, sizeof(buf));
15792 wifi_getApSecurityMFPConfig(ap_index, buf);
15793 if (strcmp(buf, "Disabled") == 0)
15794 security->mfp = wifi_mfp_cfg_disabled;
15795 else if (strcmp(buf, "Optional") == 0)
15796 security->mfp = wifi_mfp_cfg_optional;
15797 else if (strcmp(buf, "Required") == 0)
15798 security->mfp = wifi_mfp_cfg_required;
15799
15800 memset(buf, 0, sizeof(buf));
15801 security->wpa3_transition_disable = FALSE;
15802 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
15803 disable = strtol(buf, NULL, 16);
15804 if (disable != 0)
15805 security->wpa3_transition_disable = TRUE;
15806
15807 memset(buf, 0, sizeof(buf));
15808 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
15809 if (strlen(buf) == 0)
15810 security->rekey_interval = 86400;
15811 else
15812 security->rekey_interval = strtol(buf, NULL, 10);
15813
15814 memset(buf, 0, sizeof(buf));
15815 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
15816 if (strlen(buf) == 0)
15817 security->strict_rekey = 1;
15818 else
15819 security->strict_rekey = strtol(buf, NULL, 10);
15820
15821 memset(buf, 0, sizeof(buf));
15822 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
15823 if (strlen(buf) == 0)
15824 security->eapol_key_retries = 4;
15825 else
15826 security->eapol_key_retries = strtol(buf, NULL, 10);
15827
15828 memset(buf, 0, sizeof(buf));
15829 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
15830 if (strlen(buf) == 0)
15831 security->disable_pmksa_caching = FALSE;
15832 else
15833 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
15834
15835 /* TODO
15836 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
15837 */
15838 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
15839 security->eap_identity_req_timeout = 0;
15840 security->eap_identity_req_retries = 0;
15841 security->eap_req_timeout = 0;
15842 security->eap_req_retries = 0;
15843 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
15844 return RETURN_OK;
15845}
15846
15847#endif /* WIFI_HAL_VERSION_3 */
15848
15849#ifdef WIFI_HAL_VERSION_3_PHASE2
15850INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
15851{
15852 char interface_name[16] = {0};
15853 char cmd[128] = {0};
15854 char buf[128] = {0};
15855 char *mac_addr = NULL;
15856 BOOL status = FALSE;
15857 size_t len = 0;
15858
15859 if(ap_index > MAX_APS)
15860 return RETURN_ERR;
15861
15862 *output_numDevices = 0;
15863 wifi_getApEnable(ap_index, &status);
15864 if (status == FALSE)
15865 return RETURN_OK;
15866
15867 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
15868 return RETURN_ERR;
15869 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
15870 _syscmd(cmd, buf, sizeof(buf));
15871
15872 mac_addr = strtok(buf, "\n");
15873 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
15874 *output_numDevices = i + 1;
15875 fprintf(stderr, "mac_addr: %s\n", mac_addr);
15876 addr_ptr = output_deviceMacAddressArray[i];
15877 mac_addr_aton(addr_ptr, mac_addr);
15878 mac_addr = strtok(NULL, "\n");
15879 }
15880
15881 return RETURN_OK;
15882}
15883#else
15884INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
15885{
15886 char interface_name[16] = {0};
15887 char cmd[128];
15888 BOOL status = false;
15889
15890 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
15891 return RETURN_ERR;
15892
15893 output_buf[0] = '\0';
15894
15895 wifi_getApEnable(ap_index,&status);
15896 if (!status)
15897 return RETURN_OK;
15898
15899 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
15900 return RETURN_ERR;
15901 sprintf(cmd, "hostapd_cli -i %s list_sta | tr '\\n' ',' | sed 's/.$//'", interface_name);
15902 _syscmd(cmd, output_buf, output_buf_size);
developer69b61b02023-03-07 17:17:44 +080015903
developer72fb0bb2023-01-11 09:46:29 +080015904 return RETURN_OK;
15905}
15906#endif
15907
15908INT wifi_getProxyArp(INT apIndex, BOOL *enable)
15909{
15910 char output[16]={'\0'};
15911 char config_file[MAX_BUF_SIZE] = {0};
15912
15913 if (!enable)
15914 return RETURN_ERR;
15915
15916 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
15917 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
15918
15919 if (strlen(output) == 0)
15920 *enable = FALSE;
15921 else if (strncmp(output, "1", 1) == 0)
15922 *enable = TRUE;
15923 else
15924 *enable = FALSE;
15925
15926 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
15927 return RETURN_OK;
15928}
15929
15930INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
15931{
15932 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
15933 return RETURN_ERR;
15934 *output_enable=TRUE;
15935 return RETURN_OK;
15936}
15937
15938INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
15939{
15940 char cmd[128] = {0};
15941 char buf[128] = {0};
15942 char line[128] = {0};
developer72fb0bb2023-01-11 09:46:29 +080015943 FILE *f = NULL;
15944 int index = 0;
15945 int exp = 0;
15946 int mantissa = 0;
15947 int duration = 0;
15948 int radio_index = 0;
15949 int max_radio_num = 0;
15950 uint twt_wake_interval = 0;
15951 int phyId = 0;
15952 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
15953
15954 wifi_getMaxRadioNumber(&max_radio_num);
15955
15956 radio_index = ap_index % max_radio_num;
15957
15958 phyId = radio_index_to_phy(radio_index);
15959 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", phyId);
15960 _syscmd(cmd, buf, sizeof(buf));
15961 *numSessionReturned = strtol(buf, NULL, 10) - 1;
15962 if (*numSessionReturned > maxNumberSessions)
15963 *numSessionReturned = maxNumberSessions;
15964 else if (*numSessionReturned < 1) {
15965 *numSessionReturned = 0;
15966 return RETURN_OK;
15967 }
15968
15969 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | tail -n %d | tr '|' ' ' | tr -s ' '", phyId, *numSessionReturned);
15970 if ((f = popen(cmd, "r")) == NULL) {
15971 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
15972 return RETURN_ERR;
15973 }
15974
15975 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
15976 while((fgets(line, sizeof(line), f)) != NULL) {
15977 char *tmp = NULL;
15978 strcpy(buf, line);
15979 tmp = strtok(buf, " ");
15980 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
15981 tmp = strtok(NULL, " ");
15982 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
15983 tmp = strtok(NULL, " ");
15984 if (strstr(tmp, "t")) {
15985 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
15986 }
15987 if (strstr(tmp, "a")) {
15988 twtSessions[index].twtParameters.operation.announced = TRUE;
15989 }
15990 tmp = strtok(NULL, " ");
15991 exp = strtol(tmp, NULL, 10);
15992 tmp = strtok(NULL, " ");
15993 mantissa = strtol(tmp, NULL, 10);
15994 tmp = strtok(NULL, " ");
15995 duration = strtol(tmp, NULL, 10);
15996
15997 // only implicit supported
15998 twtSessions[index].twtParameters.operation.implicit = TRUE;
15999 // only individual agreement supported
16000 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
16001
16002 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
16003 twt_wake_interval = mantissa * (1 << exp);
16004 if (mantissa == 0 || twt_wake_interval/mantissa != (1 << exp)) {
16005 // Overflow handling
16006 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
16007 } else {
16008 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
16009 }
16010 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
16011 index++;
16012 }
16013
16014 pclose(f);
16015 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
16016 return RETURN_OK;
16017}
developercc5cbfb2023-06-13 18:29:52 +080016018
16019INT wifi_enableGreylistAccessControl(BOOL enable)
16020{
16021 char inf_name[IFNAMSIZ] = {0};
16022 int if_idx, ret = 0;
16023 struct nl_msg *msg = NULL;
16024 struct nlattr * msg_data = NULL;
16025 struct mtk_nl80211_param param;
16026 struct unl unl_ins;
16027 unsigned short apIndex = 0;
16028
16029 for (apIndex = 0; apIndex < MAX_APS; apIndex++) {
16030 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
16031 continue;
16032
16033 if_idx = if_nametoindex(inf_name);
16034 if (!if_idx) {
16035 wifi_debug(DEBUG_ERROR, "can't finde ifname(%s) index,ERROR\n", inf_name);
16036 continue;
16037 }
16038
16039 /*init mtk nl80211 vendor cmd*/
16040 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_ACL;
16041 param.if_type = NL80211_ATTR_IFINDEX;
16042 param.if_idx = if_idx;
16043 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
16044 if (ret) {
16045 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
16046 return RETURN_ERR;
16047 }
16048
16049 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_ACL_POLICY, enable == FALSE ? 0 : 1)) {
16050 wifi_debug(DEBUG_ERROR, "Nla put attribute error\n");
16051 nlmsg_free(msg);
16052 mtk_nl80211_deint(&unl_ins);
16053 continue;
16054 }
16055
16056 /*send mtk nl80211 vendor msg*/
16057 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
16058 if (ret) {
16059 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
16060 mtk_nl80211_deint(&unl_ins);
16061 continue;
16062 }
16063 /*deinit mtk nl80211 vendor msg*/
16064 mtk_nl80211_deint(&unl_ins);
16065 wifi_debug(DEBUG_NOTICE, " %s cmd success.\n", inf_name);
16066 }
16067
16068 return RETURN_OK;
16069}