blob: e33d6e147f9cce95772f5e8dca436e595631a1ee [file] [log] [blame]
developer72fb0bb2023-01-11 09:46:29 +08001/*
2 * If not stated otherwise in this file or this component's LICENSE file the
3 * following copyright and licenses apply:
4 *
5 * Copyright 2019 RDK Management
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18*/
19
20/*
21* Material from the TR181 data model is Copyright (c) 2010-2017, Broadband Forum
22* Licensed under the BSD-3 license
23*/
24
25/*
26* This file includes material that is Copyright (c) 2020, Plume Design Inc.
27* Licensed under the BSD-3 license
28*/
29
30/* Code in rxStatsInfo_callback and other callbacks is credited as follows:
31Copyright (c) 2007, 2008 Johannes Berg
32Copyright (c) 2007 Andy Lutomirski
33Copyright (c) 2007 Mike Kershaw
34Copyright (c) 2008-2009 Luis R. Rodriguez
35Licensed under the ISC license
36*/
37#define MTK_IMPL
38#define HAL_NETLINK_IMPL
39#define _GNU_SOURCE /* needed for strcasestr */
40
41#include <stdio.h>
42#include <stdlib.h>
43#include <unistd.h>
44#include <string.h>
45#include <fcntl.h>
46#include <stdbool.h>
47#include "wifi_hal.h"
48
49#ifdef HAL_NETLINK_IMPL
50#include <errno.h>
51#include <netlink/attr.h>
52#include <netlink/netlink.h>
53#include <netlink/genl/genl.h>
54#include <netlink/genl/family.h>
55#include <netlink/genl/ctrl.h>
56#include <linux/nl80211.h>
developer8dd72532023-05-17 19:58:35 +080057#include <net/if.h>
58#include <unl.h>
59#include "mtk_vendor_nl80211.h"
developer72fb0bb2023-01-11 09:46:29 +080060#endif
61
62#include <ev.h>
63#include <wpa_ctrl.h>
64#include <errno.h>
65#include <time.h>
66#define MAC_ALEN 6
67
68#define MAX_BUF_SIZE 256
69#define MAX_CMD_SIZE 256
70#define IF_NAME_SIZE 16
71#define CONFIG_PREFIX "/nvram/hostapd"
72#define ACL_PREFIX "/nvram/hostapd-acl"
73#define DENY_PREFIX "/nvram/hostapd-deny"
74//#define ACL_PREFIX "/tmp/wifi_acl_list" //RDKB convention
75#define SOCK_PREFIX "/var/run/hostapd/wifi"
76#define VAP_STATUS_FILE "/nvram/vap-status"
77#define ESSID_FILE "/tmp/essid"
78#define GUARD_INTERVAL_FILE "/nvram/guard-interval"
79#define CHANNEL_STATS_FILE "/tmp/channel_stats"
80#define DFS_ENABLE_FILE "/nvram/dfs_enable.txt"
81#define VLAN_FILE "/nvram/hostapd.vlan"
82#define PSK_FILE "/nvram/hostapd"
83#define MCS_FILE "/tmp/MCS"
developera1255e42023-05-13 17:45:02 +080084#define POWER_PERCENTAGE "/tmp/POWER"
85#define MGMT_POWER_CTRL "/tmp/mgmt_power_ctrl"
86/*LOGAN_DAT_FILE: may be different on customer's platform.*/
87#define LOGAN_DAT_FILE "/etc/wireless/mediatek/mt7990.b"
developerb2977562023-05-24 17:54:12 +080088#define ROM_LOGAN_DAT_FILE "/rom/etc/wireless/mediatek/mt7990.b"
developera1255e42023-05-13 17:45:02 +080089
developer72fb0bb2023-01-11 09:46:29 +080090#define NOACK_MAP_FILE "/tmp/NoAckMap"
developerfead3972023-05-25 20:15:02 +080091#define RADIO_RESET_FILE "/nvram/radio_reset"
developerf6a87542023-05-16 15:47:28 +080092
developer72fb0bb2023-01-11 09:46:29 +080093#define BRIDGE_NAME "brlan0"
developerd1824452023-05-18 12:30:04 +080094#define BASE_PHY_INDEX 1
95#define BASE_RADIO_INDEX 0
developer72fb0bb2023-01-11 09:46:29 +080096
97/*
98 MAX_APS - Number of all AP available in system
99 2x Home AP
100 2x Backhaul AP
101 2x Guest AP
102 2x Secure Onboard AP
103 2x Service AP
104
105*/
106
107
108#define MAX_APS MAX_NUM_RADIOS*5
developer7e4a2a62023-04-06 19:56:03 +0800109
110#define PREFIX_WIFI2G "ra"
111#define PREFIX_WIFI5G "rai"
112#define PREFIX_WIFI6G "rax"
developer72fb0bb2023-01-11 09:46:29 +0800113
developer47cc27a2023-05-17 23:09:58 +0800114#define PREFIX_SSID_2G "RDKB_2G"
115#define PREFIX_SSID_5G "RDKB_5G"
116#define PREFIX_SSID_6G "RDKB_6G"
117
developer72fb0bb2023-01-11 09:46:29 +0800118#ifndef RADIO_PREFIX
119#define RADIO_PREFIX "wlan"
120#endif
121
122#define MAX_ASSOCIATED_STA_NUM 2007
123
124//Uncomment to enable debug logs
125//#define WIFI_DEBUG
developer49b17232023-05-19 16:35:19 +0800126enum {
127 DEBUG_OFF = 0,
128 DEBUG_ERROR = 1,
129 DEBUG_WARN = 2,
130 DEBUG_NOTICE = 3,
131 DEBUG_INFO = 4
132};
133int wifi_debug_level = DEBUG_NOTICE;
134#define wifi_debug(level, fmt, args...) \
135{ \
136 if (level <= wifi_debug_level) \
137 { \
developer2edaf012023-05-24 14:24:53 +0800138 printf("[%s][%d]"fmt"", __func__, __LINE__, ##args); \
developer49b17232023-05-19 16:35:19 +0800139 } \
140}
developer72fb0bb2023-01-11 09:46:29 +0800141
142#ifdef WIFI_DEBUG
143#define wifi_dbg_printf printf
144#define WIFI_ENTRY_EXIT_DEBUG printf
145#else
146#define wifi_dbg_printf(format, args...) printf("")
147#define WIFI_ENTRY_EXIT_DEBUG(format, args...) printf("")
148#endif
149
150#define HOSTAPD_CONF_0 "/nvram/hostapd0.conf" //private-wifi-2g
151#define HOSTAPD_CONF_1 "/nvram/hostapd1.conf" //private-wifi-5g
152#define HOSTAPD_CONF_4 "/nvram/hostapd4.conf" //public-wifi-2g
153#define HOSTAPD_CONF_5 "/nvram/hostapd5.conf" //public-wifi-5g
154#define DEF_HOSTAPD_CONF_0 "/usr/ccsp/wifi/hostapd0.conf"
155#define DEF_HOSTAPD_CONF_1 "/usr/ccsp/wifi/hostapd1.conf"
156#define DEF_HOSTAPD_CONF_4 "/usr/ccsp/wifi/hostapd4.conf"
157#define DEF_HOSTAPD_CONF_5 "/usr/ccsp/wifi/hostapd5.conf"
158#define DEF_RADIO_PARAM_CONF "/usr/ccsp/wifi/radio_param_def.cfg"
159#define LM_DHCP_CLIENT_FORMAT "%63d %17s %63s %63s"
160
161#define HOSTAPD_HT_CAPAB "[LDPC][SHORT-GI-20][SHORT-GI-40][MAX-AMSDU-7935]"
162
163#define BW_FNAME "/nvram/bw_file.txt"
164
165#define PS_MAX_TID 16
166
developer96b38512023-02-22 11:17:45 +0800167#define MAX_CARD_INDEX 3
168
developer72fb0bb2023-01-11 09:46:29 +0800169static wifi_radioQueueType_t _tid_ac_index_get[PS_MAX_TID] = {
170 WIFI_RADIO_QUEUE_TYPE_BE, /* 0 */
171 WIFI_RADIO_QUEUE_TYPE_BK, /* 1 */
172 WIFI_RADIO_QUEUE_TYPE_BK, /* 2 */
173 WIFI_RADIO_QUEUE_TYPE_BE, /* 3 */
174 WIFI_RADIO_QUEUE_TYPE_VI, /* 4 */
175 WIFI_RADIO_QUEUE_TYPE_VI, /* 5 */
176 WIFI_RADIO_QUEUE_TYPE_VO, /* 6 */
177 WIFI_RADIO_QUEUE_TYPE_VO, /* 7 */
178 WIFI_RADIO_QUEUE_TYPE_BE, /* 8 */
179 WIFI_RADIO_QUEUE_TYPE_BK, /* 9 */
180 WIFI_RADIO_QUEUE_TYPE_BK, /* 10 */
181 WIFI_RADIO_QUEUE_TYPE_BE, /* 11 */
182 WIFI_RADIO_QUEUE_TYPE_VI, /* 12 */
183 WIFI_RADIO_QUEUE_TYPE_VI, /* 13 */
184 WIFI_RADIO_QUEUE_TYPE_VO, /* 14 */
185 WIFI_RADIO_QUEUE_TYPE_VO, /* 15 */
186};
187
188typedef unsigned long long u64;
189
190/* Enum to define WiFi Bands */
191typedef enum
192{
193 band_invalid = -1,
194 band_2_4 = 0,
195 band_5 = 1,
196 band_6 = 2,
197} wifi_band;
198
developer17038e62023-03-02 14:43:43 +0800199char* wifi_band_str[] = {
200 "2G",
201 "5G",
202 "6G",
203};
204
developer72fb0bb2023-01-11 09:46:29 +0800205typedef enum {
206 WIFI_MODE_A = 0x01,
207 WIFI_MODE_B = 0x02,
208 WIFI_MODE_G = 0x04,
209 WIFI_MODE_N = 0x08,
210 WIFI_MODE_AC = 0x10,
211 WIFI_MODE_AX = 0x20,
developera1255e42023-05-13 17:45:02 +0800212 WIFI_MODE_BE = 0x40,
developer72fb0bb2023-01-11 09:46:29 +0800213} wifi_ieee80211_Mode;
214
developerd1824452023-05-18 12:30:04 +0800215typedef enum ht_config_bw{
216 HT_BW_20,
217 HT_BW_40,
218};
219
220typedef enum vht_config_bw{
221 VHT_BW_2040,
222 VHT_BW_80,
223 VHT_BW_160,
224 VHT_BW_8080,
225};
226
227typedef enum eht_config_bw{
228 EHT_BW_20,
229 EHT_BW_40,
230 EHT_BW_80,
231 EHT_BW_160,
232 EHT_BW_320,
233};
234
developer72fb0bb2023-01-11 09:46:29 +0800235#ifdef WIFI_HAL_VERSION_3
236
237// Return number of elements in array
238#ifndef ARRAY_SIZE
239#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
240#endif /* ARRAY_SIZE */
241
242#ifndef ARRAY_AND_SIZE
243#define ARRAY_AND_SIZE(x) (x),ARRAY_SIZE(x)
244#endif /* ARRAY_AND_SIZE */
245
246#define WIFI_ITEM_STR(key, str) {0, sizeof(str)-1, (int)key, (intptr_t)str}
247
248typedef struct {
249 int32_t value;
250 int32_t param;
251 intptr_t key;
252 intptr_t data;
253} wifi_secur_list;
254
255static int util_unii_5g_centerfreq(const char *ht_mode, int channel);
256static int util_unii_6g_centerfreq(const char *ht_mode, int channel);
257wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key);
258wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str);
259char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key);
260static int ieee80211_channel_to_frequency(int channel, int *freqMHz);
developer47cc27a2023-05-17 23:09:58 +0800261static void wifi_PrepareDefaultHostapdConfigs(void);
262static void wifi_psk_file_reset();
developerb2977562023-05-24 17:54:12 +0800263static void wifi_psk_file_reset_by_radio(char radio_idx);
264static void wifi_dat_file_reset();
265static void wifi_dat_file_reset_by_radio(char radio_idx);
developer262f4cb2023-05-24 12:22:04 +0800266static int util_get_sec_chan_offset(int channel, const char* ht_mode);
developer47cc27a2023-05-17 23:09:58 +0800267
developer49b17232023-05-19 16:35:19 +0800268/*type define the nl80211 call back func*/
269typedef int (*mtk_nl80211_cb) (struct nl_msg *, void *);
270
271/**
272*struct mtk_nl80211_param
273* init mtk nl80211 using parameters
274* @sub_cmd: the cmd define in the mtk_vendor_nl80211.h.
275* @if_type: now only support the NL80211_ATTR_IFINDEX/NL80211_ATTR_WIPHY.
276* @if_idx: the index should match the interface or wiphy.
277* Note: NA
278**/
279struct mtk_nl80211_param {
280 unsigned int sub_cmd;
281 int if_type;
282 int if_idx;
283};
284
285/**
developer121a8e72023-05-22 09:19:39 +0800286*struct mtk_nl80211_cb_data
287* init mtk nl80211 call back parameters
288* @out_buf: store the mtk vendor output msg for wifi hal buffer.
289* @out_len: the output buffer length.
290* Note: NA
291**/
292struct mtk_nl80211_cb_data {
293 char * out_buf;
294 unsigned int out_len;
295};
296
297/**
developer49b17232023-05-19 16:35:19 +0800298*mtk_nl80211_init
299* init mtk nl80211 netlink and init the vendor msg common part.
300* @nl: netlink, just init it.
301* @msg: netlink message will alloc it.
302* the msg send success/fails is not free by app
303* only the nla_put etc api fails should use nlmsg_free.
304* @msg_data: vendor data msg attr pointer.
305* @param: init using interface and sub_cmd parameter.
306*
307*init the netlink context and mtk netlink vendor msg.
308*
309*return:
310* 0: success
311* other: fail
312**/
313
314int mtk_nl80211_init(struct unl *nl, struct nl_msg **msg,
315 struct nlattr **msg_data, struct mtk_nl80211_param *param) {
316 /*sanity check here*/
317 if (!nl || !param) {
318 (void)fprintf(stderr,
319 "[%s][%d]:nl(0x%lx) or param(0x%lx) is null, error!\n",
320 __func__, __LINE__, nl, param);
321 return -1;
322 }
323 /*if_type check*/
324 if ( param->if_type != NL80211_ATTR_IFINDEX && param->if_type != NL80211_ATTR_WIPHY) {
325 (void)fprintf(stderr,
326 "[%s][%d]:if_type(0x%x) is not supported, only 0x%x and 0x%x supported.\n",
327 __func__, __LINE__, param->if_type, NL80211_ATTR_IFINDEX, NL80211_ATTR_WIPHY);
328 return -1;
329 }
330 /*init the nl*/
331 if (unl_genl_init(nl, "nl80211") < 0) {
332 (void)fprintf(stderr, "[%s][%d]::Failed to connect to nl80211\n",
333 __func__, __LINE__);
334 return -1;
335 }
336 /*init the msg*/
337 *msg = unl_genl_msg(nl, NL80211_CMD_VENDOR, false);
338
339 if (nla_put_u32(*msg, param->if_type, param->if_idx) ||
340 nla_put_u32(*msg, NL80211_ATTR_VENDOR_ID, MTK_NL80211_VENDOR_ID) ||
341 nla_put_u32(*msg, NL80211_ATTR_VENDOR_SUBCMD, param->sub_cmd)) {
342 (void)fprintf(stderr,
343 "[%s][%d]:Nla put error: if_type: 0x%x, if_idx: 0x%x, sub_cmd: 0x%x\n",
344 __func__, __LINE__, param->if_type, param->if_idx, param->sub_cmd);
345 goto err;
346 }
347
348 *msg_data = nla_nest_start(*msg, NL80211_ATTR_VENDOR_DATA);
349 if (!*msg_data) {
350 (void)fprintf(stderr, "[%s][%d]:Nla put NL80211_ATTR_VENDOR_DATA start error\n",
351 __func__, __LINE__);
352 goto err;
353 }
354
355 return 0;
356err:
developer49b17232023-05-19 16:35:19 +0800357 nlmsg_free(*msg);
358 unl_free(nl);
359 return -1;
360}
361
362/**
363*mtk_nl80211_send
364* set the vendor cmd call back and sent the vendor msg.
365* @nl: netlink.
366* @msg: netlink message.
367* @msg_data: vendor data msg attr pointer.
368* @handler: if the msg have call back shoud add the call back func
369* the event msg will handle by the call back func(exp:get cmd)
370* other set it as NULL(exp:set cmd).
371* @arg:call back func arg parameter.
372*add end of the netlink msg, set the call back and send msg
373*
374*return:
375* 0: success
376* other: fail
377**/
378int mtk_nl80211_send(struct unl *nl, struct nl_msg *msg,
379 struct nlattr *msg_data, mtk_nl80211_cb handler, void *arg) {
380 int ret = 0;
381 /*sanity check*/
382 if (!nl || !msg || !msg_data) {
383 (void)fprintf(stderr,
384 "[%s][%d]:nl(0x%lx),msg(0x%lx) or msg_data(0x%lx) is null, error!\n",
385 __func__, __LINE__, nl, msg, msg_data);
386 return -1;
387 }
388 /*end the msg attr of vendor data*/
389 nla_nest_end(msg, msg_data);
390 /*send the msg and set call back */
391 ret = unl_genl_request(nl, msg, handler, arg);
392 if (ret)
393 (void)fprintf(stderr, "send nl80211 cmd fails\n");
394 return ret;
395}
396
397/**
398*mtk_nl80211_deint
developer2edaf012023-05-24 14:24:53 +0800399* deinit the netlink.
developer49b17232023-05-19 16:35:19 +0800400* @nl: netlink.
401*
developer2edaf012023-05-24 14:24:53 +0800402*free deinit the netlink.
developer49b17232023-05-19 16:35:19 +0800403*
404*return:
405* 0: success
406**/
407
408int mtk_nl80211_deint(struct unl *nl) {
409 unl_free(nl);
410 return 0;
411}
412
developer72fb0bb2023-01-11 09:46:29 +0800413
414static wifi_secur_list map_security[] =
415{
416 WIFI_ITEM_STR(wifi_security_mode_none, "None"),
417 WIFI_ITEM_STR(wifi_security_mode_wep_64, "WEP-64"),
418 WIFI_ITEM_STR(wifi_security_mode_wep_128, "WEP-128"),
419 WIFI_ITEM_STR(wifi_security_mode_wpa_personal, "WPA-Personal"),
420 WIFI_ITEM_STR(wifi_security_mode_wpa_enterprise, "WPA-Enterprise"),
421 WIFI_ITEM_STR(wifi_security_mode_wpa2_personal, "WPA2-Personal"),
422 WIFI_ITEM_STR(wifi_security_mode_wpa2_enterprise, "WPA2-Enterprise"),
423 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_personal, "WPA-WPA2-Personal"),
424 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_enterprise, "WPA-WPA2-Enterprise"),
425 WIFI_ITEM_STR(wifi_security_mode_wpa3_personal, "WPA3-Personal"),
426 WIFI_ITEM_STR(wifi_security_mode_wpa3_transition, "WPA3-Personal-Transition"),
427 WIFI_ITEM_STR(wifi_security_mode_wpa3_enterprise, "WPA3-Enterprise")
428};
429
430wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key)
431{
432 wifi_secur_list *item;
433 int i;
434
435 for (item = list,i = 0;i < list_sz; item++, i++) {
436 if ((int)(item->key) == key) {
437 return item;
438 }
439 }
440
441 return NULL;
442}
443
444char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key)
445{
446 wifi_secur_list *item = wifi_get_item_by_key(list, list_sz, key);
447
448 if (!item) {
449 return "";
450 }
451
452 return (char *)(item->data);
453}
454
455wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str)
456{
457 wifi_secur_list *item;
458 int i;
459
460 for (item = list,i = 0;i < list_sz; item++, i++) {
461 if (strcmp((char *)(item->data), str) == 0) {
462 return item;
463 }
464 }
465
466 return NULL;
467}
468#endif /* WIFI_HAL_VERSION_3 */
469
developer96b38512023-02-22 11:17:45 +0800470
471static char l1profile[32] = "/etc/wireless/l1profile.dat";
developer17038e62023-03-02 14:43:43 +0800472char main_prefix[MAX_NUM_RADIOS][IFNAMSIZ];
473char ext_prefix[MAX_NUM_RADIOS][IFNAMSIZ];
474#define MAX_SSID_LEN 64
475char default_ssid[MAX_NUM_RADIOS][MAX_SSID_LEN];;
developer745f0bd2023-03-06 14:32:53 +0800476int radio_band[MAX_NUM_RADIOS];
developer17038e62023-03-02 14:43:43 +0800477
478static int array_index_to_vap_index(UINT radioIndex, int arrayIndex);
479static int vap_index_to_array_index(int vapIndex, int *radioIndex, int *arrayIndex);
480
developer96b38512023-02-22 11:17:45 +0800481
482static int
483get_value(const char *conf_file, const char *param, char *value, int len)
484{
485 FILE *fp;
486 int ret = -1;
487 int param_len = strlen(param);
488 int buf_len;
489 char buf[256];
490
491 fp = fopen(conf_file, "r");
492 if (!fp) {
493 return -1;
494 }
495
496 while (fgets(buf, sizeof(buf), fp)) {
497 buf_len = strlen(buf);
498 if (buf[buf_len - 1] == '\n') {
499 buf_len--;
500 buf[buf_len] = '\0';
501 }
502 if ((buf_len > param_len) &&
503 (strncmp(buf, param, param_len) == 0) &&
504 (buf[param_len] == '=')) {
505
506 if (buf_len == (param_len + 1)) {
507 value[0] = '\0';
508 ret = 0;
509 } else {
510 ret = snprintf(value, len, "%s", buf + (param_len + 1));
511 }
512 fclose(fp);
513 return ret;
514 }
515 }
516 fclose(fp);
517 return -1;
518}
519
520static int
521get_value_by_idx(const char *conf_file, const char *param, int idx, char *value, int len)
522{
523 char buf[256];
524 int ret;
525 char *save_ptr = NULL;
526 char *tok = NULL;
527
528 ret = get_value(conf_file, param, buf, sizeof(buf));
529 if (ret < 0)
530 return ret;
531
532 tok = strtok_r(buf, ";", &save_ptr);
533 do {
534 if (idx == 0 || tok == NULL)
535 break;
536 else
537 idx--;
538
539 tok = strtok_r(NULL, ";", &save_ptr);
540 } while (tok != NULL);
541
542 if (tok) {
543 ret = snprintf(value, len, "%s", tok);
544 } else {
545 ret = 0;
546 value[0] = '\0';
547 }
548
549 return ret;
550}
551
552
developer72fb0bb2023-01-11 09:46:29 +0800553#ifdef HAL_NETLINK_IMPL
554typedef struct {
555 int id;
556 struct nl_sock* socket;
557 struct nl_cb* cb;
558} Netlink;
559
560static int mac_addr_aton(unsigned char *mac_addr, char *arg)
561{
562 unsigned int mac_addr_int[6]={};
563 sscanf(arg, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", mac_addr_int+0, mac_addr_int+1, mac_addr_int+2, mac_addr_int+3, mac_addr_int+4, mac_addr_int+5);
564 mac_addr[0] = mac_addr_int[0];
565 mac_addr[1] = mac_addr_int[1];
566 mac_addr[2] = mac_addr_int[2];
567 mac_addr[3] = mac_addr_int[3];
568 mac_addr[4] = mac_addr_int[4];
569 mac_addr[5] = mac_addr_int[5];
570 return 0;
571}
572
573static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
574{
575 unsigned int mac_addr_int[6]={};
576 mac_addr_int[0] = arg[0];
577 mac_addr_int[1] = arg[1];
578 mac_addr_int[2] = arg[2];
579 mac_addr_int[3] = arg[3];
580 mac_addr_int[4] = arg[4];
581 mac_addr_int[5] = arg[5];
582 snprintf(mac_addr, 20, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", mac_addr_int[0], mac_addr_int[1],mac_addr_int[2],mac_addr_int[3],mac_addr_int[4],mac_addr_int[5]);
583 return;
584}
585
586static int ieee80211_frequency_to_channel(int freq)
587{
588 /* see 802.11-2007 17.3.8.3.2 and Annex J */
589 if (freq == 2484)
590 return 14;
591 /* see 802.11ax D6.1 27.3.23.2 and Annex E */
592 else if (freq == 5935)
593 return 2;
594 else if (freq < 2484)
595 return (freq - 2407) / 5;
596 else if (freq >= 4910 && freq <= 4980)
597 return (freq - 4000) / 5;
598 else if (freq < 5950)
599 return (freq - 5000) / 5;
600 else if (freq <= 45000) /* DMG band lower limit */
601 /* see 802.11ax D6.1 27.3.23.2 */
602 return (freq - 5950) / 5;
603 else if (freq >= 58320 && freq <= 70200)
604 return (freq - 56160) / 2160;
605 else
606 return 0;
607}
608
609static int initSock80211(Netlink* nl) {
610 nl->socket = nl_socket_alloc();
611 if (!nl->socket) {
612 fprintf(stderr, "Failing to allocate the sock\n");
613 return -ENOMEM;
614 }
615
616 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
617
618 if (genl_connect(nl->socket)) {
619 fprintf(stderr, "Failed to connect\n");
620 nl_close(nl->socket);
621 nl_socket_free(nl->socket);
622 return -ENOLINK;
623 }
624
625 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
626 if (nl->id< 0) {
627 fprintf(stderr, "interface not found.\n");
628 nl_close(nl->socket);
629 nl_socket_free(nl->socket);
630 return -ENOENT;
631 }
632
633 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
634 if ((!nl->cb)) {
635 fprintf(stderr, "Failed to allocate netlink callback.\n");
636 nl_close(nl->socket);
637 nl_socket_free(nl->socket);
638 return ENOMEM;
639 }
640
641 return nl->id;
642}
643
644static int nlfree(Netlink *nl)
645{
646 nl_cb_put(nl->cb);
647 nl_close(nl->socket);
648 nl_socket_free(nl->socket);
649 return 0;
650}
651
652static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
653 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
654 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
655 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
656};
657
658static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
659};
660
661static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
662};
663
664typedef struct _wifi_channelStats_loc {
665 INT array_size;
666 INT ch_number;
667 BOOL ch_in_pool;
668 INT ch_noise;
669 BOOL ch_radar_noise;
670 INT ch_max_80211_rssi;
671 INT ch_non_80211_noise;
672 INT ch_utilization;
673 ULLONG ch_utilization_total;
674 ULLONG ch_utilization_busy;
675 ULLONG ch_utilization_busy_tx;
676 ULLONG ch_utilization_busy_rx;
677 ULLONG ch_utilization_busy_self;
678 ULLONG ch_utilization_busy_ext;
679} wifi_channelStats_t_loc;
680
681typedef struct wifi_device_info {
682 INT wifi_devIndex;
683 UCHAR wifi_devMacAddress[6];
684 CHAR wifi_devIPAddress[64];
685 BOOL wifi_devAssociatedDeviceAuthentiationState;
686 INT wifi_devSignalStrength;
687 INT wifi_devTxRate;
688 INT wifi_devRxRate;
689} wifi_device_info_t;
690
691#endif
692
693//For 5g Alias Interfaces
694static BOOL priv_flag = TRUE;
695static BOOL pub_flag = TRUE;
696static BOOL Radio_flag = TRUE;
697//wifi_setApBeaconRate(1, beaconRate);
698
699BOOL multiple_set = FALSE;
700
701struct params
702{
703 char * name;
704 char * value;
705};
706
707static int _syscmd(char *cmd, char *retBuf, int retBufSize)
708{
709 FILE *f;
710 char *ptr = retBuf;
711 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
712
713 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
714 if((f = popen(cmd, "r")) == NULL) {
715 fprintf(stderr,"\npopen %s error\n", cmd);
716 return RETURN_ERR;
717 }
718
719 while(!feof(f))
720 {
721 *ptr = 0;
722 if(bufSize>=128) {
723 bufbytes=128;
724 } else {
725 bufbytes=bufSize-1;
726 }
727
728 fgets(ptr,bufbytes,f);
729 readbytes=strlen(ptr);
730
731 if(!readbytes)
732 break;
733
734 bufSize-=readbytes;
735 ptr += readbytes;
736 }
737 cmd_ret = pclose(f);
738 retBuf[retBufSize-1]=0;
739 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
740
741 return cmd_ret >> 8;
742}
743
744INT radio_index_to_phy(int radioIndex)
745{
developer17038e62023-03-02 14:43:43 +0800746 /* TODO */
747 return radioIndex;
developer72fb0bb2023-01-11 09:46:29 +0800748}
749
750INT wifi_getMaxRadioNumber(INT *max_radio_num)
751{
752 char cmd[64] = {0};
753 char buf[4] = {0};
754
755 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
756
757 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
758 _syscmd(cmd, buf, sizeof(buf));
759 *max_radio_num = strtoul(buf, NULL, 10) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS:strtoul(buf, NULL, 10);
760
761 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
762
763 return RETURN_OK;
764}
765
developer17038e62023-03-02 14:43:43 +0800766wifi_band radio_index_to_band(int radioIndex)
767{
developer745f0bd2023-03-06 14:32:53 +0800768 return radio_band[radioIndex];
developer17038e62023-03-02 14:43:43 +0800769}
770
developer72fb0bb2023-01-11 09:46:29 +0800771wifi_band wifi_index_to_band(int apIndex)
772{
773 char cmd[128] = {0};
774 char buf[64] = {0};
775 int nl80211_band = 0;
776 int i = 0;
777 int phyIndex = 0;
778 int radioIndex = 0;
779 int max_radio_num = 0;
780 wifi_band band = band_invalid;
781
782 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
783
784 wifi_getMaxRadioNumber(&max_radio_num);
785 radioIndex = apIndex % max_radio_num;
786 phyIndex = radio_index_to_phy(radioIndex);
787 while(i < 10){
788 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Band .:' | tail -n 1 | tr -d ':\\n' | awk '{print $2}'", phyIndex);
789 _syscmd(cmd, buf, sizeof(buf));
790 nl80211_band = strtol(buf, NULL, 10);
791 if (nl80211_band == 1)
792 band = band_2_4;
793 else if (nl80211_band == 2)
794 band = band_5;
795 else if (nl80211_band == 4) // band == 3 is 60GHz
796 band = band_6;
797
798 if(band != band_invalid)
799 break;
developer69b61b02023-03-07 17:17:44 +0800800
developer72fb0bb2023-01-11 09:46:29 +0800801 i++;
802 sleep(1);
803 }
804
805 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
806 return band;
807}
808
809static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
810{
developer7e4a2a62023-04-06 19:56:03 +0800811 char cmd[MAX_CMD_SIZE] = {0};
812 char buf[MAX_BUF_SIZE] = {0};
813 int ret = 0;
developer72fb0bb2023-01-11 09:46:29 +0800814
developer7e4a2a62023-04-06 19:56:03 +0800815 ret = snprintf(cmd, MAX_CMD_SIZE, "cat %s 2> /dev/null | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"",
816 conf_file, param);
developer72fb0bb2023-01-11 09:46:29 +0800817
developer7e4a2a62023-04-06 19:56:03 +0800818 if (ret < 0) {
819 printf("%s: snprintf error!", __func__);
820 return -1;
821 }
822
823 ret = _syscmd(cmd, buf, sizeof(buf));
824 if ((ret != 0) && (strlen(buf) == 0)) {
825 printf("%s: _syscmd error!", __func__);
826 return -1;
827 }
828
829 snprintf(output, output_size, "%s", buf);
830
831 return 0;
developer72fb0bb2023-01-11 09:46:29 +0800832}
833
834static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
835{
developer7e4a2a62023-04-06 19:56:03 +0800836 char cmd[MAX_CMD_SIZE] = {0};
837 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +0800838
developer7e4a2a62023-04-06 19:56:03 +0800839 for (int i = 0; i < item_count; i++) {
developer72fb0bb2023-01-11 09:46:29 +0800840 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
developer7e4a2a62023-04-06 19:56:03 +0800841 if (strlen(buf) == 0) /*no such item, insert it*/
developera1255e42023-05-13 17:45:02 +0800842 snprintf(cmd, sizeof(cmd), "sed -i -e '$a %s=%s' %s", list[i].name, list[i].value, conf_file);
developer7e4a2a62023-04-06 19:56:03 +0800843 else /*find the item, update it*/
developer72fb0bb2023-01-11 09:46:29 +0800844 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=%s/\" %s", list[i].name, list[i].name, list[i].value, conf_file);
developera1255e42023-05-13 17:45:02 +0800845
developer72fb0bb2023-01-11 09:46:29 +0800846 if(_syscmd(cmd, buf, sizeof(buf)))
847 return -1;
848 }
849
developera1255e42023-05-13 17:45:02 +0800850 return 0;
851}
developerfde01262023-05-22 15:15:24 +0800852
developera1255e42023-05-13 17:45:02 +0800853static int wifi_datfileRead(char *conf_file, char *param, char *output, int output_size)
854{
855 char cmd[MAX_CMD_SIZE] = {0};
developera1255e42023-05-13 17:45:02 +0800856 int ret = 0;
developerfde01262023-05-22 15:15:24 +0800857 int len;
858
859 ret = snprintf(cmd, sizeof(cmd), "datconf -f %s get %s", conf_file, param);
860 if (ret < 0) {
861 printf("%s: snprintf error!", __func__);
862 return -1;
863 }
864
865 ret = _syscmd(cmd, output, output_size);
866 if ((ret != 0) && (strlen(output) == 0)) {
867 printf("%s: _syscmd error!", __func__);
868 return -1;
869 }
developera1255e42023-05-13 17:45:02 +0800870
developerfde01262023-05-22 15:15:24 +0800871 len = strlen(output);
872 if ((len > 0) && (output[len - 1] == '\n')) {
873 output[len - 1] = '\0';
874 }
875
876 return 0;
877}
developera1255e42023-05-13 17:45:02 +0800878
developer3a85ab82023-05-25 11:59:38 +0800879static int wifi_datfileRead2(char *conf_file, int idx, char *param, char *output, int output_size)
developerfde01262023-05-22 15:15:24 +0800880{
881 char cmd[MAX_CMD_SIZE] = {0};
882 int ret = 0;
883 int len;
884
developer3a85ab82023-05-25 11:59:38 +0800885 ret = snprintf(cmd, sizeof(cmd), "datconf -f %s get %s %d", conf_file, param, idx);
developera1255e42023-05-13 17:45:02 +0800886 if (ret < 0) {
887 printf("%s: snprintf error!", __func__);
888 return -1;
889 }
890
developerfde01262023-05-22 15:15:24 +0800891 ret = _syscmd(cmd, output, output_size);
892 if ((ret != 0) && (strlen(output) == 0)) {
developera1255e42023-05-13 17:45:02 +0800893 printf("%s: _syscmd error!", __func__);
894 return -1;
895 }
896
developerfde01262023-05-22 15:15:24 +0800897 len = strlen(output);
898 if ((len > 0) && (output[len - 1] == '\n')) {
899 output[len - 1] = '\0';
900 }
developera1255e42023-05-13 17:45:02 +0800901
developer72fb0bb2023-01-11 09:46:29 +0800902 return 0;
903}
904
developera1255e42023-05-13 17:45:02 +0800905static int wifi_datfileWrite(char *conf_file, struct params *list, int item_count)
906{
developerfde01262023-05-22 15:15:24 +0800907 int ret;
developera1255e42023-05-13 17:45:02 +0800908 char cmd[MAX_CMD_SIZE] = {0};
909 char buf[MAX_BUF_SIZE] = {0};
910
911 for (int i = 0; i < item_count; i++) {
developerfde01262023-05-22 15:15:24 +0800912 ret = snprintf(cmd, sizeof(cmd), "datconf -f %s set %s \"%s\"", conf_file, list[i].name, list[i].value);
913 if (ret < 0) {
914 printf("%s: snprintf error!", __func__);
915 return -1;
916 }
developera1255e42023-05-13 17:45:02 +0800917
918 if(_syscmd(cmd, buf, sizeof(buf)))
919 return -1;
920 }
921
922 return 0;
923}
924
developer3a85ab82023-05-25 11:59:38 +0800925static int wifi_datfileWrite2(char *conf_file, int idx, struct params *list, int item_count)
developerfde01262023-05-22 15:15:24 +0800926{
927 int ret;
928 char cmd[MAX_CMD_SIZE] = {0};
929 char buf[MAX_BUF_SIZE] = {0};
930
931 for (int i = 0; i < item_count; i++) {
developer3a85ab82023-05-25 11:59:38 +0800932 ret = snprintf(cmd, sizeof(cmd), "datconf -f %s set %s %d \"%s\"", conf_file, list[i].name, idx, list[i].value);
developerfde01262023-05-22 15:15:24 +0800933 if (ret < 0) {
934 printf("%s: snprintf error!", __func__);
935 return -1;
936 }
937
938 if(_syscmd(cmd, buf, sizeof(buf)))
939 return -1;
940 }
941
942 return 0;
943}
944
945static int wifi_l1ProfileRead(char *param, char *output, int output_size)
946{
947 char buf[MAX_BUF_SIZE] = {0};
948 int ret;
949
950 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
951 if (!param || !output || (output_size <= 0)) {
952 fprintf(stderr, "%s: invalid parameters", __func__);
953 return RETURN_ERR;
954 }
955
956 ret = wifi_datfileRead(l1profile, param, output, output_size);
957 if (ret != 0) {
958 fprintf(stderr, "%s: wifi_datfileRead %s from %s failed, ret:%d", __func__, param, l1profile, ret);
959 return RETURN_ERR;
960 }
961
962 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
963 return RETURN_OK;
964}
965
developer3a85ab82023-05-25 11:59:38 +0800966static int wifi_l1ProfileRead2(char *param, int idx, char *output, int output_size)
967{
968 char buf[MAX_BUF_SIZE] = {0};
969 int ret;
970
971 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
972 if (!param || !output || (output_size <= 0)) {
973 fprintf(stderr, "%s: invalid parameters", __func__);
974 return RETURN_ERR;
975 }
976
977 ret = wifi_datfileRead2(l1profile, idx, param, output, output_size);
978 if (ret != 0) {
979 fprintf(stderr, "%s: wifi_datfileRead2 %s from %s failed, ret:%d", __func__, param, l1profile, ret);
980 return RETURN_ERR;
981 }
982
983 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
984 return RETURN_OK;
985}
986
987
developerfde01262023-05-22 15:15:24 +0800988static int wifi_CardProfileRead(int card_idx, char *param, char *output, int output_size)
989{
990 char option[64];
991 char card_profile_path[64];
992 int ret;
993
994 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
995
996 if (!param || !output || (output_size <= 0)) {
997 fprintf(stderr, "%s: invalid parameters", __func__);
998 return RETURN_ERR;
999 }
1000
1001 snprintf(option, sizeof(option), "INDEX%d_profile_path", card_idx);
1002 ret = wifi_l1ProfileRead(option, card_profile_path, sizeof(card_profile_path));
1003 if (ret != 0) {
1004 fprintf(stderr, "%s: wifi_l1ProfileRead %s failed, ret:%d", __func__, option, ret);
1005 return RETURN_ERR;
1006 }
1007
1008 ret = wifi_datfileRead(card_profile_path, param, output, output_size);
1009 if (ret != 0) {
1010 fprintf(stderr, "%s: wifi_datfileRead %s from %s failed, ret:%d", __func__, param, card_profile_path, ret);
1011 return RETURN_ERR;
1012 }
1013
1014 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1015 return RETURN_OK;
1016}
1017
1018static int wifi_BandProfileRead(int card_idx,
1019 int radio_idx,
1020 char *param,
1021 char *output,
1022 int output_size,
1023 char *default_value)
1024{
1025 char option[64];
1026 char band_profile_path[64];
1027 int ret;
1028
1029 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1030 if (!param || !output || (output_size <= 0)) {
1031 fprintf(stderr, "%s: invalid parameters", __func__);
1032 return RETURN_ERR;
1033 }
1034
1035 snprintf(option, sizeof(option), "BN%d_profile_path", radio_idx);
1036 ret = wifi_CardProfileRead(card_idx, option, band_profile_path, sizeof(band_profile_path));
1037 if (ret != 0) {
1038 fprintf(stderr, "%s: wifi_CardProfileRead %s failed, ret:%d", __func__, option);
1039 return RETURN_ERR;
1040 }
1041
1042 ret = wifi_datfileRead(band_profile_path, param, output, output_size);
1043 if (ret != 0) {
1044 if (default_value) {
1045 snprintf(output, output_size, "%s", default_value);
1046 } else {
1047 output[0] = '\0';
1048 }
1049 }
1050
1051 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1052 return RETURN_OK;
1053}
1054
1055static int wifi_BandProfileRead2(int card_idx,
1056 int radio_idx,
developer3a85ab82023-05-25 11:59:38 +08001057 int idx,
developerfde01262023-05-22 15:15:24 +08001058 char *param,
1059 char *output,
1060 int output_size,
1061 char* default_value)
1062{
1063 char option[64];
1064 char band_profile_path[64];
1065 int ret;
1066
1067 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1068 if (!param || !output || (output_size <= 0)) {
1069 fprintf(stderr, "%s: invalid parameters", __func__);
1070 return RETURN_ERR;
1071 }
1072
1073 snprintf(option, sizeof(option), "BN%d_profile_path", radio_idx);
1074 ret = wifi_CardProfileRead(card_idx, option, band_profile_path, sizeof(band_profile_path));
1075 if (ret != 0) {
1076 fprintf(stderr, "%s: wifi_CardProfileRead %s failed, ret:%d", __func__, option);
1077 return RETURN_ERR;
1078 }
1079
developer3a85ab82023-05-25 11:59:38 +08001080 ret = wifi_datfileRead2(band_profile_path, idx, param, output, output_size);
developerfde01262023-05-22 15:15:24 +08001081 if (ret != 0) {
1082 if (default_value) {
1083 snprintf(output, output_size, "%s", default_value);
1084 } else {
1085 output[0] = '\0';
1086 }
1087 }
1088
1089 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1090 return RETURN_OK;
1091
1092}
1093
1094static int wifi_BandProfileWrite(int card_idx, int radio_idx, struct params *list, int item_count)
1095{
1096 char option[64];
1097 char band_profile_path[64];
1098 int ret;
1099
1100 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1101
1102 snprintf(option, sizeof(option), "BN%d_profile_path", radio_idx);
1103 ret = wifi_CardProfileRead(card_idx, option, band_profile_path, sizeof(band_profile_path));
1104 if (ret != 0) {
1105 fprintf(stderr, "%s: wifi_CardProfileRead %s failed, ret:%d", __func__, option);
1106 return RETURN_ERR;
1107 }
1108
1109 for (int i = 0; i < item_count; i++) {
1110 }
1111 ret = wifi_datfileWrite(band_profile_path, list, item_count);
1112 if (ret != 0) {
1113 fprintf(stderr, "%s: wifi_datfileWrite failed, ret:%d", __func__);
1114 return RETURN_ERR;
1115 }
1116
1117 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1118 return RETURN_OK;
1119
1120}
1121
1122static int wifi_BandProfileWrite2(int card_idx,
1123 int radio_idx,
developer3a85ab82023-05-25 11:59:38 +08001124 int idx,
developerfde01262023-05-22 15:15:24 +08001125 struct params *list,
1126 int item_count)
1127{
1128 char option[64];
1129 char band_profile_path[64];
1130 char buf[64];
1131 char buf2[MAX_BUF_SIZE];
1132 int ret;
1133
1134 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1135
1136 snprintf(option, sizeof(option), "BN%d_profile_path", radio_idx);
1137 ret = wifi_CardProfileRead(card_idx, option, band_profile_path, sizeof(band_profile_path));
1138 if (ret != 0) {
1139 fprintf(stderr, "%s: wifi_CardProfileRead %s failed, ret:%d", __func__, option);
1140 return RETURN_ERR;
1141 }
1142
developer3a85ab82023-05-25 11:59:38 +08001143 ret = wifi_datfileWrite2(band_profile_path, idx, list, item_count);
developerfde01262023-05-22 15:15:24 +08001144 if (ret != 0) {
1145 fprintf(stderr, "%s: wifi_datfileWrite failed, ret:%d", __func__);
1146 return RETURN_ERR;
1147 }
1148
1149 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1150 return RETURN_OK;
1151
1152}
1153
1154
1155
developer72fb0bb2023-01-11 09:46:29 +08001156//For Getting Current Interface Name from corresponding hostapd configuration
1157static int wifi_GetInterfaceName(int apIndex, char *interface_name)
1158{
1159 char config_file[128] = {0};
1160
1161 if (interface_name == NULL)
1162 return RETURN_ERR;
1163
1164 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1165
1166 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
1167 wifi_hostapdRead(config_file, "interface", interface_name, 16);
1168 if (strlen(interface_name) == 0)
1169 return RETURN_ERR;
1170
1171 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1172 return RETURN_OK;
1173}
1174
developera1255e42023-05-13 17:45:02 +08001175static UCHAR get_bssnum_byindex(INT radio_index, UCHAR *bss_cnt)
1176{
1177 char interface_name[IF_NAME_SIZE] = {0};
1178 char cmd[MAX_BUF_SIZE]={'\0'};
1179 char buf[MAX_CMD_SIZE]={'\0'};
1180 UCHAR channel = 0;
1181
1182 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
1183 return RETURN_ERR;
1184 /*interface name to channel number*/
1185 snprintf(cmd, sizeof(cmd), "iw dev %s info | grep -i 'channel' | cut -d ' ' -f2", interface_name);
1186 _syscmd(cmd, buf, sizeof(buf));
1187 channel = atoi(buf);
1188 WIFI_ENTRY_EXIT_DEBUG("%s:channel=%d\n", __func__, channel);
1189 /*count dev number with the same channel*/
1190 snprintf(cmd, sizeof(cmd), "iw dev | grep -i 'channel %d' | wc -l", channel);
1191 _syscmd(cmd, buf, sizeof(buf));
1192 *bss_cnt = atoi(buf) - 1;/*1 for apcli interface*/
1193 WIFI_ENTRY_EXIT_DEBUG("%s:bss_cnt=%d\n", __func__, *bss_cnt);
1194 return RETURN_OK;
1195}
developer72fb0bb2023-01-11 09:46:29 +08001196
1197static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
1198{
1199 char interface_name[16] = {0};
1200 if (multiple_set == TRUE)
1201 return RETURN_OK;
1202 char cmd[MAX_CMD_SIZE]="", output[32]="";
1203 FILE *fp;
1204 int i;
1205 //NOTE RELOAD should be done in ApplySSIDSettings
1206 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
1207 return RETURN_ERR;
1208 for(i=0; i<item_count; i++, list++)
1209 {
developerf6a87542023-05-16 15:47:28 +08001210 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s SET %s %s", interface_name, list->name, list->value);
developer72fb0bb2023-01-11 09:46:29 +08001211 if((fp = popen(cmd, "r"))==NULL)
1212 {
1213 perror("popen failed");
1214 return -1;
1215 }
1216 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
1217 {
1218 pclose(fp);
1219 perror("fgets failed");
1220 return -1;
1221 }
1222 pclose(fp);
1223 }
1224 return 0;
1225}
1226
developer7e4a2a62023-04-06 19:56:03 +08001227static int wifi_quick_reload_ap(int apIndex)
1228{
1229 char interface_name[IF_NAME_SIZE] = {0};
1230 char cmd[MAX_CMD_SIZE] = {0};
1231 char buf[MAX_BUF_SIZE] = {0};
1232
1233 if (multiple_set == TRUE)
1234 return RETURN_OK;
1235
1236 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
1237 return RETURN_ERR;
1238
1239 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s reload", interface_name);
1240 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
1241 return RETURN_ERR;
1242
1243 return RETURN_OK;
1244}
1245
developer72fb0bb2023-01-11 09:46:29 +08001246static int wifi_reloadAp(int apIndex)
1247{
1248 char interface_name[16] = {0};
1249 if (multiple_set == TRUE)
1250 return RETURN_OK;
1251 char cmd[MAX_CMD_SIZE]="";
1252 char buf[MAX_BUF_SIZE]="";
1253
1254 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
1255 return RETURN_ERR;
1256 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s reload", interface_name);
1257 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
1258 return RETURN_ERR;
1259
1260 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s disable", interface_name);
1261 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
1262 return RETURN_ERR;
1263
1264 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s enable", interface_name);
1265 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
1266 return RETURN_ERR;
1267
1268 return RETURN_OK;
1269}
1270
1271INT File_Reading(CHAR *file, char *Value)
1272{
1273 FILE *fp = NULL;
1274 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
1275 int count = 0;
1276
1277 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1278 fp = popen(file,"r");
1279 if(fp == NULL)
1280 return RETURN_ERR;
1281
1282 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
1283 {
1284 for(count=0;buf[count]!='\n';count++)
1285 copy_buf[count]=buf[count];
1286 copy_buf[count]='\0';
1287 }
1288 strcpy(Value,copy_buf);
1289 pclose(fp);
1290 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1291
1292 return RETURN_OK;
1293}
1294
1295void wifi_RestartHostapd_2G()
1296{
1297 int Public2GApIndex = 4;
1298
1299 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1300 wifi_setApEnable(Public2GApIndex, FALSE);
1301 wifi_setApEnable(Public2GApIndex, TRUE);
1302 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1303}
1304
1305void wifi_RestartHostapd_5G()
1306{
1307 int Public5GApIndex = 5;
1308
1309 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1310 wifi_setApEnable(Public5GApIndex, FALSE);
1311 wifi_setApEnable(Public5GApIndex, TRUE);
1312 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1313}
1314
1315void wifi_RestartPrivateWifi_2G()
1316{
1317 int PrivateApIndex = 0;
1318
1319 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1320 wifi_setApEnable(PrivateApIndex, FALSE);
1321 wifi_setApEnable(PrivateApIndex, TRUE);
1322 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1323}
1324
1325void wifi_RestartPrivateWifi_5G()
1326{
1327 int Private5GApIndex = 1;
1328
1329 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1330 wifi_setApEnable(Private5GApIndex, FALSE);
1331 wifi_setApEnable(Private5GApIndex, TRUE);
1332 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1333}
1334
1335static int writeBandWidth(int radioIndex,char *bw_value)
1336{
1337 char buf[MAX_BUF_SIZE];
1338 char cmd[MAX_CMD_SIZE];
1339
1340 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
1341 if(_syscmd(cmd, buf, sizeof(buf)))
1342 {
1343 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
1344 _syscmd(cmd, buf, sizeof(buf));
1345 return RETURN_OK;
1346 }
1347
1348 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
1349 _syscmd(cmd,buf,sizeof(buf));
1350 return RETURN_OK;
1351}
1352
1353static int readBandWidth(int radioIndex,char *bw_value)
1354{
1355 char buf[MAX_BUF_SIZE] = {0};
1356 char cmd[MAX_CMD_SIZE] = {0};
1357 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
1358 _syscmd(cmd,buf,sizeof(buf));
1359 if(NULL!=strstr(buf,"20MHz"))
developer72fb0bb2023-01-11 09:46:29 +08001360 strcpy(bw_value,"20MHz");
developer72fb0bb2023-01-11 09:46:29 +08001361 else if(NULL!=strstr(buf,"40MHz"))
developer72fb0bb2023-01-11 09:46:29 +08001362 strcpy(bw_value,"40MHz");
developer72fb0bb2023-01-11 09:46:29 +08001363 else if(NULL!=strstr(buf,"80MHz"))
developer72fb0bb2023-01-11 09:46:29 +08001364 strcpy(bw_value,"80MHz");
developerd1824452023-05-18 12:30:04 +08001365 else if(NULL!=strstr(buf,"160MHz"))
1366 strcpy(bw_value,"160MHz");
1367 else if(NULL!=strstr(buf,"320MHz"))
1368 strcpy(bw_value,"320MHz");
developer72fb0bb2023-01-11 09:46:29 +08001369 else
developer72fb0bb2023-01-11 09:46:29 +08001370 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08001371 return RETURN_OK;
1372}
1373
1374// Input could be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
1375INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
1376{
1377 struct params params={'\0'};
1378 char config_file[MAX_BUF_SIZE] = {0};
1379 char buf[MAX_BUF_SIZE] = {'\0'};
1380
1381 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1382 // Copy the numeric value
1383 if (strlen (beaconRate) >= 5) {
1384 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
1385 buf[strlen(beaconRate) - 4] = '\0';
1386 } else if (strlen(beaconRate) > 0)
1387 strcpy(buf, beaconRate);
1388 else
1389 return RETURN_ERR;
1390
1391 params.name = "beacon_rate";
1392 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
1393 if (strncmp(buf, "5.5", 3) == 0) {
1394 snprintf(buf, sizeof(buf), "55");
1395 params.value = buf;
1396 } else {
1397 strcat(buf, "0");
1398 params.value = buf;
1399 }
1400
1401 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1402 wifi_hostapdWrite(config_file, &params, 1);
1403 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1404 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1405
1406 return RETURN_OK;
1407}
1408
1409INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
1410{
1411 char config_file[128] = {'\0'};
1412 char temp_output[128] = {'\0'};
1413 char buf[128] = {'\0'};
1414 char cmd[128] = {'\0'};
1415 int rate = 0;
1416 int phyId = 0;
1417
1418 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1419 if (NULL == beaconRate)
1420 return RETURN_ERR;
1421
1422 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1423 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
1424 phyId = radio_index_to_phy(radioIndex);
1425 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
1426 if(strlen(buf) > 0) {
1427 if (strncmp(buf, "55", 2) == 0)
1428 snprintf(temp_output, sizeof(temp_output), "5.5Mbps");
1429 else {
1430 rate = strtol(buf, NULL, 10)/10;
1431 snprintf(temp_output, sizeof(temp_output), "%dMbps", rate);
1432 }
1433 } else {
1434 // config not set, so we would use lowest rate as default
1435 sprintf(cmd, "iw phy%d info | grep Bitrates -A1 | tail -n 1 | awk '{print $2}' | tr -d '.0\\n'", phyId);
1436 _syscmd(cmd, buf, sizeof(buf));
1437 snprintf(temp_output, sizeof(temp_output), "%sMbps", buf);
1438 }
1439 strncpy(beaconRate, temp_output, sizeof(temp_output));
1440 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1441
1442 return RETURN_OK;
1443}
1444
1445INT wifi_setLED(INT radioIndex, BOOL enable)
1446{
1447 return 0;
1448}
1449INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
1450{
1451 return RETURN_OK;
1452}
1453/**********************************************************************************
1454 *
developer69b61b02023-03-07 17:17:44 +08001455 * Wifi Subsystem level function prototypes
developer72fb0bb2023-01-11 09:46:29 +08001456 *
1457**********************************************************************************/
1458//---------------------------------------------------------------------------------------------------
1459//Wifi system api
1460//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
developer69b61b02023-03-07 17:17:44 +08001461INT wifi_getHalVersion(CHAR *output_string) //RDKB
developer72fb0bb2023-01-11 09:46:29 +08001462{
1463 if(!output_string)
1464 return RETURN_ERR;
1465 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
1466
1467 return RETURN_OK;
1468}
1469
1470
1471/* wifi_factoryReset() function */
1472/**
developer69b61b02023-03-07 17:17:44 +08001473* @description Clears internal variables to implement a factory reset of the Wi-Fi
developer72fb0bb2023-01-11 09:46:29 +08001474* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
1475*
1476* @param None
1477*
1478* @return The status of the operation.
1479* @retval RETURN_OK if successful.
1480* @retval RETURN_ERR if any error is detected
1481*
1482* @execution Synchronous
1483* @sideeffect None
1484*
1485* @note This function must not suspend and must not invoke any blocking system
1486* calls. It should probably just send a message to a driver event handler task.
1487*
1488*/
1489INT wifi_factoryReset()
1490{
developer47cc27a2023-05-17 23:09:58 +08001491 char cmd[MAX_CMD_SIZE] = {0};
1492 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08001493
developer47cc27a2023-05-17 23:09:58 +08001494 /*delete running hostapd conf files*/
1495 wifi_dbg_printf("\n[%s]: deleting hostapd conf file.", __func__);
1496 snprintf(cmd, MAX_CMD_SIZE, "rm -rf /nvram/*.conf");
1497 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08001498
developer47cc27a2023-05-17 23:09:58 +08001499 wifi_PrepareDefaultHostapdConfigs();
1500 wifi_psk_file_reset();
1501
1502 memset(cmd, 0, MAX_CMD_SIZE);
1503 memset(buf, 0, MAX_BUF_SIZE);
1504
1505 snprintf(cmd, MAX_CMD_SIZE, "systemctl restart hostapd.service");
1506 _syscmd(cmd, buf, sizeof(buf));
1507
1508 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08001509}
1510
1511/* wifi_factoryResetRadios() function */
1512/**
1513* @description Restore all radio parameters without touching access point parameters. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
1514*
1515* @param None
1516* @return The status of the operation
1517* @retval RETURN_OK if successful
1518* @retval RETURN_ERR if any error is detected
1519*
1520* @execution Synchronous
1521*
1522* @sideeffect None
1523*
1524* @note This function must not suspend and must not invoke any blocking system
1525* calls. It should probably just send a message to a driver event handler task.
1526*
1527*/
1528INT wifi_factoryResetRadios()
1529{
1530 if((RETURN_OK == wifi_factoryResetRadio(0)) && (RETURN_OK == wifi_factoryResetRadio(1)))
1531 return RETURN_OK;
1532
1533 return RETURN_ERR;
1534}
1535
developerfead3972023-05-25 20:15:02 +08001536ULONG get_radio_reset_cnt(int radioIndex)
1537{
1538 char cmd[MAX_CMD_SIZE] = {0};
1539 char buf[MAX_BUF_SIZE] = {0};
1540 ULONG reset_count = 0;
1541
1542 snprintf(cmd, MAX_CMD_SIZE, "cat %s 2> /dev/null | grep \"^reset%d=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"",
1543 RADIO_RESET_FILE, radioIndex);
1544 _syscmd(cmd, buf, sizeof(buf));
1545
1546 if (strlen(buf) == 0)
1547 return 0;
1548 else {
1549 reset_count = atol(buf);
1550 return reset_count;
1551 }
1552}
1553void update_radio_reset_cnt(int radioIndex)
1554{
1555 char cmd[MAX_CMD_SIZE] = {0};
1556 char buf[MAX_BUF_SIZE] = {0};
1557 ULONG reset_count = 0;
1558
1559 snprintf(cmd, MAX_CMD_SIZE, "cat %s 2> /dev/null | grep \"^reset%d=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"",
1560 RADIO_RESET_FILE, radioIndex);
1561 _syscmd(cmd, buf, sizeof(buf));
1562
1563 if (strlen(buf) == 0)
1564 snprintf(cmd, sizeof(cmd), "sed -i -e '$a reset%d=1' %s", radioIndex, RADIO_RESET_FILE);
1565 else {
1566 reset_count = atol(buf);
1567 reset_count++;
1568 snprintf(cmd, sizeof(cmd), "sed -i \"s/^reset%d=.*/reset%d=%lu/\" %s", radioIndex, radioIndex, reset_count, RADIO_RESET_FILE);
1569 }
1570 _syscmd(cmd, buf, sizeof(buf));
1571}
developer72fb0bb2023-01-11 09:46:29 +08001572
1573/* wifi_factoryResetRadio() function */
1574/**
1575* @description Restore selected radio parameters without touching access point parameters
1576*
1577* @param radioIndex - Index of Wi-Fi Radio channel
1578*
1579* @return The status of the operation.
1580* @retval RETURN_OK if successful.
1581* @retval RETURN_ERR if any error is detected
1582*
1583* @execution Synchronous.
1584* @sideeffect None.
1585*
1586* @note This function must not suspend and must not invoke any blocking system
1587* calls. It should probably just send a message to a driver event handler task.
1588*
1589*/
1590INT wifi_factoryResetRadio(int radioIndex) //RDKB
1591{
developer47cc27a2023-05-17 23:09:58 +08001592 char cmd[MAX_CMD_SIZE] = {0};
1593 char buf[MAX_BUF_SIZE] = {0};
1594 char vap_idx = 0;
developer72fb0bb2023-01-11 09:46:29 +08001595
developer47cc27a2023-05-17 23:09:58 +08001596 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08001597
developerb2977562023-05-24 17:54:12 +08001598 wifi_dat_file_reset_by_radio(radioIndex);
developer47cc27a2023-05-17 23:09:58 +08001599
developerb2977562023-05-24 17:54:12 +08001600 /*reset gi setting*/
1601 snprintf(cmd, sizeof(cmd), "echo 'Auto' > %s%d.txt", GUARD_INTERVAL_FILE, radioIndex);
developer47cc27a2023-05-17 23:09:58 +08001602 _syscmd(cmd, buf, sizeof(buf));
1603
developerb2977562023-05-24 17:54:12 +08001604 /*TBD: check mbss issue*/
1605 wifi_factoryResetAP(radioIndex);
developerfead3972023-05-25 20:15:02 +08001606 update_radio_reset_cnt(radioIndex);
developerb2977562023-05-24 17:54:12 +08001607
developer47cc27a2023-05-17 23:09:58 +08001608 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
1609 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08001610}
1611
1612/* wifi_initRadio() function */
1613/**
1614* Description: This function call initializes the specified radio.
developer69b61b02023-03-07 17:17:44 +08001615* Implementation specifics may dictate the functionality since
developer72fb0bb2023-01-11 09:46:29 +08001616* different hardware implementations may have different initilization requirements.
1617* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
1618*
1619* @return The status of the operation.
1620* @retval RETURN_OK if successful.
1621* @retval RETURN_ERR if any error is detected
1622*
1623* @execution Synchronous.
1624* @sideeffect None.
1625*
1626* @note This function must not suspend and must not invoke any blocking system
1627* calls. It should probably just send a message to a driver event handler task.
1628*
1629*/
1630INT wifi_initRadio(INT radioIndex)
1631{
1632 //TODO: Initializes the wifi subsystem (for specified radio)
1633 return RETURN_OK;
1634}
1635void macfilter_init()
1636{
1637 char count[4]={'\0'};
1638 char buf[253]={'\0'};
1639 char tmp[19]={'\0'};
1640 int dev_count,block,mac_entry=0;
1641 char res[4]={'\0'};
1642 char acl_file_path[64] = {'\0'};
1643 FILE *fp = NULL;
1644 int index=0;
1645 char iface[10]={'\0'};
1646 char config_file[MAX_BUF_SIZE] = {0};
1647
1648
1649 sprintf(acl_file_path,"/tmp/mac_filter.sh");
1650
1651 fp=fopen(acl_file_path,"w+");
1652 if (fp == NULL) {
1653 fprintf(stderr, "%s: failed to open file %s.\n", __func__, acl_file_path);
developer17038e62023-03-02 14:43:43 +08001654 return;
developer72fb0bb2023-01-11 09:46:29 +08001655 }
1656 sprintf(buf,"#!/bin/sh \n");
1657 fprintf(fp,"%s\n",buf);
1658
1659 system("chmod 0777 /tmp/mac_filter.sh");
1660
1661 for(index=0;index<=1;index++)
1662 {
1663 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
1664 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
1665 sprintf(buf,"syscfg get %dcountfilter",index);
1666 _syscmd(buf,count,sizeof(count));
1667 mac_entry=atoi(count);
1668
1669 sprintf(buf,"syscfg get %dblockall",index);
1670 _syscmd(buf,res,sizeof(res));
1671 block = atoi(res);
1672
1673 //Allow only those macs mentioned in ACL
1674 if(block==1)
1675 {
1676 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1677 fprintf(fp,"%s\n",buf);
1678 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1679 {
1680 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1681 _syscmd(buf,tmp,sizeof(tmp));
1682 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
1683 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
1684 fprintf(fp,"%s\n",buf);
1685 }
1686 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
1687 fprintf(fp,"%s\n",buf);
1688 }
1689
1690 //Block all the macs mentioned in ACL
1691 else if(block==2)
1692 {
1693 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1694 fprintf(fp,"%s\n",buf);
1695
1696 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1697 {
1698 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1699 _syscmd(buf,tmp,sizeof(tmp));
1700 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
1701 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
1702 fprintf(fp,"%s\n",buf);
1703 }
1704 }
1705 }
1706 fclose(fp);
1707}
1708
developer17038e62023-03-02 14:43:43 +08001709
1710static void
1711wifi_ParseProfile(void)
1712{
1713 int i;
1714 int max_radio_num = 0;
1715 int card_idx;
1716 int band_idx;
1717 int phy_idx = 0;
developer745f0bd2023-03-06 14:32:53 +08001718 int wireless_mode = 0;
developer17038e62023-03-02 14:43:43 +08001719 char buf[MAX_BUF_SIZE] = {0};
1720 char chip_name[12];
1721 char card_profile[MAX_BUF_SIZE] = {0};
1722 char band_profile[MAX_BUF_SIZE] = {0};
1723 FILE* fp;
1724
1725 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1726
1727 memset(main_prefix, 0, sizeof(main_prefix));
1728 memset(ext_prefix, 0, sizeof(ext_prefix));
1729 memset(default_ssid, 0, sizeof(default_ssid));
developer745f0bd2023-03-06 14:32:53 +08001730 for (i = 0; i < MAX_NUM_RADIOS; i++)
1731 radio_band[i] = band_invalid;
developer17038e62023-03-02 14:43:43 +08001732
1733 if (wifi_getMaxRadioNumber(&max_radio_num) != RETURN_OK) {
1734 /* LOG */
1735 return;
1736 }
1737
1738 for (card_idx = 0; card_idx < 3; card_idx++) {
1739 snprintf(buf, sizeof(buf), "INDEX%d", card_idx);
1740 if (get_value(l1profile, buf, chip_name, sizeof(chip_name)) < 0) {
1741 break;
1742 }
1743 snprintf(buf, sizeof(buf), "INDEX%d_profile_path", card_idx);
1744 if (get_value(l1profile, buf, card_profile, sizeof(card_profile)) < 0) {
1745 break;
1746 }
1747 for (band_idx = 0; band_idx < 3; band_idx++) {
1748 snprintf(buf, sizeof(buf), "BN%d_profile_path", band_idx);
1749 if (get_value(card_profile, buf, band_profile, sizeof(band_profile)) < 0) {
1750 /* LOG */
1751 break;
1752 }
1753
1754 snprintf(buf, sizeof(buf), "INDEX%d_main_ifname", card_idx);
1755 if (get_value_by_idx(l1profile, buf, band_idx, main_prefix[phy_idx], IFNAMSIZ) < 0) {
1756 /* LOG */
1757 }
1758
1759 snprintf(buf, sizeof(buf), "INDEX%d_ext_ifname", card_idx);
1760 if (get_value_by_idx(l1profile, buf, band_idx, ext_prefix[phy_idx], IFNAMSIZ) < 0) {
1761 /* LOG */
1762 }
1763
1764 if (get_value(band_profile, "SSID1", default_ssid[phy_idx], sizeof(default_ssid[phy_idx])) < 0) {
1765 /* LOG */
1766 }
developer745f0bd2023-03-06 14:32:53 +08001767 if (get_value(band_profile, "WirelessMode", buf, sizeof(buf)) < 0) {
1768 /* LOG */
1769 }
1770
1771 wireless_mode = atoi(buf);
1772 switch (wireless_mode) {
1773 case 22:
1774 case 16:
1775 case 6:
1776 case 4:
1777 case 1:
1778 radio_band[phy_idx] = band_2_4;
1779 break;
1780 case 23:
1781 case 17:
1782 case 14:
1783 case 11:
1784 case 2:
1785 radio_band[phy_idx] = band_5;
1786 break;
1787 case 24:
1788 case 18:
1789 radio_band[phy_idx] = band_6;
1790 break;
1791 }
developer17038e62023-03-02 14:43:43 +08001792 phy_idx++;
1793 }
1794 }
1795
1796 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1797}
1798
1799static void
1800wifi_PrepareDefaultHostapdConfigs(void)
1801{
developer0132ed92023-03-21 13:48:53 +08001802 int radio_idx;
1803 int bss_idx;
1804 int ap_idx;
developer0132ed92023-03-21 13:48:53 +08001805 char buf[MAX_BUF_SIZE] = {0};
1806 char config_file[MAX_BUF_SIZE] = {0};
1807 char ssid[MAX_BUF_SIZE] = {0};
1808 char interface[32] = {0};
1809 char ret_buf[MAX_BUF_SIZE] = {0};
1810 char psk_file[64] = {0};
1811 struct params params[3];
developer47cc27a2023-05-17 23:09:58 +08001812 char *band_str[3] = {"2G", "5G", "6G"};
developer17038e62023-03-02 14:43:43 +08001813
developer0132ed92023-03-21 13:48:53 +08001814 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1815 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++) {
developer47cc27a2023-05-17 23:09:58 +08001816
developer0132ed92023-03-21 13:48:53 +08001817 for (bss_idx = 0; bss_idx < 5; bss_idx++) {
developer47cc27a2023-05-17 23:09:58 +08001818 ap_idx = array_index_to_vap_index(radio_idx, bss_idx);
developer0132ed92023-03-21 13:48:53 +08001819
developer47cc27a2023-05-17 23:09:58 +08001820 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_idx);
developere740c2a2023-05-23 18:34:32 +08001821 snprintf(buf, sizeof(buf), "cp /etc/hostapd-%s.conf %s", wifi_band_str[radio_idx], config_file);
developer47cc27a2023-05-17 23:09:58 +08001822 _syscmd(buf, ret_buf, sizeof(ret_buf));
developer17038e62023-03-02 14:43:43 +08001823
developer47cc27a2023-05-17 23:09:58 +08001824 if (radio_idx == band_2_4) {
1825 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_2G, bss_idx);
1826 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI2G, bss_idx);
1827 } else if (radio_idx == band_5) {
1828 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_5G, bss_idx);
1829 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI5G, bss_idx);
1830 } else if (radio_idx == band_6) {
1831 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_6G, bss_idx);
1832 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI6G, bss_idx);
1833 }
developer17038e62023-03-02 14:43:43 +08001834
developer47cc27a2023-05-17 23:09:58 +08001835 /* fix wpa_psk_file path */
1836 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", ap_idx);
developer17038e62023-03-02 14:43:43 +08001837
developer47cc27a2023-05-17 23:09:58 +08001838 params[0].name = "ssid";
1839 params[0].value = ssid;
1840 params[1].name = "interface";
1841 params[1].value = interface;
1842 params[2].name = "wpa_psk_file";
1843 params[2].value = psk_file;
developer17038e62023-03-02 14:43:43 +08001844
developer47cc27a2023-05-17 23:09:58 +08001845 wifi_hostapdWrite(config_file, params, 3);
developer0132ed92023-03-21 13:48:53 +08001846 }
1847 }
1848 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer17038e62023-03-02 14:43:43 +08001849}
1850
1851static void
1852wifiBringUpInterfacesForRadio(int radio_idx)
1853{
developer0132ed92023-03-21 13:48:53 +08001854 int bss_idx;
1855 int ap_idx;
1856 int band_idx;
1857 char cmd[MAX_CMD_SIZE] = {0};
1858 char config_file[MAX_BUF_SIZE] = {0};
1859 char ret_buf[MAX_BUF_SIZE] = {0};
developer8a3bbbf2023-03-15 17:47:23 +08001860 char inf_name[IF_NAME_SIZE] = {0};
developer17038e62023-03-02 14:43:43 +08001861
1862 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer8a3bbbf2023-03-15 17:47:23 +08001863
developered997d32023-04-18 22:45:39 +08001864 bss_idx = 0;
1865 /*TBD: we need refine setup flow and mbss flow*/
1866// for (bss_idx = 0; bss_idx < 5; bss_idx++) {
developer0132ed92023-03-21 13:48:53 +08001867 ap_idx = array_index_to_vap_index(radio_idx, bss_idx);
1868
1869 snprintf(cmd, sizeof(cmd), "touch %s%d.psk", PSK_FILE, ap_idx);
1870 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1871
1872 memset(cmd, 0, MAX_CMD_SIZE);
1873 memset(ret_buf, 0, MAX_BUF_SIZE);
developer17038e62023-03-02 14:43:43 +08001874
developer0132ed92023-03-21 13:48:53 +08001875 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_idx);
1876 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:%s", radio_idx, config_file);
1877 _syscmd(cmd, ret_buf, sizeof(ret_buf));
developer8a3bbbf2023-03-15 17:47:23 +08001878
1879 wifi_GetInterfaceName(ap_idx, inf_name);
1880
1881 memset(cmd, 0, MAX_CMD_SIZE);
1882 memset(ret_buf, 0, MAX_BUF_SIZE);
1883
1884 /* fix vap-status file */
1885 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=1/\" %s", inf_name, inf_name, VAP_STATUS_FILE);
1886 _syscmd(cmd, ret_buf, sizeof(ret_buf));
developered997d32023-04-18 22:45:39 +08001887// }
1888
1889 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer17038e62023-03-02 14:43:43 +08001890}
1891
1892static void
1893wifi_BringUpInterfaces(void)
1894{
1895 int radio_idx;
1896 int bss_idx;
1897 int ap_idx;
1898 int band_idx;
1899 char cmd[MAX_BUF_SIZE] = {0};
1900 char config_file[MAX_BUF_SIZE] = {0};
1901 char ret_buf[MAX_BUF_SIZE]={'\0'};
1902
1903 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1904 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++) {
1905 band_idx = radio_index_to_band(radio_idx);
1906 if (band_idx < 0) {
1907 break;
1908 }
1909 wifiBringUpInterfacesForRadio(radio_idx);
1910 }
1911 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1912}
1913
1914static void
1915wifi_BringDownInterfacesForRadio(int radio_idx)
1916{
1917 int bss_idx;
1918 int ap_idx;
1919 int band_idx;
1920 char cmd[MAX_BUF_SIZE] = {0};
1921 char config_file[MAX_BUF_SIZE] = {0};
1922 char ret_buf[MAX_BUF_SIZE]={'\0'};
1923
1924 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer17038e62023-03-02 14:43:43 +08001925
developer8a3bbbf2023-03-15 17:47:23 +08001926 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s", main_prefix[radio_idx]);
1927 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1928
1929
developer17038e62023-03-02 14:43:43 +08001930 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1931}
1932
1933
1934static void
1935wifi_BringDownInterfaces(void)
1936{
1937 int radio_idx;
1938 int bss_idx;
1939 int ap_idx;
1940 int band_idx;
1941 char cmd[MAX_BUF_SIZE] = {0};
1942 char config_file[MAX_BUF_SIZE] = {0};
1943 char ret_buf[MAX_BUF_SIZE]={'\0'};
1944
1945 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1946 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++) {
1947 band_idx = radio_index_to_band(radio_idx);
1948 if (band_idx < 0) {
1949 break;
1950 }
1951 wifi_BringDownInterfacesForRadio(radio_idx);
1952 }
1953 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1954}
1955
developerb2977562023-05-24 17:54:12 +08001956static void wifi_dat_file_reset()
1957{
1958 char radio_idx = 0;
1959
1960 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++)
1961 wifi_dat_file_reset_by_radio(radio_idx);
1962}
1963
1964static void wifi_dat_file_reset_by_radio(char radio_idx)
1965{
1966 char cmd[MAX_CMD_SIZE] = {0};
1967 char ret_buf[MAX_BUF_SIZE] = {0};
1968 char rom_dat_file[MAX_CMD_SIZE]= {0};
1969 char dat_file[MAX_CMD_SIZE]= {0};
1970
1971 snprintf(rom_dat_file, sizeof(rom_dat_file), "%s%d.dat", ROM_LOGAN_DAT_FILE, radio_idx);
1972 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, radio_idx);
1973 snprintf(cmd, MAX_CMD_SIZE, "cp -rf %s %s", rom_dat_file, dat_file);
1974 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1975
1976}
1977
developer47cc27a2023-05-17 23:09:58 +08001978static void wifi_psk_file_reset()
1979{
1980 char cmd[MAX_CMD_SIZE] = {0};
1981 char ret_buf[MAX_BUF_SIZE] = {0};
1982 char psk_file[MAX_CMD_SIZE]= {0};
1983 char vap_idx = 0;
1984
1985 for (vap_idx = 0; vap_idx < MAX_APS; vap_idx++) {
1986 snprintf(psk_file, sizeof(psk_file), "%s%d.psk", PSK_FILE, vap_idx);
1987
1988 if (access(psk_file, F_OK) != 0) {
1989 snprintf(cmd, MAX_CMD_SIZE, "touch %s", psk_file);
1990 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1991 } else {
1992 snprintf(cmd, MAX_CMD_SIZE, "echo '' > %s", psk_file);
1993 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1994 }
1995 }
1996}
1997
developerb2977562023-05-24 17:54:12 +08001998static void wifi_psk_file_reset_by_radio(char radio_idx)
1999{
2000 char cmd[MAX_CMD_SIZE] = {0};
2001 char ret_buf[MAX_BUF_SIZE] = {0};
2002 char psk_file[MAX_CMD_SIZE]= {0};
2003 char vap_idx = 0;
2004
2005 for (vap_idx = radio_idx; vap_idx < MAX_APS; vap_idx += MAX_NUM_RADIOS) {
2006 snprintf(psk_file, sizeof(psk_file), "%s%d.psk", PSK_FILE, vap_idx);
2007
2008 if (access(psk_file, F_OK) != 0) {
2009 snprintf(cmd, MAX_CMD_SIZE, "touch %s", psk_file);
2010 _syscmd(cmd, ret_buf, sizeof(ret_buf));
2011 } else {
2012 snprintf(cmd, MAX_CMD_SIZE, "echo '' > %s", psk_file);
2013 _syscmd(cmd, ret_buf, sizeof(ret_buf));
2014 }
2015 }
2016
2017}
2018
2019
developer8a3bbbf2023-03-15 17:47:23 +08002020static void wifi_vap_status_reset()
2021{
2022 char cmd[MAX_CMD_SIZE] = {0};
2023 char ret_buf[MAX_BUF_SIZE] = {0};
2024 char radio_idx = 0;
2025 char bss_idx = 0;
developer8666b312023-03-24 14:05:31 +08002026
developer8a3bbbf2023-03-15 17:47:23 +08002027 if (access(VAP_STATUS_FILE, F_OK) != 0) {
2028 snprintf(cmd, MAX_CMD_SIZE, "touch %s", VAP_STATUS_FILE);
2029 _syscmd(cmd, ret_buf, sizeof(ret_buf));
2030 } else {
2031 snprintf(cmd, MAX_CMD_SIZE, "echo '' > %s", VAP_STATUS_FILE);
2032 _syscmd(cmd, ret_buf, sizeof(ret_buf));
2033 }
2034
2035 memset(cmd, 0, MAX_CMD_SIZE);
2036 memset(ret_buf, 0, MAX_BUF_SIZE);
2037
2038 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++)
2039 for (bss_idx = 0; bss_idx < 5; bss_idx++) {
2040 snprintf(cmd, MAX_CMD_SIZE, "echo %s%d=0 >> %s", ext_prefix[radio_idx], bss_idx, VAP_STATUS_FILE);
2041 _syscmd(cmd, ret_buf, sizeof(ret_buf));
2042 }
2043
developerfead3972023-05-25 20:15:02 +08002044}
2045
2046static void wifi_radio_reset_count_reset()
2047{
2048 char cmd[MAX_CMD_SIZE] = {0};
2049 char ret_buf[MAX_BUF_SIZE] = {0};
2050
2051 if (access(VAP_STATUS_FILE, F_OK) != 0) {
2052 snprintf(cmd, MAX_CMD_SIZE, "touch %s", RADIO_RESET_FILE);
2053 _syscmd(cmd, ret_buf, sizeof(ret_buf));
2054 } else {
2055 snprintf(cmd, MAX_CMD_SIZE, "echo '' > %s", RADIO_RESET_FILE);
2056 _syscmd(cmd, ret_buf, sizeof(ret_buf));
2057 }
developer8a3bbbf2023-03-15 17:47:23 +08002058}
developer17038e62023-03-02 14:43:43 +08002059
developer72fb0bb2023-01-11 09:46:29 +08002060// Initializes the wifi subsystem (all radios)
2061INT wifi_init() //RDKB
2062{
developer96b38512023-02-22 11:17:45 +08002063 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2064 //Not intitializing macfilter for Turris-Omnia Platform for now
2065 //macfilter_init();
developer17038e62023-03-02 14:43:43 +08002066 wifi_ParseProfile();
2067 wifi_PrepareDefaultHostapdConfigs();
developer47cc27a2023-05-17 23:09:58 +08002068 wifi_psk_file_reset();
developer17038e62023-03-02 14:43:43 +08002069 //system("/usr/sbin/iw reg set US");
2070 system("systemctl start hostapd.service");
2071 sleep(2);
developer8a3bbbf2023-03-15 17:47:23 +08002072
2073 wifi_vap_status_reset();
developerfead3972023-05-25 20:15:02 +08002074 wifi_radio_reset_count_reset();
developer96b38512023-02-22 11:17:45 +08002075
2076 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08002077
2078 return RETURN_OK;
2079}
2080
2081/* wifi_reset() function */
2082/**
2083* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
developer69b61b02023-03-07 17:17:44 +08002084* Implementation specifics may dictate what is actualy reset since
developer72fb0bb2023-01-11 09:46:29 +08002085* different hardware implementations may have different requirements.
2086* Parameters : None
2087*
2088* @return The status of the operation.
2089* @retval RETURN_OK if successful.
2090* @retval RETURN_ERR if any error is detected
2091*
2092* @execution Synchronous.
2093* @sideeffect None.
2094*
2095* @note This function must not suspend and must not invoke any blocking system
2096* calls. It should probably just send a message to a driver event handler task.
2097*
2098*/
2099INT wifi_reset()
2100{
developer17038e62023-03-02 14:43:43 +08002101
2102 wifi_BringDownInterfaces();
2103 sleep(2);
2104
developer96b38512023-02-22 11:17:45 +08002105 //TODO: resets the wifi subsystem, deletes all APs
2106 system("systemctl stop hostapd.service");
2107 sleep(2);
developer17038e62023-03-02 14:43:43 +08002108
developer96b38512023-02-22 11:17:45 +08002109 system("systemctl start hostapd.service");
2110 sleep(5);
developer17038e62023-03-02 14:43:43 +08002111
2112 wifi_PrepareDefaultHostapdConfigs();
developer47cc27a2023-05-17 23:09:58 +08002113 wifi_psk_file_reset();
developer17038e62023-03-02 14:43:43 +08002114 sleep(2);
developer8a3bbbf2023-03-15 17:47:23 +08002115
2116 wifi_vap_status_reset();
2117
developer72fb0bb2023-01-11 09:46:29 +08002118 return RETURN_OK;
2119}
2120
2121/* wifi_down() function */
2122/**
2123* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
developer69b61b02023-03-07 17:17:44 +08002124* Implementation specifics may dictate some functionality since
developer72fb0bb2023-01-11 09:46:29 +08002125* different hardware implementations may have different requirements.
2126*
2127* @param None
2128*
2129* @return The status of the operation
2130* @retval RETURN_OK if successful
2131* @retval RETURN_ERR if any error is detected
2132*
2133* @execution Synchronous
2134* @sideeffect None
2135*
2136* @note This function must not suspend and must not invoke any blocking system
2137* calls. It should probably just send a message to a driver event handler task.
2138*
2139*/
2140INT wifi_down()
2141{
developer96b38512023-02-22 11:17:45 +08002142 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developerb2977562023-05-24 17:54:12 +08002143 int max_num_radios = 0;
2144 wifi_getMaxRadioNumber(&max_num_radios);
developer17038e62023-03-02 14:43:43 +08002145
developerb2977562023-05-24 17:54:12 +08002146 for (int radioIndex = 0; radioIndex < max_num_radios; radioIndex++)
2147 wifi_setRadioEnable(radioIndex, FALSE);
2148
developer72fb0bb2023-01-11 09:46:29 +08002149 return RETURN_OK;
2150}
2151
2152
2153/* wifi_createInitialConfigFiles() function */
2154/**
2155* @description This function creates wifi configuration files. The format
developer69b61b02023-03-07 17:17:44 +08002156* and content of these files are implementation dependent. This function call is
2157* used to trigger this task if necessary. Some implementations may not need this
2158* function. If an implementation does not need to create config files the function call can
developer72fb0bb2023-01-11 09:46:29 +08002159* do nothing and return RETURN_OK.
2160*
2161* @param None
2162*
2163* @return The status of the operation
2164* @retval RETURN_OK if successful
2165* @retval RETURN_ERR if any error is detected
2166*
2167* @execution Synchronous
2168* @sideeffect None
2169*
2170* @note This function must not suspend and must not invoke any blocking system
2171* calls. It should probably just send a message to a driver event handler task.
2172*
2173*/
2174INT wifi_createInitialConfigFiles()
2175{
2176 //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)
2177 return RETURN_OK;
2178}
2179
developer7e4a2a62023-04-06 19:56:03 +08002180/* outputs the country code to a max 64 character string */
developer72fb0bb2023-01-11 09:46:29 +08002181INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
2182{
developerfde01262023-05-22 15:15:24 +08002183 int ret;
developer72fb0bb2023-01-11 09:46:29 +08002184
developerfde01262023-05-22 15:15:24 +08002185 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer7e4a2a62023-04-06 19:56:03 +08002186
developerfde01262023-05-22 15:15:24 +08002187 ret = wifi_BandProfileRead(0, radioIndex, "CountryCode", output_string, 64, NULL);
2188 if (ret != 0) {
2189 fprintf(stderr, "%s: wifi_BandProfileRead CountryCode failed\n", __func__);
2190 return RETURN_ERR;
2191 }
developer7e4a2a62023-04-06 19:56:03 +08002192
developerfde01262023-05-22 15:15:24 +08002193 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer7e4a2a62023-04-06 19:56:03 +08002194
developerfde01262023-05-22 15:15:24 +08002195 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08002196}
2197
2198INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
2199{
developer7e4a2a62023-04-06 19:56:03 +08002200 /*Set wifi config. Wait for wifi reset to apply*/
2201 char str[MAX_BUF_SIZE] = {0};
2202 char cmd[MAX_CMD_SIZE] = {0};
2203 struct params params;
2204 char config_file[MAX_BUF_SIZE] = {0};
2205 int ret = 0;
developer72fb0bb2023-01-11 09:46:29 +08002206
developer7e4a2a62023-04-06 19:56:03 +08002207 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08002208
developer7e4a2a62023-04-06 19:56:03 +08002209 if(NULL == CountryCode || strlen(CountryCode) >= 32 ) {
2210 printf("%s: input para error!!!\n", __func__);
2211 return RETURN_ERR;
2212 }
developer72fb0bb2023-01-11 09:46:29 +08002213
developer7e4a2a62023-04-06 19:56:03 +08002214 if (!strlen(CountryCode))
2215 strncpy(CountryCode, "US", sizeof("US")); /*default set the code to US*/
developer72fb0bb2023-01-11 09:46:29 +08002216
developer7e4a2a62023-04-06 19:56:03 +08002217 params.name = "country_code";
2218 params.value = CountryCode;
developer72fb0bb2023-01-11 09:46:29 +08002219
developer7e4a2a62023-04-06 19:56:03 +08002220 snprintf(config_file, MAX_BUF_SIZE, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2221 ret = wifi_hostapdWrite(config_file, &params, 1);
2222
2223 if (ret) {
2224 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n",
2225 __func__, ret);
2226 }
2227
2228 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2229
2230 if (ret) {
2231 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n",
2232 __func__, ret);
2233 }
2234
2235 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
2236
2237 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08002238}
2239
2240INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
2241{
2242 char interface_name[16] = {0};
2243 char channel_util_file[64] = {0};
2244 char cmd[128] = {0};
2245 char buf[128] = {0};
2246 char line[128] = {0};
2247 char *param = NULL, *value = NULL;
2248 int read = 0;
2249 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
2250 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
2251 size_t len = 0;
2252 FILE *f = NULL;
2253
2254 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2255
2256 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
2257 return RETURN_ERR;
2258 snprintf(cmd, sizeof(cmd), "iw %s scan | grep signal | awk '{print $2}' | sort -n | tail -n1", interface_name);
2259 _syscmd(cmd, buf, sizeof(buf));
2260 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
2261
2262 memset(cmd, 0, sizeof(cmd));
2263 memset(buf, 0, sizeof(buf));
2264 snprintf(cmd, sizeof(cmd), "iw %s survey dump | grep 'in use' -A6", interface_name);
2265 if ((f = popen(cmd, "r")) == NULL) {
2266 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
2267 return RETURN_ERR;
2268 }
2269
2270 read = getline(&line, &len, f);
2271 while (read != -1) {
2272 param = strtok(line, ":\t");
2273 value = strtok(NULL, " ");
2274 if(strstr(param, "frequency") != NULL) {
2275 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
2276 }
2277 if(strstr(param, "noise") != NULL) {
2278 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
2279 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
2280 }
2281 if(strstr(param, "channel active time") != NULL) {
2282 ActiveTime = strtol(value, NULL, 10);
2283 }
2284 if(strstr(param, "channel busy time") != NULL) {
2285 BusyTime = strtol(value, NULL, 10);
2286 }
2287 if(strstr(param, "channel transmit time") != NULL) {
2288 TransmitTime = strtol(value, NULL, 10);
2289 }
2290 read = getline(&line, &len, f);
2291 }
2292 pclose(f);
2293
2294 // The file should store the last active, busy and transmit time
2295 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
2296 f = fopen(channel_util_file, "r");
2297 if (f != NULL) {
2298 read = getline(&line, &len, f);
2299 preActiveTime = strtol(line, NULL, 10);
2300 read = getline(&line, &len, f);
2301 preBusyTime = strtol(line, NULL, 10);
2302 read = getline(&line, &len, f);
2303 preTransmitTime = strtol(line, NULL, 10);
2304 fclose(f);
2305 }
2306
2307 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
2308 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
2309
2310 f = fopen(channel_util_file, "w");
2311 if (f != NULL) {
2312 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
2313 fclose(f);
2314 }
2315 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2316 return RETURN_OK;
2317}
2318
2319/**********************************************************************************
2320 *
2321 * Wifi radio level function prototypes
2322 *
2323**********************************************************************************/
2324
2325//Get the total number of radios in this wifi subsystem
2326INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
2327{
2328 if (NULL == output)
2329 return RETURN_ERR;
2330 *output = MAX_NUM_RADIOS;
2331
2332 return RETURN_OK;
2333}
2334
developer69b61b02023-03-07 17:17:44 +08002335//Get the total number of SSID entries in this wifi subsystem
developer72fb0bb2023-01-11 09:46:29 +08002336INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
2337{
2338 if (NULL == output)
2339 return RETURN_ERR;
2340 *output = MAX_APS;
2341
2342 return RETURN_OK;
2343}
2344
2345//Get the Radio enable config parameter
2346INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
2347{
developer3a85ab82023-05-25 11:59:38 +08002348 char option[64] = {};
developer72fb0bb2023-01-11 09:46:29 +08002349 char buf[128] = {0}, cmd[128] = {0};
developer3a85ab82023-05-25 11:59:38 +08002350 int ret;
2351
2352 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08002353
2354 if (NULL == output_bool)
2355 return RETURN_ERR;
2356
developer3a85ab82023-05-25 11:59:38 +08002357 snprintf(option, sizeof(option), "INDEX%d_main_ifname", 0);
2358 ret = wifi_l1ProfileRead2(option, radioIndex, buf, sizeof(buf));
2359 if ((ret != 0) || (strlen(buf) <= 0)) {
2360 *output_bool = 0;
developer72fb0bb2023-01-11 09:46:29 +08002361 return RETURN_ERR;
developer3a85ab82023-05-25 11:59:38 +08002362 }
developer72fb0bb2023-01-11 09:46:29 +08002363
developer3a85ab82023-05-25 11:59:38 +08002364 snprintf(cmd, sizeof(cmd), "iw %s info | grep channel", buf);
2365 _syscmd(cmd, buf, sizeof(buf));
2366 if (strlen(buf) == 0) {
2367 *output_bool = 0;
2368 } else {
2369 *output_bool = 1;
2370 }
developer72fb0bb2023-01-11 09:46:29 +08002371
developer3a85ab82023-05-25 11:59:38 +08002372 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08002373 return RETURN_OK;
2374}
2375
developere82c0ca2023-05-10 16:25:35 +08002376typedef long time_t;
2377static time_t radio_up_time[MAX_NUM_RADIOS];
2378
developer72fb0bb2023-01-11 09:46:29 +08002379INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
2380{
2381 char interface_name[16] = {0};
2382 char cmd[MAX_CMD_SIZE] = {0};
developer8a3bbbf2023-03-15 17:47:23 +08002383 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08002384 int apIndex, ret;
developer69b61b02023-03-07 17:17:44 +08002385 int max_radio_num = 0;
developer72fb0bb2023-01-11 09:46:29 +08002386 int phyId = 0;
2387
2388 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2389
2390 phyId = radio_index_to_phy(radioIndex);
2391
2392 wifi_getMaxRadioNumber(&max_radio_num);
2393
developer8a3bbbf2023-03-15 17:47:23 +08002394 if(enable == FALSE) {
developer47cc27a2023-05-17 23:09:58 +08002395
2396 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
2397 return RETURN_ERR;
2398
2399 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s", interface_name);
developer8a3bbbf2023-03-15 17:47:23 +08002400 _syscmd(cmd, buf, sizeof(buf));
developere82c0ca2023-05-10 16:25:35 +08002401 if(strncmp(buf, "OK", 2))
2402 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
developer8a3bbbf2023-03-15 17:47:23 +08002403 } else {
developere82c0ca2023-05-10 16:25:35 +08002404 for (apIndex = radioIndex; apIndex < MAX_APS; apIndex += max_radio_num) {
developer72fb0bb2023-01-11 09:46:29 +08002405 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
2406 return RETURN_ERR;
2407
developer8a3bbbf2023-03-15 17:47:23 +08002408 memset(cmd, 0, MAX_CMD_SIZE);
2409 memset(buf, 0, MAX_BUF_SIZE);
2410
developer72fb0bb2023-01-11 09:46:29 +08002411 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
2412 _syscmd(cmd, buf, sizeof(buf));
developer8a3bbbf2023-03-15 17:47:23 +08002413
2414 if(*buf == '1') {
2415
2416 memset(cmd, 0, MAX_CMD_SIZE);
2417 memset(buf, 0, MAX_BUF_SIZE);
2418
developer72fb0bb2023-01-11 09:46:29 +08002419 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
2420 phyId, apIndex);
2421 _syscmd(cmd, buf, sizeof(buf));
developer8a3bbbf2023-03-15 17:47:23 +08002422
developer72fb0bb2023-01-11 09:46:29 +08002423 }
2424 }
developere82c0ca2023-05-10 16:25:35 +08002425 time(&radio_up_time[radioIndex]);
developer72fb0bb2023-01-11 09:46:29 +08002426 }
2427
2428 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2429 return RETURN_OK;
2430}
2431
2432//Get the Radio enable status
2433INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
2434{
2435 if (NULL == output_bool)
2436 return RETURN_ERR;
2437
2438 return wifi_getRadioEnable(radioIndex, output_bool);
2439}
2440
2441//Get the Radio Interface name from platform, eg "wlan0"
2442INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
2443{
2444 if (NULL == output_string || radioIndex>=MAX_NUM_RADIOS || radioIndex<0)
2445 return RETURN_ERR;
2446 return wifi_GetInterfaceName(radioIndex, output_string);
2447}
2448
2449//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
2450//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.
2451INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
2452{
2453 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
2454 // For max bit rate, we should always choose the best MCS
2455 char mode[64] = {0};
2456 char channel_bandwidth_str[64] = {0};
2457 char *tmp = NULL;
2458 UINT mode_map = 0;
2459 UINT num_subcarrier = 0;
2460 UINT code_bits = 0;
2461 float code_rate = 0; // use max code rate
2462 int NSS = 0;
2463 UINT Symbol_duration = 0;
developer69b61b02023-03-07 17:17:44 +08002464 UINT GI_duration = 0;
developer72fb0bb2023-01-11 09:46:29 +08002465 wifi_band band = band_invalid;
2466 wifi_guard_interval_t gi = wifi_guard_interval_auto;
2467 BOOL enable = FALSE;
2468 float bit_rate = 0;
developera1255e42023-05-13 17:45:02 +08002469 int ant_bitmap = 0;
developer72fb0bb2023-01-11 09:46:29 +08002470
2471 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2472 if (NULL == output_string)
2473 return RETURN_ERR;
2474
2475 wifi_getRadioEnable(radioIndex, &enable);
2476 if (enable == FALSE) {
2477 snprintf(output_string, 64, "0 Mb/s");
2478 return RETURN_OK;
2479 }
2480
2481 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
2482 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
2483 return RETURN_ERR;
2484 }
2485
2486 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
2487 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
2488 return RETURN_ERR;
2489 }
2490
2491 if (gi == wifi_guard_interval_3200)
2492 GI_duration = 32;
2493 else if (gi == wifi_guard_interval_1600)
2494 GI_duration = 16;
2495 else if (gi == wifi_guard_interval_800)
2496 GI_duration = 8;
2497 else // auto, 400
2498 GI_duration = 4;
2499
2500 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
2501 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
2502 return RETURN_ERR;
2503 }
2504
2505 if (strstr(channel_bandwidth_str, "80+80") != NULL)
2506 strcpy(channel_bandwidth_str, "160");
2507
2508 if (mode_map & WIFI_MODE_AX) {
2509 if (strstr(channel_bandwidth_str, "160") != NULL)
2510 num_subcarrier = 1960;
2511 else if (strstr(channel_bandwidth_str, "80") != NULL)
2512 num_subcarrier = 980;
2513 else if (strstr(channel_bandwidth_str, "40") != NULL)
2514 num_subcarrier = 468;
2515 else if (strstr(channel_bandwidth_str, "20") != NULL)
2516 num_subcarrier = 234;
2517 code_bits = 10;
2518 code_rate = (float)5/6;
2519 Symbol_duration = 128;
developera1255e42023-05-13 17:45:02 +08002520 GI_duration = 8;/*HE no GI 400ns*/
developer72fb0bb2023-01-11 09:46:29 +08002521 } else if (mode_map & WIFI_MODE_AC) {
2522 if (strstr(channel_bandwidth_str, "160") != NULL)
2523 num_subcarrier = 468;
2524 else if (strstr(channel_bandwidth_str, "80") != NULL)
2525 num_subcarrier = 234;
2526 else if (strstr(channel_bandwidth_str, "40") != NULL)
2527 num_subcarrier = 108;
2528 else if (strstr(channel_bandwidth_str, "20") != NULL)
2529 num_subcarrier = 52;
2530 code_bits = 8;
2531 code_rate = (float)5/6;
2532 Symbol_duration = 32;
2533 } else if (mode_map & WIFI_MODE_N) {
2534 if (strstr(channel_bandwidth_str, "160") != NULL)
2535 num_subcarrier = 468;
2536 else if (strstr(channel_bandwidth_str, "80") != NULL)
2537 num_subcarrier = 234;
2538 else if (strstr(channel_bandwidth_str, "40") != NULL)
2539 num_subcarrier = 108;
2540 else if (strstr(channel_bandwidth_str, "20") != NULL)
2541 num_subcarrier = 52;
2542 code_bits = 6;
2543 code_rate = (float)3/4;
2544 Symbol_duration = 32;
2545 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
2546 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
2547 snprintf(output_string, 64, "65 Mb/s");
2548 return RETURN_OK;
2549 } else {
2550 snprintf(output_string, 64, "0 Mb/s");
2551 return RETURN_OK;
2552 }
2553
2554 // Spatial streams
developera1255e42023-05-13 17:45:02 +08002555 if (wifi_getRadioTxChainMask(radioIndex, &ant_bitmap) != RETURN_OK) {
developer72fb0bb2023-01-11 09:46:29 +08002556 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
2557 return RETURN_ERR;
2558 }
developera1255e42023-05-13 17:45:02 +08002559 for (; ant_bitmap > 0; ant_bitmap >>= 1)
2560 NSS += ant_bitmap & 1;
developer72fb0bb2023-01-11 09:46:29 +08002561
2562 // multiple 10 is to align duration unit (0.1 us)
2563 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
2564 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
developera1255e42023-05-13 17:45:02 +08002565 WIFI_ENTRY_EXIT_DEBUG("%s:num_subcarrier=%d, code_bits=%d, code_rate=%.3f, nss=%d, symbol time=%u, %.1f Mb/s\n",
2566 __func__, num_subcarrier, code_bits, code_rate, NSS, Symbol_duration + GI_duration, bit_rate);
developer72fb0bb2023-01-11 09:46:29 +08002567 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2568
2569 return RETURN_OK;
2570}
2571#if 0
2572INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
2573{
2574 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2575 char cmd[64];
2576 char buf[1024];
2577 int apIndex;
2578
developer69b61b02023-03-07 17:17:44 +08002579 if (NULL == output_string)
developer72fb0bb2023-01-11 09:46:29 +08002580 return RETURN_ERR;
2581
2582 apIndex=(radioIndex==0)?0:1;
2583
2584 snprintf(cmd, sizeof(cmd), "iwconfig %s | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", interface_name);
2585 _syscmd(cmd,buf, sizeof(buf));
2586
2587 snprintf(output_string, 64, "%s", buf);
2588 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2589 return RETURN_OK;
2590}
2591#endif
2592
2593
2594//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
2595//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.
2596INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
2597{
2598 wifi_band band = band_invalid;
2599
2600 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2601 if (NULL == output_string)
2602 return RETURN_ERR;
2603
2604 band = wifi_index_to_band(radioIndex);
2605
2606 memset(output_string, 0, 10);
2607 if (band == band_2_4)
2608 strcpy(output_string, "2.4GHz");
2609 else if (band == band_5)
2610 strcpy(output_string, "5GHz");
2611 else if (band == band_6)
2612 strcpy(output_string, "6GHz");
2613 else
2614 return RETURN_ERR;
2615 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2616
2617 return RETURN_OK;
2618#if 0
2619 char buf[MAX_BUF_SIZE]={'\0'};
2620 char str[MAX_BUF_SIZE]={'\0'};
2621 char cmd[MAX_CMD_SIZE]={'\0'};
2622 char *ch=NULL;
2623 char *ch2=NULL;
2624
2625 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2626 if (NULL == output_string)
2627 return RETURN_ERR;
2628
2629
2630 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2631
2632 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
2633 {
2634 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2635 return RETURN_ERR;
2636 }
2637 ch=strchr(buf,'\n');
2638 *ch='\0';
2639 ch=strchr(buf,'=');
2640 if(ch==NULL)
2641 return RETURN_ERR;
2642
2643
2644 ch++;
2645
2646 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
2647 strcpy(buf,"0");
2648 if(strlen(ch) == 1)
2649 ch=strcat(buf,ch);
2650
2651
2652 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2653
2654 if(_syscmd(cmd,str,64) == RETURN_ERR)
2655 {
2656 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2657 return RETURN_ERR;
2658 }
2659
2660
2661 ch2=strchr(str,'\n');
2662 //replace \n with \0
2663 *ch2='\0';
2664 ch2=strchr(str,'=');
2665 if(ch2==NULL)
2666 {
2667 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2668 return RETURN_ERR;
2669 }
2670 else
2671 wifi_dbg_printf("%s",ch2+1);
2672
2673
2674 ch2++;
2675
2676
2677 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
2678
2679 memset(buf,'\0',sizeof(buf));
2680 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
2681 {
2682 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2683 return RETURN_ERR;
2684 }
2685 if (strstr(buf,"2.4") != NULL )
2686 strcpy(output_string,"2.4GHz");
2687 else if(strstr(buf,"5.") != NULL )
2688 strcpy(output_string,"5GHz");
2689 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2690
2691 return RETURN_OK;
2692#endif
2693}
2694
2695//Get the frequency band at which the radio is operating, eg: "2.4GHz"
2696//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.
2697INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
2698{
2699 wifi_band band = band_invalid;
2700 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2701 if (NULL == output_string)
2702 return RETURN_ERR;
2703 band = wifi_index_to_band(radioIndex);
2704
developer69b61b02023-03-07 17:17:44 +08002705 if (band == band_2_4)
developer72fb0bb2023-01-11 09:46:29 +08002706 snprintf(output_string, 64, "2.4GHz");
2707 else if (band == band_5)
developer69b61b02023-03-07 17:17:44 +08002708 snprintf(output_string, 64, "5GHz");
developer72fb0bb2023-01-11 09:46:29 +08002709 else if (band == band_6)
2710 snprintf(output_string, 64, "6GHz");
2711
2712 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2713
2714 return RETURN_OK;
2715#if 0
2716 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2717 char buf[MAX_BUF_SIZE]={'\0'};
2718 char str[MAX_BUF_SIZE]={'\0'};
2719 char cmd[MAX_CMD_SIZE]={'\0'};
2720 char *ch=NULL;
2721 char *ch2=NULL;
2722 char ch1[5]="0";
2723
2724 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2725
2726 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
2727 {
2728 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2729 return RETURN_ERR;
2730 }
2731
2732 ch=strchr(buf,'\n');
2733 *ch='\0';
2734 ch=strchr(buf,'=');
2735 if(ch==NULL)
2736 return RETURN_ERR;
2737 ch++;
2738
2739 if(strlen(ch)==1)
2740 {
2741 strcat(ch1,ch);
2742
2743 }
2744 else
2745 {
2746 strcpy(ch1,ch);
2747 }
2748
2749
2750
2751 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2752 if(_syscmd(cmd,str,64) == RETURN_ERR)
2753 {
2754 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2755 return RETURN_ERR;
2756 }
2757
2758
2759 ch2=strchr(str,'\n');
2760 //replace \n with \0
2761 *ch2='\0';
2762 ch2=strchr(str,'=');
2763 if(ch2==NULL)
2764 {
2765 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2766 return RETURN_ERR;
2767 }
2768 else
2769 wifi_dbg_printf("%s",ch2+1);
2770 ch2++;
2771
2772
2773 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
2774 memset(buf,'\0',sizeof(buf));
2775 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
2776 {
2777 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2778 return RETURN_ERR;
2779 }
2780
2781
2782 if(strstr(buf,"2.4")!=NULL)
2783 {
2784 strcpy(output_string,"2.4GHz");
2785 }
2786 if(strstr(buf,"5.")!=NULL)
2787 {
2788 strcpy(output_string,"5GHz");
2789 }
2790 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2791 return RETURN_OK;
2792#endif
2793}
2794
2795//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
2796//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.
2797INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
2798{
2799 char cmd[128]={0};
2800 char buf[128]={0};
2801 char temp_output[128] = {0};
2802 wifi_band band;
2803 int phyId = 0;
2804
2805 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer69b61b02023-03-07 17:17:44 +08002806 if (NULL == output_string)
developer72fb0bb2023-01-11 09:46:29 +08002807 return RETURN_ERR;
2808
2809 band = wifi_index_to_band(radioIndex);
2810 if (band == band_2_4) {
2811 strcat(temp_output, "b,g,");
2812 } else if (band == band_5) {
2813 strcat(temp_output, "a,");
2814 }
2815 phyId = radio_index_to_phy(radioIndex);
2816 // ht capabilities
2817 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);
2818 _syscmd(cmd, buf, sizeof(buf));
2819 if (strlen(buf) >= 4 && strncmp(buf, "0x00", 4) != 0) {
2820 strcat(temp_output, "n,");
2821 }
2822
2823 // vht capabilities
2824 if (band == band_5) {
2825 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'VHT Capabilities' | cut -d '(' -f2 | cut -c1-10 | tr -d '\\n'", phyId);
2826 _syscmd(cmd, buf, sizeof(buf));
2827 if (strlen(buf) >= 10 && strncmp(buf, "0x00000000", 10) != 0) {
2828 strcat(temp_output, "ac,");
2829 }
2830 }
2831
2832 // he capabilities
2833 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);
2834 _syscmd(cmd, buf, sizeof(buf));
2835 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
2836 strcat(temp_output, "ax,");
2837 }
2838
developere82c0ca2023-05-10 16:25:35 +08002839 // eht capabilities
2840 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);
2841 _syscmd(cmd, buf, sizeof(buf));
2842 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
2843 strcat(temp_output, "be,");
2844 }
2845
developer72fb0bb2023-01-11 09:46:29 +08002846 // Remove the last comma
2847 if (strlen(temp_output) != 0)
2848 temp_output[strlen(temp_output)-1] = '\0';
2849 strncpy(output_string, temp_output, strlen(temp_output));
2850 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2851 return RETURN_OK;
2852}
2853
2854//Get the radio operating mode, and pure mode flag. eg: "ac"
2855//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.
2856INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
2857{
2858 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2859 if (NULL == output_string)
2860 return RETURN_ERR;
2861
2862 if (radioIndex == 0) {
2863 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
2864 *gOnly = FALSE;
2865 *nOnly = TRUE;
2866 *acOnly = FALSE;
2867 } else {
2868 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
2869 *gOnly = FALSE;
2870 *nOnly = FALSE;
2871 *acOnly = FALSE;
2872 }
2873 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2874
2875 return RETURN_OK;
2876#if 0
2877 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2878 char buf[64] = {0};
2879 char config_file[MAX_BUF_SIZE] = {0};
2880
developer69b61b02023-03-07 17:17:44 +08002881 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
developer72fb0bb2023-01-11 09:46:29 +08002882 return RETURN_ERR;
2883
2884 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2885 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
2886
2887 wifi_dbg_printf("\nhw_mode=%s\n",buf);
developer69b61b02023-03-07 17:17:44 +08002888 if (strlen(buf) == 0)
developer72fb0bb2023-01-11 09:46:29 +08002889 {
2890 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
2891 return RETURN_ERR;
2892 }
2893 if(strcmp(buf,"g")==0)
2894 {
2895 wifi_dbg_printf("\nG\n");
2896 *gOnly=TRUE;
2897 *nOnly=FALSE;
2898 *acOnly=FALSE;
2899 }
2900 else if(strcmp(buf,"n")==0)
2901 {
2902 wifi_dbg_printf("\nN\n");
2903 *gOnly=FALSE;
2904 *nOnly=TRUE;
2905 *acOnly=FALSE;
2906 }
2907 else if(strcmp(buf,"ac")==0)
2908 {
2909 wifi_dbg_printf("\nac\n");
2910 *gOnly=FALSE;
2911 *nOnly=FALSE;
2912 *acOnly=TRUE;
2913 }
2914 /* hostapd-5G.conf has "a" as hw_mode */
2915 else if(strcmp(buf,"a")==0)
2916 {
2917 wifi_dbg_printf("\na\n");
2918 *gOnly=FALSE;
2919 *nOnly=FALSE;
2920 *acOnly=FALSE;
2921 }
2922 else
2923 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
2924
2925 //for a,n mode
2926 if(radioIndex == 1)
2927 {
2928 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
2929 if(strcmp(buf,"1")==0)
2930 {
2931 strncpy(output_string, "n", 1);
2932 *nOnly=FALSE;
2933 }
2934 }
2935
2936 wifi_dbg_printf("\nReturning from getRadioStandard\n");
2937 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2938 return RETURN_OK;
2939#endif
2940}
2941
developer0f10c772023-05-16 21:43:39 +08002942enum WIFI_MODE {
2943 WMODE_INVALID = 0,
2944 WMODE_A = 1 << 0,
2945 WMODE_B = 1 << 1,
2946 WMODE_G = 1 << 2,
2947 WMODE_GN = 1 << 3,
2948 WMODE_AN = 1 << 4,
2949 WMODE_AC = 1 << 5,
2950 WMODE_AX_24G = 1 << 6,
2951 WMODE_AX_5G = 1 << 7,
2952 WMODE_AX_6G = 1 << 8,
2953 WMODE_BE_24G = 1 << 9,
2954 WMODE_BE_5G = 1 << 10,
2955 WMODE_BE_6G = 1 << 11,
2956 /*
2957 * total types of supported wireless mode,
2958 * add this value once yow add new type
2959 */
2960 WMODE_COMP = 12,
2961};
2962
2963#define RADIO_MODE_LEN 32
developerfead3972023-05-25 20:15:02 +08002964
2965int get_radio_mode_handler(struct nl_msg *msg, void *cb)
developer72fb0bb2023-01-11 09:46:29 +08002966{
developerfead3972023-05-25 20:15:02 +08002967 struct nlattr *tb[NL80211_ATTR_MAX + 1];
2968 struct nlattr *vndr_tb[MTK_NL80211_VENDOR_ATTR_GET_RUNTIME_INFO_MAX + 1];
2969 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
2970 unsigned int *phymode;
2971 int err = 0;
2972 struct mtk_nl80211_cb_data *cb_data = cb;
developer72fb0bb2023-01-11 09:46:29 +08002973
developerfead3972023-05-25 20:15:02 +08002974 if (!msg || !cb_data) {
2975 wifi_debug(DEBUG_ERROR, "msg(0x%lx) or cb_data(0x%lx) is null,error.\n", msg, cb_data);
2976 return NL_SKIP;
2977 }
developer72fb0bb2023-01-11 09:46:29 +08002978
developerfead3972023-05-25 20:15:02 +08002979 err = nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
2980 genlmsg_attrlen(gnlh, 0), NULL);
2981 if (err < 0) {
2982 wifi_debug(DEBUG_ERROR, "nla_parse radio nl80211 msg fails,error.\n");
2983 return NL_SKIP;
2984 }
developer0f10c772023-05-16 21:43:39 +08002985
developerfead3972023-05-25 20:15:02 +08002986 if (tb[NL80211_ATTR_VENDOR_DATA]) {
2987 err = nla_parse_nested(vndr_tb, MTK_NL80211_VENDOR_ATTR_GET_RUNTIME_INFO_MAX,
2988 tb[NL80211_ATTR_VENDOR_DATA], NULL);
2989 if (err < 0)
2990 return NL_SKIP;
developer72fb0bb2023-01-11 09:46:29 +08002991
developerfead3972023-05-25 20:15:02 +08002992 if (vndr_tb[MTK_NL80211_VENDOR_ATTR_GET_RUNTIME_INFO_GET_WMODE]) {
2993 phymode = (unsigned int *)nla_data(vndr_tb[MTK_NL80211_VENDOR_ATTR_GET_RUNTIME_INFO_GET_WMODE]);
2994
2995 memset(cb_data->out_buf, 0, cb_data->out_len);
2996 memmove(cb_data->out_buf, phymode, sizeof(unsigned int));
2997 }
2998 } else
2999 wifi_debug(DEBUG_ERROR, "No Stats from driver.\n");
3000
3001 return NL_OK;
3002}
developer0f10c772023-05-16 21:43:39 +08003003
developerfead3972023-05-25 20:15:02 +08003004void phymode_to_puremode(INT radioIndex, CHAR *output_string, UINT *pureMode, UINT phymode)
3005{
3006 wifi_band band;
3007 unsigned char radio_mode_tem_len;
3008
3009 band = wifi_index_to_band(radioIndex);
developer0f10c772023-05-16 21:43:39 +08003010 // puremode is a bit map
developer72fb0bb2023-01-11 09:46:29 +08003011 *pureMode = 0;
developer0f10c772023-05-16 21:43:39 +08003012 memset(output_string, 0, RADIO_MODE_LEN);
3013
3014 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
3015
3016 switch (band) {
3017 case band_2_4:
3018 if (phymode & WMODE_B) {
3019 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "b,");
3020 *pureMode |= WIFI_MODE_B;
3021 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
3022 }
3023 if (phymode & WMODE_G) {
3024 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "g,");
3025 *pureMode |= WIFI_MODE_G;
3026 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
3027 }
3028 if (phymode & WMODE_GN) {
3029 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "n,");
3030 *pureMode |= WIFI_MODE_N;
3031 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
3032 }
3033 if (phymode & WMODE_AX_24G) {
3034 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "ax,");
3035 *pureMode |= WIFI_MODE_AX;
3036 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
3037 }
3038 if (phymode & WMODE_BE_24G) {
3039 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "be,");
3040 *pureMode |= WIFI_MODE_BE;
3041 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
3042 }
3043 break;
3044 case band_5:
3045 if (phymode & WMODE_A) {
3046 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "a,");
3047 *pureMode |= WIFI_MODE_A;
3048 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
3049 }
3050 if (phymode & WMODE_AN) {
3051 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "n,");
3052 *pureMode |= WIFI_MODE_N;
3053 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
3054 }
3055 if (phymode & WMODE_AC) {
3056 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "ac,");
3057 *pureMode |= WIFI_MODE_AC;
3058 }
3059 if (phymode & WMODE_AX_5G) {
3060 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "ax,");
3061 *pureMode |= WIFI_MODE_AX;
3062 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
3063 }
3064 if (phymode & WMODE_BE_5G) {
3065 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "be,");
3066 *pureMode |= WIFI_MODE_BE;
3067 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
3068 }
3069 break;
3070 case band_6:
3071 if (phymode & WMODE_AX_6G) {
3072 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "ax,");
3073 *pureMode |= WIFI_MODE_AX;
3074 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
3075 }
3076 if (phymode & WMODE_BE_6G) {
3077 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "be,");
3078 *pureMode |= WIFI_MODE_BE;
3079 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
3080 }
3081 break;
3082 default:
3083 fprintf(stderr, "%s band_idx invalid\n", __func__);
3084 break;
3085 }
3086
3087 /* Remove the last comma */
3088 if (strlen(output_string) != 0)
3089 output_string[strlen(output_string)-1] = '\0';
developer72fb0bb2023-01-11 09:46:29 +08003090
developerfead3972023-05-25 20:15:02 +08003091}
3092
3093INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
3094{
3095 unsigned int phymode;
3096 char interface_name[IF_NAME_SIZE] = {0};
3097 struct mtk_nl80211_param params;
3098 int ret = -1;
3099 unsigned int if_idx = 0;
3100 struct unl unl_ins;
3101 struct nl_msg *msg = NULL;
3102 struct nlattr * msg_data = NULL;
3103 struct mtk_nl80211_param param;
3104 struct mtk_nl80211_cb_data cb_data;
3105
3106 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3107 if(NULL == output_string || NULL == pureMode)
3108 return RETURN_ERR;
3109
3110 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3111 return RETURN_ERR;
3112
3113 if_idx = if_nametoindex(interface_name);
3114 if (!if_idx) {
3115 wifi_debug(DEBUG_ERROR, "can't finde ifname(%s) index,ERROR\n", interface_name);
3116 return RETURN_ERR;
3117 }
3118 /*init mtk nl80211 vendor cmd*/
3119 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_GET_RUNTIME_INFO;
3120 param.if_type = NL80211_ATTR_IFINDEX;
3121 param.if_idx = if_idx;
3122
3123 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
3124 if (ret) {
3125 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
3126 return RETURN_ERR;
3127 }
3128
3129 /*add mtk vendor cmd data*/
3130 if (nla_put_u16(msg, MTK_NL80211_VENDOR_ATTR_GET_RUNTIME_INFO_GET_WMODE, 0)) {
3131 wifi_debug(DEBUG_ERROR, "Nla put GET_RUNTIME_INFO_GET_WMODE attribute error\n");
3132 nlmsg_free(msg);
3133 goto err;
3134 }
3135
3136 /*send mtk nl80211 vendor msg*/
3137 cb_data.out_buf = (char *)&phymode;
3138 cb_data.out_len = sizeof(unsigned int);
3139
3140 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, get_radio_mode_handler, &cb_data);
3141
3142 if (ret) {
3143 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
3144 goto err;
3145 }
3146 /*deinit mtk nl80211 vendor msg*/
3147 mtk_nl80211_deint(&unl_ins);
3148
3149 phymode_to_puremode(radioIndex, output_string, pureMode, phymode);
3150 wifi_debug(DEBUG_NOTICE,"send cmd success\n");
3151
developer72fb0bb2023-01-11 09:46:29 +08003152 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3153 return RETURN_OK;
developerfead3972023-05-25 20:15:02 +08003154err:
3155 mtk_nl80211_deint(&unl_ins);
3156 wifi_debug(DEBUG_ERROR,"send cmd fails\n");
3157 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08003158}
3159
3160// Set the radio operating mode, and pure mode flag.
3161INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
3162{
developer69b61b02023-03-07 17:17:44 +08003163 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
developer72fb0bb2023-01-11 09:46:29 +08003164 if (strcmp (channelMode,"11A") == 0)
3165 {
3166 writeBandWidth(radioIndex,"20MHz");
3167 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
3168 printf("\nChannel Mode is 802.11a (5GHz)\n");
3169 }
3170 else if (strcmp (channelMode,"11NAHT20") == 0)
3171 {
3172 writeBandWidth(radioIndex,"20MHz");
3173 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
3174 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
3175 }
3176 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
3177 {
3178 writeBandWidth(radioIndex,"40MHz");
3179 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
3180 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
3181 }
3182 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
3183 {
3184 writeBandWidth(radioIndex,"40MHz");
3185 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
3186 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
3187 }
3188 else if (strcmp (channelMode,"11ACVHT20") == 0)
3189 {
3190 writeBandWidth(radioIndex,"20MHz");
3191 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
3192 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
3193 }
3194 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
3195 {
3196 writeBandWidth(radioIndex,"40MHz");
3197 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
3198 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
3199 }
3200 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
3201 {
3202 writeBandWidth(radioIndex,"40MHz");
3203 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
3204 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
3205 }
3206 else if (strcmp (channelMode,"11ACVHT80") == 0)
3207 {
3208 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
3209 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
3210 }
3211 else if (strcmp (channelMode,"11ACVHT160") == 0)
3212 {
3213 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
3214 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
developer69b61b02023-03-07 17:17:44 +08003215 }
developer72fb0bb2023-01-11 09:46:29 +08003216 else if (strcmp (channelMode,"11B") == 0)
3217 {
3218 writeBandWidth(radioIndex,"20MHz");
3219 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
3220 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
3221 }
3222 else if (strcmp (channelMode,"11G") == 0)
3223 {
3224 writeBandWidth(radioIndex,"20MHz");
3225 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
3226 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
3227 }
3228 else if (strcmp (channelMode,"11NGHT20") == 0)
3229 {
3230 writeBandWidth(radioIndex,"20MHz");
3231 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
3232 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
3233 }
3234 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
3235 {
3236 writeBandWidth(radioIndex,"40MHz");
3237 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
3238 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
3239 }
3240 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
3241 {
3242 writeBandWidth(radioIndex,"40MHz");
3243 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
3244 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
3245 }
developer69b61b02023-03-07 17:17:44 +08003246 else
developer72fb0bb2023-01-11 09:46:29 +08003247 {
3248 return RETURN_ERR;
3249 }
3250 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3251
3252 return RETURN_OK;
3253}
3254
developer0f10c772023-05-16 21:43:39 +08003255typedef enum _RT_802_11_PHY_MODE {
3256 PHY_11BG_MIXED = 0,
3257 PHY_11B = 1,
3258 PHY_11A = 2,
3259 PHY_11ABG_MIXED = 3,
3260 PHY_11G = 4,
3261 PHY_11ABGN_MIXED = 5, /* both band 5 */
3262 PHY_11N_2_4G = 6, /* 11n-only with 2.4G band 6 */
3263 PHY_11GN_MIXED = 7, /* 2.4G band 7 */
3264 PHY_11AN_MIXED = 8, /* 5G band 8 */
3265 PHY_11BGN_MIXED = 9, /* if check 802.11b. 9 */
3266 PHY_11AGN_MIXED = 10, /* if check 802.11b. 10 */
3267 PHY_11N_5G = 11, /* 11n-only with 5G band 11 */
3268 PHY_11VHT_N_ABG_MIXED = 12, /* 12 -> AC/A/AN/B/G/GN mixed */
3269 PHY_11VHT_N_AG_MIXED = 13, /* 13 -> AC/A/AN/G/GN mixed */
3270 PHY_11VHT_N_A_MIXED = 14, /* 14 -> AC/AN/A mixed in 5G band */
3271 PHY_11VHT_N_MIXED = 15, /* 15 -> AC/AN mixed in 5G band */
3272 PHY_11AX_24G = 16,
3273 PHY_11AX_5G = 17,
3274 PHY_11AX_6G = 18,
3275 PHY_11AX_24G_6G = 19,
3276 PHY_11AX_5G_6G = 20,
3277 PHY_11AX_24G_5G_6G = 21,
3278 PHY_11BE_24G = 22,
3279 PHY_11BE_5G = 23,
3280 PHY_11BE_6G = 24,
3281 PHY_11BE_24G_6G = 25,
3282 PHY_11BE_5G_6G = 26,
3283 PHY_11BE_24G_5G_6G = 27,
3284 PHY_MODE_MAX,
3285} RT_802_11_PHY_MODE;
3286
3287unsigned int puremode_to_wireless_mode(INT radioIndex, UINT pureMode)
3288{
3289 int band_idx = 0;
developerfead3972023-05-25 20:15:02 +08003290 unsigned char wireless_mode = PHY_MODE_MAX;
developer0f10c772023-05-16 21:43:39 +08003291
3292 band_idx = radio_index_to_band(radioIndex);
3293
3294 switch (band_idx) {
3295 case band_2_4:
3296 if (pureMode == (WIFI_MODE_G | WIFI_MODE_N))
3297 wireless_mode = PHY_11GN_MIXED;
3298 if (pureMode == (WIFI_MODE_B | WIFI_MODE_G | WIFI_MODE_N))
3299 wireless_mode = PHY_11BGN_MIXED;
3300 if (pureMode & WIFI_MODE_AX)
3301 wireless_mode = PHY_11AX_24G;
3302 if (pureMode & WIFI_MODE_BE)
3303 wireless_mode = PHY_11BE_24G;
3304 break;
3305 case band_5:
3306 if (pureMode == WIFI_MODE_N)
3307 wireless_mode = PHY_11N_5G;
3308 if ((pureMode == WIFI_MODE_AC) || (pureMode == (WIFI_MODE_N | WIFI_MODE_AC)))
3309 wireless_mode = PHY_11VHT_N_MIXED;
3310 if (pureMode == (WIFI_MODE_A | WIFI_MODE_N | WIFI_MODE_AC))
3311 wireless_mode = PHY_11VHT_N_A_MIXED;
3312 if (pureMode & WIFI_MODE_AX)
3313 wireless_mode = PHY_11AX_5G;
3314 if (pureMode & WIFI_MODE_BE)
3315 wireless_mode = PHY_11BE_5G;
3316 break;
3317 case band_6:
3318 if (pureMode & WIFI_MODE_AX)
3319 wireless_mode = PHY_11AX_6G;
3320 if (pureMode & WIFI_MODE_BE)
3321 wireless_mode = PHY_11BE_6G;
3322 break;
3323 default:
3324 fprintf(stderr, "%s band_idx invalid\n", __func__);
3325 break;
3326 }
3327
3328 return wireless_mode;
3329}
3330
developer72fb0bb2023-01-11 09:46:29 +08003331// Set the radio operating mode, and pure mode flag.
3332INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
3333{
developerfead3972023-05-25 20:15:02 +08003334 unsigned char wireless_mode = PHY_MODE_MAX;
developer69b61b02023-03-07 17:17:44 +08003335
developer0f10c772023-05-16 21:43:39 +08003336 char interface_name[IF_NAME_SIZE] = {0};
developerfead3972023-05-25 20:15:02 +08003337 int ret = -1;
3338 unsigned int if_idx = 0;
3339 struct unl unl_ins;
3340 struct nl_msg *msg = NULL;
3341 struct nlattr * msg_data = NULL;
3342 struct mtk_nl80211_param param;
developer72fb0bb2023-01-11 09:46:29 +08003343
developer0f10c772023-05-16 21:43:39 +08003344 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08003345
developer0f10c772023-05-16 21:43:39 +08003346 wireless_mode = puremode_to_wireless_mode(radioIndex, pureMode);
developer72fb0bb2023-01-11 09:46:29 +08003347
developer0f10c772023-05-16 21:43:39 +08003348 if (wireless_mode == PHY_MODE_MAX) {
3349 fprintf(stderr, "%s wireless_mode invalid pureMode = %x\n", __func__, pureMode);
3350 return RETURN_ERR;
3351 }
developer72fb0bb2023-01-11 09:46:29 +08003352
developer0f10c772023-05-16 21:43:39 +08003353 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3354 return RETURN_ERR;
developerfead3972023-05-25 20:15:02 +08003355
3356 if_idx = if_nametoindex(interface_name);
3357 if (!if_idx) {
3358 wifi_debug(DEBUG_ERROR,"can't finde ifname(%s) index,ERROR\n", interface_name);
3359 return RETURN_ERR;
3360 }
3361 /*init mtk nl80211 vendor cmd*/
3362 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_AP_BSS;
3363 param.if_type = NL80211_ATTR_IFINDEX;
3364 param.if_idx = if_idx;
3365
3366 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
3367 if (ret) {
3368 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
3369 return RETURN_ERR;
3370 }
3371
3372 /*add mtk vendor cmd data*/
3373 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_AP_WIRELESS_MODE, wireless_mode)) {
3374 wifi_debug(DEBUG_ERROR, "Nla put AP_WIRELESS_MODE attribute error\n");
3375 nlmsg_free(msg);
3376 goto err;
3377 }
3378 /*send mtk nl80211 vendor msg*/
3379 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
3380 if (ret) {
3381 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
3382 goto err;
3383 }
3384 /*deinit mtk nl80211 vendor msg*/
3385 mtk_nl80211_deint(&unl_ins);
3386 wifi_debug(DEBUG_NOTICE, "set cmd success.\n");
developer72fb0bb2023-01-11 09:46:29 +08003387
developer0f10c772023-05-16 21:43:39 +08003388 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3389
3390 return RETURN_OK;
developerfead3972023-05-25 20:15:02 +08003391err:
3392 mtk_nl80211_deint(&unl_ins);
3393 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
3394 return RETURN_ERR;
developer0f10c772023-05-16 21:43:39 +08003395}
3396
3397INT wifi_setRadioMode_by_dat(INT radioIndex, UINT pureMode)
3398{
developerfead3972023-05-25 20:15:02 +08003399 unsigned char wireless_mode = PHY_MODE_MAX;
developer0f10c772023-05-16 21:43:39 +08003400 char interface_name[IF_NAME_SIZE] = {0};
developer0f10c772023-05-16 21:43:39 +08003401 char buf[MAX_BUF_SIZE] = {0};
developer0f10c772023-05-16 21:43:39 +08003402 char dat_file[MAX_BUF_SIZE] = {0};
3403 struct params params={0};
3404
3405 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, pureMode, __LINE__);
3406
3407 wireless_mode = puremode_to_wireless_mode(radioIndex, pureMode);
3408
3409 if (wireless_mode == PHY_MODE_MAX) {
3410 fprintf(stderr, "%s wireless_mode invalid pureMode = %x\n", __func__, pureMode);
3411 return RETURN_ERR;
3412 }
3413
3414 params.name = "WirelessMode";
3415 snprintf(buf, sizeof(buf), "%d", wireless_mode);
3416 params.value = buf;
3417
3418 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, radioIndex);
3419 wifi_datfileWrite(dat_file, &params, 1);
3420
developer72fb0bb2023-01-11 09:46:29 +08003421 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3422
3423 return RETURN_OK;
3424}
3425
3426INT wifi_setRadioHwMode(INT radioIndex, CHAR *hw_mode) {
3427
3428 char config_file[64] = {0};
3429 char buf[64] = {0};
3430 struct params params = {0};
3431 wifi_band band = band_invalid;
3432
3433 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3434
3435 band = wifi_index_to_band(radioIndex);
3436
3437 if (strncmp(hw_mode, "a", 1) == 0 && (band != band_5 && band != band_6))
3438 return RETURN_ERR;
3439 else if ((strncmp(hw_mode, "b", 1) == 0 || strncmp(hw_mode, "g", 1) == 0) && band != band_2_4)
3440 return RETURN_ERR;
3441 else if ((strncmp(hw_mode, "a", 1) && strncmp(hw_mode, "b", 1) && strncmp(hw_mode, "g", 1)) || band == band_invalid)
3442 return RETURN_ERR;
3443
3444 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3445 params.name = "hw_mode";
3446 params.value = hw_mode;
3447 wifi_hostapdWrite(config_file, &params, 1);
3448 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3449
3450 if (band == band_2_4) {
3451 if (strncmp(hw_mode, "b", 1) == 0) {
3452 wifi_setRadioMode(radioIndex, "20MHz", WIFI_MODE_B);
3453 snprintf(buf, sizeof(buf), "%s", "1,2,5.5,11");
3454 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
3455 snprintf(buf, sizeof(buf), "%s", "1,2");
3456 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
3457 } else {
3458 // We don't set mode here, because we don't know whitch mode should be set (g, n or ax?).
3459
3460 snprintf(buf, sizeof(buf), "%s", "6,9,12,18,24,36,48,54");
3461 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
3462 snprintf(buf, sizeof(buf), "%s", "6,12,24");
3463 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
3464 }
3465 }
3466
3467 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3468 return RETURN_OK;
3469}
3470
3471INT wifi_setNoscan(INT radioIndex, CHAR *noscan)
3472{
3473 char config_file[64] = {0};
3474 struct params params = {0};
3475 wifi_band band = band_invalid;
3476
3477 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3478
3479 band = wifi_index_to_band(radioIndex);
3480 if (band != band_2_4)
3481 return RETURN_OK;
3482
3483 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3484 params.name = "noscan";
3485 params.value = noscan;
3486 wifi_hostapdWrite(config_file, &params, 1);
3487 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3488
3489 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3490 return RETURN_OK;
3491}
3492
3493//Get the list of supported channel. eg: "1-11"
3494//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.
3495INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
3496{
3497 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer69b61b02023-03-07 17:17:44 +08003498 if (NULL == output_string)
developer72fb0bb2023-01-11 09:46:29 +08003499 return RETURN_ERR;
3500 char cmd[256] = {0};
3501 char buf[128] = {0};
3502 BOOL dfs_enable = false;
3503 int phyId = 0;
3504
3505 // Parse possible channel number and separate them with commas.
3506 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
3507 phyId = radio_index_to_phy(radioIndex);
3508 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
3509 if (dfs_enable)
3510 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 +08003511 else
developer72fb0bb2023-01-11 09:46:29 +08003512 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);
3513
3514 _syscmd(cmd,buf,sizeof(buf));
3515 strncpy(output_string, buf, sizeof(buf));
3516
3517 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3518 return RETURN_OK;
3519}
developerd1824452023-05-18 12:30:04 +08003520//Getting current radio extension channel
3521INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
3522{
3523 CHAR buf[150] = {0};
3524 CHAR cmd[150] = {0};
3525
3526 wifi_datfileRead(file, "HT_EXTCHA", buf, sizeof(buf));
developer262f4cb2023-05-24 12:22:04 +08003527 if (strncmp(buf, "Below", 5) == 0) //below
developerd1824452023-05-18 12:30:04 +08003528 strcpy(Value,"BelowControlChannel");
developer262f4cb2023-05-24 12:22:04 +08003529 if(strncmp(buf, "Above", 5) == 0) //above
developerd1824452023-05-18 12:30:04 +08003530 strcpy(Value,"AboveControlChannel");
3531 return RETURN_OK;
3532}
developerf6a87542023-05-16 15:47:28 +08003533
developer72fb0bb2023-01-11 09:46:29 +08003534//Get the list for used channel. eg: "1,6,9,11"
3535//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.
3536INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
3537{
3538 char interface_name[16] = {0};
3539 char cmd[128] = {0};
3540 char buf[128] = {0};
3541 char config_file[64] = {0};
3542 int channel = 0;
3543 int freq = 0;
3544 int bandwidth = 0;
3545 int center_freq = 0;
3546 int center_channel = 0;
3547 int channel_delta = 0;
3548 wifi_band band = band_invalid;
3549
3550 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3551
3552 if (NULL == output_string)
3553 return RETURN_ERR;
3554
3555 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3556 return RETURN_ERR;
3557 sprintf(cmd, "iw %s info | grep channel | sed -e 's/[^0-9 ]//g'", interface_name);
3558 _syscmd(cmd, buf, sizeof(buf));
3559 if (strlen(buf) == 0) {
3560 fprintf(stderr, "%s: failed to get channel information from iw.\n", __func__);
3561 return RETURN_ERR;
3562 }
3563 sscanf(buf, "%d %d %d %*d %d", &channel, &freq, &bandwidth, &center_freq);
3564
3565 if (bandwidth == 20) {
3566 snprintf(output_string, 256, "%d", channel);
3567 return RETURN_OK;
3568 }
3569
3570 center_channel = ieee80211_frequency_to_channel(center_freq);
3571
3572 band = wifi_index_to_band(radioIndex);
3573 if (band == band_2_4 && bandwidth == 40) {
developerd1824452023-05-18 12:30:04 +08003574 sprintf(config_file, "%s%d.dat", LOGAN_DAT_FILE, band);
developer72fb0bb2023-01-11 09:46:29 +08003575 memset(buf, 0, sizeof(buf));
3576 wifi_halgetRadioExtChannel(config_file, buf); // read ht_capab for HT40+ or -
3577
3578 if (strncmp(buf, "AboveControlChannel", strlen("AboveControlChannel")) == 0 && channel < 10) {
3579 snprintf(output_string, 256, "%d,%d", channel, channel+4);
3580 } else if (strncmp(buf, "BelowControlChannel", strlen("BelowControlChannel")) == 0 && channel > 4) {
3581 snprintf(output_string, 256, "%d,%d", channel-4, channel);
3582 } else {
3583 fprintf(stderr, "%s: invalid channel %d set with %s\n.", __func__, channel, buf);
3584 return RETURN_ERR;
3585 }
3586 } else if (band == band_5 || band == band_6){
3587 // 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 +08003588 // 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 +08003589 channel_delta = (bandwidth-20)/10;
developerd1824452023-05-18 12:30:04 +08003590 memset(output_string, 0, 256);
3591 for (int i = center_channel-channel_delta; i <= center_channel+channel_delta; i+=4) {
3592 // If i is not the last channel, we add a comma.
3593 snprintf(buf, sizeof(buf), "%d%s", i, i==center_channel+channel_delta?"":",");
3594 strncat(output_string, buf, strlen(buf));
3595 }
developer72fb0bb2023-01-11 09:46:29 +08003596 } else
3597 return RETURN_ERR;
3598
3599 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3600 return RETURN_OK;
3601}
3602
developer69b61b02023-03-07 17:17:44 +08003603//Get the running channel number
developerd1824452023-05-18 12:30:04 +08003604INT wifi_getRadioChannel(INT radioIndex, ULONG *output_ulong) //RDKB
developer72fb0bb2023-01-11 09:46:29 +08003605{
3606 char channel_str[16] = {0};
3607 char config_file[128] = {0};
developerd1824452023-05-18 12:30:04 +08003608 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08003609
3610 if (output_ulong == NULL)
3611 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08003612 band = wifi_index_to_band(radioIndex);
3613 snprintf(config_file, sizeof(config_file), "%s%d.dat", LOGAN_DAT_FILE, band);
3614 wifi_datfileRead(config_file, "Channel", channel_str, sizeof(channel_str));
developer72fb0bb2023-01-11 09:46:29 +08003615
3616 *output_ulong = strtoul(channel_str, NULL, 10);
3617
3618 return RETURN_OK;
3619}
3620
3621
3622INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
3623{
3624 char cmd[1024] = {0}, buf[5] = {0};
3625 char interface_name[16] = {0};
3626
3627 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3628 if (NULL == output_ulong)
3629 return RETURN_ERR;
3630
3631 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
3632 if (wifi_getApName(apIndex,interface_name) != RETURN_OK)
3633 return RETURN_ERR;
3634 _syscmd(cmd,buf,sizeof(buf));
3635 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
3636 if (*output_ulong == 0) {
3637 return RETURN_ERR;
3638 }
3639
3640 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3641 return RETURN_OK;
3642}
3643
3644//Storing the previous channel value
3645INT wifi_storeprevchanval(INT radioIndex)
3646{
3647 char buf[256] = {0};
3648 char output[4]={'\0'};
3649 char config_file[MAX_BUF_SIZE] = {0};
developerd1824452023-05-18 12:30:04 +08003650 wifi_band band = band_invalid;
3651
3652 band = wifi_index_to_band(radioIndex);
3653 if (band == band_invalid) {
3654 return RETURN_ERR;
3655 wifi_dbg_printf("[%s]: Invalid radio index", __func__);
3656 }
3657 snprintf(config_file, sizeof(config_file), "%s%d.dat",LOGAN_DAT_FILE, band);
3658 wifi_datfileRead(config_file, "Channel", output, sizeof(output));
3659
3660 if(band == band_2_4)
developer72fb0bb2023-01-11 09:46:29 +08003661 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
developerd1824452023-05-18 12:30:04 +08003662 else if(band == band_5)
developer72fb0bb2023-01-11 09:46:29 +08003663 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
developerd1824452023-05-18 12:30:04 +08003664 else
3665 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval6G_AutoChannelEnable");
developer72fb0bb2023-01-11 09:46:29 +08003666 system(buf);
3667 Radio_flag = FALSE;
3668 return RETURN_OK;
3669}
3670
3671//Set the running channel number
3672INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
3673{
3674 // We only write hostapd config here
3675 char str_channel[8]={0};
3676 char *list_channel;
3677 char config_file[128] = {0};
3678 char possible_channels[256] = {0};
developerd1824452023-05-18 12:30:04 +08003679 char config_file_dat[128] = {0};
developer72fb0bb2023-01-11 09:46:29 +08003680 int max_radio_num = 0;
3681 struct params list = {0};
developerd1824452023-05-18 12:30:04 +08003682 struct params dat = {0};
3683 struct params acs = {0};
3684 wifi_band band = band_invalid;
3685 bool acs_channel = false;
developer72fb0bb2023-01-11 09:46:29 +08003686
3687 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3688
developerd1824452023-05-18 12:30:04 +08003689 if (channel == 0)
3690 acs_channel = true;
developer72fb0bb2023-01-11 09:46:29 +08003691 // Check valid
3692 sprintf(str_channel, "%lu", channel);
3693
developerd1824452023-05-18 12:30:04 +08003694
developer72fb0bb2023-01-11 09:46:29 +08003695 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
3696 list_channel = strtok(possible_channels, ",");
3697 while(true)
3698 {
3699 if(list_channel == NULL) { // input not in the list
3700 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
3701 return RETURN_ERR;
3702 }
3703 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
3704 break;
3705 list_channel = strtok(NULL, ",");
3706 }
developerd1824452023-05-18 12:30:04 +08003707 /*
developer72fb0bb2023-01-11 09:46:29 +08003708 list.name = "channel";
3709 list.value = str_channel;
3710 wifi_getMaxRadioNumber(&max_radio_num);
3711 for(int i=0; i<=MAX_APS/max_radio_num;i++)
3712 {
3713 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
3714 wifi_hostapdWrite(config_file, &list, 1);
3715 }
developerd1824452023-05-18 12:30:04 +08003716 */
3717 dat.name = "Channel";
3718 dat.value = str_channel;
3719 band = wifi_index_to_band(radioIndex);
3720 snprintf(config_file_dat, sizeof(config_file_dat), "%s%d.dat", LOGAN_DAT_FILE, band);
3721 wifi_datfileWrite(config_file_dat, &dat, 1);
3722 if (acs_channel == true) {
3723 acs.name = "AutoChannelSelect";
3724 acs.value = "3";
3725 } else {
3726 acs.name = "AutoChannelSelect";
3727 acs.value = "0";
3728 }
3729 wifi_datfileWrite(config_file_dat, &acs, 1);
developerc0772e62023-05-18 15:10:48 +08003730 wifi_reloadAp(radioIndex);
developer72fb0bb2023-01-11 09:46:29 +08003731 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3732 return RETURN_OK;
3733}
3734
3735INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
3736{
3737 struct params list[2];
3738 char str_idx[16];
3739 char config_file[64];
3740 int max_num_radios = 0;
3741 wifi_band band = band_invalid;
3742
3743 band = wifi_index_to_band(radioIndex);
3744 if (band == band_2_4)
3745 return RETURN_OK;
3746
3747 snprintf(str_idx, sizeof(str_idx), "%lu", channel);
3748 list[0].name = "vht_oper_centr_freq_seg0_idx";
3749 list[0].value = str_idx;
3750 list[1].name = "he_oper_centr_freq_seg0_idx";
3751 list[1].value = str_idx;
3752
3753 wifi_getMaxRadioNumber(&max_num_radios);
3754 for(int i=0; i<=MAX_APS/max_num_radios; i++)
3755 {
3756 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
3757 if (band == band_6)
3758 wifi_hostapdWrite(config_file, &list[1], 1);
3759 else
3760 wifi_hostapdWrite(config_file, list, 2);
3761 }
3762
3763 return RETURN_OK;
3764}
3765
3766//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
3767//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
3768INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
3769{
3770 //Set to wifi config only. Wait for wifi reset to apply.
3771 char buf[256] = {0};
3772 char str_channel[256] = {0};
3773 int count = 0;
3774 ULONG Value = 0;
3775 FILE *fp = NULL;
3776 if(enable == TRUE)
3777 {
3778 wifi_setRadioChannel(radioIndex,Value);
3779 }
3780 return RETURN_OK;
3781}
3782
3783INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
3784{
3785 if (output_bool == NULL)
3786 return RETURN_ERR;
3787
3788 *output_bool = TRUE;
3789
3790 return RETURN_OK;
3791}
3792
3793INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
3794{
developer69b61b02023-03-07 17:17:44 +08003795 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08003796 return RETURN_ERR;
3797 *output_bool=FALSE;
3798 return RETURN_OK;
3799}
3800
3801INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
3802{
developer69b61b02023-03-07 17:17:44 +08003803 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08003804 return RETURN_ERR;
3805 *output_bool=FALSE;
3806 return RETURN_OK;
3807}
3808
3809INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
3810{
3811 //Set to wifi config only. Wait for wifi reset to apply.
3812 return RETURN_OK;
3813}
3814
3815INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
3816{
3817 return RETURN_OK;
3818}
3819
3820INT wifi_factoryResetAP(int apIndex)
3821{
developer47cc27a2023-05-17 23:09:58 +08003822 char ap_config_file[MAX_CMD_SIZE] = {0};
3823 char cmd[MAX_CMD_SIZE] = {0};
3824 char ret_buf[MAX_BUF_SIZE] = {0};
3825 int radio_idx = 0;
3826 int bss_idx = 0;
3827 char ssid[32] = {0};
3828 char interface[IF_NAME_SIZE] = {0};
3829 char psk_file[MAX_CMD_SIZE] = {0};
3830 struct params params[3] = {0};
3831 char *band_str[3] = {"2G", "5G", "6G"};
developer72fb0bb2023-01-11 09:46:29 +08003832
3833 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3834
developer47cc27a2023-05-17 23:09:58 +08003835 /*del old config file*/
3836 snprintf(ap_config_file, MAX_CMD_SIZE, "%s%d.conf", CONFIG_PREFIX, apIndex);
3837 snprintf(cmd, MAX_CMD_SIZE, "rm %s", ap_config_file);
3838 _syscmd(cmd, ret_buf, sizeof(ret_buf));
developer72fb0bb2023-01-11 09:46:29 +08003839
developer47cc27a2023-05-17 23:09:58 +08003840 memset(cmd, 0, sizeof(cmd));
3841 memset(ret_buf, 0, sizeof(ret_buf));
developer72fb0bb2023-01-11 09:46:29 +08003842
developer47cc27a2023-05-17 23:09:58 +08003843 vap_index_to_array_index(apIndex, &radio_idx, &bss_idx);
3844
3845 /*prepare new config file*/
developere740c2a2023-05-23 18:34:32 +08003846 snprintf(cmd, sizeof(cmd), "cp /etc/hostapd-%s.conf %s", wifi_band_str[radio_idx], ap_config_file);
developer47cc27a2023-05-17 23:09:58 +08003847 _syscmd(cmd, ret_buf, sizeof(ret_buf));
3848
3849 if (radio_idx == band_2_4) {
3850 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_2G, bss_idx);
3851 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI2G, bss_idx);
3852 } else if (radio_idx == band_5) {
3853 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_5G, bss_idx);
3854 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI5G, bss_idx);
3855 } else if (radio_idx == band_6) {
3856 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_6G, bss_idx);
3857 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI6G, bss_idx);
3858 }
3859
3860 /* fix wpa_psk_file path */
3861 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", apIndex);
3862
3863 params[0].name = "ssid";
3864 params[0].value = ssid;
3865 params[1].name = "interface";
3866 params[1].value = interface;
3867 params[2].name = "wpa_psk_file";
3868 params[2].value = psk_file;
3869
3870 wifi_hostapdWrite(ap_config_file, params, 3);
3871
3872 /*clear psk file*/
3873 memset(cmd, 0, sizeof(cmd));
3874 memset(ret_buf, 0, sizeof(ret_buf));
3875
3876 snprintf(psk_file, sizeof(psk_file), "%s%d.psk", PSK_FILE, apIndex);
3877
3878 if (access(psk_file, F_OK) != 0) {
3879 snprintf(cmd, MAX_CMD_SIZE, "touch %s", psk_file);
3880 _syscmd(cmd, ret_buf, sizeof(ret_buf));
3881 } else {
3882 snprintf(cmd, MAX_CMD_SIZE, "echo '' > %s", psk_file);
3883 _syscmd(cmd, ret_buf, sizeof(ret_buf));
3884 }
3885
3886 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3887
3888 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08003889}
3890
3891//To set Band Steering AP group
3892//To-do
3893INT wifi_setBandSteeringApGroup(char *ApGroup)
3894{
3895 return RETURN_OK;
3896}
3897
3898INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
3899{
3900 char config_file[128] = {'\0'};
3901 char buf[128] = {'\0'};
3902
3903 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3904 if (dtimInterval == NULL)
3905 return RETURN_ERR;
3906
3907 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developer885b56c2023-05-22 15:02:46 +08003908 wifi_hostapdRead(config_file, "dtim_period", buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08003909
3910 if (strlen(buf) == 0) {
3911 *dtimInterval = 2;
3912 } else {
3913 *dtimInterval = strtoul(buf, NULL, 10);
3914 }
3915
3916 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3917 return RETURN_OK;
3918}
3919
3920INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
3921{
3922 struct params params={0};
3923 char config_file[MAX_BUF_SIZE] = {'\0'};
3924 char buf[MAX_BUF_SIZE] = {'\0'};
3925
3926 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3927 if (dtimInterval < 1 || dtimInterval > 255) {
3928 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
3929 return RETURN_ERR;
3930 }
developer69b61b02023-03-07 17:17:44 +08003931
developer72fb0bb2023-01-11 09:46:29 +08003932 params.name = "dtim_period";
3933 snprintf(buf, sizeof(buf), "%d", dtimInterval);
3934 params.value = buf;
3935
3936 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
3937 wifi_hostapdWrite(config_file, &params, 1);
3938 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3939
3940 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3941 return RETURN_OK;
3942}
3943
3944//Check if the driver support the Dfs
3945INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
3946{
3947 wifi_band band = band_invalid;
developer69b61b02023-03-07 17:17:44 +08003948 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08003949 return RETURN_ERR;
3950 *output_bool=FALSE;
3951
3952 band = wifi_index_to_band(radioIndex);
3953 if (band == band_5)
3954 *output_bool = TRUE;
3955 return RETURN_OK;
3956}
3957
3958//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.
3959//The value of this parameter is a comma seperated list of channel number
3960INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
3961{
developer69b61b02023-03-07 17:17:44 +08003962 if (NULL == output_pool)
developer72fb0bb2023-01-11 09:46:29 +08003963 return RETURN_ERR;
3964 if (radioIndex==1)
developer69b61b02023-03-07 17:17:44 +08003965 return RETURN_OK;//TODO need to handle for 5GHz band, i think
developer72fb0bb2023-01-11 09:46:29 +08003966 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
3967
3968 return RETURN_OK;
3969}
3970
3971INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
3972{
3973 //Set to wifi config. And apply instantly.
3974 return RETURN_OK;
3975}
3976
3977INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
3978{
developer69b61b02023-03-07 17:17:44 +08003979 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
developer72fb0bb2023-01-11 09:46:29 +08003980 return RETURN_ERR;
3981 *output_interval_seconds=1800;
3982 *output_dwell_milliseconds=40;
3983
3984 return RETURN_OK;
3985}
3986
3987INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
3988{
3989 //Set to wifi config. And apply instantly.
3990 return RETURN_OK;
3991}
3992
3993INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
3994{
3995 if (output_bool == NULL)
3996 return RETURN_ERR;
developer69b61b02023-03-07 17:17:44 +08003997 *output_bool = true;
3998 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08003999}
4000
4001INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
4002{
4003 return RETURN_OK;
4004}
4005
4006//Get the Dfs enable status
4007INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
4008{
4009 char buf[16] = {0};
4010 FILE *f = NULL;
developerd1824452023-05-18 12:30:04 +08004011 char config_file_dat[128] = {0};
developerd1824452023-05-18 12:30:04 +08004012 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08004013
4014 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4015
4016 if (output_bool == NULL)
4017 return RETURN_ERR;
developerf6a87542023-05-16 15:47:28 +08004018 *output_bool = TRUE; // default
developerd1824452023-05-18 12:30:04 +08004019 band = wifi_index_to_band(radioIndex);
4020 snprintf(config_file_dat, sizeof(config_file_dat), "%s%d.dat", LOGAN_DAT_FILE, band);
4021
developer262f4cb2023-05-24 12:22:04 +08004022 wifi_datfileRead(config_file_dat, "DfsEnable", buf, sizeof(buf));
developerd1824452023-05-18 12:30:04 +08004023
4024 if (strncmp(buf, "0", 1) == 0)
4025 *output_bool = FALSE;
developer72fb0bb2023-01-11 09:46:29 +08004026 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4027 return RETURN_OK;
4028}
4029
4030//Set the Dfs enable status
4031INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
4032{
4033 char config_file[128] = {0};
developerd1824452023-05-18 12:30:04 +08004034 char config_dat_file[128] = {0};
developer72fb0bb2023-01-11 09:46:29 +08004035 FILE *f = NULL;
developerd1824452023-05-18 12:30:04 +08004036 struct params dat = {0};
4037 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08004038
4039 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4040
4041 f = fopen(DFS_ENABLE_FILE, "w");
4042 if (f == NULL)
4043 return RETURN_ERR;
4044 fprintf(f, "%d", enable);
4045 fclose(f);
4046
developer72fb0bb2023-01-11 09:46:29 +08004047 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
4048
developerd1824452023-05-18 12:30:04 +08004049 dat.name = "DfsEnable";
developer262f4cb2023-05-24 12:22:04 +08004050 dat.value = enable?"1":"0";
developerd1824452023-05-18 12:30:04 +08004051 band = wifi_index_to_band(radioIndex);
4052 snprintf(config_dat_file, sizeof(config_dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
4053 wifi_datfileWrite(config_dat_file, &dat, 1);
developer72fb0bb2023-01-11 09:46:29 +08004054 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4055 return RETURN_OK;
4056}
4057
4058//Check if the driver support the AutoChannelRefreshPeriod
4059INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
4060{
developer69b61b02023-03-07 17:17:44 +08004061 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08004062 return RETURN_ERR;
4063 *output_bool=FALSE; //not support
4064
4065 return RETURN_OK;
4066}
4067
4068//Get the ACS refresh period in seconds
4069INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
4070{
developer69b61b02023-03-07 17:17:44 +08004071 if (NULL == output_ulong)
developer72fb0bb2023-01-11 09:46:29 +08004072 return RETURN_ERR;
4073 *output_ulong=300;
4074
4075 return RETURN_OK;
4076}
4077
4078//Set the ACS refresh period in seconds
4079INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
4080{
4081 return RETURN_ERR;
4082}
4083
4084//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
4085//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.
4086INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
4087{
developer8666b312023-03-24 14:05:31 +08004088 char cmd[MAX_CMD_SIZE] = {0}, buf[64] = {0};
developer72fb0bb2023-01-11 09:46:29 +08004089 char extchannel[128] = {0};
developer8666b312023-03-24 14:05:31 +08004090 char interface_name[64] = {0};
4091 int ret = 0, len=0;
developer72fb0bb2023-01-11 09:46:29 +08004092 BOOL radio_enable = FALSE;
4093 wifi_band band;
4094
4095 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4096
developerd1824452023-05-18 12:30:04 +08004097 if (NULL == output_string) {
4098 WIFI_ENTRY_EXIT_DEBUG("output_string is nuill %s: %d \n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08004099 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08004100 }
4101 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR) {
4102 WIFI_ENTRY_EXIT_DEBUG("wifi_getRadioEnable failed %s: %d \n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08004103 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08004104 }
4105 if (radio_enable != TRUE) {
4106 WIFI_ENTRY_EXIT_DEBUG("Radio %d is not enable failed %s: %d \n", radioIndex, __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08004107 return RETURN_OK;
developerd1824452023-05-18 12:30:04 +08004108 }
developer8666b312023-03-24 14:05:31 +08004109 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4110 return RETURN_ERR;
4111 /*IW command get BW320 to do*/
developerd1824452023-05-18 12:30:04 +08004112
developer8666b312023-03-24 14:05:31 +08004113 snprintf(cmd, sizeof(cmd),"iw dev %s info | grep 'width' | cut -d ' ' -f6 | tr -d '\\n'", interface_name);
4114 ret = _syscmd(cmd, buf, sizeof(buf));
4115 len = strlen(buf);
4116 if((ret != 0) || (len == 0))
4117 {
4118 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
4119 return RETURN_ERR;
4120 }
4121
developer72fb0bb2023-01-11 09:46:29 +08004122 band = wifi_index_to_band(radioIndex);
developer8666b312023-03-24 14:05:31 +08004123 if (band == band_2_4 && strncmp(buf, "20", 2) == 0) {
developer72fb0bb2023-01-11 09:46:29 +08004124 wifi_getRadioExtChannel(radioIndex, extchannel);
developer8666b312023-03-24 14:05:31 +08004125 if (strncmp(extchannel, "Auto", 4) != 0) // not auto means we have set HT40+/-
4126 snprintf(buf, sizeof(buf), "40");
developer72fb0bb2023-01-11 09:46:29 +08004127 }
developer8666b312023-03-24 14:05:31 +08004128 snprintf(output_string, 64, "%sMHz", buf);
developer72fb0bb2023-01-11 09:46:29 +08004129 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4130
4131 return RETURN_OK;
developerfead3972023-05-25 20:15:02 +08004132}
4133
4134enum mwctl_chan_width {
4135 MWCTL_CHAN_WIDTH_20,
4136 MWCTL_CHAN_WIDTH_40,
4137 MWCTL_CHAN_WIDTH_80,
4138 MWCTL_CHAN_WIDTH_160,
4139 MWCTL_CHAN_WIDTH_320,
4140};
4141
4142struct bw_option {
4143 unsigned int bandwith;
4144 enum mwctl_chan_width mode;
4145};
4146
4147struct bw_option bw_opt[] = {
4148 {20, MWCTL_CHAN_WIDTH_20},
4149 {40, MWCTL_CHAN_WIDTH_40},
4150 {80, MWCTL_CHAN_WIDTH_80},
4151 {160, MWCTL_CHAN_WIDTH_160},
4152 {320, MWCTL_CHAN_WIDTH_320},
4153};
4154
4155INT wifi_setChannel_netlink(INT radioIndex, UINT* channel, UINT *bandwidth)
4156{
4157 int ret = -1;
4158 int i;
4159 struct unl unl_ins;
4160 struct nl_msg *msg = NULL;
4161 struct nlattr * msg_data = NULL;
4162 struct mtk_nl80211_param param;
4163 bool b_match = FALSE;
4164
4165 /*init mtk nl80211 vendor cmd*/
4166 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_CHANNEL;
4167 param.if_type = NL80211_ATTR_WIPHY;
4168 param.if_idx = radio_index_to_phy(radioIndex);
4169
4170 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
4171 if (ret) {
4172 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
4173 return RETURN_ERR;
4174 }
4175
4176 /*add mtk vendor cmd data*/
4177 if (channel != NULL)
4178 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_CHAN_SET_NUM, *channel)) {
4179 wifi_debug(DEBUG_ERROR, "Nla put CHAN_SET_NUM attribute error\n");
4180 nlmsg_free(msg);
4181 goto err;
4182 }
4183
4184 if (bandwidth != NULL) {
4185 for (i = 0; i < (sizeof(bw_opt)/sizeof(bw_opt[0])); i++) {
4186 if (bw_opt[i].bandwith == *bandwidth) {
4187 b_match = true;
4188 if (nla_put_u32(msg, MTK_NL80211_VENDOR_ATTR_CHAN_SET_BW, bw_opt[i].mode)) {
4189 wifi_debug(DEBUG_ERROR, "Nla put CHAN_SET_BW attribute error\n");
4190 nlmsg_free(msg);
4191 goto err;
4192 }
4193 break;
4194 }
4195 }
4196
4197 if (!b_match) {
4198 wifi_debug(DEBUG_ERROR, "Cannot find bandwith error\n");
4199 nlmsg_free(msg);
4200 goto err;
4201 }
4202 }
4203
4204 /*send mtk nl80211 vendor msg*/
4205 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
4206 if (ret) {
4207 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
4208 goto err;
4209 }
4210 /*deinit mtk nl80211 vendor msg*/
4211 mtk_nl80211_deint(&unl_ins);
4212 wifi_debug(DEBUG_NOTICE, "set cmd success.\n");
4213 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4214
4215 return RETURN_OK;
4216err:
4217 mtk_nl80211_deint(&unl_ins);
4218 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
4219 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08004220}
developerfead3972023-05-25 20:15:02 +08004221
developer72fb0bb2023-01-11 09:46:29 +08004222//Set the Operating Channel Bandwidth.
4223INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
4224{
4225 char config_file[128];
developerd1824452023-05-18 12:30:04 +08004226 char ht_value[16];
4227 char vht_value[16];
4228 char eht_value[16];
4229 struct params dat[3];
4230 wifi_band band = band_invalid;
developerfead3972023-05-25 20:15:02 +08004231 unsigned int bw = 20;
4232 int ret = 0;
developer72fb0bb2023-01-11 09:46:29 +08004233
4234 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4235
4236 if(NULL == bandwidth)
4237 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08004238 band = wifi_index_to_band(radioIndex);
developer72fb0bb2023-01-11 09:46:29 +08004239
developerd1824452023-05-18 12:30:04 +08004240 if(strstr(bandwidth,"320") != NULL) {
4241 snprintf(ht_value, sizeof(ht_value), "%d", HT_BW_40);
4242 snprintf(vht_value, sizeof(vht_value), "%d", VHT_BW_160);
4243 snprintf(eht_value, sizeof(eht_value), "%d", EHT_BW_320);
developer262f4cb2023-05-24 12:22:04 +08004244 bw = 320;
developerd1824452023-05-18 12:30:04 +08004245 } else if(strstr(bandwidth,"160") != NULL) {
4246 snprintf(ht_value, sizeof(ht_value), "%d", HT_BW_40);
4247 snprintf(vht_value, sizeof(vht_value), "%d", VHT_BW_160);
4248 snprintf(eht_value, sizeof(eht_value), "%d", EHT_BW_160);
developer262f4cb2023-05-24 12:22:04 +08004249 bw = 160;
developerd1824452023-05-18 12:30:04 +08004250 } else if(strstr(bandwidth,"80") != NULL) {
4251 snprintf(ht_value, sizeof(ht_value), "%d", HT_BW_40);
4252 snprintf(vht_value, sizeof(vht_value), "%d", VHT_BW_80);
4253 snprintf(eht_value, sizeof(eht_value), "%d", EHT_BW_80);
developer262f4cb2023-05-24 12:22:04 +08004254 bw = 80;
developerd1824452023-05-18 12:30:04 +08004255 } else if(strstr(bandwidth,"40") != NULL) {
4256 snprintf(ht_value, sizeof(ht_value), "%d", HT_BW_40);
4257 snprintf(vht_value, sizeof(vht_value), "%d", VHT_BW_2040);
4258 snprintf(eht_value, sizeof(eht_value), "%d", EHT_BW_40);
developerfead3972023-05-25 20:15:02 +08004259 bw = 40;
developerd1824452023-05-18 12:30:04 +08004260 } else if(strstr(bandwidth,"20") != NULL) {
4261 snprintf(ht_value, sizeof(ht_value), "%d", HT_BW_20);
4262 snprintf(vht_value, sizeof(vht_value), "%d", VHT_BW_2040);
4263 snprintf(eht_value, sizeof(eht_value), "%d", EHT_BW_20);
developer262f4cb2023-05-24 12:22:04 +08004264 bw = 20;
developerd1824452023-05-18 12:30:04 +08004265 } else {
developer72fb0bb2023-01-11 09:46:29 +08004266 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
4267 return RETURN_ERR;
4268 }
4269
developerd1824452023-05-18 12:30:04 +08004270 snprintf(config_file, sizeof(config_file), "%s%d.dat", LOGAN_DAT_FILE, band);
4271 dat[0].name = "HT_BW";
4272 dat[0].value = ht_value;
4273 dat[1].name = "VHT_BW";
4274 dat[1].value = vht_value;
4275 dat[2].name = "EHT_ApBw";
4276 dat[2].value = eht_value;
4277 wifi_datfileWrite(config_file, dat, 3);
developerfead3972023-05-25 20:15:02 +08004278 ret = wifi_setChannel_netlink(radioIndex, NULL, &bw);
4279 if (ret != RETURN_OK) {
4280 fprintf(stderr, "%s: wifi_setChannel return error.\n", __func__);
4281 return RETURN_ERR;
4282 }
developer72fb0bb2023-01-11 09:46:29 +08004283
4284 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4285 return RETURN_OK;
4286}
4287
developer72fb0bb2023-01-11 09:46:29 +08004288//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
4289//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.
4290INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
4291{
4292 char config_file[64] = {0};
developerd1824452023-05-18 12:30:04 +08004293 char config_dat_file[64] = {0};
developer72fb0bb2023-01-11 09:46:29 +08004294 char mode_str[16] = {0};
4295 char buf[64] = {0};
developerd1824452023-05-18 12:30:04 +08004296 char cmd[MAX_CMD_SIZE] = {0};
4297 char interface_name[64] = {0};
4298 int ret = 0, len=0;
developer72fb0bb2023-01-11 09:46:29 +08004299 wifi_band band;
developerd1824452023-05-18 12:30:04 +08004300 ULONG channel = 0;
4301 int centr_channel = 0;
developer72fb0bb2023-01-11 09:46:29 +08004302 UINT mode_map = 0;
developerd1824452023-05-18 12:30:04 +08004303 int freq=0;
developer72fb0bb2023-01-11 09:46:29 +08004304
4305 if (output_string == NULL)
4306 return RETURN_ERR;
4307
4308 wifi_getRadioMode(radioIndex, mode_str, &mode_map);
4309
4310 band = wifi_index_to_band(radioIndex);
4311 if (band == band_invalid)
4312 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08004313 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4314 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08004315
4316 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4317
4318 snprintf(output_string, 64, "Auto");
developer23e71282023-01-18 10:25:19 +08004319 if (band == band_2_4 || (!(mode_map&WIFI_MODE_AC) && !(mode_map&WIFI_MODE_AX))) {
developerd1824452023-05-18 12:30:04 +08004320 // 2G band or ac and ax mode is disable, we will check HT_EXTCHA
4321 snprintf(config_dat_file, sizeof(config_dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
4322 wifi_halgetRadioExtChannel(config_dat_file, output_string);
developer23e71282023-01-18 10:25:19 +08004323 if (!(mode_map&WIFI_MODE_N))
developer72fb0bb2023-01-11 09:46:29 +08004324 snprintf(output_string, 64, "Auto");
4325 } else {
4326 // 5G and 6G band with ac or ax mode.
4327 wifi_getRadioChannel(radioIndex, &channel);
developerd1824452023-05-18 12:30:04 +08004328 snprintf(cmd, sizeof(cmd),"iw dev %s info | grep 'center1' | cut -d ' ' -f9 | tr -d '\\n'", interface_name);
4329
4330 ret = _syscmd(cmd, buf, sizeof(buf));
4331 len = strlen(buf);
4332 if((ret != 0) || (len == 0))
4333 {
4334 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
4335 return RETURN_ERR;
4336 }
4337 sscanf(buf, "%d", &freq);
4338 centr_channel = ieee80211_frequency_to_channel(freq);
4339 if (centr_channel > (int)channel)
developer72fb0bb2023-01-11 09:46:29 +08004340 snprintf(output_string, 64, "AboveControlChannel");
4341 else
4342 snprintf(output_string, 64, "BelowControlChannel");
4343 }
4344
4345 return RETURN_OK;
4346}
4347
4348//Set the extension channel.
4349INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
developer69b61b02023-03-07 17:17:44 +08004350{
developer72fb0bb2023-01-11 09:46:29 +08004351 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4352 struct params params={0};
4353 char config_file[64] = {0};
developerd1824452023-05-18 12:30:04 +08004354 char config_dat_file[64] = {0};
4355 char ext_channel[64] = {0};
developer72fb0bb2023-01-11 09:46:29 +08004356 char buf[128] = {0};
4357 char cmd[128] = {0};
4358 int max_radio_num =0, ret = 0, bandwidth = 0;
4359 unsigned long channel = 0, centr_channel = 0;
4360 bool stbcEnable = FALSE;
4361 params.name = "ht_capab";
4362 wifi_band band;
4363
4364 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
4365 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
4366 _syscmd(cmd, buf, sizeof(buf));
4367 if (strlen(buf) != 0)
4368 stbcEnable = TRUE;
4369 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, buf) != RETURN_OK)
4370 return RETURN_ERR;
4371 bandwidth = strtol(buf, NULL, 10);
4372 // TDK expected to get error with 20MHz
developer262f4cb2023-05-24 12:22:04 +08004373 // we handle 20MHz in function wifi_RemoveRadioExtChannel().
developer72fb0bb2023-01-11 09:46:29 +08004374 if (bandwidth == 20 || strstr(buf, "80+80") != NULL)
4375 return RETURN_ERR;
4376
4377 band = wifi_index_to_band(radioIndex);
4378 if (band == band_invalid)
4379 return RETURN_ERR;
4380
4381 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK)
4382 return RETURN_ERR;
4383
developer262f4cb2023-05-24 12:22:04 +08004384 snprintf(buf, sizeof(buf), "HT%d", bandwidth);
4385 ret = util_get_sec_chan_offset(channel, buf);
4386 if (ret == -EINVAL)
4387 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08004388
4389 if(NULL!= strstr(string,"Above")) {
developer262f4cb2023-05-24 12:22:04 +08004390 if ((band == band_2_4 && channel > 9) || (band == band_5 && ret == -1))
4391 return RETURN_OK;
4392 strcpy(ext_channel, "Above");
developer72fb0bb2023-01-11 09:46:29 +08004393 } else if(NULL!= strstr(string,"Below")) {
developer262f4cb2023-05-24 12:22:04 +08004394 if ((band == band_2_4 && channel < 5) || (band == band_5 && ret == -1))
4395 return RETURN_OK;
4396 strcpy(ext_channel, "Below");
4397 } else {
developerd1824452023-05-18 12:30:04 +08004398 printf("%s: invalid EXT_CHA:%s\n", __func__, string);
developer262f4cb2023-05-24 12:22:04 +08004399 return RETURN_ERR;
4400 }
developerd1824452023-05-18 12:30:04 +08004401 params.name = "HT_EXTCHA";
developer72fb0bb2023-01-11 09:46:29 +08004402 params.value = ext_channel;
4403
developerd1824452023-05-18 12:30:04 +08004404 snprintf (config_dat_file, sizeof(config_dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
4405 wifi_datfileWrite(config_dat_file, &params, 1);
4406
developer72fb0bb2023-01-11 09:46:29 +08004407 wifi_getMaxRadioNumber(&max_radio_num);
4408 for(int i=0; i<=MAX_APS/max_radio_num; i++)
4409 {
4410 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(max_radio_num*i));
developer72fb0bb2023-01-11 09:46:29 +08004411 wifi_setRadioSTBCEnable(radioIndex+(max_radio_num*i), stbcEnable);
4412 }
4413
4414 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
4415 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4416 return RETURN_OK;
4417}
4418
4419//Get the guard interval value. eg "400nsec" or "800nsec"
4420//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.
4421INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
4422{
4423 wifi_guard_interval_t GI;
4424
4425 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4426
4427 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
4428 return RETURN_ERR;
4429
4430 if (GI == wifi_guard_interval_400)
4431 strcpy(output_string, "400nsec");
4432 else if (GI == wifi_guard_interval_800)
4433 strcpy(output_string, "800nsec");
4434 else if (GI == wifi_guard_interval_1600)
4435 strcpy(output_string, "1600nsec");
4436 else if (GI == wifi_guard_interval_3200)
4437 strcpy(output_string, "3200nsec");
4438 else
4439 strcpy(output_string, "Auto");
4440
4441 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4442 return RETURN_OK;
4443}
4444
4445//Set the guard interval value.
4446INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
4447{
4448 wifi_guard_interval_t GI;
4449 int ret = 0;
4450
4451 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4452
4453 if (strcmp(string, "400nsec") == 0)
4454 GI = wifi_guard_interval_400;
4455 else if (strcmp(string , "800nsec") == 0)
4456 GI = wifi_guard_interval_800;
4457 else if (strcmp(string , "1600nsec") == 0)
4458 GI = wifi_guard_interval_1600;
4459 else if (strcmp(string , "3200nsec") == 0)
4460 GI = wifi_guard_interval_3200;
4461 else
4462 GI = wifi_guard_interval_auto;
4463
4464 ret = wifi_setGuardInterval(radioIndex, GI);
4465
4466 if (ret == RETURN_ERR) {
4467 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
4468 return RETURN_ERR;
4469 }
4470
4471 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4472 return RETURN_OK;
4473}
4474
4475//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
4476INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
4477{
4478 char buf[32]={0};
4479 char mcs_file[64] = {0};
4480 char cmd[64] = {0};
4481 int mode_bitmap = 0;
4482
4483 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4484 if(output_int == NULL)
4485 return RETURN_ERR;
4486 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
4487
4488 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
4489 _syscmd(cmd, buf, sizeof(buf));
4490 if (strlen(buf) > 0)
4491 *output_int = strtol(buf, NULL, 10);
4492 else {
4493 // output the max MCS for the current radio mode
4494 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
4495 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
4496 return RETURN_ERR;
4497 }
4498 if (mode_bitmap & WIFI_MODE_AX) {
4499 *output_int = 11;
4500 } else if (mode_bitmap & WIFI_MODE_AC) {
4501 *output_int = 9;
4502 } else if (mode_bitmap & WIFI_MODE_N) {
4503 *output_int = 7;
4504 }
4505 }
4506 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4507
4508 return RETURN_OK;
4509}
4510
4511//Set the Modulation Coding Scheme index
4512INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
4513{
developera1255e42023-05-13 17:45:02 +08004514 /*Only HE mode can specify MCS capability. We don't support MCS in HT mode,
4515 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 +08004516 char config_file[64] = {0};
4517 char set_value[16] = {0};
4518 char mcs_file[32] = {0};
developer72fb0bb2023-01-11 09:46:29 +08004519 struct params set_config = {0};
4520 FILE *f = NULL;
developera1255e42023-05-13 17:45:02 +08004521 INT nss = 0;
4522 int ant_bitmap = 0;
4523 unsigned short cal_value = 0;
4524 UCHAR tval = 0, i = 0;
developer72fb0bb2023-01-11 09:46:29 +08004525
4526 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4527
4528 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4529
4530 // -1 means auto
4531 if (MCS > 15 || MCS < -1) {
4532 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
4533 return RETURN_ERR;
4534 }
developera1255e42023-05-13 17:45:02 +08004535 wifi_getRadioTxChainMask(radioIndex, &ant_bitmap);/*nss is a bit map value,1111*/
4536 for(; ant_bitmap > 0; ant_bitmap >>= 1)
4537 nss += 1;
4538 //printf("%s:nss = %d\n", __func__, nss);
4539 /*16-bit combination of 2-bit values of Max HE-MCS For 1..8 SS;each 2-bit value have following meaning:
4540 0 = HE-MCS 0-7, 1 = HE-MCS 0-9, 2 = HE-MCS 0-11, 3 = not supported*/
developer72fb0bb2023-01-11 09:46:29 +08004541 if (MCS > 9 || MCS == -1)
developera1255e42023-05-13 17:45:02 +08004542 tval = 2;/*one stream value*/
developer72fb0bb2023-01-11 09:46:29 +08004543 else if (MCS > 7)
developera1255e42023-05-13 17:45:02 +08004544 tval = 1;
developer72fb0bb2023-01-11 09:46:29 +08004545 else
developera1255e42023-05-13 17:45:02 +08004546 tval = 0;
4547 for (i = 0; i < nss; i++)
4548 cal_value |= (tval << (2*i));
4549 snprintf(set_value, sizeof(set_value), "%x", cal_value);
4550 WIFI_ENTRY_EXIT_DEBUG("%s:set=%s, cal=%x\n", __func__, set_value, cal_value);
4551 set_config.name = "he_basic_mcs_nss_set";/*He capability in beacon or response*/
developer72fb0bb2023-01-11 09:46:29 +08004552 set_config.value = set_value;
4553
4554 wifi_hostapdWrite(config_file, &set_config, 1);
4555 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
4556
4557 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
4558 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
4559 f = fopen(mcs_file, "w");
4560 if (f == NULL) {
4561 fprintf(stderr, "%s: fopen failed\n", __func__);
4562 return RETURN_ERR;
4563 }
4564 fprintf(f, "%d", MCS);
4565 fclose(f);
4566
4567 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4568 return RETURN_OK;
4569}
4570
4571//Get supported Transmit Power list, eg : "0,25,50,75,100"
4572//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.
4573INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
4574{
4575 if (NULL == output_list)
4576 return RETURN_ERR;
4577 snprintf(output_list, 64,"0,25,50,75,100");
4578 return RETURN_OK;
4579}
4580
4581//Get current Transmit Power in dBm units.
4582//The transmite power level is in units of full power for this radio.
4583INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
4584{
4585 char interface_name[16] = {0};
4586 char cmd[128]={0};
4587 char buf[16]={0};
developera1255e42023-05-13 17:45:02 +08004588 char pwr_file[128]={0};
4589
developer72fb0bb2023-01-11 09:46:29 +08004590 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4591
4592 if(output_ulong == NULL)
4593 return RETURN_ERR;
4594
4595 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4596 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +08004597/*
developer72fb0bb2023-01-11 09:46:29 +08004598 snprintf(cmd, sizeof(cmd), "iw %s info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", interface_name);
4599 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08004600 *output_ulong = strtol(buf, NULL, 10);
developera1255e42023-05-13 17:45:02 +08004601*/
4602 snprintf(pwr_file, sizeof(pwr_file), "%s%d.txt", POWER_PERCENTAGE, radioIndex);
4603 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", pwr_file);
4604 _syscmd(cmd, buf, sizeof(buf));
4605 if (strlen(buf) > 0)
4606 *output_ulong = strtol(buf, NULL, 10);
4607 else
4608 *output_ulong = 100;
developer72fb0bb2023-01-11 09:46:29 +08004609 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4610 return RETURN_OK;
4611}
4612
4613//Set Transmit Power
4614//The transmite power level is in units of full power for this radio.
4615INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
4616{
4617 char interface_name[16] = {0};
4618 char *support;
developer72fb0bb2023-01-11 09:46:29 +08004619 char buf[128]={0};
4620 char txpower_str[64] = {0};
developera1255e42023-05-13 17:45:02 +08004621 char pwr_file[128]={0};
4622 FILE *f = NULL;
developerfead3972023-05-25 20:15:02 +08004623 int if_idx, ret = 0;
4624 struct nl_msg *msg = NULL;
4625 struct nlattr * msg_data = NULL;
4626 struct mtk_nl80211_param param;
4627 struct unl unl_ins;
developer72fb0bb2023-01-11 09:46:29 +08004628
4629 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4630
4631 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4632 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +08004633 // Get the Tx power supported list and check that is the input in the list
4634 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
4635 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
4636 support = strtok(buf, ",");
4637 while(true)
4638 {
4639 if(support == NULL) { // input not in the list
4640 wifi_dbg_printf("Input value is invalid.\n");
4641 return RETURN_ERR;
4642 }
4643 if (strncmp(txpower_str, support, strlen(support)) == 0) {
4644 break;
4645 }
4646 support = strtok(NULL, ",");
4647 }
developerfead3972023-05-25 20:15:02 +08004648
4649 if_idx = if_nametoindex(interface_name);
4650 /*init mtk nl80211 vendor cmd*/
4651 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_TXPOWER;
4652 param.if_type = NL80211_ATTR_IFINDEX;
4653 param.if_idx = if_idx;
4654 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
4655 if (ret) {
4656 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
4657 return RETURN_ERR;
4658 }
4659 /*add mtk vendor cmd data*/
4660 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_TXPWR_PERCENTAGE_EN, 1)) {
4661 wifi_debug(DEBUG_ERROR, "Nla put attribute error\n");
4662 nlmsg_free(msg);
4663 goto err;
4664 }
4665
4666 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_TXPWR_DROP_CTRL, TransmitPower)) {
4667 wifi_debug(DEBUG_ERROR, "Nla put attribute error\n");
4668 nlmsg_free(msg);
4669 goto err;
4670 }
4671
4672 /*send mtk nl80211 vendor msg*/
4673 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
4674 if (ret) {
4675 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
4676 goto err;
4677 }
4678 /*deinit mtk nl80211 vendor msg*/
4679 mtk_nl80211_deint(&unl_ins);
4680 wifi_debug(DEBUG_NOTICE, "set cmd success.\n");
4681
developera1255e42023-05-13 17:45:02 +08004682 snprintf(pwr_file, sizeof(pwr_file), "%s%d.txt", POWER_PERCENTAGE, radioIndex);
4683 f = fopen(pwr_file, "w");
4684 if (f == NULL) {
4685 fprintf(stderr, "%s: fopen failed\n", __func__);
4686 return RETURN_ERR;
4687 }
4688 fprintf(f, "%d", TransmitPower);
4689 fclose(f);
4690/* 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 +08004691 _syscmd(cmd, buf, sizeof(buf));
4692 maximum_tx = strtol(buf, NULL, 10);
4693
4694 // Get the Tx power supported list and check that is the input in the list
4695 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
4696 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
4697 support = strtok(buf, ",");
4698 while(true)
4699 {
4700 if(support == NULL) { // input not in the list
4701 wifi_dbg_printf("Input value is invalid.\n");
4702 return RETURN_ERR;
4703 }
4704 if (strncmp(txpower_str, support, strlen(support)) == 0) {
4705 break;
4706 }
4707 support = strtok(NULL, ",");
4708 }
4709 txpower = TransmitPower*maximum_tx/100;
4710 phyId = radio_index_to_phy(radioIndex);
4711 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", phyId, txpower);
4712 _syscmd(cmd, buf, sizeof(buf));
4713 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera1255e42023-05-13 17:45:02 +08004714*/
4715 return RETURN_OK;
developerfead3972023-05-25 20:15:02 +08004716err:
4717 mtk_nl80211_deint(&unl_ins);
4718 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
4719 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08004720}
4721
4722//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
4723INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
4724{
developer69b61b02023-03-07 17:17:44 +08004725 if (NULL == Supported)
developer72fb0bb2023-01-11 09:46:29 +08004726 return RETURN_ERR;
4727 *Supported = TRUE;
4728
4729 return RETURN_OK;
4730}
4731
4732//Get 80211h feature enable
4733INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
4734{
4735 char buf[64]={'\0'};
4736 char config_file[64] = {'\0'};
4737
4738 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4739 if(enable == NULL)
4740 return RETURN_ERR;
4741
4742 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
developerd1824452023-05-18 12:30:04 +08004743 /* wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf)); */
4744 wifi_datfileRead(config_file, "IEEE80211H", buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08004745
4746 if (strncmp(buf, "1", 1) == 0)
4747 *enable = TRUE;
4748 else
4749 *enable = FALSE;
4750
4751 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4752 return RETURN_OK;
4753}
4754
4755//Set 80211h feature enable
4756INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
4757{
4758 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4759 struct params params={'\0'};
developerd1824452023-05-18 12:30:04 +08004760 struct params dat={0};
developer72fb0bb2023-01-11 09:46:29 +08004761 char config_file[MAX_BUF_SIZE] = {0};
developerd1824452023-05-18 12:30:04 +08004762 char config_dat_file[MAX_BUF_SIZE] = {0};
4763 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08004764
4765 params.name = "ieee80211h";
4766
4767 if (enable) {
4768 params.value = "1";
4769 } else {
4770 params.value = "0";
4771 }
4772
developerd1824452023-05-18 12:30:04 +08004773 dat.name = "IEEE80211H";
4774 dat.value = params.value;
4775
4776 band = wifi_index_to_band(radioIndex);
4777 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4778 snprintf(config_dat_file, sizeof(config_dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
developer69b61b02023-03-07 17:17:44 +08004779
developerd1824452023-05-18 12:30:04 +08004780 wifi_hostapdWrite(config_file, &params, 1);
4781 wifi_datfileWrite(config_dat_file, &dat, 1);
developer72fb0bb2023-01-11 09:46:29 +08004782 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
4783 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4784 return RETURN_OK;
4785}
4786
4787//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.
4788INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
4789{
4790 if (NULL == output)
4791 return RETURN_ERR;
4792 *output=100;
4793
4794 return RETURN_OK;
4795}
4796
4797//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.
4798INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
4799{
4800 if (NULL == output)
4801 return RETURN_ERR;
4802 *output = -99;
4803
4804 return RETURN_OK;
4805}
4806
4807INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
4808{
4809 return RETURN_ERR;
4810}
4811
4812
4813//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
4814INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
4815{
4816 char interface_name[16] = {0};
4817 char cmd[MAX_BUF_SIZE]={'\0'};
4818 char buf[MAX_CMD_SIZE]={'\0'};
4819
4820 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4821 if(output == NULL)
4822 return RETURN_ERR;
4823
4824 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4825 return RETURN_ERR;
4826 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", interface_name);
4827 _syscmd(cmd, buf, sizeof(buf));
4828 *output = atoi(buf);
4829
4830 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4831 return RETURN_OK;
4832}
developer69b61b02023-03-07 17:17:44 +08004833
developer72fb0bb2023-01-11 09:46:29 +08004834INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
4835{
4836 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4837 struct params params={'\0'};
4838 char buf[MAX_BUF_SIZE] = {'\0'};
4839 char config_file[MAX_BUF_SIZE] = {'\0'};
4840
4841 if (BeaconPeriod < 15 || BeaconPeriod > 65535)
4842 return RETURN_ERR;
4843
4844 params.name = "beacon_int";
4845 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
4846 params.value = buf;
4847
4848 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
4849 wifi_hostapdWrite(config_file, &params, 1);
developer69b61b02023-03-07 17:17:44 +08004850
developer72fb0bb2023-01-11 09:46:29 +08004851 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
4852 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4853 return RETURN_OK;
4854}
4855
4856//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.
4857INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
4858{
4859 //TODO: need to revisit below implementation
4860 char *temp;
4861 char temp_output[128] = {0};
4862 char temp_TransmitRates[64] = {0};
4863 char config_file[64] = {0};
4864
4865 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4866 if (NULL == output)
4867 return RETURN_ERR;
4868 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
4869 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
developer69b61b02023-03-07 17:17:44 +08004870
developer72fb0bb2023-01-11 09:46:29 +08004871 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
4872 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
4873 } else {
4874 temp = strtok(temp_TransmitRates," ");
4875 while(temp!=NULL)
4876 {
4877 // Convert 100 kbps to Mbps
4878 temp[strlen(temp)-1]=0;
4879 if((temp[0]=='5') && (temp[1]=='\0'))
4880 {
4881 temp="5.5";
4882 }
4883 strcat(temp_output,temp);
4884 temp = strtok(NULL," ");
4885 if(temp!=NULL)
4886 {
4887 strcat(temp_output,",");
4888 }
4889 }
4890 strcpy(output,temp_output);
4891 }
4892 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4893 return RETURN_OK;
4894}
4895
4896INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
4897{
4898 char *temp;
4899 char temp1[128];
4900 char temp_output[128];
4901 char temp_TransmitRates[128];
4902 char set[128];
4903 char sub_set[128];
4904 int set_count=0,subset_count=0;
4905 int set_index=0,subset_index=0;
4906 char *token;
4907 int flag=0, i=0;
4908 struct params params={'\0'};
4909 char config_file[MAX_BUF_SIZE] = {0};
4910 wifi_band band = wifi_index_to_band(radioIndex);
4911
4912 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4913 if(NULL == TransmitRates)
4914 return RETURN_ERR;
4915 strcpy(sub_set,TransmitRates);
4916
4917 //Allow only supported Data transmit rate to be set
4918 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
4919 token = strtok(sub_set,",");
4920 while( token != NULL ) /* split the basic rate to be set, by comma */
4921 {
4922 sub_set[subset_count]=atoi(token);
4923 subset_count++;
4924 token=strtok(NULL,",");
4925 }
4926 token=strtok(set,",");
4927 while(token!=NULL) /* split the supported rate by comma */
4928 {
4929 set[set_count]=atoi(token);
4930 set_count++;
4931 token=strtok(NULL,",");
4932 }
4933 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
4934 {
4935 for(set_index=0;set_index < set_count;set_index++)
4936 {
4937 flag=0;
4938 if(sub_set[subset_index]==set[set_index])
4939 break;
4940 else
4941 flag=1; /* No match found */
4942 }
4943 if(flag==1)
4944 return RETURN_ERR; //If value not found return Error
4945 }
4946 strcpy(temp_TransmitRates,TransmitRates);
4947
4948 for(i=0;i<strlen(temp_TransmitRates);i++)
4949 {
4950 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
4951 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
4952 {
4953 continue;
4954 }
4955 else
4956 {
4957 return RETURN_ERR;
4958 }
4959 }
4960 strcpy(temp_output,"");
4961 temp = strtok(temp_TransmitRates,",");
4962 while(temp!=NULL)
4963 {
4964 strcpy(temp1,temp);
4965 if(band == band_5)
4966 {
4967 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
4968 {
4969 return RETURN_ERR;
4970 }
4971 }
4972
4973 if(strcmp(temp,"5.5")==0)
4974 {
4975 strcpy(temp1,"55");
4976 }
4977 else
4978 {
4979 strcat(temp1,"0");
4980 }
4981 strcat(temp_output,temp1);
4982 temp = strtok(NULL,",");
4983 if(temp!=NULL)
4984 {
4985 strcat(temp_output," ");
4986 }
4987 }
4988 strcpy(TransmitRates,temp_output);
4989
4990 params.name= "basic_rates";
4991 params.value =TransmitRates;
4992
4993 wifi_dbg_printf("\n%s:",__func__);
4994 wifi_dbg_printf("\nparams.value=%s\n",params.value);
4995 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
4996 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
4997 wifi_hostapdWrite(config_file,&params,1);
4998 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4999 return RETURN_OK;
5000}
5001
5002//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
5003INT wifi_GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
5004{
5005 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5006 FILE *fp = NULL;
5007 char path[256] = {0}, output_string[256] = {0};
5008 int count = 0;
5009 char *interface = NULL;
5010
5011 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
5012 if (fp == NULL)
5013 {
5014 printf("Failed to run command in Function %s\n", __FUNCTION__);
5015 return RETURN_ERR;
5016 }
5017 if (fgets(path, sizeof(path) - 1, fp) != NULL)
5018 {
5019 interface = strchr(path, '=');
5020
5021 if (interface != NULL)
5022 {
5023 strcpy(output_string, interface + 1);
5024 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
5025 interface_name[count] = output_string[count];
5026
5027 interface_name[count] = '\0';
5028 }
5029 }
5030 pclose(fp);
5031 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5032 return RETURN_OK;
5033}
5034
5035INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
5036{
5037 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5038 output_struct->radio_BytesSent = 0;
5039 output_struct->radio_BytesReceived = 0;
5040 output_struct->radio_PacketsSent = 0;
5041 output_struct->radio_PacketsReceived = 0;
5042 output_struct->radio_ErrorsSent = 0;
5043 output_struct->radio_ErrorsReceived = 0;
5044 output_struct->radio_DiscardPacketsSent = 0;
5045 output_struct->radio_DiscardPacketsReceived = 0;
5046 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5047 return RETURN_OK;
5048}
5049
5050
5051INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
5052{
5053 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5054 CHAR buf[MAX_CMD_SIZE] = {0};
5055 CHAR Value[MAX_BUF_SIZE] = {0};
5056 FILE *fp = NULL;
5057
5058 if (ifname == NULL || strlen(ifname) <= 1)
5059 return RETURN_OK;
5060
5061 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
5062 system(buf);
5063
5064 fp = fopen("/tmp/Radio_Stats.txt", "r");
5065 if(fp == NULL)
5066 {
5067 printf("/tmp/Radio_Stats.txt not exists \n");
5068 return RETURN_ERR;
5069 }
5070 fclose(fp);
5071
5072 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
5073 File_Reading(buf, Value);
5074 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
5075
5076 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
5077 File_Reading(buf, Value);
5078 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
5079
5080 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
5081 File_Reading(buf, Value);
5082 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
5083
5084 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
5085 File_Reading(buf, Value);
5086 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
5087
5088 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
5089 File_Reading(buf, Value);
5090 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
5091
5092 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
5093 File_Reading(buf, Value);
5094 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
5095
5096 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
5097 File_Reading(buf, Value);
5098 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
5099
5100 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
5101 File_Reading(buf, Value);
5102 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
5103
5104 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5105 return RETURN_OK;
5106}
5107
5108INT GetIfacestatus(CHAR *interface_name, CHAR *status)
5109{
developer7e4a2a62023-04-06 19:56:03 +08005110 CHAR buf[MAX_CMD_SIZE] = {0};
5111 INT count = 0;
developer72fb0bb2023-01-11 09:46:29 +08005112
developer7e4a2a62023-04-06 19:56:03 +08005113 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5114
5115 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL) {
5116 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
5117 File_Reading(buf, status);
5118 }
5119
5120 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5121 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08005122}
5123
5124//Get detail radio traffic static info
5125INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
5126{
5127
developer69b61b02023-03-07 17:17:44 +08005128#if 0
5129 //ifconfig radio_x
developer72fb0bb2023-01-11 09:46:29 +08005130 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
5131 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
5132 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
5133 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
5134
5135 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
5136 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
5137 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.
5138 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.
5139
developer69b61b02023-03-07 17:17:44 +08005140 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 +08005141 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].
5142 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
5143 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.
5144 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
5145 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
5146 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
5147 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
5148 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
5149
5150 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
5151 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
5152 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
5153 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.
5154
5155 return RETURN_OK;
5156#endif
5157
5158 CHAR interface_name[64] = {0};
5159 BOOL iface_status = FALSE;
5160 wifi_radioTrafficStats2_t radioTrafficStats = {0};
5161
5162 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5163 if (NULL == output_struct)
5164 return RETURN_ERR;
5165
5166 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
5167 return RETURN_ERR;
5168
5169 wifi_getApEnable(radioIndex, &iface_status);
5170
5171 if (iface_status == TRUE)
5172 wifi_halGetIfStats(interface_name, &radioTrafficStats);
5173 else
5174 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
5175
5176 output_struct->radio_BytesSent = radioTrafficStats.radio_BytesSent;
5177 output_struct->radio_BytesReceived = radioTrafficStats.radio_BytesReceived;
5178 output_struct->radio_PacketsSent = radioTrafficStats.radio_PacketsSent;
5179 output_struct->radio_PacketsReceived = radioTrafficStats.radio_PacketsReceived;
5180 output_struct->radio_ErrorsSent = radioTrafficStats.radio_ErrorsSent;
5181 output_struct->radio_ErrorsReceived = radioTrafficStats.radio_ErrorsReceived;
5182 output_struct->radio_DiscardPacketsSent = radioTrafficStats.radio_DiscardPacketsSent;
5183 output_struct->radio_DiscardPacketsReceived = radioTrafficStats.radio_DiscardPacketsReceived;
5184
5185 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
5186 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].
5187 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
5188 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.
5189 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
5190 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
5191 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
5192 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
5193 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
5194
5195 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
5196 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
5197 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
5198 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.
5199
5200 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5201
5202 return RETURN_OK;
5203}
5204
5205//Set radio traffic static Measureing rules
5206INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
5207{
5208 //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
5209 // Else, save the MeasuringRate and MeasuringInterval for future usage
5210
5211 return RETURN_OK;
5212}
5213
5214//To start or stop RadioTrafficStats
5215INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
5216{
5217 //zqiu: If the RadioTrafficStats process running
5218 // if(enable)
5219 // return RETURN_OK.
5220 // else
5221 // Stop RadioTrafficStats process
developer69b61b02023-03-07 17:17:44 +08005222 // Else
developer72fb0bb2023-01-11 09:46:29 +08005223 // if(enable)
5224 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
5225 // else
5226 // return RETURN_OK.
5227
5228 return RETURN_OK;
5229}
5230
5231//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
5232INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
5233{
5234 //zqiu: Please ignor signalIndex.
developer69b61b02023-03-07 17:17:44 +08005235 if (NULL == SignalLevel)
developer72fb0bb2023-01-11 09:46:29 +08005236 return RETURN_ERR;
developer47cc27a2023-05-17 23:09:58 +08005237
developer72fb0bb2023-01-11 09:46:29 +08005238 *SignalLevel=(radioIndex==0)?-19:-19;
5239
5240 return RETURN_OK;
5241}
5242
5243//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
5244INT wifi_applyRadioSettings(INT radioIndex)
5245{
5246 return RETURN_OK;
5247}
5248
5249//Get the radio index assocated with this SSID entry
5250INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
5251{
5252 if(NULL == radioIndex)
5253 return RETURN_ERR;
5254 int max_radio_num = 0;
5255 wifi_getMaxRadioNumber(&max_radio_num);
5256 *radioIndex = ssidIndex%max_radio_num;
5257 return RETURN_OK;
5258}
5259
5260//Device.WiFi.SSID.{i}.Enable
5261//Get SSID enable configuration parameters (not the SSID enable status)
5262INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
5263{
developer69b61b02023-03-07 17:17:44 +08005264 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08005265 return RETURN_ERR;
5266
5267 return wifi_getApEnable(ssidIndex, output_bool);
5268}
5269
5270//Device.WiFi.SSID.{i}.Enable
5271//Set SSID enable configuration parameters
5272INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
5273{
5274 return wifi_setApEnable(ssidIndex, enable);
5275}
5276
5277//Device.WiFi.SSID.{i}.Status
5278//Get the SSID enable status
5279INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
5280{
5281 char cmd[MAX_CMD_SIZE]={0};
5282 char buf[MAX_BUF_SIZE]={0};
5283 BOOL output_bool;
5284
5285 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5286 if (NULL == output_string)
5287 return RETURN_ERR;
developer69b61b02023-03-07 17:17:44 +08005288
developer72fb0bb2023-01-11 09:46:29 +08005289 wifi_getApEnable(ssidIndex,&output_bool);
5290 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
5291
5292 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5293 return RETURN_OK;
5294}
5295
5296// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
5297INT wifi_getSSIDName(INT apIndex, CHAR *output)
5298{
5299 char config_file[MAX_BUF_SIZE] = {0};
5300
developer69b61b02023-03-07 17:17:44 +08005301 if (NULL == output)
developer72fb0bb2023-01-11 09:46:29 +08005302 return RETURN_ERR;
5303
5304 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5305 wifi_hostapdRead(config_file,"ssid",output,32);
5306
5307 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
5308 return RETURN_OK;
5309}
5310
developer69b61b02023-03-07 17:17:44 +08005311// Set a max 32 byte string and sets an internal variable to the SSID name
developer72fb0bb2023-01-11 09:46:29 +08005312INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
5313{
5314 char str[MAX_BUF_SIZE]={'\0'};
5315 char cmd[MAX_CMD_SIZE]={'\0'};
5316 struct params params;
5317 char config_file[MAX_BUF_SIZE] = {0};
5318
5319 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5320 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
5321 return RETURN_ERR;
5322
5323 params.name = "ssid";
5324 params.value = ssid_string;
5325 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5326 wifi_hostapdWrite(config_file, &params, 1);
5327 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5328 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5329
5330 return RETURN_OK;
5331}
5332
5333//Get the BSSID
5334INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
5335{
developer7e4a2a62023-04-06 19:56:03 +08005336 char cmd[MAX_CMD_SIZE] = {0};
5337 char inf_name[IF_NAME_SIZE] = {0};
5338 char conf_file[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08005339
developer7e4a2a62023-04-06 19:56:03 +08005340 if (!output_string)
developer72fb0bb2023-01-11 09:46:29 +08005341 return RETURN_ERR;
5342
developer47cc27a2023-05-17 23:09:58 +08005343 if (wifi_GetInterfaceName(ssidIndex, inf_name) != RETURN_OK)
5344 return RETURN_ERR;
developer7e4a2a62023-04-06 19:56:03 +08005345
developer5b2f10c2023-05-25 17:02:21 +08005346 if (ssidIndex < 0 || ssidIndex > MAX_APS) {
5347 wifi_debug(DEBUG_ERROR, "innvalide ssidIdex(%d)\n", ssidIndex);
5348 strncpy(output_string, "\0", 1);
5349 return RETURN_ERR;
5350 }
5351 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep bssid | cut -d '=' -f2 | tr -d '\\n'", inf_name);
5352 _syscmd(cmd, output_string, 64);
developer7e4a2a62023-04-06 19:56:03 +08005353
developer5b2f10c2023-05-25 17:02:21 +08005354 /* if hostapd does not control interface even if this interface has been brought up,
5355 * try to get its mac address by iw command.
5356 */
5357 if(strlen(output_string) == 0) {
5358 memset(cmd, 0, sizeof(cmd));
5359 snprintf(cmd, sizeof(cmd), "iw dev %s info | grep \"addr\" | awk \'{print $2}\'", inf_name);
5360 _syscmd(cmd, output_string, 64);
5361 }
developer72fb0bb2023-01-11 09:46:29 +08005362
developer5b2f10c2023-05-25 17:02:21 +08005363 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08005364}
5365
5366//Get the MAC address associated with this Wifi SSID
5367INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
5368{
5369 wifi_getBaseBSSID(ssidIndex,output_string);
5370 return RETURN_OK;
5371}
5372
5373//Get the basic SSID traffic static info
5374//Apply SSID and AP (in the case of Acess Point devices) to the hardware
5375//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
5376INT wifi_applySSIDSettings(INT ssidIndex)
5377{
5378 char interface_name[16] = {0};
5379 BOOL status = false;
5380 char cmd[MAX_CMD_SIZE] = {0};
5381 char buf[MAX_CMD_SIZE] = {0};
5382 int apIndex, ret;
5383 int max_radio_num = 0;
5384 int radioIndex = 0;
5385
5386 wifi_getMaxRadioNumber(&max_radio_num);
5387
5388 radioIndex = ssidIndex % max_radio_num;
5389
5390 wifi_getApEnable(ssidIndex,&status);
5391 // Do not apply when ssid index is disabled
5392 if (status == false)
5393 return RETURN_OK;
5394
5395 /* Doing full remove and add for ssid Index
5396 * Not all hostapd options are supported with reload
5397 * for example macaddr_acl
5398 */
5399 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
5400 return RETURN_ERR;
5401
5402 ret = wifi_setApEnable(ssidIndex,true);
5403
5404 /* Workaround for hostapd issue with multiple bss definitions
5405 * when first created interface will be removed
5406 * then all vaps other vaps on same phy are removed
5407 * after calling setApEnable to false readd all enabled vaps */
5408 for(int i=0; i < MAX_APS/max_radio_num; i++) {
5409 apIndex = max_radio_num*i+radioIndex;
5410 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5411 return RETURN_ERR;
5412 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
5413 _syscmd(cmd, buf, sizeof(buf));
5414 if(*buf == '1')
5415 wifi_setApEnable(apIndex, true);
5416 }
5417
5418 return ret;
5419}
5420
5421struct channels_noise {
5422 int channel;
5423 int noise;
5424};
5425
5426// Return noise array for each channel
5427int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
5428{
5429 char interface_name[16] = {0};
5430 FILE *f = NULL;
5431 char cmd[128] = {0};
5432 char line[256] = {0};
5433 size_t len = 0;
5434 ssize_t read = 0;
5435 int tmp = 0, arr_index = -1;
5436
5437 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
5438 return RETURN_ERR;
5439 sprintf(cmd, "iw dev %s survey dump | grep 'frequency\\|noise' | awk '{print $2}'", interface_name);
5440
5441 if ((f = popen(cmd, "r")) == NULL) {
5442 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
5443 return RETURN_ERR;
5444 }
developer69b61b02023-03-07 17:17:44 +08005445
developer72fb0bb2023-01-11 09:46:29 +08005446 while(fgets(line, sizeof(line), f) != NULL) {
5447 if(arr_index < channels_num){
5448 sscanf(line, "%d", &tmp);
5449 if (tmp > 0) { // channel frequency, the first line must be frequency
5450 arr_index++;
5451 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
5452 } else { // noise
5453 channels_noise_arr[arr_index].noise = tmp;
5454 }
5455 }else{
5456 break;
5457 }
5458 }
5459 pclose(f);
5460 return RETURN_OK;
5461}
5462
5463//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
5464//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
developer69b61b02023-03-07 17:17:44 +08005465INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
developer72fb0bb2023-01-11 09:46:29 +08005466{
5467 int index = -1;
5468 wifi_neighbor_ap2_t *scan_array = NULL;
5469 char cmd[256]={0};
5470 char buf[128]={0};
5471 char file_name[32] = {0};
5472 char filter_SSID[32] = {0};
5473 char line[256] = {0};
5474 char interface_name[16] = {0};
5475 char *ret = NULL;
5476 int freq=0;
5477 FILE *f = NULL;
5478 size_t len=0;
5479 int channels_num = 0;
5480 int vht_channel_width = 0;
5481 int get_noise_ret = RETURN_ERR;
5482 bool filter_enable = false;
5483 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
5484 int phyId = 0;
5485
5486 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
5487
5488 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
5489 return RETURN_ERR;
5490
5491 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
5492 f = fopen(file_name, "r");
5493 if (f != NULL) {
5494 fgets(filter_SSID, sizeof(file_name), f);
5495 if (strlen(filter_SSID) != 0)
5496 filter_enable = true;
5497 fclose(f);
5498 }
5499
5500 phyId = radio_index_to_phy(radioIndex);
5501 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
5502 _syscmd(cmd, buf, sizeof(buf));
5503 channels_num = strtol(buf, NULL, 10);
5504
5505
5506
5507 sprintf(cmd, "iw dev %s scan | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
5508 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", interface_name, interface_name);
5509 fprintf(stderr, "cmd: %s\n", cmd);
5510 if ((f = popen(cmd, "r")) == NULL) {
5511 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
5512 return RETURN_ERR;
5513 }
developer69b61b02023-03-07 17:17:44 +08005514
developer72fb0bb2023-01-11 09:46:29 +08005515 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
5516 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
developer69b61b02023-03-07 17:17:44 +08005517
developer72fb0bb2023-01-11 09:46:29 +08005518 ret = fgets(line, sizeof(line), f);
5519 while (ret != NULL) {
5520 if(strstr(line, "BSS") != NULL) { // new neighbor info
developer69b61b02023-03-07 17:17:44 +08005521 // 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 +08005522 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
5523 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
5524
5525 if (!filter_BSS) {
5526 index++;
5527 wifi_neighbor_ap2_t *tmp;
5528 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
5529 if (tmp == NULL) { // no more memory to use
5530 index--;
5531 wifi_dbg_printf("%s: realloc failed\n", __func__);
5532 break;
5533 }
5534 scan_array = tmp;
5535 }
5536 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
5537
5538 filter_BSS = false;
5539 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
5540 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
5541 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
5542 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
5543 } else if (strstr(line, "freq") != NULL) {
5544 sscanf(line," freq: %d", &freq);
5545 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
5546
5547 if (freq >= 2412 && freq <= 2484) {
5548 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
5549 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
5550 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
5551 }
5552 else if (freq >= 5160 && freq <= 5805) {
5553 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
5554 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
5555 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
5556 }
5557
5558 scan_array[index].ap_Noise = 0;
5559 if (get_noise_ret == RETURN_OK) {
5560 for (int i = 0; i < channels_num; i++) {
5561 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
5562 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
5563 break;
5564 }
5565 }
5566 }
5567 } else if (strstr(line, "beacon interval") != NULL) {
5568 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
5569 } else if (strstr(line, "signal") != NULL) {
5570 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
5571 } else if (strstr(line,"SSID") != NULL) {
5572 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
5573 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
5574 filter_BSS = true;
5575 }
5576 } else if (strstr(line, "Supported rates") != NULL) {
5577 char SRate[80] = {0}, *tmp = NULL;
5578 memset(buf, 0, sizeof(buf));
5579 strcpy(SRate, line);
5580 tmp = strtok(SRate, ":");
5581 tmp = strtok(NULL, ":");
5582 strcpy(buf, tmp);
5583 memset(SRate, 0, sizeof(SRate));
5584
5585 tmp = strtok(buf, " \n");
5586 while (tmp != NULL) {
5587 strcat(SRate, tmp);
5588 if (SRate[strlen(SRate) - 1] == '*') {
5589 SRate[strlen(SRate) - 1] = '\0';
5590 }
5591 strcat(SRate, ",");
5592
5593 tmp = strtok(NULL, " \n");
5594 }
5595 SRate[strlen(SRate) - 1] = '\0';
5596 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
5597 } else if (strstr(line, "DTIM") != NULL) {
5598 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
5599 } else if (strstr(line, "VHT capabilities") != NULL) {
5600 strcat(scan_array[index].ap_SupportedStandards, ",ac");
5601 strcpy(scan_array[index].ap_OperatingStandards, "ac");
5602 } else if (strstr(line, "HT capabilities") != NULL) {
5603 strcat(scan_array[index].ap_SupportedStandards, ",n");
5604 strcpy(scan_array[index].ap_OperatingStandards, "n");
5605 } else if (strstr(line, "VHT operation") != NULL) {
5606 ret = fgets(line, sizeof(line), f);
5607 sscanf(line," * channel width: %d", &vht_channel_width);
5608 if(vht_channel_width == 1) {
5609 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
5610 } else {
5611 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
5612 }
5613 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
5614 continue;
5615 } else if (strstr(line, "HT operation") != NULL) {
5616 ret = fgets(line, sizeof(line), f);
5617 sscanf(line," * secondary channel offset: %s", &buf);
5618 if (!strcmp(buf, "above")) {
5619 //40Mhz +
5620 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
5621 }
5622 else if (!strcmp(buf, "below")) {
5623 //40Mhz -
5624 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
5625 } else {
5626 //20Mhz
5627 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
5628 }
5629 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
5630 continue;
5631 } else if (strstr(line, "HE capabilities") != NULL) {
5632 strcat(scan_array[index].ap_SupportedStandards, ",ax");
5633 strcpy(scan_array[index].ap_OperatingStandards, "ax");
5634 ret = fgets(line, sizeof(line), f);
5635 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
5636 if (strstr(line, "HE40/2.4GHz") != NULL)
5637 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
5638 else
5639 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
5640 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
5641 if (strstr(line, "HE80/5GHz") != NULL) {
5642 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
5643 ret = fgets(line, sizeof(line), f);
5644 } else
5645 continue;
5646 if (strstr(line, "HE160/5GHz") != NULL)
5647 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
5648 }
5649 continue;
5650 } else if (strstr(line, "WPA") != NULL) {
5651 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
5652 } else if (strstr(line, "RSN") != NULL) {
5653 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
5654 } else if (strstr(line, "Group cipher") != NULL) {
5655 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
5656 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
5657 strcpy(scan_array[index].ap_EncryptionMode, "AES");
5658 }
5659 }
5660 ret = fgets(line, sizeof(line), f);
5661 }
5662
5663 if (!filter_BSS) {
5664 *output_array_size = index + 1;
5665 } else {
5666 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
5667 *output_array_size = index;
5668 }
5669 *neighbor_ap_array = scan_array;
5670 pclose(f);
5671 free(channels_noise_arr);
5672 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5673 return RETURN_OK;
5674}
5675
5676//>> Deprecated: used for old RDKB code.
5677INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
5678{
5679 INT status = RETURN_ERR;
5680
5681 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5682 output_struct->wifi_PLCPErrorCount = 0;
5683 output_struct->wifi_FCSErrorCount = 0;
5684 output_struct->wifi_InvalidMACCount = 0;
5685 output_struct->wifi_PacketsOtherReceived = 0;
5686 output_struct->wifi_Noise = 0;
5687 status = RETURN_OK;
5688 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5689 return status;
5690}
5691
5692INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
5693{
5694 char interface_name[16] = {0};
5695 char cmd[128] = {0};
5696 char buf[1280] = {0};
5697 char *pos = NULL;
5698
5699 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5700 if (NULL == output_struct)
5701 return RETURN_ERR;
5702
5703 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5704 return RETURN_ERR;
5705
5706 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
5707
5708 snprintf(cmd, sizeof(cmd), "ifconfig %s", interface_name);
5709 _syscmd(cmd, buf, sizeof(buf));
5710
5711 pos = buf;
5712 if ((pos = strstr(pos, "RX packets:")) == NULL)
5713 return RETURN_ERR;
5714 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
5715
5716 if ((pos = strstr(pos, "TX packets:")) == NULL)
5717 return RETURN_ERR;
5718 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
5719
5720 if ((pos = strstr(pos, "RX bytes:")) == NULL)
5721 return RETURN_ERR;
5722 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
5723
5724 if ((pos = strstr(pos, "TX bytes:")) == NULL)
5725 return RETURN_ERR;
5726 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
5727
5728 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l | tr -d '\n'", interface_name);
5729 _syscmd(cmd, buf, sizeof(buf));
5730 sscanf(buf, "%lu", &output_struct->wifi_Associations);
5731
5732#if 0
5733 //TODO: need to revisit below implementation
5734 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5735 char interface_name[MAX_BUF_SIZE] = {0};
5736 char interface_status[MAX_BUF_SIZE] = {0};
5737 char Value[MAX_BUF_SIZE] = {0};
5738 char buf[MAX_CMD_SIZE] = {0};
5739 char cmd[MAX_CMD_SIZE] = {0};
5740 FILE *fp = NULL;
5741
5742 if (NULL == output_struct) {
5743 return RETURN_ERR;
5744 }
5745
5746 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
5747
5748 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
5749 {
5750 if(apIndex == 0) //private_wifi for 2.4G
5751 {
5752 wifi_GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
5753 }
5754 else if(apIndex == 1) //private_wifi for 5G
5755 {
5756 wifi_GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
5757 }
5758 else if(apIndex == 4) //public_wifi for 2.4G
5759 {
5760 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
5761 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
5762 {
5763 return RETURN_ERR;
5764 }
5765 if(buf[0] == '#')//tp-link
5766 wifi_GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
5767 else//tenda
5768 wifi_GetInterfaceName_virtualInterfaceName_2G(interface_name);
5769 }
5770 else if(apIndex == 5) //public_wifi for 5G
5771 {
5772 wifi_GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
5773 }
5774
5775 GetIfacestatus(interface_name, interface_status);
5776
5777 if(0 != strcmp(interface_status, "1"))
5778 return RETURN_ERR;
5779
5780 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
5781 system(cmd);
5782
5783 fp = fopen("/tmp/SSID_Stats.txt", "r");
5784 if(fp == NULL)
5785 {
5786 printf("/tmp/SSID_Stats.txt not exists \n");
5787 return RETURN_ERR;
5788 }
5789 fclose(fp);
5790
5791 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
5792 File_Reading(buf, Value);
5793 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
5794
5795 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
5796 File_Reading(buf, Value);
5797 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
5798
5799 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
5800 File_Reading(buf, Value);
5801 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
5802
5803 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
5804 File_Reading(buf, Value);
5805 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
5806
5807 /* There is no specific parameter from caller to associate the value wifi_Associations */
5808 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
5809 //_syscmd(cmd, buf, sizeof(buf));
5810 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
5811 }
5812#endif
5813 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5814 return RETURN_OK;
5815}
5816
5817INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
5818{
5819 char interface_name[MAX_BUF_SIZE] = {0};
5820 char interface_status[MAX_BUF_SIZE] = {0};
5821 char Value[MAX_BUF_SIZE] = {0};
5822 char buf[MAX_CMD_SIZE] = {0};
5823 char cmd[MAX_CMD_SIZE] = {0};
5824 FILE *fp = NULL;
5825
5826 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5827 if (NULL == output_struct)
5828 return RETURN_ERR;
5829
5830 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
5831
5832 if (wifi_GetInterfaceName(apIndex,interface_name) != RETURN_OK)
5833 return RETURN_ERR;
5834 GetIfacestatus(interface_name, interface_status);
5835
5836 if(0 != strcmp(interface_status, "1"))
5837 return RETURN_ERR;
5838
5839 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
5840 system(cmd);
5841
5842 fp = fopen("/tmp/SSID_Stats.txt", "r");
5843 if(fp == NULL)
5844 {
5845 printf("/tmp/SSID_Stats.txt not exists \n");
5846 return RETURN_ERR;
5847 }
5848 fclose(fp);
5849
5850 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
5851 File_Reading(buf, Value);
5852 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
5853
5854 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
5855 File_Reading(buf, Value);
5856 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
5857
5858 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
5859 File_Reading(buf, Value);
5860 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
5861
5862 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
5863 File_Reading(buf, Value);
5864 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
5865
5866 output_struct->wifi_UnicastPacketsSent = 0;
5867 output_struct->wifi_UnicastPacketsReceived = 0;
5868 output_struct->wifi_MulticastPacketsSent = 0;
5869 output_struct->wifi_MulticastPacketsReceived = 0;
5870 output_struct->wifi_BroadcastPacketsSent = 0;
5871 output_struct->wifi_BroadcastPacketsRecevied = 0;
5872 output_struct->wifi_UnknownPacketsReceived = 0;
5873
5874 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5875 return RETURN_OK;
5876}
5877
5878INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
5879{
5880 INT status = RETURN_ERR;
5881
5882 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5883 //Below values should get updated from hal
5884 output_struct->wifi_RetransCount=0;
5885 output_struct->wifi_FailedRetransCount=0;
5886 output_struct->wifi_RetryCount=0;
5887 output_struct->wifi_MultipleRetryCount=0;
5888 output_struct->wifi_ACKFailureCount=0;
5889 output_struct->wifi_AggregatedPacketCount=0;
5890
5891 status = RETURN_OK;
5892 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5893
5894 return status;
5895}
5896
5897INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
5898{
5899 INT status = RETURN_ERR;
5900 UINT index;
5901 wifi_neighbor_ap_t *pt=NULL;
5902
5903 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5904 *output_array_size=2;
5905 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
5906 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
5907 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
5908 strcpy(pt->ap_Radio,"");
5909 strcpy(pt->ap_SSID,"");
5910 strcpy(pt->ap_BSSID,"");
5911 strcpy(pt->ap_Mode,"");
5912 pt->ap_Channel=1;
5913 pt->ap_SignalStrength=0;
5914 strcpy(pt->ap_SecurityModeEnabled,"");
5915 strcpy(pt->ap_EncryptionMode,"");
5916 strcpy(pt->ap_OperatingFrequencyBand,"");
5917 strcpy(pt->ap_SupportedStandards,"");
5918 strcpy(pt->ap_OperatingStandards,"");
5919 strcpy(pt->ap_OperatingChannelBandwidth,"");
5920 pt->ap_BeaconPeriod=1;
5921 pt->ap_Noise=0;
5922 strcpy(pt->ap_BasicDataTransferRates,"");
5923 strcpy(pt->ap_SupportedDataTransferRates,"");
5924 pt->ap_DTIMPeriod=1;
5925 pt->ap_ChannelUtilization = 1;
5926 }
5927
5928 status = RETURN_OK;
5929 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5930
5931 return status;
5932}
5933
5934//----------------- AP HAL -------------------------------
5935
5936//>> Deprecated: used for old RDKB code.
5937INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
5938{
5939 if (NULL == output_ulong || NULL == output_struct)
5940 return RETURN_ERR;
5941 *output_ulong = 0;
5942 *output_struct = NULL;
5943 return RETURN_OK;
5944}
5945
5946#ifdef HAL_NETLINK_IMPL
5947static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
5948 struct nlattr *tb[NL80211_ATTR_MAX + 1];
5949 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
5950 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
5951 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
5952 char mac_addr[20];
5953 static int count=0;
5954 int rate=0;
5955
5956 wifi_device_info_t *out = (wifi_device_info_t*)arg;
5957
5958 nla_parse(tb,
5959 NL80211_ATTR_MAX,
5960 genlmsg_attrdata(gnlh, 0),
5961 genlmsg_attrlen(gnlh, 0),
5962 NULL);
5963
5964 if(!tb[NL80211_ATTR_STA_INFO]) {
5965 fprintf(stderr, "sta stats missing!\n");
5966 return NL_SKIP;
5967 }
5968
5969
5970 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
5971 fprintf(stderr, "failed to parse nested attributes!\n");
5972 return NL_SKIP;
5973 }
5974
5975 //devIndex starts from 1
5976 if( ++count == out->wifi_devIndex )
5977 {
5978 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
5979 //Getting the mac addrress
5980 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
5981
5982 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
5983 fprintf(stderr, "failed to parse nested rate attributes!");
5984 return NL_SKIP;
5985 }
5986
5987 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
5988 if(rinfo[NL80211_RATE_INFO_BITRATE])
5989 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
5990 out->wifi_devTxRate = rate/10;
5991 }
5992
5993 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
5994 fprintf(stderr, "failed to parse nested rate attributes!");
5995 return NL_SKIP;
5996 }
5997
5998 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
5999 if(rinfo[NL80211_RATE_INFO_BITRATE])
6000 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
6001 out->wifi_devRxRate = rate/10;
6002 }
6003 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
6004 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
6005
6006 out->wifi_devAssociatedDeviceAuthentiationState = 1;
6007 count = 0; //starts the count for next cycle
6008 return NL_STOP;
6009 }
6010
6011 return NL_SKIP;
6012
6013}
6014#endif
6015
6016INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
6017{
6018#ifdef HAL_NETLINK_IMPL
6019 Netlink nl = {0};
6020 char if_name[10] = {0};
6021 char interface_name[16] = {0};
6022
6023 wifi_device_info_t info = {0};
6024 info.wifi_devIndex = devIndex;
6025
6026 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6027 return RETURN_ERR;
6028
6029 snprintf(if_name,sizeof(if_name),"%s", interface_name);
6030
6031 nl.id = initSock80211(&nl);
6032
6033 if (nl.id < 0) {
6034 fprintf(stderr, "Error initializing netlink \n");
6035 return -1;
6036 }
6037
6038 struct nl_msg* msg = nlmsg_alloc();
6039
6040 if (!msg) {
6041 fprintf(stderr, "Failed to allocate netlink message.\n");
6042 nlfree(&nl);
6043 return -2;
6044 }
6045
6046 genlmsg_put(msg,
developer8dd72532023-05-17 19:58:35 +08006047 NL_AUTO_PID,
developer72fb0bb2023-01-11 09:46:29 +08006048 NL_AUTO_SEQ,
6049 nl.id,
6050 0,
6051 NLM_F_DUMP,
6052 NL80211_CMD_GET_STATION,
6053 0);
6054
6055 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
developer8dd72532023-05-17 19:58:35 +08006056 nl_send_auto_complete(nl.socket, msg);
developer72fb0bb2023-01-11 09:46:29 +08006057 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
6058 nl_recvmsgs(nl.socket, nl.cb);
6059 nlmsg_free(msg);
6060 nlfree(&nl);
6061
6062 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
6063 output_struct->wifi_devRxRate = info.wifi_devRxRate;
6064 output_struct->wifi_devTxRate = info.wifi_devTxRate;
6065 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
6066 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
6067 return RETURN_OK;
6068#else
6069 //iw utility to retrieve station information
6070#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
6071#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
6072#define MACFILE "/tmp/wifi_AssoMac.txt"
6073#define TXRATEFILE "/tmp/wifi_txrate.txt"
6074#define RXRATEFILE "/tmp/wifi_rxrate.txt"
6075 FILE *file = NULL;
6076 char if_name[10] = {'\0'};
6077 char pipeCmd[256] = {'\0'};
6078 char line[256] = {0};
6079 char interface_name[16] = {0};
6080 int count = 0, device = 0;
6081
6082 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6083 return RETURN_ERR;
6084
6085 snprintf(if_name,sizeof(if_name),"%s", interface_name);
6086
6087 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
6088 file = popen(pipeCmd, "r");
6089
6090 if(file == NULL)
6091 return RETURN_ERR; //popen failed
6092
6093 fgets(line, sizeof line, file);
6094 device = atoi(line);
6095 pclose(file);
6096
6097 if(device == 0)
6098 return RETURN_ERR; //No devices are connected
6099
6100 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
6101 system(pipeCmd);
6102
6103 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
6104
6105 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
6106
6107 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
6108
6109 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
6110
6111 //devIndex starts from 1, ++count
6112 if((file = fopen(SIGNALFILE, "r")) != NULL )
6113 {
6114 for(count =0;fgets(line, sizeof line, file) != NULL;)
6115 {
6116 if (++count == devIndex)
6117 {
6118 output_struct->wifi_devSignalStrength = atoi(line);
6119 break;
6120 }
6121 }
6122 fclose(file);
6123 }
6124 else
6125 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
6126
6127 if((file = fopen(MACFILE, "r")) != NULL )
6128 {
6129 for(count =0;fgets(line, sizeof line, file) != NULL;)
6130 {
6131 if (++count == devIndex)
6132 {
6133 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]);
6134 break;
6135 }
6136 }
6137 fclose(file);
6138 }
6139 else
6140 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
6141
6142 if((file = fopen(TXRATEFILE, "r")) != NULL )
6143 {
6144 for(count =0;fgets(line, sizeof line, file) != NULL;)
6145 {
6146 if (++count == devIndex)
6147 {
6148 output_struct->wifi_devTxRate = atoi(line);
6149 break;
6150 }
6151 }
6152 fclose(file);
6153 }
6154 else
6155 fprintf(stderr,"fopen wifi_txrate.txt failed");
6156
6157 if((file = fopen(RXRATEFILE, "r")) != NULL)
6158 {
6159 for(count =0;fgets(line, sizeof line, file) != NULL;)
6160 {
6161 if (++count == devIndex)
6162 {
6163 output_struct->wifi_devRxRate = atoi(line);
6164 break;
6165 }
6166 }
6167 fclose(file);
6168 }
6169 else
6170 fprintf(stderr,"fopen wifi_rxrate.txt failed");
6171
6172 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
6173
6174 return RETURN_OK;
6175#endif
6176}
6177
6178INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
6179{
6180 if (NULL == device)
6181 return RETURN_ERR;
6182 return RETURN_OK;
6183}
6184//<<
6185
6186
6187//--------------wifi_ap_hal-----------------------------
6188//enables CTS protection for the radio used by this AP
6189INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
6190{
6191 //save config and Apply instantly
6192 return RETURN_ERR;
6193}
6194
6195// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
6196INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
6197{
6198 char config_file[64] = {'\0'};
developerd1824452023-05-18 12:30:04 +08006199 char config_dat_file[64] = {'\0'};
developer72fb0bb2023-01-11 09:46:29 +08006200 char buf[64] = {'\0'};
developerd1824452023-05-18 12:30:04 +08006201 struct params list = {0};
6202 struct params dat = {0};
6203 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08006204
6205 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6206 list.name = "ht_coex";
6207 snprintf(buf, sizeof(buf), "%d", enable);
6208 list.value = buf;
6209
developerd1824452023-05-18 12:30:04 +08006210 dat.name = "HT_BSSCoexistence";
6211 dat.value = buf;
6212
6213 band = wifi_index_to_band(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08006214 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developerd1824452023-05-18 12:30:04 +08006215 snprintf(config_dat_file, sizeof(config_dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
developer72fb0bb2023-01-11 09:46:29 +08006216 wifi_hostapdWrite(config_file, &list, 1);
developer262f4cb2023-05-24 12:22:04 +08006217 wifi_datfileWrite(config_dat_file, &dat, 1);
developer72fb0bb2023-01-11 09:46:29 +08006218 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6219
6220 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6221
6222 return RETURN_OK;
6223}
6224
6225//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
6226INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
6227{
6228 char config_file[MAX_BUF_SIZE] = {'\0'};
6229 char buf[MAX_BUF_SIZE] = {'\0'};
6230 struct params list;
6231
6232 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6233 if (threshold < 256 || threshold > 2346 )
6234 return RETURN_ERR;
6235 list.name = "fragm_threshold";
6236 snprintf(buf, sizeof(buf), "%d", threshold);
6237 list.value = buf;
6238
6239 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6240 wifi_hostapdWrite(config_file, &list, 1);
6241 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6242
6243 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6244
6245 return RETURN_OK;
6246}
6247
6248// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
6249INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
6250{
6251 char config_file[64] = {'\0'};
6252 char cmd[512] = {'\0'};
6253 char buf[512] = {'\0'};
6254 char stbc_config[16] = {'\0'};
6255 wifi_band band;
6256 int iterator = 0;
6257 BOOL current_stbc = FALSE;
6258 int ant_count = 0;
6259 int ant_bitmap = 0;
6260 struct params list;
developera1255e42023-05-13 17:45:02 +08006261 char dat_file[64] = {'\0'};
developer72fb0bb2023-01-11 09:46:29 +08006262
6263 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6264
6265 band = wifi_index_to_band(radioIndex);
6266 if (band == band_invalid)
6267 return RETURN_ERR;
6268
6269 if (band == band_2_4)
6270 iterator = 1;
developera1255e42023-05-13 17:45:02 +08006271 else if ((band == band_5) || (band == band_6))
developer72fb0bb2023-01-11 09:46:29 +08006272 iterator = 2;
6273 else
6274 return RETURN_OK;
6275
6276 wifi_getRadioTxChainMask(radioIndex, &ant_bitmap);
6277 for (; ant_bitmap > 0; ant_bitmap >>= 1)
6278 ant_count += ant_bitmap & 1;
6279
6280 if (ant_count == 1 && STBC_Enable == TRUE) {
6281 fprintf(stderr, "%s: can not enable STBC when using only one antenna\n", __func__);
6282 return RETURN_OK;
6283 }
6284
6285 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
6286
6287 // set ht and vht config
6288 for (int i = 0; i < iterator; i++) {
6289 memset(stbc_config, 0, sizeof(stbc_config));
6290 memset(cmd, 0, sizeof(cmd));
6291 memset(buf, 0, sizeof(buf));
6292 list.name = (i == 0)?"ht_capab":"vht_capab";
6293 snprintf(stbc_config, sizeof(stbc_config), "%s", list.name);
6294 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
6295 _syscmd(cmd, buf, sizeof(buf));
6296 if (strlen(buf) != 0)
6297 current_stbc = TRUE;
6298 if (current_stbc == STBC_Enable)
6299 continue;
6300
6301 if (STBC_Enable == TRUE) {
6302 // Append the STBC flags in capab config
6303 memset(cmd, 0, sizeof(cmd));
6304 if (i == 0)
6305 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
6306 else
6307 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1][RX-STBC-1]/' %s", config_file);
6308 _syscmd(cmd, buf, sizeof(buf));
6309 } else if (STBC_Enable == FALSE) {
6310 // Remove the STBC flags and remain other flags in capab
6311 memset(cmd, 0, sizeof(cmd));
6312 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
6313 _syscmd(cmd, buf, sizeof(buf));
6314 memset(cmd, 0, sizeof(cmd));
6315 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
6316 _syscmd(cmd, buf, sizeof(buf));
6317 }
6318 wifi_hostapdRead(config_file, list.name, buf, sizeof(buf));
6319 list.value = buf;
6320 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
6321 }
developera1255e42023-05-13 17:45:02 +08006322 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
6323 snprintf(cmd, sizeof(cmd), "sed -r -i 's/^HT_STBC=.*/HT_STBC=%d/g' %s", STBC_Enable, dat_file);
6324 _syscmd(cmd, buf, sizeof(buf));
6325 if ((band == band_5) || (band == band_6)) {
6326 snprintf(cmd, sizeof(cmd), "sed -r -i 's/^VHT_STBC=.*/VHT_STBC=%d/g' %s", STBC_Enable, dat_file);
6327 _syscmd(cmd, buf, sizeof(buf));
6328 }
6329 /*wifi_reloadAp(radioIndex);
6330 the caller do this.*/
developer72fb0bb2023-01-11 09:46:29 +08006331
6332 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6333 return RETURN_OK;
6334}
6335
6336// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
6337INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
6338{
developer2c22d832023-05-18 17:46:26 +08006339 char dat_file[128] = {0};
6340 BOOL enable;
6341 wifi_band band;
6342 char amdus_buff[8] = {'\0'};
developer72fb0bb2023-01-11 09:46:29 +08006343
developer2c22d832023-05-18 17:46:26 +08006344 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08006345
developer2c22d832023-05-18 17:46:26 +08006346 band = wifi_index_to_band(radioIndex);
6347 if (band == band_invalid) {
6348 printf("%s:Band Error\n", __func__);
6349 return RETURN_ERR;
6350 }
6351 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
6352 wifi_datfileRead(dat_file, "HT_AMSDU", amdus_buff, sizeof(amdus_buff));
6353 if (strncmp(amdus_buff, "1", 1) == 0)
developer72fb0bb2023-01-11 09:46:29 +08006354 *output_bool = TRUE;
developer2c22d832023-05-18 17:46:26 +08006355 else
6356 *output_bool = FALSE;
developer72fb0bb2023-01-11 09:46:29 +08006357
developer2c22d832023-05-18 17:46:26 +08006358 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6359
6360 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006361}
6362
6363// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
6364INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
6365{
developer2c22d832023-05-18 17:46:26 +08006366 char dat_file[128] = {0};
6367 BOOL enable;
6368 wifi_band band;
6369 char amdus_buff[8] = {'\0'};
6370 struct params params = {0};
developer72fb0bb2023-01-11 09:46:29 +08006371
developer2c22d832023-05-18 17:46:26 +08006372 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08006373
developer2c22d832023-05-18 17:46:26 +08006374 band = wifi_index_to_band(radioIndex);
6375 if (band == band_invalid) {
6376 printf("%s:Band Error\n", __func__);
6377 return RETURN_ERR;
6378 }
6379 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
6380 wifi_datfileRead(dat_file, "HT_AMSDU", amdus_buff, sizeof(amdus_buff));
6381 if (strncmp(amdus_buff, "1", 1) == 0)
6382 enable = TRUE;
6383 else
6384 enable = FALSE;
6385 if (amsduEnable == enable)
6386 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006387
developer2c22d832023-05-18 17:46:26 +08006388 params.name = "HT_AMSDU";
6389 if (amsduEnable)
6390 params.value = "1";
6391 else
6392 params.value = "0";
6393 wifi_datfileWrite(dat_file, &params, 1);
6394 wifi_reloadAp(radioIndex);
developer72fb0bb2023-01-11 09:46:29 +08006395
developer2c22d832023-05-18 17:46:26 +08006396 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08006397
developer72fb0bb2023-01-11 09:46:29 +08006398 return RETURN_OK;
6399}
6400
6401//P2 // outputs the number of Tx streams
6402INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
6403{
6404 char buf[8] = {0};
6405 char cmd[128] = {0};
6406 int phyId = 0;
6407
6408 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6409
6410 phyId = radio_index_to_phy(radioIndex);
6411 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Configured Antennas' | awk '{print $4}'", phyId);
6412 _syscmd(cmd, buf, sizeof(buf));
6413
6414 *output_int = (INT)strtol(buf, NULL, 16);
6415
6416 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6417
6418 return RETURN_OK;
6419}
6420
6421INT fitChainMask(INT radioIndex, int antcount)
6422{
6423 char buf[128] = {0};
6424 char cmd[128] = {0};
6425 char config_file[64] = {0};
6426 wifi_band band;
6427 struct params list[2] = {0};
6428
6429 band = wifi_index_to_band(radioIndex);
6430 if (band == band_invalid)
6431 return RETURN_ERR;
6432
6433 list[0].name = "he_mu_beamformer";
6434 list[1].name = "he_su_beamformer";
6435
6436 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
6437 if (antcount == 1) {
6438 // remove config about multiple antennas
6439 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
6440 _syscmd(cmd, buf, sizeof(buf));
6441
6442 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SOUNDING-DIMENSION-.\\]//' %s", config_file);
6443 _syscmd(cmd, buf, sizeof(buf));
6444
6445 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SU-BEAMFORMER\\]//' %s", config_file);
6446 _syscmd(cmd, buf, sizeof(buf));
6447
6448 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[MU-BEAMFORMER\\]//' %s", config_file);
6449 _syscmd(cmd, buf, sizeof(buf));
6450
6451 list[0].value = "0";
6452 list[1].value = "0";
6453 } else {
6454 // 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.
6455 if (band == band_2_4 || band == band_5) {
6456 snprintf(cmd, sizeof(cmd), "cat %s | grep '^ht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
6457 _syscmd(cmd, buf, sizeof(buf));
6458 if (strlen(buf) > 0) {
6459 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC]/' %s", config_file);
6460 _syscmd(cmd, buf, sizeof(buf));
6461 }
6462 }
6463 if (band == band_5) {
6464 snprintf(cmd, sizeof(cmd), "cat %s | grep '^vht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
6465 _syscmd(cmd, buf, sizeof(buf));
6466 if (strlen(buf) > 0) {
6467 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1]/' %s", config_file);
6468 _syscmd(cmd, buf, sizeof(buf));
6469 }
6470 }
6471
6472 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SU-BEAMFORMER\\]'", config_file);
6473 _syscmd(cmd, buf, sizeof(buf));
6474 if (strlen(buf) == 0) {
6475 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SU-BEAMFORMER]/' %s", config_file);
6476 _syscmd(cmd, buf, sizeof(buf));
6477 }
6478
6479 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[MU-BEAMFORMER\\]'", config_file);
6480 _syscmd(cmd, buf, sizeof(buf));
6481 if (strlen(buf) == 0) {
6482 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[MU-BEAMFORMER]/' %s", config_file);
6483 _syscmd(cmd, buf, sizeof(buf));
6484 }
6485
6486 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SOUNDING-DIMENSION-.\\]'", config_file);
6487 _syscmd(cmd, buf, sizeof(buf));
6488 if (strlen(buf) == 0) {
6489 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SOUNDING-DIMENSION-%d]/' %s", antcount, config_file);
6490 } else {
6491 snprintf(cmd, sizeof(cmd), "sed -r -i 's/(SOUNDING-DIMENSION-)./\\1%d/' %s", antcount, config_file);
6492 }
6493 _syscmd(cmd, buf, sizeof(buf));
6494
6495 list[0].value = "1";
6496 list[1].value = "1";
6497 }
6498 wifi_hostapdWrite(config_file, list, 2);
6499}
6500
6501//P2 // sets the number of Tx streams to an enviornment variable
6502INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
6503{
6504 char cmd[128] = {0};
6505 char buf[128] = {0};
6506 int phyId = 0;
6507 int cur_mask = 0;
developera1255e42023-05-13 17:45:02 +08006508 int antcountmsk = 0;
6509 INT cur_nss = 0;
6510 UCHAR dat_file[64] = {0};
6511 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08006512
6513 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6514
6515 if (numStreams <= 0) {
6516 fprintf(stderr, "%s: chainmask is not supported %d.\n", __func__, numStreams);
6517 return RETURN_ERR;
6518 }
6519
developera1255e42023-05-13 17:45:02 +08006520 wifi_getRadioTxChainMask(radioIndex, &cur_mask);//this is mask value
6521 for(; cur_mask > 0; cur_mask >>= 1)//convert to number of streams.
6522 cur_nss += 1;
6523 WIFI_ENTRY_EXIT_DEBUG("%s:cur_nss=%d, new_nss=%d\n", __func__, cur_nss, numStreams);
6524 if (cur_nss == numStreams)
developer72fb0bb2023-01-11 09:46:29 +08006525 return RETURN_OK;
6526
6527 wifi_setRadioEnable(radioIndex, FALSE);
6528
6529 phyId = radio_index_to_phy(radioIndex);
developera1255e42023-05-13 17:45:02 +08006530 //iw need mask value.
6531 for (;numStreams > 0; numStreams--)
6532 antcountmsk |= 0x1 << (numStreams - 1);
6533 snprintf(cmd, sizeof(cmd), "iw phy%d set antenna 0x%x 2>&1", phyId, antcountmsk);
developer72fb0bb2023-01-11 09:46:29 +08006534 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006535 if (strlen(buf) > 0) {
6536 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
6537 return RETURN_ERR;
6538 }
developera1255e42023-05-13 17:45:02 +08006539 band = wifi_index_to_band(radioIndex);
6540 if (band == band_invalid) {
6541 printf("%s:Band Error\n", __func__);
6542 return RETURN_ERR;
6543 }
6544 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
6545 snprintf(cmd, sizeof(cmd), "sed -r -i 's/^HT_TxStream=.*/HT_TxStream=%d/g' %s", numStreams, dat_file);
6546 _syscmd(cmd, buf, sizeof(buf));
6547 if (strlen(buf) > 0) {
6548 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
6549 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006550 }
developera1255e42023-05-13 17:45:02 +08006551 snprintf(cmd, sizeof(cmd), "sed -r -i 's/^HT_RxStream=.*/HT_RxStream=%d/g' %s", numStreams, dat_file);
6552 _syscmd(cmd, buf, sizeof(buf));
6553 if (strlen(buf) > 0) {
6554 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
6555 return RETURN_ERR;
6556 }
6557 fitChainMask(radioIndex, numStreams);
developer72fb0bb2023-01-11 09:46:29 +08006558 wifi_setRadioEnable(radioIndex, TRUE);
6559
6560 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6561 return RETURN_OK;
6562}
6563
6564//P2 // outputs the number of Rx streams
6565INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
6566{
6567 char buf[8] = {0};
6568 char cmd[128] = {0};
6569 int phyId = 0;
6570
6571 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6572
6573 phyId = radio_index_to_phy(radioIndex);
6574 sprintf(cmd, "iw phy%d info | grep 'Configured Antennas' | awk '{print $6}'", phyId);
6575 _syscmd(cmd, buf, sizeof(buf));
6576
6577 *output_int = (INT)strtol(buf, NULL, 16);
6578
6579 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6580
6581 return RETURN_OK;
6582}
6583
6584//P2 // sets the number of Rx streams to an enviornment variable
6585INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
6586{
6587 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6588 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
6589 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
6590 return RETURN_ERR;
6591 }
6592 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6593 return RETURN_ERR;
6594}
6595
6596//Get radio RDG enable setting
6597INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
6598{
developer47cc27a2023-05-17 23:09:58 +08006599 if (NULL == output_bool)
6600 return RETURN_ERR;
6601
6602 *output_bool = TRUE;
6603 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006604}
6605
6606//Get radio RDG enable setting
6607INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
6608{
developer47cc27a2023-05-17 23:09:58 +08006609 char cmd[MAX_CMD_SIZE] = {0};
6610 char buf[MAX_BUF_SIZE] = {0};
6611 char rdg_status[2] = {0};
6612 char dat_file[MAX_CMD_SIZE] = {0};
6613 struct params params = {0};
6614
6615 if (NULL == output_bool)
6616 return RETURN_ERR;
6617
6618 /*prepare dat file path*/
6619 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, radioIndex);
6620
6621 wifi_datfileRead(dat_file, "HT_RDG", rdg_status, sizeof(rdg_status));
6622 if (!strncmp(rdg_status, "1", sizeof(rdg_status)))
6623 *output_bool = TRUE;
6624 else
6625 *output_bool = FALSE;
6626
6627 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006628}
6629
6630//Set radio RDG enable setting
6631INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
6632{
developer47cc27a2023-05-17 23:09:58 +08006633 char cmd[MAX_CMD_SIZE] = {0};
6634 char buf[MAX_BUF_SIZE] = {0};
6635 char dat_file[MAX_CMD_SIZE] = {0};
6636 struct params params = {0};
6637
6638 /*prepare dat file path*/
6639 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, radioIndex);
6640
6641 params.name = "HT_RDG";
6642
6643 if (enable) {
6644 params.value = "1";
6645 } else {
6646 params.value = "0";
6647 }
6648
6649 wifi_datfileWrite(dat_file, &params, 1);
6650
6651 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006652}
6653
developer5cd4c862023-05-26 09:34:42 +08006654
6655int mtk_get_ba_auto_status_callback(struct nl_msg *msg, void *data)
developer72fb0bb2023-01-11 09:46:29 +08006656{
developer5cd4c862023-05-26 09:34:42 +08006657 struct nlattr *tb[NL80211_ATTR_MAX + 1];
6658 struct nlattr *vndr_tb[MTK_NL80211_VENDOR_AP_BA_ATTR_MAX + 1];
6659 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
6660 unsigned char status;
6661 unsigned char *out_status = data;
6662 int err = 0;
developer8e6583c2023-05-23 13:36:06 +08006663
developer5cd4c862023-05-26 09:34:42 +08006664 err = nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
6665 genlmsg_attrlen(gnlh, 0), NULL);
6666 if (err < 0){
6667 wifi_debug(DEBUG_ERROR, "get NL80211_ATTR_MAX fails\n");
6668 return err;
6669 }
developer8e6583c2023-05-23 13:36:06 +08006670
developer5cd4c862023-05-26 09:34:42 +08006671 if (tb[NL80211_ATTR_VENDOR_DATA]) {
6672 err = nla_parse_nested(vndr_tb, MTK_NL80211_VENDOR_AP_BA_ATTR_MAX,
6673 tb[NL80211_ATTR_VENDOR_DATA], NULL);
6674 if (err < 0){
6675 wifi_debug(DEBUG_ERROR, "get MTK_NL80211_VENDOR_AP_BA_ATTR_MAX fails\n");
6676 return err;
6677 }
developer8e6583c2023-05-23 13:36:06 +08006678
developer5cd4c862023-05-26 09:34:42 +08006679 if (vndr_tb[MTK_NL80211_VENDOR_ATTR_AP_BA_EN_INFO]) {
6680 status = nla_get_u8(vndr_tb[MTK_NL80211_VENDOR_ATTR_AP_BA_EN_INFO]);
6681 if (status == 0) {
6682 wifi_debug(DEBUG_NOTICE, "disabled\n");
6683 } else {
6684 wifi_debug(DEBUG_NOTICE, "enabled\n");
6685 }
6686 *out_status = status;
6687 }
6688 }
developer8e6583c2023-05-23 13:36:06 +08006689
developer5cd4c862023-05-26 09:34:42 +08006690 return 0;
6691}
developer8e6583c2023-05-23 13:36:06 +08006692
developer5cd4c862023-05-26 09:34:42 +08006693int mtk_get_ba_decline_status_callback(struct nl_msg *msg, void *data)
6694{
6695 struct nlattr *tb[NL80211_ATTR_MAX + 1];
6696 struct nlattr *vndr_tb[MTK_NL80211_VENDOR_AP_BA_ATTR_MAX + 1];
6697 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
6698 unsigned char status;
6699 unsigned char *out_status = data;
6700 int err = 0;
6701
6702 err = nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
6703 genlmsg_attrlen(gnlh, 0), NULL);
6704 if (err < 0) {
6705 wifi_debug(DEBUG_ERROR, "get NL80211_ATTR_MAX fails\n");
6706 return err;
6707 }
6708
6709 if (tb[NL80211_ATTR_VENDOR_DATA]) {
6710 err = nla_parse_nested(vndr_tb, MTK_NL80211_VENDOR_AP_BA_ATTR_MAX,
6711 tb[NL80211_ATTR_VENDOR_DATA], NULL);
6712 if (err < 0) {
6713 wifi_debug(DEBUG_ERROR, "get MTK_NL80211_VENDOR_AP_BA_ATTR_MAX fails\n");
6714 return err;
6715 }
6716
6717 if (vndr_tb[MTK_NL80211_VENDOR_ATTR_AP_BA_DECLINE_INFO]) {
6718 status = nla_get_u8(vndr_tb[MTK_NL80211_VENDOR_ATTR_AP_BA_DECLINE_INFO]);
6719 if (status == 0) {
6720 wifi_debug(DEBUG_NOTICE, "disabled\n");
6721 } else {
6722 wifi_debug(DEBUG_NOTICE, "enabled\n");
6723 }
6724 *out_status = status;
6725 }
6726 }
6727
6728 return NL_OK;
developer72fb0bb2023-01-11 09:46:29 +08006729}
6730
developer5cd4c862023-05-26 09:34:42 +08006731INT mtk_wifi_get_ba_decl_auto_status(
6732 INT apIndex, INT vendor_data_attr, mtk_nl80211_cb call_back, BOOL *output_bool)
6733{
6734 char inf_name[IF_NAME_SIZE] = {0};
6735 struct mtk_nl80211_param params;
6736 unsigned int if_idx = 0;
6737 int ret = -1;
6738 struct unl unl_ins;
6739 struct nl_msg *msg = NULL;
6740 struct nlattr * msg_data = NULL;
6741 struct mtk_nl80211_param param;
6742
6743 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
6744 return RETURN_ERR;
6745 if_idx = if_nametoindex(inf_name);
6746 if (!if_idx) {
6747 wifi_debug(DEBUG_ERROR,"can't finde ifname(%s) index,ERROR\n", inf_name);
6748 return RETURN_ERR;
6749 }
6750 /*init mtk nl80211 vendor cmd*/
6751 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_BA;
6752 param.if_type = NL80211_ATTR_IFINDEX;
6753 param.if_idx = if_idx;
6754
6755 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
6756 if (ret) {
6757 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
6758 return RETURN_ERR;
6759 }
6760 /*add mtk vendor cmd data*/
6761 if (nla_put_u8(msg, vendor_data_attr, 0xf)) {
6762 wifi_debug(DEBUG_ERROR, "Nla put vendor_data_attr(%d) attribute error\n", vendor_data_attr);
6763 nlmsg_free(msg);
6764 goto err;
6765 }
6766
6767 /*send mtk nl80211 vendor msg*/
6768 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, call_back, output_bool);
6769 if (ret) {
6770 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
6771 goto err;
6772 }
6773 /*deinit mtk nl80211 vendor msg*/
6774 mtk_nl80211_deint(&unl_ins);
6775 wifi_debug(DEBUG_NOTICE,"send cmd success, get output_bool:%d\n", *output_bool);
6776 return RETURN_OK;
6777err:
6778 mtk_nl80211_deint(&unl_ins);
6779 wifi_debug(DEBUG_ERROR,"send cmd fails\n");
6780 return RETURN_ERR;
6781}
6782//Get radio ADDBA enable setting
6783INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
6784{
6785 if (output_bool == NULL) {
6786 wifi_debug(DEBUG_ERROR, "invalid: output_bool is null\n");
6787 return RETURN_ERR;
6788 }
6789 if (mtk_wifi_get_ba_decl_auto_status(radioIndex,
6790 MTK_NL80211_VENDOR_ATTR_AP_BA_DECLINE_INFO, mtk_get_ba_decline_status_callback, output_bool) != RETURN_OK) {
6791 wifi_debug(DEBUG_ERROR, "cmd MTK_NL80211_VENDOR_ATTR_AP_BA_DECLINE_INFO(0x%x) fails\n",
6792 MTK_NL80211_VENDOR_ATTR_AP_BA_DECLINE_INFO);
6793 return RETURN_ERR;
6794 }
6795 wifi_debug(DEBUG_NOTICE, "cmd success:output_bool(%d)\n", *output_bool);
6796 return RETURN_OK;
6797}
6798
developer72fb0bb2023-01-11 09:46:29 +08006799//Set radio ADDBA enable setting
6800INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
6801{
6802 return RETURN_ERR;
6803}
6804
6805//Get radio auto block ack enable setting
6806INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
6807{
developer5cd4c862023-05-26 09:34:42 +08006808 if (output_bool == NULL) {
6809 wifi_debug(DEBUG_ERROR, "invalid: output_bool is null\n");
6810 return RETURN_ERR;
6811 }
developer8e6583c2023-05-23 13:36:06 +08006812
developer5cd4c862023-05-26 09:34:42 +08006813 if (mtk_wifi_get_ba_decl_auto_status(radioIndex,
6814 MTK_NL80211_VENDOR_ATTR_AP_BA_EN_INFO,
6815 mtk_get_ba_auto_status_callback, output_bool) != RETURN_OK) {
6816 wifi_debug(DEBUG_ERROR, "cmd MTK_NL80211_VENDOR_ATTR_AP_BA_EN_INFO(0x%x) fails\n",
6817 MTK_NL80211_VENDOR_ATTR_AP_BA_EN_INFO);
6818 return RETURN_ERR;
6819 }
6820 wifi_debug(DEBUG_NOTICE, "cmd success:output_bool(%d)\n", *output_bool);
6821 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006822}
6823
6824//Set radio auto block ack enable setting
6825INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
6826{
6827 return RETURN_ERR;
6828}
6829
6830//Get radio 11n pure mode enable support
6831INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
6832{
6833 if (NULL == output_bool)
6834 return RETURN_ERR;
6835 *output_bool = TRUE;
6836 return RETURN_OK;
6837}
6838
6839//Get radio 11n pure mode enable setting
6840INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
6841{
6842 if (NULL == output_bool)
6843 return RETURN_ERR;
6844 *output_bool = TRUE;
6845 return RETURN_OK;
6846}
6847
6848//Set radio 11n pure mode enable setting
6849INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
6850{
6851 return RETURN_ERR;
6852}
6853
developer5cd4c862023-05-26 09:34:42 +08006854
6855int mtk_get_igmp_status_callback(struct nl_msg *msg, void *data)
developer72fb0bb2023-01-11 09:46:29 +08006856{
developer5cd4c862023-05-26 09:34:42 +08006857 struct nlattr *tb[NL80211_ATTR_MAX + 1];
6858 struct nlattr *vndr_tb[MTK_NL80211_VENDOR_MCAST_SNOOP_ATTR_MAX + 1];
6859 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
6860 unsigned char status = 0, *out_status = data;
6861 int err = 0;
developer72fb0bb2023-01-11 09:46:29 +08006862
developer5cd4c862023-05-26 09:34:42 +08006863 err = nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
6864 genlmsg_attrlen(gnlh, 0), NULL);
6865 if (err < 0) {
6866 wifi_debug(DEBUG_ERROR, "get NL80211_ATTR_MAX fails\n");
6867 return err;
6868 }
developer72fb0bb2023-01-11 09:46:29 +08006869
developer5cd4c862023-05-26 09:34:42 +08006870 if (tb[NL80211_ATTR_VENDOR_DATA]) {
6871 err = nla_parse_nested(vndr_tb, MTK_NL80211_VENDOR_MCAST_SNOOP_ATTR_MAX,
6872 tb[NL80211_ATTR_VENDOR_DATA], NULL);
6873 if (err < 0){
6874 wifi_debug(DEBUG_ERROR, "get MTK_NL80211_VENDOR_MCAST_SNOOP_ATTR_MAX fails\n");
6875 return err;
6876 }
developer72fb0bb2023-01-11 09:46:29 +08006877
developer5cd4c862023-05-26 09:34:42 +08006878 if (vndr_tb[MTK_NL80211_VENDOR_ATTR_MCAST_SNOOP_ENABLE]) {
6879 status = nla_get_u8(vndr_tb[MTK_NL80211_VENDOR_ATTR_MCAST_SNOOP_ENABLE]);
6880 if (status == 0) {
6881 wifi_debug(DEBUG_NOTICE, "disabled\n");
6882 } else {
6883 wifi_debug(DEBUG_NOTICE, "enabled\n");
6884 }
6885 *out_status = status;
6886 wifi_debug(DEBUG_NOTICE, "status: %d\n", *out_status);
6887 }
6888 }
6889
6890 return 0;
6891}
6892
6893INT mtk_wifi_set_igmp_en_status(
6894 INT apIndex, INT vendor_data_attr, mtk_nl80211_cb call_back,
6895 unsigned char in_en_stat, BOOL *output_bool)
6896{
6897 char inf_name[IF_NAME_SIZE] = {0};
6898 struct mtk_nl80211_param params;
6899 unsigned int if_idx = 0;
6900 int ret = -1;
6901 struct unl unl_ins;
6902 struct nl_msg *msg = NULL;
6903 struct nlattr * msg_data = NULL;
6904 struct mtk_nl80211_param param;
6905
6906 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
6907 return RETURN_ERR;
6908 if_idx = if_nametoindex(inf_name);
6909 if (!if_idx) {
6910 wifi_debug(DEBUG_ERROR,"can't finde ifname(%s) index,ERROR\n", inf_name);
6911 return RETURN_ERR;
6912 }
6913 /*init mtk nl80211 vendor cmd*/
6914 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_MULTICAST_SNOOPING;
6915 param.if_type = NL80211_ATTR_IFINDEX;
6916 param.if_idx = if_idx;
6917
6918 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
6919 if (ret) {
6920 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
6921 return RETURN_ERR;
6922 }
6923 /*add mtk vendor cmd data*/
6924 if (nla_put_u8(msg, vendor_data_attr, in_en_stat)) {
6925 wifi_debug(DEBUG_ERROR, "Nla put vendor_data_attr(%d) attribute error\n", vendor_data_attr);
6926 nlmsg_free(msg);
6927 goto err;
6928 }
6929
6930 /*send mtk nl80211 vendor msg*/
6931 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, call_back, output_bool);
6932 if (ret) {
6933 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
6934 goto err;
6935 }
6936 /*deinit mtk nl80211 vendor msg*/
6937 mtk_nl80211_deint(&unl_ins);
6938 if (output_bool) {
6939 wifi_debug(DEBUG_NOTICE, "send cmd success, get output_bool:%d\n", *output_bool);
6940 } else {
6941 wifi_debug(DEBUG_NOTICE, "send cmd success.\n");
6942 }
6943 return RETURN_OK;
6944err:
6945 mtk_nl80211_deint(&unl_ins);
6946 wifi_debug(DEBUG_ERROR,"send cmd fails\n");
6947 return RETURN_ERR;
6948}
6949
6950
6951//Get radio IGMP snooping enable setting
6952INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
6953{
6954 if (output_bool == NULL) {
6955 wifi_debug(DEBUG_ERROR, "invalid: output_bool is null\n");
6956 return RETURN_ERR;
6957 }
6958 if (mtk_wifi_set_igmp_en_status
6959 (radioIndex, MTK_NL80211_VENDOR_ATTR_MCAST_SNOOP_ENABLE,
6960 mtk_get_igmp_status_callback, 0xf, output_bool)!= RETURN_OK) {
6961 wifi_debug(DEBUG_ERROR, "send MTK_NL80211_VENDOR_ATTR_MCAST_SNOOP_ENABLE cmd fails\n");
6962 return RETURN_ERR;
6963 }
6964 wifi_debug(DEBUG_ERROR, "send cmd success: get igmp status:(%d)\n", *output_bool);
developer72fb0bb2023-01-11 09:46:29 +08006965 return RETURN_OK;
6966}
6967
6968//Set radio IGMP snooping enable setting
6969INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
6970{
developer5cd4c862023-05-26 09:34:42 +08006971 if (mtk_wifi_set_igmp_en_status
6972 (radioIndex, MTK_NL80211_VENDOR_ATTR_MCAST_SNOOP_ENABLE,
6973 NULL, enable, NULL) != RETURN_OK) {
6974 wifi_debug(DEBUG_ERROR, "send MTK_NL80211_VENDOR_ATTR_MCAST_SNOOP_ENABLE cmd fails\n");
6975 return RETURN_ERR;
6976 }
6977 wifi_debug(DEBUG_ERROR, "send cmd success: set igmp enable(%d)\n", enable);
developer72fb0bb2023-01-11 09:46:29 +08006978 return RETURN_OK;
6979}
6980
6981//Get the Reset count of radio
developer69b61b02023-03-07 17:17:44 +08006982INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
developer72fb0bb2023-01-11 09:46:29 +08006983{
developer69b61b02023-03-07 17:17:44 +08006984 if (NULL == output_int)
developer72fb0bb2023-01-11 09:46:29 +08006985 return RETURN_ERR;
developerfead3972023-05-25 20:15:02 +08006986 *output_int = get_radio_reset_cnt(radioIndex);
developer72fb0bb2023-01-11 09:46:29 +08006987
6988 return RETURN_OK;
6989}
6990
6991
6992//---------------------------------------------------------------------------------------------------
6993//
6994// Additional Wifi AP level APIs used for Access Point devices
6995//
6996//---------------------------------------------------------------------------------------------------
6997
6998// creates a new ap and pushes these parameters to the hardware
6999INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
7000{
7001 // Deprecated when use hal version 3, use wifi_createVap() instead.
7002 return RETURN_OK;
7003}
7004
7005// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
7006INT wifi_deleteAp(INT apIndex)
7007{
developer7e4a2a62023-04-06 19:56:03 +08007008 char interface_name[16] = {0};
7009 char buf[MAX_BUF_SIZE];
7010 char cmd[MAX_CMD_SIZE];
developer72fb0bb2023-01-11 09:46:29 +08007011
developer7e4a2a62023-04-06 19:56:03 +08007012 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7013 return RETURN_ERR;
developer8a3bbbf2023-03-15 17:47:23 +08007014
developer7e4a2a62023-04-06 19:56:03 +08007015 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw REMOVE %s", interface_name);
7016 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08007017
developer7e4a2a62023-04-06 19:56:03 +08007018 wifi_removeApSecVaribles(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08007019
developer7e4a2a62023-04-06 19:56:03 +08007020 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08007021}
7022
7023// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
7024INT wifi_getApName(INT apIndex, CHAR *output_string)
7025{
developer7e4a2a62023-04-06 19:56:03 +08007026 char interface_name[IF_NAME_SIZE] = {0};
developer47cc27a2023-05-17 23:09:58 +08007027 int radio_idx = 0;
7028 int bss_idx = 0;
developer72fb0bb2023-01-11 09:46:29 +08007029
developer7e4a2a62023-04-06 19:56:03 +08007030 if(!output_string)
7031 return RETURN_ERR;
7032
7033 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
7034 vap_index_to_array_index(apIndex, &radio_idx, &bss_idx);
7035
7036 snprintf(output_string, IF_NAME_SIZE, "%s%d", ext_prefix[radio_idx], bss_idx); // For wifiagent generating data model.
7037 } else
7038 snprintf(output_string, IF_NAME_SIZE, "%s", interface_name);
7039
7040 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08007041}
7042
7043// Outputs the index number in that corresponds to the SSID string
7044INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
7045{
developer7e4a2a62023-04-06 19:56:03 +08007046 char cmd [128] = {0};
7047 char buf[32] = {0};
7048 char ap_idx = 0;
7049 char *apIndex_str = NULL;
7050 char radio_idx = 0;
7051 char bss_idx = 0;
developer72fb0bb2023-01-11 09:46:29 +08007052
developer7e4a2a62023-04-06 19:56:03 +08007053 snprintf(cmd, sizeof(cmd), "grep -rn ^interface=%s$ /nvram/hostapd*.conf | cut -d '.' -f1 | cut -d 'd' -f2 | tr -d '\\n'",
7054 inputSsidString);
7055 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08007056
developer7e4a2a62023-04-06 19:56:03 +08007057 if (strlen(buf)) {
7058 apIndex_str = strtok(buf, "\n");
7059 *output_int = strtoul(apIndex_str, NULL, 10);
7060 return RETURN_OK;
7061 }
developer72fb0bb2023-01-11 09:46:29 +08007062
developer7e4a2a62023-04-06 19:56:03 +08007063 /* If interface name is not in hostapd config, the caller maybe wifi agent to generate data model.*/
7064 if (strstr(inputSsidString, PREFIX_WIFI6G)) {
7065 bss_idx = atoi(inputSsidString + strlen(PREFIX_WIFI6G));
7066 radio_idx = 2;
7067 } else if (strstr(inputSsidString, PREFIX_WIFI5G)) {
7068 bss_idx = atoi(inputSsidString + strlen(PREFIX_WIFI5G));
7069 radio_idx = 1;
7070 } else if (strstr(inputSsidString, PREFIX_WIFI2G)) {
7071 bss_idx = atoi(inputSsidString + strlen(PREFIX_WIFI2G));
7072 radio_idx = 0;
7073 } else {
7074 printf("%s: hostapd conf not find, unknow inf(%s), return ERROR!!!(%d).\n",
7075 __func__, inputSsidString, ap_idx);
7076 *output_int = -1;
7077 return RETURN_ERR;
7078 }
7079
7080 ap_idx = array_index_to_vap_index(radio_idx, bss_idx);
7081
7082 if (ap_idx >= 0 && ap_idx < MAX_VAP) {
7083 printf("%s: hostapd conf not find, inf(%s), use inf idx(%d).\n",
7084 __func__, inputSsidString, ap_idx);
7085 *output_int = ap_idx;
7086 return RETURN_OK;
7087 }
7088
7089 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007090}
7091
7092INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
7093{
7094 return wifi_getIndexFromName(inputSsidString, output_int);
7095}
7096
7097// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
7098INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
7099{
7100 char buf[MAX_BUF_SIZE] = {0};
7101 char cmd[MAX_CMD_SIZE] = {0};
7102 char config_file[MAX_BUF_SIZE] = {0};
7103
7104 if(NULL == output_string)
7105 return RETURN_ERR;
7106
7107 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7108 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
7109 if((strcmp(buf,"3")==0))
7110 snprintf(output_string, 32, "WPAand11i");
7111 else if((strcmp(buf,"2")==0))
7112 snprintf(output_string, 32, "11i");
7113 else if((strcmp(buf,"1")==0))
7114 snprintf(output_string, 32, "WPA");
7115 else
7116 snprintf(output_string, 32, "None");
7117
7118 return RETURN_OK;
7119}
7120
7121// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
7122INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
7123{
7124 char config_file[MAX_BUF_SIZE] = {0};
7125 struct params list;
7126
7127 if (NULL == beaconTypeString)
7128 return RETURN_ERR;
7129 list.name = "wpa";
7130 list.value = "0";
7131
7132 if((strcmp(beaconTypeString,"WPAand11i")==0))
7133 list.value="3";
7134 else if((strcmp(beaconTypeString,"11i")==0))
7135 list.value="2";
7136 else if((strcmp(beaconTypeString,"WPA")==0))
7137 list.value="1";
7138
7139 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7140 wifi_hostapdWrite(config_file, &list, 1);
7141 wifi_hostapdProcessUpdate(apIndex, &list, 1);
7142 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
7143 return RETURN_OK;
7144}
7145
7146// sets the beacon interval on the hardware for this AP
7147INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
7148{
7149 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7150 struct params params={'\0'};
7151 char buf[MAX_BUF_SIZE] = {'\0'};
7152 char config_file[MAX_BUF_SIZE] = {'\0'};
7153
7154 params.name = "beacon_int";
7155 snprintf(buf, sizeof(buf), "%u", beaconInterval);
7156 params.value = buf;
7157
7158 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7159 wifi_hostapdWrite(config_file, &params, 1);
developer69b61b02023-03-07 17:17:44 +08007160
developer72fb0bb2023-01-11 09:46:29 +08007161 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7162 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7163 return RETURN_OK;
7164}
7165
7166INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
7167{
7168 if (wifi_setApDTIMInterval(apIndex, dtimInterval) != RETURN_OK)
7169 return RETURN_ERR;
7170 return RETURN_OK;
7171}
7172
7173// Get the packet size threshold supported.
7174INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
7175{
7176 //save config and apply instantly
7177 if (NULL == output_bool)
7178 return RETURN_ERR;
7179 *output_bool = TRUE;
7180 return RETURN_OK;
7181}
7182
7183// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
7184INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
7185{
developer72fb0bb2023-01-11 09:46:29 +08007186 char buf[16] = {0};
7187 char config_file[128] = {0};
7188 struct params param = {0};
7189
7190 if (threshold > 65535) {
7191 fprintf(stderr, "%s: rts threshold %u is too big.\n", __func__, threshold);
7192 return RETURN_ERR;
7193 }
7194
developer23e71282023-01-18 10:25:19 +08007195 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developer72fb0bb2023-01-11 09:46:29 +08007196 snprintf(buf, sizeof(buf), "%u", threshold);
7197 param.name = "rts_threshold";
7198 param.value = buf;
7199 wifi_hostapdWrite(config_file, &param, 1);
7200 wifi_hostapdProcessUpdate(apIndex, &param, 1);
7201 wifi_reloadAp(apIndex);
7202
7203 return RETURN_OK;
7204}
7205
7206// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
7207INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
7208{
7209 if (NULL == output_string)
7210 return RETURN_ERR;
7211 snprintf(output_string, 32, "TKIPandAESEncryption");
7212 return RETURN_OK;
7213
7214}
7215
7216// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
7217INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
7218{
7219 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7220 char *param_name = NULL;
7221 char buf[32] = {0}, config_file[MAX_BUF_SIZE] = {0};
7222
7223 if(NULL == output_string)
7224 return RETURN_ERR;
7225
7226 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7227 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
7228
7229 if(strcmp(buf,"0")==0)
7230 {
7231 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
7232 snprintf(output_string, 32, "None");
7233 return RETURN_OK;
7234 }
7235 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
7236 param_name = "rsn_pairwise";
7237 else if((strcmp(buf,"1")==0))
7238 param_name = "wpa_pairwise";
7239 else
7240 return RETURN_ERR;
7241 memset(output_string,'\0',32);
7242 wifi_hostapdRead(config_file,param_name,output_string,32);
7243 if (strlen(output_string) == 0) { // rsn_pairwise is optional. When it is empty use wpa_pairwise instead.
7244 param_name = "wpa_pairwise";
7245 memset(output_string, '\0', 32);
7246 wifi_hostapdRead(config_file, param_name, output_string, 32);
7247 }
7248 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
7249
developere5750452023-05-15 16:46:42 +08007250 if(strcmp(output_string,"TKIP CCMP") == 0)
7251 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
7252 else if(strcmp(output_string,"TKIP") == 0)
developer72fb0bb2023-01-11 09:46:29 +08007253 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
7254 else if(strcmp(output_string,"CCMP") == 0)
7255 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
developer72fb0bb2023-01-11 09:46:29 +08007256
7257 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7258 return RETURN_OK;
7259}
7260
7261// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
7262INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
7263{
7264 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7265 struct params params={'\0'};
7266 char output_string[32];
7267 char config_file[MAX_BUF_SIZE] = {0};
7268
7269 memset(output_string,'\0',32);
developere5750452023-05-15 16:46:42 +08007270 wifi_getApBeaconType(apIndex,output_string);
developer72fb0bb2023-01-11 09:46:29 +08007271
7272 if(strcmp(encMode, "TKIPEncryption") == 0)
7273 params.value = "TKIP";
7274 else if(strcmp(encMode,"AESEncryption") == 0)
7275 params.value = "CCMP";
7276 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
7277 params.value = "TKIP CCMP";
7278
7279 if((strcmp(output_string,"WPAand11i")==0))
7280 {
7281 params.name = "wpa_pairwise";
7282 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7283 wifi_hostapdWrite(config_file, &params, 1);
7284 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7285
7286 params.name = "rsn_pairwise";
7287 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7288 wifi_hostapdWrite(config_file, &params, 1);
7289 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7290
7291 return RETURN_OK;
7292 }
7293 else if((strcmp(output_string,"11i")==0))
7294 {
7295 params.name = "rsn_pairwise";
7296 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7297 wifi_hostapdWrite(config_file, &params, 1);
7298 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7299 return RETURN_OK;
7300 }
7301 else if((strcmp(output_string,"WPA")==0))
7302 {
7303 params.name = "wpa_pairwise";
7304 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7305 wifi_hostapdWrite(config_file, &params, 1);
7306 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7307 return RETURN_OK;
7308 }
7309
7310 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7311 return RETURN_OK;
7312}
7313
7314// deletes internal security varable settings for this ap
7315INT wifi_removeApSecVaribles(INT apIndex)
7316{
7317 //TODO: remove the entry in hostapd config file
7318 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s.conf//g' /tmp/conf_filename", interface_name);
7319 //_syscmd(cmd, buf, sizeof(buf));
7320
7321 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s//g' /tmp/conf_filename", interface_name);
7322 //_syscmd(cmd, buf, sizeof(buf));
7323 return RETURN_ERR;
7324}
7325
7326// changes the hardware settings to disable encryption on this ap
7327INT wifi_disableApEncryption(INT apIndex)
7328{
7329 //Apply instantly
7330 return RETURN_ERR;
7331}
7332
7333// set the authorization mode on this ap
7334// mode mapping as: 1: open, 2: shared, 4:auto
7335INT wifi_setApAuthMode(INT apIndex, INT mode)
7336{
7337 struct params params={0};
7338 char config_file[64] = {0};
7339 int ret;
7340
7341 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
7342
7343 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
7344 params.name = "auth_algs";
7345
developere5750452023-05-15 16:46:42 +08007346 if ((mode & 1 && mode & 2) || mode & 4)
developer72fb0bb2023-01-11 09:46:29 +08007347 params.value = "3";
7348 else if (mode & 2)
7349 params.value = "2";
7350 else if (mode & 1)
7351 params.value = "1";
7352 else
7353 params.value = "0";
7354
7355 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7356 wifi_hostapdWrite(config_file, &params, 1);
7357 wifi_hostapdProcessUpdate(apIndex, &params, 1);
developere5750452023-05-15 16:46:42 +08007358 wifi_reloadAp(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08007359 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
7360
7361 return RETURN_OK;
7362}
7363
7364// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
7365INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
7366{
7367 //save to wifi config, and wait for wifi restart to apply
7368 struct params params={'\0'};
7369 char config_file[MAX_BUF_SIZE] = {0};
7370 int ret;
7371
7372 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7373 if(authMode == NULL)
7374 return RETURN_ERR;
7375
7376 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
7377 params.name = "wpa_key_mgmt";
7378
7379 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
7380 params.value = "WPA-PSK";
7381 else if(strcmp(authMode,"EAPAuthentication") == 0)
7382 params.value = "WPA-EAP";
7383 else if (strcmp(authMode, "SAEAuthentication") == 0)
7384 params.value = "SAE";
7385 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
7386 params.value = "WPA-EAP-SUITE-B-192";
7387 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
7388 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer3086e2f2023-01-17 09:40:01 +08007389 else if (strcmp(authMode, "Enhanced_Open") == 0)
7390 params.value = "OWE";
developer72fb0bb2023-01-11 09:46:29 +08007391 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
7392 return RETURN_OK; //This is taken careof in beaconType
7393
7394 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7395 ret=wifi_hostapdWrite(config_file,&params,1);
7396 if(!ret)
7397 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
7398 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7399
7400 return ret;
7401}
7402
7403// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
7404INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
7405{
7406 //save to wifi config, and wait for wifi restart to apply
7407 char BeaconType[50] = {0};
7408 char config_file[MAX_BUF_SIZE] = {0};
7409
7410 *authMode = 0;
7411 wifi_getApBeaconType(apIndex,BeaconType);
7412 printf("%s____%s \n",__FUNCTION__,BeaconType);
7413
7414 if(strcmp(BeaconType,"None") == 0)
7415 strcpy(authMode,"None");
7416 else
7417 {
7418 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7419 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
7420 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
7421 if(strcmp(authMode,"WPA-PSK") == 0)
7422 strcpy(authMode,"SharedAuthentication");
7423 else if(strcmp(authMode,"WPA-EAP") == 0)
7424 strcpy(authMode,"EAPAuthentication");
7425 }
7426
7427 return RETURN_OK;
7428}
7429
7430// Outputs the number of stations associated per AP
7431INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
7432{
7433 char interface_name[16] = {0};
7434 char cmd[128]={0};
7435 char buf[128]={0};
7436 BOOL status = false;
7437
7438 if(apIndex > MAX_APS)
7439 return RETURN_ERR;
7440
7441 wifi_getApEnable(apIndex,&status);
7442 if (!status)
7443 return RETURN_OK;
7444
7445 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);//alternate method
7446 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7447 return RETURN_ERR;
7448 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l", interface_name);
7449 _syscmd(cmd, buf, sizeof(buf));
7450 sscanf(buf,"%lu", output_ulong);
7451
7452 return RETURN_OK;
7453}
7454
7455// manually removes any active wi-fi association with the device specified on this ap
7456INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
7457{
developer7e4a2a62023-04-06 19:56:03 +08007458 char inf_name[16] = {0};
7459 char cmd[MAX_CMD_SIZE] = {0};
7460 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08007461
developer7e4a2a62023-04-06 19:56:03 +08007462 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
developer72fb0bb2023-01-11 09:46:29 +08007463 return RETURN_ERR;
developer7e4a2a62023-04-06 19:56:03 +08007464
7465 snprintf(cmd, sizeof(cmd),"hostapd_cli -i %s disassociate %s", inf_name, client_mac);
7466 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08007467
7468 return RETURN_OK;
7469}
7470
7471// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
7472INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
7473{
developer7e4a2a62023-04-06 19:56:03 +08007474 int max_radio_num = 0;
7475
7476 if(NULL == output_int)
7477 return RETURN_ERR;
7478
7479 wifi_getMaxRadioNumber(&max_radio_num);
7480 *output_int = apIndex % max_radio_num;
7481
7482 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08007483}
7484
7485// sets the radio index for the specific ap
7486INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
7487{
7488 //set to config only and wait for wifi reset to apply settings
7489 return RETURN_ERR;
7490}
7491
developer121a8e72023-05-22 09:19:39 +08007492
7493#define MAX_ACL_DUMP_LEN 4096
7494int mtk_acl_list_dump_callback(struct nl_msg *msg, void *cb)
7495{
7496 struct nlattr *tb[NL80211_ATTR_MAX + 1];
7497 struct nlattr *vndr_tb[MTK_NL80211_VENDOR_AP_ACL_ATTR_MAX + 1];
7498 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
7499 char *show_str = NULL;
developer2edaf012023-05-24 14:24:53 +08007500 int err = 0;
developer121a8e72023-05-22 09:19:39 +08007501 unsigned short acl_result_len = 0;
7502 struct mtk_nl80211_cb_data *cb_data = cb;
developer121a8e72023-05-22 09:19:39 +08007503 if (!msg || !cb_data) {
developer2edaf012023-05-24 14:24:53 +08007504 wifi_debug(DEBUG_ERROR, "msg(0x%lx) or cb_data(0x%lx) is null,error.\n", msg, cb_data);
developer121a8e72023-05-22 09:19:39 +08007505 return NL_SKIP;
7506 }
developer121a8e72023-05-22 09:19:39 +08007507 err = nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
7508 genlmsg_attrlen(gnlh, 0), NULL);
7509 if (err < 0) {
developer2edaf012023-05-24 14:24:53 +08007510 wifi_debug(DEBUG_ERROR, "nla_parse acl list nl80211 msg fails,error.\n");
developer121a8e72023-05-22 09:19:39 +08007511 return NL_SKIP;
7512 }
developer121a8e72023-05-22 09:19:39 +08007513 if (tb[NL80211_ATTR_VENDOR_DATA]) {
7514 err = nla_parse_nested(vndr_tb, MTK_NL80211_VENDOR_AP_ACL_ATTR_MAX,
7515 tb[NL80211_ATTR_VENDOR_DATA], NULL);
7516 if (err < 0)
7517 return NL_SKIP;
7518 if (vndr_tb[MTK_NL80211_VENDOR_ATTR_ACL_LIST_INFO]) {
7519 acl_result_len = nla_len(vndr_tb[MTK_NL80211_VENDOR_ATTR_ACL_LIST_INFO]);
7520 show_str = nla_data(vndr_tb[MTK_NL80211_VENDOR_ATTR_ACL_LIST_INFO]);
7521 if (acl_result_len > MAX_ACL_DUMP_LEN) {
7522 wifi_debug(DEBUG_ERROR,"the scan result len is invalid !!!\n");
7523 return NL_SKIP;
7524 } else if (*(show_str + acl_result_len - 1) != '\0') {
7525 wifi_debug(DEBUG_INFO, "the result string is not ended with right terminator, handle it!!!\n");
7526 *(show_str + acl_result_len - 1) = '\0';
7527 }
7528 wifi_debug(DEBUG_INFO, "driver msg:%s\n", show_str);
developer2edaf012023-05-24 14:24:53 +08007529
7530 if (cb_data->out_len >= acl_result_len) {
7531 memset(cb_data->out_buf, 0, cb_data->out_len);
7532 /*skip the first line: 'policy=1\n' to find the acl mac addrs*/
7533 memmove(cb_data->out_buf, show_str, acl_result_len);
7534 wifi_debug(DEBUG_INFO, "out buff:%s\n", cb_data->out_buf);
7535 } else {
7536 memset(cb_data->out_buf, 0, cb_data->out_len);
developer121a8e72023-05-22 09:19:39 +08007537 }
developer121a8e72023-05-22 09:19:39 +08007538 } else
7539 wifi_debug(DEBUG_ERROR, "no acl result attr\n");
7540 } else
7541 wifi_debug(DEBUG_ERROR, "no any acl result from driver\n");
7542 return NL_OK;
7543}
developer72fb0bb2023-01-11 09:46:29 +08007544// Get the ACL MAC list per AP
developer2edaf012023-05-24 14:24:53 +08007545INT mtk_wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
developer72fb0bb2023-01-11 09:46:29 +08007546{
developer7e4a2a62023-04-06 19:56:03 +08007547 char inf_name[IF_NAME_SIZE] = {0};
developer121a8e72023-05-22 09:19:39 +08007548 struct mtk_nl80211_param params;
7549 unsigned int if_idx = 0;
7550 int ret = -1;
7551 struct unl unl_ins;
7552 struct nl_msg *msg = NULL;
7553 struct nlattr * msg_data = NULL;
7554 struct mtk_nl80211_param param;
7555 struct mtk_nl80211_cb_data cb_data;
developer7e4a2a62023-04-06 19:56:03 +08007556 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
7557 return RETURN_ERR;
developer121a8e72023-05-22 09:19:39 +08007558 if_idx = if_nametoindex(inf_name);
7559 if (!if_idx) {
developer2edaf012023-05-24 14:24:53 +08007560 wifi_debug(DEBUG_ERROR,"can't finde ifname(%s) index,ERROR\n", inf_name);
developer121a8e72023-05-22 09:19:39 +08007561 return RETURN_ERR;
7562 }
7563 /*init mtk nl80211 vendor cmd*/
7564 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_ACL;
7565 param.if_type = NL80211_ATTR_IFINDEX;
7566 param.if_idx = if_idx;
7567
7568 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
7569 if (ret) {
7570 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
7571 return RETURN_ERR;
7572 }
developer121a8e72023-05-22 09:19:39 +08007573 /*add mtk vendor cmd data*/
7574 if (nla_put_flag(msg, MTK_NL80211_VENDOR_ATTR_ACL_SHOW_ALL)) {
developer2edaf012023-05-24 14:24:53 +08007575 wifi_debug(DEBUG_ERROR, "Nla put ACL_SHOW_ALL attribute error\n");
developer121a8e72023-05-22 09:19:39 +08007576 nlmsg_free(msg);
7577 goto err;
7578 }
developer72fb0bb2023-01-11 09:46:29 +08007579
developer121a8e72023-05-22 09:19:39 +08007580 /*send mtk nl80211 vendor msg*/
7581 cb_data.out_buf = macArray;
7582 cb_data.out_len = buf_size;
7583
7584 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, mtk_acl_list_dump_callback, &cb_data);
7585 if (ret) {
7586 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
7587 goto err;
7588 }
7589 /*deinit mtk nl80211 vendor msg*/
7590 mtk_nl80211_deint(&unl_ins);
developer2edaf012023-05-24 14:24:53 +08007591 wifi_debug(DEBUG_NOTICE,"send cmd success, get out_buf:%s\n", macArray);
developer72fb0bb2023-01-11 09:46:29 +08007592 return RETURN_OK;
developer121a8e72023-05-22 09:19:39 +08007593err:
7594 mtk_nl80211_deint(&unl_ins);
developer2edaf012023-05-24 14:24:53 +08007595 wifi_debug(DEBUG_ERROR,"send cmd fails\n");
developer121a8e72023-05-22 09:19:39 +08007596 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007597}
7598
developer2edaf012023-05-24 14:24:53 +08007599INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
7600{
7601 char *mac_arry_buf = NULL;
7602
7603 mac_arry_buf = malloc(buf_size);
7604 if (!mac_arry_buf) {
7605 wifi_debug(DEBUG_ERROR,"malloc mac_arry_buf fails\n");
7606 return RETURN_ERR;
7607 }
7608 memset(mac_arry_buf, 0, buf_size);
7609 if (mtk_wifi_getApAclDevices(apIndex, mac_arry_buf, buf_size) != RETURN_OK) {
7610 wifi_debug(DEBUG_ERROR,"mtk_wifi_getApAclDevices get fails\n");
7611 free(mac_arry_buf);
7612 mac_arry_buf = NULL;
7613 return RETURN_ERR;
7614 }
7615 /*
7616 mtk format to wifi hal format:
7617 "policy=1
7618 00:11:22:33:44:55
7619 00:11:22:33:44:66
7620 "
7621 -->
7622 "00:11:22:33:44:55
7623 00:11:22:33:44:66
7624 "
7625 */
7626 memset(macArray, 0, buf_size);
7627 if (*mac_arry_buf != '\0' && strchr(mac_arry_buf,'\n')) {
7628 memmove(macArray, strchr(mac_arry_buf,'\n')+1, strlen(strchr(mac_arry_buf,'\n')+1)+1);
7629 wifi_debug(DEBUG_NOTICE,"macArray:\n%s\n", macArray);
7630 }
7631 free(mac_arry_buf);
7632 mac_arry_buf = NULL;
7633 return RETURN_OK;
7634}
7635
developer72fb0bb2023-01-11 09:46:29 +08007636INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
7637{
developer72fb0bb2023-01-11 09:46:29 +08007638
developer7e4a2a62023-04-06 19:56:03 +08007639 wifi_getApAclDevices(apIndex, macArray, buf_size);
developer72fb0bb2023-01-11 09:46:29 +08007640
7641 return RETURN_OK;
7642}
7643
7644
7645// Get the list of stations associated per AP
7646INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
7647{
developer7e4a2a62023-04-06 19:56:03 +08007648 char interface_name[IF_NAME_SIZE] = {0};
7649 char cmd[MAX_CMD_SIZE];
developer72fb0bb2023-01-11 09:46:29 +08007650
developer7e4a2a62023-04-06 19:56:03 +08007651 if(apIndex > 3) //Currently supporting apIndex upto 3
7652 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007653
developer7e4a2a62023-04-06 19:56:03 +08007654 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7655 return RETURN_ERR;
7656
7657 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s list_sta", interface_name);
7658 _syscmd(cmd, macArray, buf_size);
7659 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08007660}
7661
developer8dd72532023-05-17 19:58:35 +08007662int hex2num(char c)
7663{
7664 if (c >= '0' && c <= '9')
7665 return c - '0';
7666 if (c >= 'a' && c <= 'f')
7667 return c - 'a' + 10;
7668 if (c >= 'A' && c <= 'F')
7669 return c - 'A' + 10;
7670 return -1;
7671}
7672
7673/**
7674 * hwaddr_aton2 - Convert ASCII string to MAC address (in any known format)
7675 * @txt: MAC address as a string (e.g., 00:11:22:33:44:55 or 0011.2233.4455)
7676 * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
7677 * Returns: Characters used (> 0) on success, -1 on failure
7678 */
7679int hwaddr_aton2(const char *txt, unsigned char *addr)
7680{
7681 int i;
7682 const char *pos = txt;
7683
7684 for (i = 0; i < 6; i++) {
7685 int a, b;
7686
7687 while (*pos == ':' || *pos == '.' || *pos == '-')
7688 pos++;
7689
7690 a = hex2num(*pos++);
7691 if (a < 0)
7692 return -1;
7693 b = hex2num(*pos++);
7694 if (b < 0)
7695 return -1;
7696 *addr++ = (a << 4) | b;
7697 }
7698
7699 return pos - txt;
7700}
7701
developer72fb0bb2023-01-11 09:46:29 +08007702// adds the mac address to the filter list
7703//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
7704INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
7705{
developer7e4a2a62023-04-06 19:56:03 +08007706 char inf_name[IF_NAME_SIZE] = {0};
developer8dd72532023-05-17 19:58:35 +08007707 int if_idx, ret = 0;
developer49b17232023-05-19 16:35:19 +08007708 struct nl_msg *msg = NULL;
7709 struct nlattr * msg_data = NULL;
7710 struct mtk_nl80211_param param;
developer8dd72532023-05-17 19:58:35 +08007711 unsigned char mac[ETH_ALEN] = {0x00, 0x0c, 0x43, 0x11, 0x22, 0x33};
7712 struct unl unl_ins;
developer7e4a2a62023-04-06 19:56:03 +08007713 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
7714 return RETURN_ERR;
developer7e4a2a62023-04-06 19:56:03 +08007715 if (!DeviceMacAddress)
7716 return RETURN_ERR;
developer8dd72532023-05-17 19:58:35 +08007717 if (hwaddr_aton2(DeviceMacAddress, mac) < 0) {
developer2edaf012023-05-24 14:24:53 +08007718 wifi_debug(DEBUG_ERROR, "error device mac address=%s\n", DeviceMacAddress);
developer8dd72532023-05-17 19:58:35 +08007719 return RETURN_ERR;
7720 }
developer8dd72532023-05-17 19:58:35 +08007721 if_idx = if_nametoindex(inf_name);
developer2edaf012023-05-24 14:24:53 +08007722 if (!if_idx) {
7723 wifi_debug(DEBUG_ERROR, "can't finde ifname(%s) index,ERROR\n", inf_name);
7724 return RETURN_ERR;
7725 }
developer49b17232023-05-19 16:35:19 +08007726 /*init mtk nl80211 vendor cmd*/
7727 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_ACL;
7728 param.if_type = NL80211_ATTR_IFINDEX;
7729 param.if_idx = if_idx;
7730 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
7731 if (ret) {
7732 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
developer8dd72532023-05-17 19:58:35 +08007733 return RETURN_ERR;
7734 }
developer49b17232023-05-19 16:35:19 +08007735 /*add mtk vendor cmd data*/
7736 if (nla_put(msg, MTK_NL80211_VENDOR_ATTR_ACL_ADD_MAC, ETH_ALEN, mac)) {
developer2edaf012023-05-24 14:24:53 +08007737 wifi_debug(DEBUG_ERROR, "Nla put attribute error\n");
developer8dd72532023-05-17 19:58:35 +08007738 nlmsg_free(msg);
7739 goto err;
7740 }
developer49b17232023-05-19 16:35:19 +08007741 /*send mtk nl80211 vendor msg*/
7742 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
7743 if (ret) {
7744 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
developer8dd72532023-05-17 19:58:35 +08007745 goto err;
7746 }
developer49b17232023-05-19 16:35:19 +08007747 /*deinit mtk nl80211 vendor msg*/
7748 mtk_nl80211_deint(&unl_ins);
7749 wifi_debug(DEBUG_NOTICE, "set cmd success.\n");
developer8dd72532023-05-17 19:58:35 +08007750 return RETURN_OK;
7751err:
developer49b17232023-05-19 16:35:19 +08007752 mtk_nl80211_deint(&unl_ins);
7753 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
developer8dd72532023-05-17 19:58:35 +08007754 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007755}
7756
7757// deletes the mac address from the filter list
7758//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
7759INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
7760{
developer2edaf012023-05-24 14:24:53 +08007761 struct unl unl_ins;
7762 int if_idx = 0, ret = 0;
7763 struct nl_msg *msg = NULL;
7764 struct nlattr * msg_data = NULL;
7765 struct mtk_nl80211_param param;
developer7e4a2a62023-04-06 19:56:03 +08007766 char inf_name[IF_NAME_SIZE] = {0};
developer2edaf012023-05-24 14:24:53 +08007767 unsigned char mac[ETH_ALEN] = {0};
developer72fb0bb2023-01-11 09:46:29 +08007768
developer7e4a2a62023-04-06 19:56:03 +08007769 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
7770 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007771
developer7e4a2a62023-04-06 19:56:03 +08007772 if (!DeviceMacAddress)
7773 return RETURN_ERR;
7774
developer2edaf012023-05-24 14:24:53 +08007775 if (hwaddr_aton2(DeviceMacAddress, mac) < 0) {
7776 wifi_debug(DEBUG_ERROR, "error device mac address=%s\n", DeviceMacAddress);
7777 return RETURN_ERR;
7778 }
developer72fb0bb2023-01-11 09:46:29 +08007779
developer2edaf012023-05-24 14:24:53 +08007780 if_idx = if_nametoindex(inf_name);
7781 if (!if_idx) {
7782 wifi_debug(DEBUG_ERROR, "can't finde ifname(%s) index,ERROR\n", inf_name);
7783 return RETURN_ERR;
7784 }
7785 /*init mtk nl80211 vendor cmd*/
7786 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_ACL;
7787 param.if_type = NL80211_ATTR_IFINDEX;
7788 param.if_idx = if_idx;
7789 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
7790 if (ret) {
7791 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
7792 return RETURN_ERR;
7793 }
7794 /*add mtk vendor cmd data*/
7795 if (nla_put(msg, MTK_NL80211_VENDOR_ATTR_ACL_DEL_MAC, ETH_ALEN, mac)) {
7796 wifi_debug(DEBUG_ERROR, "Nla put attribute error\n");
7797 nlmsg_free(msg);
7798 goto err;
7799 }
7800 /*send mtk nl80211 vendor msg*/
7801 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
7802 if (ret) {
7803 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
7804 goto err;
7805 }
7806 /*deinit mtk nl80211 vendor msg*/
7807 mtk_nl80211_deint(&unl_ins);
7808 wifi_debug(DEBUG_NOTICE, "set cmd success.\n");
7809 return RETURN_OK;
7810err:
7811 mtk_nl80211_deint(&unl_ins);
7812 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
7813 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007814}
7815
7816// outputs the number of devices in the filter list
7817INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
7818{
developer7e4a2a62023-04-06 19:56:03 +08007819 char inf_name[IF_NAME_SIZE] = {0};
developer2edaf012023-05-24 14:24:53 +08007820 char *mac_arry = NULL, *ptr = NULL, mac_str[18] = {0};
7821 UINT buf_size = 1024;
7822 UINT sta_num = 0;
7823 unsigned char mac[ETH_ALEN] = {0};
developer72fb0bb2023-01-11 09:46:29 +08007824 if(output_uint == NULL)
7825 return RETURN_ERR;
7826
developer2edaf012023-05-24 14:24:53 +08007827 mac_arry = (char *)malloc(buf_size);
7828 if (mac_arry == NULL) {
7829 wifi_debug(DEBUG_ERROR, "malloc mac_arry fails\n");
developer7e4a2a62023-04-06 19:56:03 +08007830 return RETURN_ERR;
developer2edaf012023-05-24 14:24:53 +08007831 }
7832 memset(mac_arry, buf_size, 0);
7833 /*mac_arry str format: 00:11:22:33:44:55\n00:11:22:33:44:66\0*/
7834 if (wifi_getApAclDevices(apIndex, mac_arry, buf_size)!= RETURN_OK) {
7835 wifi_debug(DEBUG_ERROR, "get acl list entries fails\n");
7836 return RETURN_ERR;
7837 }
7838 /*count the acl str nums:*/
7839 wifi_debug(DEBUG_NOTICE, "mac_arry: %s\n", mac_arry);
developer7e4a2a62023-04-06 19:56:03 +08007840
developer2edaf012023-05-24 14:24:53 +08007841 /*mac addr string format:
7842 exp1: 00:11:22:33:44:55\0
7843 exp2: 00:11:22:33:44:55\n00:11:22:33:44:66\0
7844 */
7845 ptr = mac_arry;
7846 while (sscanf(ptr, "%17s", mac_str) == 1) {
7847 if (hwaddr_aton2(mac_str, mac) >= 0)
7848 sta_num++;
7849 ptr = strstr(ptr, mac_str) + strlen(mac_str);
7850 }
7851 *output_uint = sta_num;
7852 wifi_debug(DEBUG_NOTICE, "output_uint: %d\n", *output_uint);
7853 free(mac_arry);
7854 mac_arry = NULL;
developer7e4a2a62023-04-06 19:56:03 +08007855 return RETURN_OK;
developer2edaf012023-05-24 14:24:53 +08007856err:
7857 free(mac_arry);
7858 mac_arry = NULL;
7859 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007860}
7861
7862INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
7863{
7864 char cmd[128]={'\0'};
7865 char buf[128]={'\0'};
7866
7867 if(strcmp(action,"DENY")==0)
7868 {
7869 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
7870 system(buf);
7871 return RETURN_OK;
7872 }
7873
7874 if(strcmp(action,"ALLOW")==0)
7875 {
7876 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
7877 system(buf);
7878 return RETURN_OK;
7879 }
7880
7881 return RETURN_ERR;
7882
7883}
7884
7885// enable kick for devices on acl black list
7886INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
7887{
developer47cc27a2023-05-17 23:09:58 +08007888 char aclArray[MAX_BUF_SIZE] = {0}, *acl = NULL;
7889 char assocArray[MAX_BUF_SIZE] = {0}, *asso = NULL;
developer72fb0bb2023-01-11 09:46:29 +08007890
7891 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
7892 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
7893
developer7e4a2a62023-04-06 19:56:03 +08007894 /* if there are no devices connected there is nothing to do */
developer72fb0bb2023-01-11 09:46:29 +08007895 if (strlen(assocArray) < 17)
7896 return RETURN_OK;
7897
developer7e4a2a62023-04-06 19:56:03 +08007898 if (enable == TRUE) {
7899 /* kick off the MAC which is in ACL array (deny list) */
7900 acl = strtok(aclArray, "\n");
developer72fb0bb2023-01-11 09:46:29 +08007901 while (acl != NULL) {
7902 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
7903 wifi_kickApAssociatedDevice(apIndex, acl);
7904
developer7e4a2a62023-04-06 19:56:03 +08007905 acl = strtok(NULL, "\n");
developer72fb0bb2023-01-11 09:46:29 +08007906 }
7907 wifi_setApMacAddressControlMode(apIndex, 2);
developer7e4a2a62023-04-06 19:56:03 +08007908 } else
developer72fb0bb2023-01-11 09:46:29 +08007909 wifi_setApMacAddressControlMode(apIndex, 0);
developer72fb0bb2023-01-11 09:46:29 +08007910
developer72fb0bb2023-01-11 09:46:29 +08007911 return RETURN_OK;
7912}
7913
7914INT wifi_setPreferPrivateConnection(BOOL enable)
7915{
7916 return RETURN_OK;
7917}
7918
7919// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
7920INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
7921{
developer2edaf012023-05-24 14:24:53 +08007922 int if_idx = 0, ret = 0;
7923 struct unl unl_ins;
7924 struct nl_msg *msg = NULL;
7925 struct nlattr * msg_data = NULL;
7926 struct mtk_nl80211_param param;
7927 int acl_policy = -1;
developer7e4a2a62023-04-06 19:56:03 +08007928 char inf_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08007929
developer7e4a2a62023-04-06 19:56:03 +08007930 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
7931 return RETURN_ERR;
developer2edaf012023-05-24 14:24:53 +08007932 if_idx = if_nametoindex(inf_name);
7933 if (!if_idx) {
7934 wifi_debug(DEBUG_ERROR, "can't finde ifname(%s) index,ERROR\n", inf_name);
7935 return RETURN_ERR;
7936 }
7937 /*init mtk nl80211 vendor cmd*/
7938 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_ACL;
7939 param.if_type = NL80211_ATTR_IFINDEX;
7940 param.if_idx = if_idx;
7941 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
7942 if (ret) {
7943 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
7944 return RETURN_ERR;
7945 }
7946 /*add mtk vendor cmd data*/
7947 if (filterMode == 0) {
7948 acl_policy = MTK_NL80211_VENDOR_ATTR_ACL_DISABLE;
7949 } else if (filterMode == 1) {
7950 acl_policy = MTK_NL80211_VENDOR_ATTR_ACL_ENABLE_WHITE_LIST;
7951 } else if (filterMode == 2) {
7952 acl_policy = MTK_NL80211_VENDOR_ATTR_ACL_ENABLE_BLACK_LIST;
7953 } else {
7954 wifi_debug(DEBUG_ERROR, "filtermode(%d) not support error\n", filterMode);
7955 nlmsg_free(msg);
7956 goto err;
7957 }
7958 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_ACL_POLICY, acl_policy)) {
7959 wifi_debug(DEBUG_ERROR, "Nla put attribute error\n");
7960 nlmsg_free(msg);
7961 goto err;
7962 }
7963 /*send mtk nl80211 vendor msg*/
7964 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
7965 if (ret) {
7966 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
7967 goto err;
7968 }
7969 /*deinit mtk nl80211 vendor msg*/
7970 mtk_nl80211_deint(&unl_ins);
7971 wifi_debug(DEBUG_NOTICE, "set cmd success.\n");
developer7e4a2a62023-04-06 19:56:03 +08007972 return RETURN_OK;
developer2edaf012023-05-24 14:24:53 +08007973err:
7974 mtk_nl80211_deint(&unl_ins);
7975 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
7976 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007977}
7978
7979// 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.
7980INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
7981{
7982 return RETURN_ERR;
7983}
7984
7985// gets the vlan ID for this ap from an internal enviornment variable
7986INT wifi_getApVlanID(INT apIndex, INT *output_int)
7987{
7988 if(apIndex==0)
7989 {
7990 *output_int=100;
7991 return RETURN_OK;
7992 }
7993
7994 return RETURN_ERR;
7995}
7996
7997// sets the vlan ID for this ap to an internal enviornment variable
7998INT wifi_setApVlanID(INT apIndex, INT vlanId)
7999{
8000 //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)
8001 return RETURN_ERR;
8002}
8003
8004// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
8005INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
8006{
8007 snprintf(bridgeName, 32, "brlan0");
8008 snprintf(IP, 32, "10.0.0.1");
8009 snprintf(subnet, 32, "255.255.255.0");
8010
8011 return RETURN_OK;
8012}
8013
8014//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
8015INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
8016{
8017 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
8018 return RETURN_ERR;
8019}
8020
8021// reset the vlan configuration for this ap
8022INT wifi_resetApVlanCfg(INT apIndex)
8023{
developera1255e42023-05-13 17:45:02 +08008024 char interface_name[16] = {0};
developer2202b332023-05-24 16:23:22 +08008025 int if_idx, ret = 0;
8026 struct nl_msg *msg = NULL;
8027 struct nlattr * msg_data = NULL;
8028 struct mtk_nl80211_param param;
8029 struct unl unl_ins;
8030 struct vlan_policy_param vlan_param;
developer72fb0bb2023-01-11 09:46:29 +08008031
developer2202b332023-05-24 16:23:22 +08008032 if (apIndex > MAX_APS) {
8033 wifi_debug(DEBUG_ERROR, "Invalid apIndex %d\n", apIndex);
8034 return RETURN_ERR;
8035 }
developer72fb0bb2023-01-11 09:46:29 +08008036
developer2202b332023-05-24 16:23:22 +08008037 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8038 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8039 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08008040
developer2202b332023-05-24 16:23:22 +08008041 /*step 1. mwctl dev %s set vlan_tag 0*/
8042 if_idx = if_nametoindex(interface_name);
8043 /*init mtk nl80211 vendor cmd*/
8044 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_VLAN;
8045 param.if_type = NL80211_ATTR_IFINDEX;
8046 param.if_idx = if_idx;
8047 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
developer72fb0bb2023-01-11 09:46:29 +08008048
developer2202b332023-05-24 16:23:22 +08008049 if (ret) {
8050 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
8051 return RETURN_ERR;
8052 }
developer72fb0bb2023-01-11 09:46:29 +08008053
developer2202b332023-05-24 16:23:22 +08008054 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_VLAN_TAG_INFO, 0)) {
8055 printf("Nla put attribute error\n");
8056 nlmsg_free(msg);
8057 goto err;
8058 }
developer72fb0bb2023-01-11 09:46:29 +08008059
developer2202b332023-05-24 16:23:22 +08008060 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
8061 if (ret) {
8062 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vendor msg fails\n");
8063 goto err;
8064 }
8065 mtk_nl80211_deint(&unl_ins);
8066 wifi_debug(DEBUG_NOTICE, "set vlan_tag 0 cmd success.\n");
developer72fb0bb2023-01-11 09:46:29 +08008067
developer2202b332023-05-24 16:23:22 +08008068 /*step 2. mwctl dev %s set vlan_priority 0*/
8069 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
8070 if (ret) {
8071 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
8072 return RETURN_ERR;
8073 }
developer72fb0bb2023-01-11 09:46:29 +08008074
developer2202b332023-05-24 16:23:22 +08008075 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_VLAN_PRIORITY_INFO, 0)) {
8076 printf("Nla put attribute error\n");
8077 nlmsg_free(msg);
8078 goto err;
8079 }
developer72fb0bb2023-01-11 09:46:29 +08008080
developer2202b332023-05-24 16:23:22 +08008081 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
8082 if (ret) {
8083 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vendor msg fails\n");
8084 goto err;
8085 }
8086 mtk_nl80211_deint(&unl_ins);
8087 wifi_debug(DEBUG_NOTICE, "set vlan_priority 0 cmd success.\n");
8088
8089 /*step 3. mwctl dev %s set vlan_id 0*/
8090 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
8091 if (ret) {
8092 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
developera1255e42023-05-13 17:45:02 +08008093 return RETURN_ERR;
developer2202b332023-05-24 16:23:22 +08008094 }
developer72fb0bb2023-01-11 09:46:29 +08008095
developer2202b332023-05-24 16:23:22 +08008096 if (nla_put_u16(msg, MTK_NL80211_VENDOR_ATTR_VLAN_ID_INFO, 0)) {
8097 printf("Nla put attribute error\n");
8098 nlmsg_free(msg);
8099 goto err;
8100 }
8101
8102 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
8103 if (ret) {
8104 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vendor msg fails\n");
8105 goto err;
8106 }
8107 mtk_nl80211_deint(&unl_ins);
8108 wifi_debug(DEBUG_NOTICE, "set vlan_id cmd success.\n");
8109
8110 /*step 4. mwctl dev %s set vlan_en 0*/
8111 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
8112 if (ret) {
8113 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
8114 return RETURN_ERR;
8115 }
8116
8117 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_VLAN_EN_INFO, 0)) {
8118 printf("Nla put attribute error\n");
8119 nlmsg_free(msg);
8120 goto err;
8121 }
8122
8123 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
8124 if (ret) {
8125 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vendor msg fails\n");
8126 goto err;
8127 }
8128 mtk_nl80211_deint(&unl_ins);
8129 wifi_debug(DEBUG_NOTICE, "set vlan_id cmd success.\n");
8130
8131 /*step 5. mwctl dev %s set vlan_policy 0:4*/
8132 vlan_param.direction = 0;
8133 vlan_param.policy = 4;
8134 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
8135 if (ret) {
8136 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
8137 return RETURN_ERR;
8138 }
8139 if (nla_put(msg, MTK_NL80211_VENDOR_ATTR_VLAN_POLICY_INFO, sizeof(vlan_param), &vlan_param)) {
8140 printf("Nla put attribute error\n");
8141 nlmsg_free(msg);
8142 goto err;
8143 }
8144
8145 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
8146 if (ret) {
8147 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vendor msg fails\n");
8148 goto err;
8149 }
8150 mtk_nl80211_deint(&unl_ins);
8151 wifi_debug(DEBUG_NOTICE, "set vlan_policy 0:4 cmd success.\n");
8152
8153 /*step 6. mwctl dev %s set vlan_policy 1:0*/
8154 vlan_param.direction = 1;
8155 vlan_param.policy = 0;
8156 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
8157 if (ret) {
8158 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
8159 return RETURN_ERR;
8160 }
8161
8162 if (nla_put(msg, MTK_NL80211_VENDOR_ATTR_VLAN_POLICY_INFO, sizeof(vlan_param), &vlan_param)) {
8163 printf("Nla put attribute error\n");
8164 nlmsg_free(msg);
8165 goto err;
8166 }
8167
8168 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
8169 if (ret) {
8170 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vendor msg fails\n");
8171 goto err;
8172 }
8173 /*deinit mtk nl80211 vendor msg*/
8174 mtk_nl80211_deint(&unl_ins);
8175 wifi_debug(DEBUG_NOTICE, "set vlan_policy 1:0 cmd success.\n");
8176
8177 /*TODO need to modify VLAN config in dat file*/
8178 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8179
8180 return RETURN_OK;
8181err:
8182 mtk_nl80211_deint(&unl_ins);
8183 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
8184 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08008185}
8186
8187// 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.
8188INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
8189{
8190 return RETURN_ERR;
8191}
8192
8193// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
8194INT wifi_startHostApd()
8195{
8196 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8197 system("systemctl start hostapd.service");
8198 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8199 return RETURN_OK;
8200 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
8201}
8202
8203// stops hostapd
developer69b61b02023-03-07 17:17:44 +08008204INT wifi_stopHostApd()
developer72fb0bb2023-01-11 09:46:29 +08008205{
8206 char cmd[128] = {0};
8207 char buf[128] = {0};
8208
8209 sprintf(cmd,"systemctl stop hostapd");
8210 _syscmd(cmd, buf, sizeof(buf));
8211
8212 return RETURN_OK;
8213}
8214
8215// restart hostapd dummy function
8216INT wifi_restartHostApd()
8217{
8218 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8219 system("systemctl restart hostapd-global");
8220 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8221
8222 return RETURN_OK;
8223}
8224
8225static int align_hostapd_config(int index)
8226{
8227 ULONG lval;
8228 wifi_getRadioChannel(index%2, &lval);
8229 wifi_setRadioChannel(index%2, lval);
8230 return RETURN_OK;
8231}
8232
8233// sets the AP enable status variable for the specified ap.
8234INT wifi_setApEnable(INT apIndex, BOOL enable)
8235{
developer7e4a2a62023-04-06 19:56:03 +08008236 char interface_name[16] = {0};
8237 char config_file[MAX_BUF_SIZE] = {0};
8238 char cmd[MAX_CMD_SIZE] = {0};
8239 char buf[MAX_BUF_SIZE] = {0};
developer47cc27a2023-05-17 23:09:58 +08008240 BOOL status = FALSE;
developer7e4a2a62023-04-06 19:56:03 +08008241 int max_radio_num = 0;
8242 int phyId = 0;
developer72fb0bb2023-01-11 09:46:29 +08008243
developer7e4a2a62023-04-06 19:56:03 +08008244 wifi_getApEnable(apIndex, &status);
developer72fb0bb2023-01-11 09:46:29 +08008245
developer7e4a2a62023-04-06 19:56:03 +08008246 wifi_getMaxRadioNumber(&max_radio_num);
8247 if (enable == status)
8248 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08008249
developer7e4a2a62023-04-06 19:56:03 +08008250 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8251 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08008252
developer7e4a2a62023-04-06 19:56:03 +08008253 if (enable == TRUE) {
8254 int radioIndex = apIndex % max_radio_num;
8255 phyId = radio_index_to_phy(radioIndex);
developer8a3bbbf2023-03-15 17:47:23 +08008256
developer7e4a2a62023-04-06 19:56:03 +08008257 snprintf(config_file, MAX_BUF_SIZE, "%s%d.conf", CONFIG_PREFIX, apIndex);
8258 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyId, config_file);
8259 _syscmd(cmd, buf, sizeof(buf));
8260 } else {
8261 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw REMOVE %s", interface_name);
8262 _syscmd(cmd, buf, sizeof(buf));
8263 }
8264 snprintf(cmd, MAX_CMD_SIZE, "sed -i -n -e '/^%s=/!p' -e '$a%s=%d' %s",
8265 interface_name, interface_name, enable, VAP_STATUS_FILE);
8266 _syscmd(cmd, buf, sizeof(buf));
8267 //Wait for wifi up/down to apply
8268 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08008269}
8270
8271// Outputs the setting of the internal variable that is set by wifi_setApEnable().
8272INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
8273{
developer7e4a2a62023-04-06 19:56:03 +08008274 char interface_name[IF_NAME_SIZE] = {0};
8275 char cmd[MAX_CMD_SIZE] = {0};
8276 char buf[MAX_BUF_SIZE] = {0};
developere740c2a2023-05-23 18:34:32 +08008277 int ret;
developer72fb0bb2023-01-11 09:46:29 +08008278
developer7e4a2a62023-04-06 19:56:03 +08008279 if ((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
8280 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08008281
developer7e4a2a62023-04-06 19:56:03 +08008282 *output_bool = 0;
developer72fb0bb2023-01-11 09:46:29 +08008283
developer7e4a2a62023-04-06 19:56:03 +08008284 if ((apIndex >= 0) && (apIndex < MAX_APS)) {
8285 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
8286 *output_bool = FALSE;
8287 return RETURN_OK;
8288 }
developere740c2a2023-05-23 18:34:32 +08008289 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status", interface_name);
8290 ret = system(cmd);
8291 if (ret == 0)
8292 *output_bool = 1;
developer7e4a2a62023-04-06 19:56:03 +08008293 }
developer72fb0bb2023-01-11 09:46:29 +08008294
developer7e4a2a62023-04-06 19:56:03 +08008295 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08008296}
8297
developer69b61b02023-03-07 17:17:44 +08008298// Outputs the AP "Enabled" "Disabled" status from driver
8299INT wifi_getApStatus(INT apIndex, CHAR *output_string)
developer72fb0bb2023-01-11 09:46:29 +08008300{
developer7e4a2a62023-04-06 19:56:03 +08008301 char cmd[128] = {0};
8302 char buf[128] = {0};
8303 BOOL output_bool;
developer72fb0bb2023-01-11 09:46:29 +08008304
developer7e4a2a62023-04-06 19:56:03 +08008305 if (!output_string) {
8306 printf("%s: null pointer!", __func__);
8307 return RETURN_ERR;
8308 }
developer72fb0bb2023-01-11 09:46:29 +08008309
developer7e4a2a62023-04-06 19:56:03 +08008310 wifi_getApEnable(apIndex, &output_bool);
developer72fb0bb2023-01-11 09:46:29 +08008311
developer7e4a2a62023-04-06 19:56:03 +08008312 if(output_bool == 1)
8313 snprintf(output_string, 32, "Up");
8314 else
8315 snprintf(output_string, 32, "Disable");
8316
8317 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08008318}
8319
8320//Indicates whether or not beacons include the SSID name.
8321// outputs a 1 if SSID on the AP is enabled, else outputs 0
8322INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
8323{
8324 //get the running status
8325 char config_file[MAX_BUF_SIZE] = {0};
8326 char buf[16] = {0};
8327
8328 if (!output)
8329 return RETURN_ERR;
8330
8331 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8332 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
8333 // default is enable
8334 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
8335 *output = TRUE;
8336
8337 return RETURN_OK;
8338}
8339
8340// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
8341INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
8342{
8343 //store the config, apply instantly
8344 char config_file[MAX_BUF_SIZE] = {0};
8345 struct params list;
8346
8347 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8348 list.name = "ignore_broadcast_ssid";
8349 list.value = enable?"0":"1";
8350
8351 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8352 wifi_hostapdWrite(config_file, &list, 1);
8353 wifi_hostapdProcessUpdate(apIndex, &list, 1);
8354 //TODO: call hostapd_cli for dynamic_config_control
8355 wifi_reloadAp(apIndex);
8356 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8357
8358 return RETURN_OK;
8359}
8360
8361//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
8362INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
8363{
developer47cc27a2023-05-17 23:09:58 +08008364 /* get the running status */
8365 if(!output_uint)
8366 return RETURN_ERR;
8367
8368 *output_uint = 15;
8369 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08008370}
8371
developer47cc27a2023-05-17 23:09:58 +08008372/*Do not support AP retry limit fix*/
developer72fb0bb2023-01-11 09:46:29 +08008373INT wifi_setApRetryLimit(INT apIndex, UINT number)
8374{
developer47cc27a2023-05-17 23:09:58 +08008375 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08008376}
8377
developer95c045d2023-05-24 19:26:28 +08008378int get_wmm_cap_status_callback(struct nl_msg *msg, void *data)
8379{
8380 struct nlattr *tb[NL80211_ATTR_MAX + 1];
8381 struct nlattr *vndr_tb[MTK_NL80211_VENDOR_WMM_ATTR_MAX + 1];
8382 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
8383 unsigned char *status = (unsigned char * *)data;
8384 int err = 0;
8385 //u16 acl_result_len = 0;
8386
8387 err = nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
8388 genlmsg_attrlen(gnlh, 0), NULL);
8389 if (err < 0)
8390 return err;
8391
8392 if (tb[NL80211_ATTR_VENDOR_DATA]) {
8393 err = nla_parse_nested(vndr_tb, MTK_NL80211_VENDOR_WMM_ATTR_MAX,
8394 tb[NL80211_ATTR_VENDOR_DATA], NULL);
8395 if (err < 0)
8396 return err;
8397
8398 if (vndr_tb[MTK_NL80211_VENDOR_ATTR_WMM_AP_CAP_INFO]) {
8399 //acl_result_len = nla_len(vndr_tb[MTK_NL80211_VENDOR_ATTR_MCAST_SNOOP_ENABLE]);
8400 *status = nla_get_u8(vndr_tb[MTK_NL80211_VENDOR_ATTR_WMM_AP_CAP_INFO]);
8401 }
8402 }
8403
8404 return 0;
8405}
8406
developer72fb0bb2023-01-11 09:46:29 +08008407//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
8408INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
8409{
developer95c045d2023-05-24 19:26:28 +08008410 int if_idx, ret = 0;
developer8e6583c2023-05-23 13:36:06 +08008411 char interface_name[16] = {0};
developer95c045d2023-05-24 19:26:28 +08008412 unsigned char status = 0;
8413 struct nl_msg *msg = NULL;
8414 struct nlattr * msg_data = NULL;
8415 struct mtk_nl80211_param param;
8416 struct unl unl_ins;
8417 struct vlan_policy_param vlan_param;
developer8e6583c2023-05-23 13:36:06 +08008418
8419 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08008420 if(!output)
8421 return RETURN_ERR;
developer8e6583c2023-05-23 13:36:06 +08008422
developer95c045d2023-05-24 19:26:28 +08008423 if (apIndex > MAX_APS) {
8424 wifi_debug(DEBUG_ERROR, "Invalid apIndex %d\n", apIndex);
8425 return RETURN_ERR;
8426 }
8427
developer8e6583c2023-05-23 13:36:06 +08008428 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8429 return RETURN_ERR;
developer95c045d2023-05-24 19:26:28 +08008430
8431 if_idx = if_nametoindex(interface_name);
8432 /*init mtk nl80211 vendor cmd*/
8433 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_WMM;
8434 param.if_type = NL80211_ATTR_IFINDEX;
8435 param.if_idx = if_idx;
8436 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
8437
8438 if (ret) {
8439 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
8440 return RETURN_ERR;
8441 }
8442
8443 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_WMM_AP_CAP_INFO, 0xf)) {
8444 wifi_debug(DEBUG_ERROR, "Nla put attribute error\n");
8445 nlmsg_free(msg);
8446 goto err;
8447 }
8448
8449 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, get_wmm_cap_status_callback,
8450 (void *)&status);
8451 if (ret) {
8452 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vendor msg fails\n");
8453 goto err;
8454 }
8455 mtk_nl80211_deint(&unl_ins);
8456
8457 *output = status == 0 ? FALSE : TRUE;
8458 wifi_debug(DEBUG_NOTICE, "wmm cap (%u).\n", (unsigned int)(*output));
developer8e6583c2023-05-23 13:36:06 +08008459
8460 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08008461 return RETURN_OK;
developer95c045d2023-05-24 19:26:28 +08008462err:
8463 mtk_nl80211_deint(&unl_ins);
8464 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
8465 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08008466}
8467
8468//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
8469INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
8470{
8471 //get the running status from driver
8472 char cmd[128] = {0};
8473 char buf[128] = {0};
8474 int max_radio_num = 0, radioIndex = 0;
8475 int phyId = 0;
8476
8477 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8478
8479 wifi_getMaxRadioNumber(&max_radio_num);
8480 radioIndex = apIndex % max_radio_num;
8481 phyId = radio_index_to_phy(radioIndex);
8482 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", phyId);
8483 _syscmd(cmd,buf, sizeof(buf));
8484
8485 if (strlen(buf) > 0)
8486 *output = true;
8487
8488 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8489
8490 return RETURN_OK;
8491}
8492
8493//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
8494INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
8495{
developer95c045d2023-05-24 19:26:28 +08008496 return wifi_getApWMMCapability(apIndex, output);
developer72fb0bb2023-01-11 09:46:29 +08008497}
8498
8499// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
8500INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
8501{
developer95c045d2023-05-24 19:26:28 +08008502 int if_idx, ret = 0;
8503 char interface_name[16] = {0};
8504 unsigned char status = 0;
8505 struct nl_msg *msg = NULL;
8506 struct nlattr * msg_data = NULL;
8507 struct mtk_nl80211_param param;
8508 struct unl unl_ins;
8509 struct vlan_policy_param vlan_param;
developer72fb0bb2023-01-11 09:46:29 +08008510
developer95c045d2023-05-24 19:26:28 +08008511 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08008512
developer95c045d2023-05-24 19:26:28 +08008513 if (apIndex > MAX_APS) {
8514 wifi_debug(DEBUG_ERROR, "Invalid apIndex %d\n", apIndex);
8515 return RETURN_ERR;
8516 }
developer72fb0bb2023-01-11 09:46:29 +08008517
developer95c045d2023-05-24 19:26:28 +08008518 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8519 return RETURN_ERR;
developer8e6583c2023-05-23 13:36:06 +08008520
developer95c045d2023-05-24 19:26:28 +08008521 if_idx = if_nametoindex(interface_name);
8522 /*init mtk nl80211 vendor cmd*/
8523 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_WMM;
8524 param.if_type = NL80211_ATTR_IFINDEX;
8525 param.if_idx = if_idx;
8526 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
8527
8528 if (ret) {
8529 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
8530 return RETURN_ERR;
8531 }
8532
8533 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_WMM_AP_CAP_INFO, enable ? 1 : 0)) {
8534 wifi_debug(DEBUG_ERROR, "Nla put attribute error\n");
8535 nlmsg_free(msg);
8536 goto err;
8537 }
8538
8539 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
8540 if (ret) {
8541 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vendor msg fails\n");
8542 goto err;
8543 }
8544 mtk_nl80211_deint(&unl_ins);
8545
8546 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8547 return RETURN_OK;
8548err:
8549 mtk_nl80211_deint(&unl_ins);
8550 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
8551 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08008552}
8553
developer95c045d2023-05-24 19:26:28 +08008554
developer72fb0bb2023-01-11 09:46:29 +08008555//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.
8556INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
8557{
8558 //get the running status from driver
8559 if(!output)
8560 return RETURN_ERR;
8561
8562 char config_file[128] = {0};
8563 char buf[16] = {0};
8564
8565 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8566 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
8567 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
8568 *output = TRUE;
8569 else
8570 *output = FALSE;
8571
8572 return RETURN_OK;
8573}
8574
8575// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
8576INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
8577{
8578 //save config and apply instantly.
8579 char config_file[MAX_BUF_SIZE] = {0};
8580 struct params list;
8581
8582 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8583 list.name = "uapsd_advertisement_enabled";
8584 list.value = enable?"1":"0";
8585
8586 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8587 wifi_hostapdWrite(config_file, &list, 1);
8588 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developere82c0ca2023-05-10 16:25:35 +08008589 wifi_quick_reload_ap(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08008590 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8591
8592 return RETURN_OK;
8593}
8594
8595// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
8596INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
8597{
8598 char interface_name[16] = {0};
8599 // assume class 0->BE, 1->BK, 2->VI, 3->VO
8600 char cmd[128] = {0};
8601 char buf[128] = {0};
8602 char ack_filepath[128] = {0};
8603 uint16_t bitmap = 0;
8604 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
8605 FILE *f = NULL;
8606
8607 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
8608
8609 // Get current setting
8610 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
8611 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
8612 _syscmd(cmd, buf, sizeof(buf));
8613 if (strlen(buf) > 0)
8614 bitmap = strtoul(buf, NULL, 10);
8615
8616 bitmap = strtoul(buf, NULL, 10);
8617
8618 if (ackPolicy == TRUE) { // True, unset this class
8619 bitmap &= ~class_map[class];
8620 } else { // False, set this class
8621 bitmap |= class_map[class];
8622 }
8623
8624 f = fopen(ack_filepath, "w");
8625 if (f == NULL) {
8626 fprintf(stderr, "%s: fopen failed\n", __func__);
8627 return RETURN_ERR;
8628 }
8629 fprintf(f, "%hu", bitmap);
8630 fclose(f);
8631
8632 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8633 return RETURN_ERR;
8634 snprintf(cmd, sizeof(cmd), "iw dev %s set noack_map 0x%04x\n", interface_name, bitmap);
8635 _syscmd(cmd, buf, sizeof(buf));
8636
8637 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
8638 return RETURN_OK;
8639}
8640
8641//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.
8642INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
8643{
8644 //get the running status from driver
8645 if(!output_uint)
8646 return RETURN_ERR;
8647
8648 char output[16]={'\0'};
8649 char config_file[MAX_BUF_SIZE] = {0};
8650
8651 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8652 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
8653 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
8654 else {
8655 int device_num = atoi(output);
8656 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
8657 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
8658 return RETURN_ERR;
8659 }
8660 else {
8661 *output_uint = device_num;
8662 }
8663 }
8664
8665 return RETURN_OK;
8666}
8667
8668INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
8669{
8670 //store to wifi config, apply instantly
8671 char str[MAX_BUF_SIZE]={'\0'};
8672 char cmd[MAX_CMD_SIZE]={'\0'};
8673 struct params params;
8674 char config_file[MAX_BUF_SIZE] = {0};
8675
8676 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8677 if (number > MAX_ASSOCIATED_STA_NUM) {
8678 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
8679 return RETURN_ERR;
8680 }
8681 sprintf(str, "%d", number);
8682 params.name = "max_num_sta";
8683 params.value = str;
8684
8685 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
8686 int ret = wifi_hostapdWrite(config_file, &params, 1);
8687 if (ret) {
8688 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
8689 ,__func__, ret);
8690 }
8691
8692 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
8693 if (ret) {
8694 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
8695 ,__func__, ret);
8696 }
8697 wifi_reloadAp(apIndex);
8698 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8699
8700 return RETURN_OK;
8701}
8702
8703//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.
8704INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
8705{
8706 //get the current threshold
8707 if(!output_uint)
8708 return RETURN_ERR;
8709 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
8710 if (*output_uint == 0)
8711 *output_uint = 50;
8712 return RETURN_OK;
8713}
8714
8715INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
8716{
8717 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
8718 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
8719 return RETURN_OK;
8720 return RETURN_ERR;
8721}
8722
8723//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.
8724INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
8725{
8726 if(!output_uint)
8727 return RETURN_ERR;
8728 *output_uint = 3;
8729 return RETURN_OK;
8730}
8731
8732//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
8733INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
8734{
8735 if(!output_uint)
8736 return RETURN_ERR;
8737 *output_uint = 3;
8738 return RETURN_OK;
8739}
8740
8741//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.
8742INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
8743{
8744 if(!output_in_seconds)
8745 return RETURN_ERR;
8746 *output_in_seconds = 0;
8747 return RETURN_OK;
8748}
8749
8750//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
8751INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
8752{
8753 if(!output || apIndex>=MAX_APS)
8754 return RETURN_ERR;
8755 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
8756 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
8757 return RETURN_OK;
developer69b61b02023-03-07 17:17:44 +08008758}
developer72fb0bb2023-01-11 09:46:29 +08008759
8760//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
8761INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
8762{
8763 char config_file[128] = {0};
8764 char wpa[16] = {0};
8765 char key_mgmt[64] = {0};
8766 char buf[16] = {0};
8767 if (!output)
8768 return RETURN_ERR;
8769
8770 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8771 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
8772
8773 strcpy(output, "None");//Copying "None" to output string for default case
8774 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
8775 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
8776 if (!strcmp(wpa, "1"))
8777 snprintf(output, 32, "WPA-Personal");
8778 else if (!strcmp(wpa, "2"))
8779 snprintf(output, 32, "WPA2-Personal");
8780 else if (!strcmp(wpa, "3"))
8781 snprintf(output, 32, "WPA-WPA2-Personal");
8782
developere5750452023-05-15 16:46:42 +08008783 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
8784 snprintf(output, 32, "WPA3-Enterprise");
developer72fb0bb2023-01-11 09:46:29 +08008785 } else if (strstr(key_mgmt, "WPA-EAP")) {
8786 if (!strcmp(wpa, "1"))
8787 snprintf(output, 32, "WPA-Enterprise");
8788 else if (!strcmp(wpa, "2"))
8789 snprintf(output, 32, "WPA2-Enterprise");
8790 else if (!strcmp(wpa, "3"))
8791 snprintf(output, 32, "WPA-WPA2-Enterprise");
8792 } else if (strstr(key_mgmt, "SAE")) {
8793 if (strstr(key_mgmt, "WPA-PSK") == NULL)
8794 snprintf(output, 32, "WPA3-Personal");
8795 else
8796 snprintf(output, 32, "WPA3-Personal-Transition");
developer72fb0bb2023-01-11 09:46:29 +08008797 }
8798
8799 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
8800 return RETURN_OK;
8801#if 0
8802 //TODO: need to revisit below implementation
8803 char securityType[32], authMode[32];
8804 int enterpriseMode=0;
8805
8806 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8807 if(!output)
8808 return RETURN_ERR;
8809
8810 wifi_getApBeaconType(apIndex, securityType);
8811 strcpy(output,"None");//By default, copying "None" to output string
8812 if (strncmp(securityType,"None", strlen("None")) == 0)
8813 return RETURN_OK;
8814
8815 wifi_getApBasicAuthenticationMode(apIndex, authMode);
8816 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
8817
8818 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
8819 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
8820 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
8821 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
8822 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
8823 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
8824 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8825
8826 return RETURN_OK;
8827#endif
8828}
developer69b61b02023-03-07 17:17:44 +08008829
developer72fb0bb2023-01-11 09:46:29 +08008830INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
8831{
8832 char securityType[32];
8833 char authMode[32];
8834
8835 //store settings and wait for wifi up to apply
8836 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8837 if(!encMode)
8838 return RETURN_ERR;
8839
8840 if (strcmp(encMode, "None")==0)
8841 {
8842 strcpy(securityType,"None");
8843 strcpy(authMode,"None");
8844 }
8845 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
8846 {
8847 strcpy(securityType,"WPAand11i");
8848 strcpy(authMode,"PSKAuthentication");
8849 }
8850 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
8851 {
8852 strcpy(securityType,"WPAand11i");
8853 strcpy(authMode,"EAPAuthentication");
8854 }
8855 else if (strcmp(encMode, "WPA-Personal")==0)
8856 {
8857 strcpy(securityType,"WPA");
8858 strcpy(authMode,"PSKAuthentication");
8859 }
8860 else if (strcmp(encMode, "WPA-Enterprise")==0)
8861 {
8862 strcpy(securityType,"WPA");
8863 strcpy(authMode,"EAPAuthentication");
8864 }
8865 else if (strcmp(encMode, "WPA2-Personal")==0)
8866 {
8867 strcpy(securityType,"11i");
8868 strcpy(authMode,"PSKAuthentication");
8869 }
8870 else if (strcmp(encMode, "WPA2-Enterprise")==0)
8871 {
8872 strcpy(securityType,"11i");
8873 strcpy(authMode,"EAPAuthentication");
8874 }
8875 else if (strcmp(encMode, "WPA3-Personal") == 0)
8876 {
8877 strcpy(securityType,"11i");
8878 strcpy(authMode,"SAEAuthentication");
8879 }
8880 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
8881 {
8882 strcpy(securityType, "11i");
8883 strcpy(authMode, "PSK-SAEAuthentication");
8884 }
8885 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
8886 {
8887 strcpy(securityType,"11i");
8888 strcpy(authMode,"EAP_192-bit_Authentication");
8889 }
developer3086e2f2023-01-17 09:40:01 +08008890 else if (strcmp(encMode, "OWE") == 0)
8891 {
8892 strcpy(securityType,"11i");
8893 strcpy(authMode,"Enhanced_Open");
8894 }
developer72fb0bb2023-01-11 09:46:29 +08008895 else
8896 {
8897 strcpy(securityType,"None");
8898 strcpy(authMode,"None");
8899 }
8900 wifi_setApBeaconType(apIndex, securityType);
8901 wifi_setApBasicAuthenticationMode(apIndex, authMode);
8902 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8903
8904 return RETURN_OK;
developer69b61b02023-03-07 17:17:44 +08008905}
developer72fb0bb2023-01-11 09:46:29 +08008906
8907
8908//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
8909// output_string must be pre-allocated as 64 character string by caller
8910// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
8911INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
8912{
8913 char buf[16] = {0};
8914 char config_file[MAX_BUF_SIZE] = {0};
8915
8916 if(output_string==NULL)
8917 return RETURN_ERR;
8918
8919 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8920 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
8921
8922 if(strcmp(buf,"0")==0)
8923 {
8924 printf("wpa_mode is %s ......... \n",buf);
8925 return RETURN_ERR;
8926 }
8927
8928 wifi_dbg_printf("\nFunc=%s\n",__func__);
8929 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developere5750452023-05-15 16:46:42 +08008930 wifi_hostapdRead(config_file,"wpa_psk",output_string,65);
developer72fb0bb2023-01-11 09:46:29 +08008931 wifi_dbg_printf("\noutput_string=%s\n",output_string);
8932
8933 return RETURN_OK;
8934}
8935
8936// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
8937// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
8938INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
8939{
8940 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
8941 struct params params={'\0'};
8942 int ret;
8943 char config_file[MAX_BUF_SIZE] = {0};
8944
8945 if(NULL == preSharedKey)
8946 return RETURN_ERR;
8947
developere5750452023-05-15 16:46:42 +08008948 params.name = "wpa_psk";
developer72fb0bb2023-01-11 09:46:29 +08008949
developere5750452023-05-15 16:46:42 +08008950 if(strlen(preSharedKey) != 64)
developer72fb0bb2023-01-11 09:46:29 +08008951 {
developere5750452023-05-15 16:46:42 +08008952 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 64 chars\n");
developer72fb0bb2023-01-11 09:46:29 +08008953 return RETURN_ERR;
8954 }
8955 params.value = preSharedKey;
8956 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8957 ret = wifi_hostapdWrite(config_file, &params, 1);
developere5750452023-05-15 16:46:42 +08008958 if(!ret) {
developer72fb0bb2023-01-11 09:46:29 +08008959 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
developere5750452023-05-15 16:46:42 +08008960 wifi_reloadAp(apIndex);
8961 }
developer72fb0bb2023-01-11 09:46:29 +08008962 return ret;
8963 //TODO: call hostapd_cli for dynamic_config_control
8964}
8965
8966//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
8967// outputs the passphrase, maximum 63 characters
8968INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
8969{
8970 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
8971
8972 wifi_dbg_printf("\nFunc=%s\n",__func__);
8973 if (NULL == output_string)
8974 return RETURN_ERR;
8975
8976 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8977 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
8978 if(strcmp(buf,"0")==0)
8979 {
8980 printf("wpa_mode is %s ......... \n",buf);
8981 return RETURN_ERR;
8982 }
8983
8984 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
8985 wifi_dbg_printf("\noutput_string=%s\n",output_string);
8986
8987 return RETURN_OK;
8988}
8989
8990// sets the passphrase enviornment variable, max 63 characters
8991INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
8992{
8993 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
8994 struct params params={'\0'};
8995 char config_file[MAX_BUF_SIZE] = {0};
8996 int ret;
8997
8998 if(NULL == passPhrase)
8999 return RETURN_ERR;
9000
9001 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
9002 {
9003 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
9004 return RETURN_ERR;
9005 }
9006 params.name = "wpa_passphrase";
9007 params.value = passPhrase;
9008 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9009 ret=wifi_hostapdWrite(config_file,&params,1);
developere5750452023-05-15 16:46:42 +08009010 if(!ret) {
developer72fb0bb2023-01-11 09:46:29 +08009011 wifi_hostapdProcessUpdate(apIndex, &params, 1);
developere5750452023-05-15 16:46:42 +08009012 wifi_reloadAp(apIndex);
9013 }
developer72fb0bb2023-01-11 09:46:29 +08009014
9015 return ret;
9016}
9017
9018//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.
9019INT wifi_setApSecurityReset(INT apIndex)
9020{
9021 char original_config_file[64] = {0};
9022 char current_config_file[64] = {0};
9023 char buf[64] = {0};
9024 char cmd[64] = {0};
9025 char wpa[4] = {0};
9026 char wpa_psk[64] = {0};
9027 char wpa_passphrase[64] = {0};
9028 char wpa_psk_file[128] = {0};
9029 char wpa_key_mgmt[64] = {0};
9030 char wpa_pairwise[32] = {0};
9031 wifi_band band;
9032 struct params list[6];
9033
9034 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9035
9036 band = wifi_index_to_band(apIndex);
9037 if (band == band_2_4)
9038 sprintf(original_config_file, "/etc/hostapd-2G.conf");
9039 else if (band == band_5)
9040 sprintf(original_config_file, "/etc/hostapd-5G.conf");
9041 else if (band == band_6)
9042 sprintf(original_config_file, "/etc/hostapd-6G.conf");
9043 else
9044 return RETURN_ERR;
9045
9046 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
9047 list[0].name = "wpa";
9048 list[0].value = wpa;
developer69b61b02023-03-07 17:17:44 +08009049
developer72fb0bb2023-01-11 09:46:29 +08009050 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
9051 list[1].name = "wpa_psk";
9052 list[1].value = wpa_psk;
9053
9054 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
9055 list[2].name = "wpa_passphrase";
9056 list[2].value = wpa_passphrase;
9057
9058 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
9059
9060 if (strlen(wpa_psk_file) == 0)
9061 strcpy(wpa_psk_file, PSK_FILE);
9062
9063 if (access(wpa_psk_file, F_OK) != 0) {
9064 sprintf(cmd, "touch %s", wpa_psk_file);
9065 _syscmd(cmd, buf, sizeof(buf));
9066 }
9067 list[3].name = "wpa_psk_file";
9068 list[3].value = wpa_psk_file;
9069
9070 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
9071 list[4].name = "wpa_key_mgmt";
9072 list[4].value = wpa_key_mgmt;
9073
9074 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
9075 list[5].name = "wpa_pairwise";
9076 list[5].value = wpa_pairwise;
9077
9078 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
9079 wifi_hostapdWrite(current_config_file, list, 6);
9080
9081 wifi_setApEnable(apIndex, FALSE);
9082 wifi_setApEnable(apIndex, TRUE);
9083
9084 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9085 return RETURN_OK;
9086}
9087
9088//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).
9089INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
9090{
9091 char config_file[64] = {0};
9092 char buf[64] = {0};
9093 char cmd[256] = {0};
9094
9095 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9096
9097 if(!IP_output || !Port_output || !RadiusSecret_output)
9098 return RETURN_ERR;
9099
9100 // Read the first matched config
9101 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9102 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
9103 _syscmd(cmd, buf, sizeof(buf));
9104 strncpy(IP_output, buf, 64);
9105
9106 memset(buf, 0, sizeof(buf));
9107 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
9108 _syscmd(cmd, buf, sizeof(buf));
9109 *Port_output = atoi(buf);
9110
9111 memset(buf, 0, sizeof(buf));
9112 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
9113 _syscmd(cmd, buf, sizeof(buf));
9114 strncpy(RadiusSecret_output, buf, 64);
9115
9116 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9117 return RETURN_OK;
9118}
9119
9120INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
9121{
9122 char config_file[64] = {0};
9123 char port_str[8] = {0};
9124 char cmd[256] = {0};
9125 char buf[128] = {0};
9126
9127 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9128
developere5750452023-05-15 16:46:42 +08009129 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
9130 return RETURN_ERR;
9131
9132 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
9133 return RETURN_ERR;
9134
developer72fb0bb2023-01-11 09:46:29 +08009135 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9136
9137 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
9138 _syscmd(cmd, buf, sizeof(buf));
9139 memset(cmd, 0, sizeof(cmd));
9140
9141 snprintf(port_str, sizeof(port_str), "%d", port);
9142 if (strlen(buf) == 0)
9143 // Append
9144 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
9145 "auth_server_addr=%s\\n"
9146 "auth_server_port=%s\\n"
9147 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
9148 else {
9149 // Delete the three lines setting after the "# radius 1" comment
9150 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
9151 _syscmd(cmd, buf, sizeof(buf));
9152 memset(cmd, 0, sizeof(cmd));
9153 // Use "# radius 1" comment to find the location to insert the radius setting
9154 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
9155 "# radius 1\\n"
9156 "auth_server_addr=%s\\n"
9157 "auth_server_port=%s\\n"
9158 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
9159 }
9160 if(_syscmd(cmd, buf, sizeof(buf))) {
9161 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
9162 return RETURN_ERR;
9163 }
9164
9165 wifi_reloadAp(apIndex);
9166 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9167 return RETURN_OK;
9168}
9169
9170INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
9171{
9172 char config_file[64] = {0};
9173 char buf[64] = {0};
9174 char cmd[256] = {0};
9175
9176 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9177
9178 if(!IP_output || !Port_output || !RadiusSecret_output)
9179 return RETURN_ERR;
9180
9181 // Read the second matched config
9182 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9183 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
9184 _syscmd(cmd, buf, sizeof(buf));
9185 strncpy(IP_output, buf, 64);
9186
9187 memset(buf, 0, sizeof(buf));
9188 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
9189 _syscmd(cmd, buf, sizeof(buf));
9190 *Port_output = atoi(buf);
9191
9192 memset(buf, 0, sizeof(buf));
9193 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
9194 _syscmd(cmd, buf, sizeof(buf));
9195 strncpy(RadiusSecret_output, buf, 64);
9196
9197 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9198 return RETURN_OK;
9199}
9200
9201INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
9202{
9203 char config_file[64] = {0};
9204 char port_str[8] = {0};
9205 char cmd[256] = {0};
9206 char buf[128] = {0};
9207
9208 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9209
developere5750452023-05-15 16:46:42 +08009210 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
9211 return RETURN_ERR;
9212
9213 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
9214 return RETURN_ERR;
9215
developer72fb0bb2023-01-11 09:46:29 +08009216 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9217
9218 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
9219 _syscmd(cmd, buf, sizeof(buf));
9220 memset(cmd, 0, sizeof(cmd));
9221
9222 snprintf(port_str, sizeof(port_str), "%d", port);
9223 if (strlen(buf) == 0)
9224 // Append
9225 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
9226 "auth_server_addr=%s\\n"
9227 "auth_server_port=%s\\n"
9228 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
9229 else {
9230 // Delete the three lines setting after the "# radius 2" comment
9231 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
9232 _syscmd(cmd, buf, sizeof(buf));
9233 memset(cmd, 0, sizeof(cmd));
9234 // Use "# radius 2" comment to find the location to insert the radius setting
9235 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
9236 "# radius 2\\n"
9237 "auth_server_addr=%s\\n"
9238 "auth_server_port=%s\\n"
9239 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
9240 }
9241 if(_syscmd(cmd, buf, sizeof(buf))) {
9242 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
9243 return RETURN_ERR;
9244 }
9245
9246 wifi_reloadAp(apIndex);
9247 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9248 return RETURN_OK;
9249}
9250
9251//RadiusSettings
9252INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
9253{
9254 if(!output)
9255 return RETURN_ERR;
9256
9257 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
developer69b61b02023-03-07 17:17:44 +08009258 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
9259 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
9260 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
9261 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 +08009262 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 +08009263 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
9264 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
9265 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 +08009266 //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.
9267
9268 return RETURN_OK;
9269}
9270
9271INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
9272{
9273 //store the paramters, and apply instantly
9274 return RETURN_ERR;
9275}
9276
9277//Device.WiFi.AccessPoint.{i}.WPS.Enable
9278//Enables or disables WPS functionality for this access point.
9279// outputs the WPS enable state of this ap in output_bool
9280INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
9281{
9282 char interface_name[16] = {0};
9283 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
9284 if(!output_bool)
9285 return RETURN_ERR;
9286 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9287 return RETURN_ERR;
9288 sprintf(cmd,"hostapd_cli -i %s get_config | grep wps_state | cut -d '=' -f2", interface_name);
9289 _syscmd(cmd, buf, sizeof(buf));
9290 if(strstr(buf, "configured"))
9291 *output_bool=TRUE;
9292 else
9293 *output_bool=FALSE;
9294
9295 return RETURN_OK;
developer69b61b02023-03-07 17:17:44 +08009296}
developer72fb0bb2023-01-11 09:46:29 +08009297
9298//Device.WiFi.AccessPoint.{i}.WPS.Enable
9299// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
9300INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
9301{
9302 char config_file[MAX_BUF_SIZE] = {0};
developere5750452023-05-15 16:46:42 +08009303 char buf[128] = {0};
developer72fb0bb2023-01-11 09:46:29 +08009304 struct params params;
9305
9306 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9307 //store the paramters, and wait for wifi up to apply
9308 params.name = "wps_state";
developere5750452023-05-15 16:46:42 +08009309 if (enable == TRUE) {
9310 wifi_getApBeaconType(apIndex, buf);
9311 if (strncmp(buf, "None", 4) == 0) // If ap didn't set encryption
9312 params.value = "1";
9313 else // If ap set encryption
9314 params.value = "2";
9315 } else {
9316 params.value = "0";
9317 }
developer72fb0bb2023-01-11 09:46:29 +08009318
9319 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9320 wifi_hostapdWrite(config_file, &params, 1);
9321 wifi_hostapdProcessUpdate(apIndex, &params, 1);
9322 wifi_reloadAp(apIndex);
9323
9324 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9325 return RETURN_OK;
9326}
9327
9328//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
9329INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
9330{
9331 if(!output)
9332 return RETURN_ERR;
9333 snprintf(output, 128, "PushButton,PIN");
9334 return RETURN_OK;
9335}
9336
9337//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
9338//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.
9339// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
9340INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
9341{
9342 if(!output)
9343 return RETURN_ERR;
9344 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
9345
9346 return RETURN_OK;
9347}
9348
9349//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
9350// 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
9351INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
9352{
9353 //apply instantly. No setting need to be stored.
9354 char methods[MAX_BUF_SIZE], *token, *next_token;
9355 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
9356 struct params params;
9357
9358 if(!methodString)
9359 return RETURN_ERR;
9360 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9361 //store the paramters, and wait for wifi up to apply
9362
9363 snprintf(methods, sizeof(methods), "%s", methodString);
9364 for(token=methods; *token; token=next_token)
9365 {
9366 strtok_r(token, ",", &next_token);
9367 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
9368 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
9369 else if(*token=='E')
9370 {
9371 if(!strcmp(methods, "Ethernet"))
9372 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
9373 else if(!strcmp(methods, "ExternalNFCToken"))
9374 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
9375 else
9376 printf("%s: Unknown WpsConfigMethod\n", __func__);
9377 }
9378 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
9379 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
9380 else if(*token=='N' && !strcmp(token, "NFCInterface"))
9381 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
9382 else if(*token=='P' )
9383 {
9384 if(!strcmp(token, "PushButton"))
developere5750452023-05-15 16:46:42 +08009385 snprintf(config_methods, sizeof(config_methods), "%s ", "push_button");
developer72fb0bb2023-01-11 09:46:29 +08009386 else if(!strcmp(token, "PIN"))
9387 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
9388 else
9389 printf("%s: Unknown WpsConfigMethod\n", __func__);
9390 }
9391 else
9392 printf("%s: Unknown WpsConfigMethod\n", __func__);
9393 }
9394 params.name = "config_methods";
9395 params.value = config_methods;
9396 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9397 wifi_hostapdWrite(config_file, &params, 1);
9398 wifi_hostapdProcessUpdate(apIndex, &params, 1);
9399 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9400
9401 return RETURN_OK;
9402}
9403
9404// outputs the pin value, ulong_pin must be allocated by the caller
9405INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
9406{
9407 char buf[MAX_BUF_SIZE] = {0};
9408 char cmd[MAX_CMD_SIZE] = {0};
9409
9410 if(!output_ulong)
9411 return RETURN_ERR;
9412 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
9413 _syscmd(cmd, buf, sizeof(buf));
9414 if(strlen(buf) > 0)
9415 *output_ulong=strtoul(buf, NULL, 10);
9416
9417 return RETURN_OK;
9418}
9419
9420// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
9421INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
9422{
9423 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
9424 char ap_pin[16] = {0};
9425 char buf[MAX_BUF_SIZE] = {0};
9426 char config_file[MAX_BUF_SIZE] = {0};
9427 ULONG prev_pin = 0;
9428 struct params params;
9429
9430 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9431 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
9432 params.name = "ap_pin";
9433 params.value = ap_pin;
9434 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9435 wifi_hostapdWrite(config_file, &params, 1);
9436 wifi_hostapdProcessUpdate(apIndex, &params, 1);
9437 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9438
9439 return RETURN_OK;
9440}
9441
9442// Output string is either Not configured or Configured, max 32 characters
9443INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
9444{
9445 char interface_name[16] = {0};
9446 char cmd[MAX_CMD_SIZE];
9447 char buf[MAX_BUF_SIZE]={0};
9448
9449 if(!output_string)
9450 return RETURN_ERR;
9451 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9452 snprintf(output_string, 32, "Not configured");
9453 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9454 return RETURN_ERR;
9455 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep wps_state | cut -d'=' -f2", interface_name);
9456 _syscmd(cmd, buf, sizeof(buf));
9457
9458 if(!strncmp(buf, "configured", 10))
9459 snprintf(output_string, 32, "Configured");
9460 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9461
9462 return RETURN_OK;
9463}
9464
9465// sets the WPS pin for this AP
9466INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
9467{
9468 char interface_name[16] = {0};
9469 char cmd[MAX_CMD_SIZE];
9470 char buf[MAX_BUF_SIZE]={0};
9471 BOOL enable;
9472
9473 wifi_getApEnable(apIndex, &enable);
9474 if (!enable)
9475 return RETURN_ERR;
9476 wifi_getApWpsEnable(apIndex, &enable);
9477 if (!enable)
9478 return RETURN_ERR;
9479
9480 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9481 return RETURN_ERR;
9482 snprintf(cmd, 64, "hostapd_cli -i%s wps_pin any %s", interface_name, pin);
9483 _syscmd(cmd, buf, sizeof(buf));
9484 if((strstr(buf, "OK"))!=NULL)
9485 return RETURN_OK;
9486
9487 return RETURN_ERR;
9488}
9489
9490// This function is called when the WPS push button has been pressed for this AP
9491INT wifi_setApWpsButtonPush(INT apIndex)
9492{
9493 char cmd[MAX_CMD_SIZE];
9494 char buf[MAX_BUF_SIZE]={0};
9495 char interface_name[16] = {0};
9496 BOOL enable=FALSE;
9497
9498 wifi_getApEnable(apIndex, &enable);
9499 if (!enable)
9500 return RETURN_ERR;
9501
9502 wifi_getApWpsEnable(apIndex, &enable);
9503 if (!enable)
9504 return RETURN_ERR;
9505
9506 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9507 return RETURN_ERR;
9508
9509 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel; hostapd_cli -i%s wps_pbc", interface_name, interface_name);
9510 _syscmd(cmd, buf, sizeof(buf));
9511
9512 if((strstr(buf, "OK"))!=NULL)
9513 return RETURN_OK;
9514 return RETURN_ERR;
9515}
9516
9517// cancels WPS mode for this AP
9518INT wifi_cancelApWPS(INT apIndex)
9519{
9520 char interface_name[16] = {0};
9521 char cmd[MAX_CMD_SIZE];
9522 char buf[MAX_BUF_SIZE]={0};
9523
9524 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9525 return RETURN_ERR;
9526 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel", interface_name);
9527 _syscmd(cmd,buf, sizeof(buf));
9528
9529 if((strstr(buf, "OK"))!=NULL)
9530 return RETURN_OK;
9531 return RETURN_ERR;
9532}
9533
9534//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
9535//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
9536INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
9537{
9538 char interface_name[16] = {0};
9539 FILE *f = NULL;
9540 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
9541 char cmd[256] = {0}, buf[2048] = {0};
9542 char *param = NULL, *value = NULL, *line=NULL;
9543 size_t len = 0;
9544 ssize_t nread = 0;
9545 wifi_associated_dev_t *dev=NULL;
9546
9547 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9548 *associated_dev_array = NULL;
9549 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9550 return RETURN_ERR;
9551 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
9552 _syscmd(cmd,buf,sizeof(buf));
9553 *output_array_size = atoi(buf);
9554
9555 if (*output_array_size <= 0)
9556 return RETURN_OK;
9557
9558 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
9559 *associated_dev_array = dev;
9560 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt" , interface_name);
9561 _syscmd(cmd,buf,sizeof(buf));
9562 f = fopen("/tmp/connected_devices.txt", "r");
9563 if (f==NULL)
9564 {
9565 *output_array_size=0;
9566 return RETURN_ERR;
9567 }
9568 while ((getline(&line, &len, f)) != -1)
9569 {
9570 param = strtok(line,"=");
9571 value = strtok(NULL,"=");
9572
9573 if( strcmp("flags",param) == 0 )
9574 {
9575 value[strlen(value)-1]='\0';
9576 if(strstr (value,"AUTHORIZED") != NULL )
9577 {
9578 dev[auth_temp].cli_AuthenticationState = 1;
9579 dev[auth_temp].cli_Active = 1;
9580 auth_temp++;
9581 read_flag=1;
9582 }
9583 }
9584 if(read_flag==1)
9585 {
9586 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
9587 {
9588 value[strlen(value)-1]='\0';
9589 sscanf(value, "%x:%x:%x:%x:%x:%x",
9590 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
9591 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
9592 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
9593 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
9594 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
9595 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
9596 mac_temp++;
9597 read_flag=0;
9598 }
9599 }
9600 }
9601 *output_array_size = auth_temp;
9602 auth_temp=0;
9603 mac_temp=0;
9604 free(line);
9605 fclose(f);
9606 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9607 return RETURN_OK;
9608}
9609
9610#define MACADDRESS_SIZE 6
9611
9612INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
9613{
9614 FILE *fp = NULL;
9615 char str[MAX_BUF_SIZE] = {0};
9616 int wificlientindex = 0 ;
9617 int count = 0;
9618 int signalstrength = 0;
9619 int arr[MACADDRESS_SIZE] = {0};
9620 unsigned char mac[MACADDRESS_SIZE] = {0};
9621 UINT wifi_count = 0;
9622 char virtual_interface_name[MAX_BUF_SIZE] = {0};
9623 char pipeCmd[MAX_CMD_SIZE] = {0};
9624
9625 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9626 *output_array_size = 0;
9627 *associated_dev_array = NULL;
9628
9629 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
9630 fp = popen(pipeCmd, "r");
developer69b61b02023-03-07 17:17:44 +08009631 if (fp == NULL)
developer72fb0bb2023-01-11 09:46:29 +08009632 {
9633 printf("Failed to run command inside function %s\n",__FUNCTION__ );
9634 return RETURN_ERR;
9635 }
9636
9637 /* Read the output a line at a time - output it. */
9638 fgets(str, sizeof(str)-1, fp);
9639 wifi_count = (unsigned int) atoi ( str );
9640 *output_array_size = wifi_count;
9641 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
9642 pclose(fp);
9643
9644 if(wifi_count == 0)
9645 {
9646 return RETURN_OK;
9647 }
9648 else
9649 {
9650 wifi_associated_dev3_t* temp = NULL;
9651 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
9652 if(temp == NULL)
9653 {
9654 printf("Error Statement. Insufficient memory \n");
9655 return RETURN_ERR;
9656 }
9657
9658 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
9659 system(pipeCmd);
9660 memset(pipeCmd,0,sizeof(pipeCmd));
9661 if(apIndex == 0)
9662 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
9663 else if(apIndex == 1)
9664 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
9665 system(pipeCmd);
9666
9667 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
9668 if(fp == NULL)
9669 {
9670 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
9671 free(temp);
9672 return RETURN_ERR;
9673 }
9674 fclose(fp);
9675
9676 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
9677 fp = popen(pipeCmd, "r");
9678 if(fp)
9679 {
9680 for(count =0 ; count < wifi_count; count++)
9681 {
9682 fgets(str, MAX_BUF_SIZE, fp);
9683 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
9684 {
9685 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
9686 {
9687 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
9688
9689 }
9690 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
9691 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]);
9692 }
9693 temp[count].cli_AuthenticationState = 1; //TODO
9694 temp[count].cli_Active = 1; //TODO
9695 }
9696 pclose(fp);
9697 }
9698
9699 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt");
9700 fp = popen(pipeCmd, "r");
9701 if(fp)
developer69b61b02023-03-07 17:17:44 +08009702 {
developer72fb0bb2023-01-11 09:46:29 +08009703 pclose(fp);
9704 }
9705 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
9706 if(fp)
9707 {
9708 for(count =0 ; count < wifi_count ;count++)
9709 {
9710 fgets(str, MAX_BUF_SIZE, fp);
9711 signalstrength = atoi(str);
9712 temp[count].cli_SignalStrength = signalstrength;
9713 temp[count].cli_RSSI = signalstrength;
9714 temp[count].cli_SNR = signalstrength + 95;
9715 }
9716 pclose(fp);
9717 }
9718
9719
9720 if((apIndex == 0) || (apIndex == 4))
9721 {
9722 for(count =0 ; count < wifi_count ;count++)
developer69b61b02023-03-07 17:17:44 +08009723 {
developer72fb0bb2023-01-11 09:46:29 +08009724 strcpy(temp[count].cli_OperatingStandard,"g");
9725 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
9726 }
9727
9728 //BytesSent
9729 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt");
9730 fp = popen(pipeCmd, "r");
9731 if(fp)
developer69b61b02023-03-07 17:17:44 +08009732 {
developer72fb0bb2023-01-11 09:46:29 +08009733 pclose(fp);
9734 }
9735 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
9736 if(fp)
9737 {
9738 for (count = 0; count < wifi_count; count++)
9739 {
9740 fgets(str, MAX_BUF_SIZE, fp);
9741 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
9742 }
9743 pclose(fp);
9744 }
9745
9746 //BytesReceived
9747 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt");
9748 fp = popen(pipeCmd, "r");
9749 if (fp)
9750 {
9751 pclose(fp);
9752 }
9753 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
9754 if (fp)
9755 {
9756 for (count = 0; count < wifi_count; count++)
9757 {
9758 fgets(str, MAX_BUF_SIZE, fp);
9759 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
9760 }
9761 pclose(fp);
9762 }
9763
9764 //PacketsSent
9765 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt");
9766 fp = popen(pipeCmd, "r");
9767 if (fp)
9768 {
9769 pclose(fp);
9770 }
9771
9772 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
9773 if (fp)
9774 {
9775 for (count = 0; count < wifi_count; count++)
9776 {
9777 fgets(str, MAX_BUF_SIZE, fp);
9778 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
9779 }
9780 pclose(fp);
9781 }
9782
9783 //PacketsReceived
9784 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt");
9785 fp = popen(pipeCmd, "r");
9786 if (fp)
9787 {
9788 pclose(fp);
9789 }
9790 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
9791 if (fp)
9792 {
9793 for (count = 0; count < wifi_count; count++)
9794 {
9795 fgets(str, MAX_BUF_SIZE, fp);
9796 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
9797 }
9798 pclose(fp);
9799 }
9800
9801 //ErrorsSent
9802 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt");
9803 fp = popen(pipeCmd, "r");
9804 if (fp)
9805 {
9806 pclose(fp);
9807 }
9808 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
9809 if (fp)
9810 {
9811 for (count = 0; count < wifi_count; count++)
9812 {
9813 fgets(str, MAX_BUF_SIZE, fp);
9814 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
9815 }
9816 pclose(fp);
9817 }
9818
9819 //ErrorsSent
9820 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt");
9821 fp = popen(pipeCmd, "r");
9822 if (fp)
9823 {
9824 pclose(fp);
9825 }
9826 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
9827 if (fp)
9828 {
9829 for (count = 0; count < wifi_count; count++)
9830 {
9831 fgets(str, MAX_BUF_SIZE, fp);
9832 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
9833 }
9834 pclose(fp);
9835 }
9836
9837 //LastDataDownlinkRate
9838 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt");
9839 fp = popen(pipeCmd, "r");
9840 if (fp)
9841 {
9842 pclose(fp);
9843 }
9844 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
9845 if (fp)
9846 {
9847 for (count = 0; count < wifi_count; count++)
9848 {
9849 fgets(str, MAX_BUF_SIZE, fp);
9850 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
9851 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
9852 }
9853 pclose(fp);
9854 }
9855
9856 //LastDataUplinkRate
9857 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt");
9858 fp = popen(pipeCmd, "r");
9859 if (fp)
9860 {
9861 pclose(fp);
9862 }
9863 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
9864 if (fp)
9865 {
9866 for (count = 0; count < wifi_count; count++)
9867 {
9868 fgets(str, MAX_BUF_SIZE, fp);
9869 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
9870 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
9871 }
9872 pclose(fp);
9873 }
9874
9875 }
9876 else if ((apIndex == 1) || (apIndex == 5))
9877 {
9878 for (count = 0; count < wifi_count; count++)
9879 {
9880 strcpy(temp[count].cli_OperatingStandard, "a");
9881 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
9882 temp[count].cli_BytesSent = 0;
9883 temp[count].cli_BytesReceived = 0;
9884 temp[count].cli_LastDataUplinkRate = 0;
9885 temp[count].cli_LastDataDownlinkRate = 0;
9886 temp[count].cli_PacketsSent = 0;
9887 temp[count].cli_PacketsReceived = 0;
9888 temp[count].cli_ErrorsSent = 0;
9889 }
9890 }
9891
9892 for (count = 0; count < wifi_count; count++)
9893 {
9894 temp[count].cli_Retransmissions = 0;
9895 temp[count].cli_DataFramesSentAck = 0;
9896 temp[count].cli_DataFramesSentNoAck = 0;
9897 temp[count].cli_MinRSSI = 0;
9898 temp[count].cli_MaxRSSI = 0;
9899 strncpy(temp[count].cli_InterferenceSources, "", 64);
9900 memset(temp[count].cli_IPAddress, 0, 64);
9901 temp[count].cli_RetransCount = 0;
9902 temp[count].cli_FailedRetransCount = 0;
9903 temp[count].cli_RetryCount = 0;
9904 temp[count].cli_MultipleRetryCount = 0;
9905 }
9906 *associated_dev_array = temp;
9907 }
9908 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9909 return RETURN_OK;
9910}
9911
developer7e4a2a62023-04-06 19:56:03 +08009912int wifihal_interfacestatus(CHAR *wifi_status, CHAR *interface_name)
developer72fb0bb2023-01-11 09:46:29 +08009913{
developer7e4a2a62023-04-06 19:56:03 +08009914 char cmd[MAX_CMD_SIZE] = {0};
9915 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08009916
developer7e4a2a62023-04-06 19:56:03 +08009917 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
9918
9919 snprintf(cmd, MAX_CMD_SIZE, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4 | tr -d '\\n'",
9920 interface_name);
9921 _syscmd(cmd, buf, MAX_BUF_SIZE);
9922
9923 strcpy(wifi_status, buf); /* TBD: check wifi_status mem lenth and replace with strcpy later */
9924
9925 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08009926 return RETURN_OK;
9927}
9928
9929/* #define HOSTAPD_STA_PARAM_ENTRIES 29
9930struct hostapd_sta_param {
9931 char key[50];
9932 char value[100];
9933}
9934
9935static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
9936 int i = 0;
9937
9938 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
9939 if (strncmp(params[i].key,key,50) == 0){
9940 return &params[i].value;
9941 }
9942 i++;
9943 }
9944 return NULL;
9945
9946} */
9947
9948static unsigned int count_occurences(const char *buf, const char *word)
9949{
9950 unsigned int n = 0;
9951 char *ptr = strstr(buf, word);
9952
9953 while (ptr++) {
9954 n++;
9955 ptr = strstr(ptr, word);
9956 }
9957
9958 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
9959 return n;
9960}
9961
9962static const char *get_line_from_str_buf(const char *buf, char *line)
9963{
9964 int i;
9965 int n = strlen(buf);
9966
9967 for (i = 0; i < n; i++) {
9968 line[i] = buf[i];
9969 if (buf[i] == '\n') {
9970 line[i] = '\0';
9971 return &buf[i + 1];
9972 }
9973 }
9974
9975 return NULL;
9976}
9977
9978INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
9979{
developer0d26f2c2023-05-25 19:46:36 +08009980 char interface_name[16] = {0};
9981 FILE *f = NULL;
9982 int auth_temp= -1;
9983 char cmd[256] = {0}, buf[2048] = {0};
9984 char *param = NULL, *value = NULL, *line=NULL;
9985 size_t len = 0;
9986 wifi_associated_dev3_t *dev=NULL;
developer72fb0bb2023-01-11 09:46:29 +08009987
9988 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer0d26f2c2023-05-25 19:46:36 +08009989 *associated_dev_array = NULL;
9990 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72fb0bb2023-01-11 09:46:29 +08009991 return RETURN_ERR;
developer0d26f2c2023-05-25 19:46:36 +08009992 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
9993 _syscmd(cmd, buf, sizeof(buf));
9994 *output_array_size = atoi(buf);
developer72fb0bb2023-01-11 09:46:29 +08009995
developer0d26f2c2023-05-25 19:46:36 +08009996 if (*output_array_size <= 0)
9997 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08009998
developer0d26f2c2023-05-25 19:46:36 +08009999 dev=(wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
10000 *associated_dev_array = dev;
10001 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/diagnostic3_devices.txt" , interface_name);
10002 _syscmd(cmd,buf,sizeof(buf));
10003 f = fopen("/tmp/diagnostic3_devices.txt", "r");
10004 if (f == NULL)
10005 {
10006 *output_array_size=0;
developer72fb0bb2023-01-11 09:46:29 +080010007 return RETURN_ERR;
10008 }
developer0d26f2c2023-05-25 19:46:36 +080010009 while ((getline(&line, &len, f)) != -1)
10010 {
10011 param = strtok(line, "=");
10012 value = strtok(NULL, "=");
developer72fb0bb2023-01-11 09:46:29 +080010013
developer0d26f2c2023-05-25 19:46:36 +080010014 if( strcmp("flags",param) == 0 )
10015 {
10016 value[strlen(value)-1]='\0';
10017 if(strstr (value,"AUTHORIZED") != NULL )
10018 {
10019 auth_temp++;
10020 dev[auth_temp].cli_AuthenticationState = 1;
10021 dev[auth_temp].cli_Active = 1;
developer72fb0bb2023-01-11 09:46:29 +080010022 }
developer0d26f2c2023-05-25 19:46:36 +080010023 } else if (auth_temp < 0) {
10024 continue;
10025 } else if( strcmp("dot11RSNAStatsSTAAddress", param) == 0 )
10026 {
10027 value[strlen(value)-1]='\0';
10028 sscanf(value, "%x:%x:%x:%x:%x:%x",
10029 (unsigned int *)&dev[auth_temp].cli_MACAddress[0],
10030 (unsigned int *)&dev[auth_temp].cli_MACAddress[1],
10031 (unsigned int *)&dev[auth_temp].cli_MACAddress[2],
10032 (unsigned int *)&dev[auth_temp].cli_MACAddress[3],
10033 (unsigned int *)&dev[auth_temp].cli_MACAddress[4],
10034 (unsigned int *)&dev[auth_temp].cli_MACAddress[5]);
10035 } else if (strcmp("signal", param) == 0) {
10036 value[strlen(value)-1]='\0';
10037 sscanf(value, "%d", &dev[auth_temp].cli_RSSI);
10038 dev[auth_temp].cli_SNR = 95 + dev[auth_temp].cli_RSSI;
developer72fb0bb2023-01-11 09:46:29 +080010039 }
developer0d26f2c2023-05-25 19:46:36 +080010040 }
10041 if (line)
10042 free(line);
10043 fclose(f);
developer72fb0bb2023-01-11 09:46:29 +080010044 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +080010045 return RETURN_OK;
10046}
10047
10048#if 0
10049//To-do
10050INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
10051{
10052 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10053
10054 //Using different approach to get required WiFi Parameters from system available commands
developer69b61b02023-03-07 17:17:44 +080010055#if 0
developer72fb0bb2023-01-11 09:46:29 +080010056 FILE *f;
10057 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
10058 char cmd[256], buf[2048];
10059 char *param , *value, *line=NULL;
10060 size_t len = 0;
10061 ssize_t nread;
10062 wifi_associated_dev3_t *dev=NULL;
10063 *associated_dev_array = NULL;
10064 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
10065 _syscmd(cmd,buf,sizeof(buf));
10066 *output_array_size = atoi(buf);
10067
10068 if (*output_array_size <= 0)
10069 return RETURN_OK;
10070
10071 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
10072 *associated_dev_array = dev;
10073 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt", interface_name);
10074 _syscmd(cmd,buf,sizeof(buf));
10075 f = fopen("/tmp/connected_devices.txt", "r");
10076 if (f==NULL)
10077 {
10078 *output_array_size=0;
10079 return RETURN_ERR;
10080 }
10081 while ((nread = getline(&line, &len, f)) != -1)
10082 {
10083 param = strtok(line,"=");
10084 value = strtok(NULL,"=");
10085
10086 if( strcmp("flags",param) == 0 )
10087 {
10088 value[strlen(value)-1]='\0';
10089 if(strstr (value,"AUTHORIZED") != NULL )
10090 {
10091 dev[auth_temp].cli_AuthenticationState = 1;
10092 dev[auth_temp].cli_Active = 1;
10093 auth_temp++;
10094 read_flag=1;
10095 }
10096 }
10097 if(read_flag==1)
10098 {
10099 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
10100 {
10101 value[strlen(value)-1]='\0';
10102 sscanf(value, "%x:%x:%x:%x:%x:%x",
10103 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
10104 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
10105 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
10106 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
10107 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
10108 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
10109
10110 }
10111 else if( strcmp("rx_packets",param) == 0 )
10112 {
10113 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
10114 }
10115
10116 else if( strcmp("tx_packets",param) == 0 )
10117 {
developer69b61b02023-03-07 17:17:44 +080010118 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
developer72fb0bb2023-01-11 09:46:29 +080010119 }
10120
10121 else if( strcmp("rx_bytes",param) == 0 )
10122 {
10123 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
10124 }
10125
10126 else if( strcmp("tx_bytes",param) == 0 )
10127 {
developer69b61b02023-03-07 17:17:44 +080010128 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
developer72fb0bb2023-01-11 09:46:29 +080010129 mac_temp++;
10130 read_flag=0;
developer69b61b02023-03-07 17:17:44 +080010131 }
developer72fb0bb2023-01-11 09:46:29 +080010132 }
10133 }
10134
10135 *output_array_size = auth_temp;
10136 auth_temp=0;
10137 mac_temp=0;
10138 free(line);
10139 fclose(f);
10140#endif
10141 char interface_name[MAX_BUF_SIZE] = {0};
10142 char wifi_status[MAX_BUF_SIZE] = {0};
10143 char hostapdconf[MAX_BUF_SIZE] = {0};
10144
10145 wifi_associated_dev3_t *dev_array = NULL;
10146 ULONG wifi_count = 0;
10147
10148 *associated_dev_array = NULL;
10149 *output_array_size = 0;
10150
10151 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
10152 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
10153 {
10154 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
10155
10156 wifi_GetInterfaceName(interface_name, hostapdconf);
10157
10158 if(strlen(interface_name) > 1)
10159 {
10160 wifihal_interfacestatus(wifi_status,interface_name);
10161 if(strcmp(wifi_status,"RUNNING") == 0)
10162 {
10163 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
10164
10165 *associated_dev_array = dev_array;
developer69b61b02023-03-07 17:17:44 +080010166 *output_array_size = wifi_count;
developer72fb0bb2023-01-11 09:46:29 +080010167 }
10168 else
10169 {
10170 *associated_dev_array = NULL;
10171 }
10172 }
10173 }
10174
10175 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10176 return RETURN_OK;
10177}
10178#endif
10179
10180/* getIPAddress function */
10181/**
10182* @description Returning IpAddress of the Matched String
10183*
developer69b61b02023-03-07 17:17:44 +080010184* @param
developer72fb0bb2023-01-11 09:46:29 +080010185* @str Having MacAddress
developer69b61b02023-03-07 17:17:44 +080010186* @ipaddr Having ipaddr
developer72fb0bb2023-01-11 09:46:29 +080010187* @return The status of the operation
10188* @retval RETURN_OK if successful
10189* @retval RETURN_ERR if any error is detected
10190*
10191*/
10192
10193INT getIPAddress(char *str,char *ipaddr)
10194{
10195 FILE *fp = NULL;
10196 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
10197 int LeaseTime = 0,ret = 0;
10198 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
10199 {
10200 return RETURN_ERR;
10201 }
10202
10203 while ( fgets(buf, sizeof(buf), fp)!= NULL )
10204 {
10205 /*
10206 Sample:sss
10207 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
10208 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
10209 */
10210 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
10211 &(LeaseTime),
10212 phyAddr,
10213 ipAddr,
10214 hostName
10215 );
10216 if(ret != 4)
10217 continue;
10218 if(strcmp(str,phyAddr) == 0)
10219 strcpy(ipaddr,ipAddr);
10220 }
10221 fclose(fp);
10222 return RETURN_OK;
10223}
10224
10225/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
10226/**
10227* @description Returning Inactive wireless connected clients informations
10228*
developer69b61b02023-03-07 17:17:44 +080010229* @param
developer72fb0bb2023-01-11 09:46:29 +080010230* @filename Holding private_wifi 2g/5g content files
10231* @associated_dev_array Having inactiv wireless clients informations
10232* @output_array_size Returning Inactive wireless counts
10233* @return The status of the operation
10234* @retval RETURN_OK if successful
10235* @retval RETURN_ERR if any error is detected
10236*
10237*/
10238
10239INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
10240{
10241 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10242 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
10243 FILE *fp = NULL;
10244 int arr[MACADDRESS_SIZE] = {0};
10245 unsigned char mac[MACADDRESS_SIZE] = {0};
10246 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
10247 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
10248 fp = popen(buf,"r");
10249 if(fp == NULL)
10250 return RETURN_ERR;
10251 else
10252 {
10253 fgets(path,sizeof(path),fp);
10254 maccount = atoi(path);
10255 }
10256 pclose(fp);
10257 *output_array_size = maccount;
10258 wifi_associated_dev3_t* temp = NULL;
10259 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
10260 *associated_dev_array = temp;
10261 if(temp == NULL)
10262 {
10263 printf("Error Statement. Insufficient memory \n");
10264 return RETURN_ERR;
10265 }
10266 memset(buf,0,sizeof(buf));
10267 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
10268 fp = popen(buf,"r");
10269 if (fp == NULL) {
10270 fprintf(stderr, "%s: failed pipe command %s.\n", __func__, buf);
10271 return RETURN_ERR;
10272 }
10273 for(count = 0; count < maccount ; count++)
10274 {
10275 fgets(path,sizeof(path),fp);
10276 for(i = 0; path[i]!='\n';i++)
10277 str[i]=path[i];
10278 str[i]='\0';
10279 getIPAddress(str,ipaddr);
10280 memset(buf,0,sizeof(buf));
10281 if(strlen(ipaddr) > 0)
10282 {
10283 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
10284 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
10285 {
10286 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
10287 {
10288 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
10289 {
10290 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
10291
10292 }
10293 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
10294 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]);
10295 }
10296 temp[count].cli_AuthenticationState = 0; //TODO
developer69b61b02023-03-07 17:17:44 +080010297 temp[count].cli_Active = 0; //TODO
developer72fb0bb2023-01-11 09:46:29 +080010298 temp[count].cli_SignalStrength = 0;
10299 }
10300 else //Active wireless clients info
10301 {
10302 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
10303 {
10304 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
10305 {
10306 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
10307
10308 }
10309 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
10310 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]);
10311 }
10312 temp[count].cli_Active = 1;
10313 }
10314 }
10315 memset(ipaddr,0,sizeof(ipaddr));
10316 }
10317 pclose(fp);
10318 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10319 return RETURN_OK;
10320}
10321//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
10322//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
10323//To get Band Steering Capability
10324INT wifi_getBandSteeringCapability(BOOL *support)
10325{
10326 *support = FALSE;
10327 return RETURN_OK;
10328}
10329
10330
10331//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
10332//To get Band Steering enable status
10333INT wifi_getBandSteeringEnable(BOOL *enable)
10334{
10335 *enable = FALSE;
10336 return RETURN_OK;
10337}
10338
10339//To turn on/off Band steering
10340INT wifi_setBandSteeringEnable(BOOL enable)
10341{
10342 return RETURN_OK;
10343}
10344
10345//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
10346//To get Band Steering AP group
10347INT wifi_getBandSteeringApGroup(char *output_ApGroup)
10348{
10349 if (NULL == output_ApGroup)
10350 return RETURN_ERR;
10351
10352 strcpy(output_ApGroup, "1,2");
10353 return RETURN_OK;
10354}
10355
10356//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
10357//to set and read the band steering BandUtilizationThreshold parameters
10358INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
10359{
10360 return RETURN_ERR;
10361}
10362
10363INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
10364{
10365 return RETURN_ERR;
10366}
10367
10368//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
10369//to set and read the band steering RSSIThreshold parameters
10370INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
10371{
10372 return RETURN_ERR;
10373}
10374
10375INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
10376{
10377 return RETURN_ERR;
10378}
10379
10380
10381//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
10382//to set and read the band steering physical modulation rate threshold parameters
10383INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
10384{
10385 //If chip is not support, return -1
10386 return RETURN_ERR;
10387}
10388
10389INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
10390{
10391 //If chip is not support, return -1
10392 return RETURN_ERR;
10393}
10394
10395//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
10396//to set and read the inactivity time (in seconds) for steering under overload condition
10397INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
10398{
10399 return RETURN_ERR;
10400}
10401
10402INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
10403{
10404 return RETURN_ERR;
10405}
10406
10407//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
10408//to set and read the inactivity time (in seconds) for steering under Idle condition
10409INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
10410{
10411 return RETURN_ERR;
10412}
10413
10414INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
10415{
10416 return RETURN_ERR;
10417}
10418
10419//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
10420//pClientMAC[64]
10421//pSourceSSIDIndex[64]
10422//pDestSSIDIndex[64]
10423//pSteeringReason[256]
10424INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
10425{
10426 //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
10427 *pSteeringTime=time(NULL);
10428 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
10429 return RETURN_OK;
10430}
10431
10432INT wifi_ifConfigDown(INT apIndex)
10433{
10434 INT status = RETURN_OK;
10435 char cmd[64];
10436
10437 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
10438 printf("%s: %s\n", __func__, cmd);
10439 system(cmd);
10440
10441 return status;
10442}
10443
10444INT wifi_ifConfigUp(INT apIndex)
10445{
10446 char interface_name[16] = {0};
10447 char cmd[128];
10448 char buf[1024];
10449
10450 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
10451 return RETURN_ERR;
10452 snprintf(cmd, sizeof(cmd), "ifconfig %s up 2>/dev/null", interface_name);
10453 _syscmd(cmd, buf, sizeof(buf));
10454 return 0;
10455}
10456
10457//>> Deprecated. Replace with wifi_applyRadioSettings
10458INT wifi_pushBridgeInfo(INT apIndex)
10459{
developerb2977562023-05-24 17:54:12 +080010460 char ip[32] = {0};
10461 char subnet[32] = {0};
10462 char bridge[32] = {0};
10463 char cmd[128] = {0};
10464 char buf[1024] = {0};
developer72fb0bb2023-01-11 09:46:29 +080010465
developerb2977562023-05-24 17:54:12 +080010466 wifi_getApBridgeInfo(apIndex, bridge, ip, subnet);
developer72fb0bb2023-01-11 09:46:29 +080010467
developerb2977562023-05-24 17:54:12 +080010468 snprintf(cmd, sizeof(cmd), "ifconfig %s %s netmask %s ", bridge, ip, subnet);
10469 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +080010470
developerb2977562023-05-24 17:54:12 +080010471 return 0;
developer72fb0bb2023-01-11 09:46:29 +080010472}
10473
10474INT wifi_pushChannel(INT radioIndex, UINT channel)
10475{
10476 char interface_name[16] = {0};
10477 char cmd[128];
10478 char buf[1024];
10479 int apIndex;
10480
developer69b61b02023-03-07 17:17:44 +080010481 apIndex=(radioIndex==0)?0:1;
developer72fb0bb2023-01-11 09:46:29 +080010482 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
10483 return RETURN_ERR;
10484 snprintf(cmd, sizeof(cmd), "iwconfig %s freq %d",interface_name,channel);
10485 _syscmd(cmd,buf, sizeof(buf));
10486
10487 return 0;
10488}
10489
10490INT wifi_pushChannelMode(INT radioIndex)
10491{
10492 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
10493 return RETURN_ERR;
10494}
10495
10496INT wifi_pushDefaultValues(INT radioIndex)
10497{
10498 //Apply Comcast specified default radio settings instantly
10499 //AMPDU=1
10500 //AMPDUFrames=32
10501 //AMPDULim=50000
10502 //txqueuelen=1000
10503
10504 return RETURN_ERR;
10505}
10506
10507INT wifi_pushTxChainMask(INT radioIndex)
10508{
10509 //Apply default TxChainMask instantly
10510 return RETURN_ERR;
10511}
10512
10513INT wifi_pushRxChainMask(INT radioIndex)
10514{
10515 //Apply default RxChainMask instantly
10516 return RETURN_ERR;
10517}
10518
10519INT wifi_pushSSID(INT apIndex, CHAR *ssid)
10520{
developer7e4a2a62023-04-06 19:56:03 +080010521 INT status;
developer72fb0bb2023-01-11 09:46:29 +080010522
developer7e4a2a62023-04-06 19:56:03 +080010523 status = wifi_setSSIDName(apIndex, ssid);
10524 wifi_quick_reload_ap(apIndex);
developer72fb0bb2023-01-11 09:46:29 +080010525
developer7e4a2a62023-04-06 19:56:03 +080010526 return status;
developer72fb0bb2023-01-11 09:46:29 +080010527}
10528
10529INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
10530{
10531 //Apply default Ssid Advertisement instantly
10532 return RETURN_ERR;
10533}
10534
10535INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
10536{
developere82c0ca2023-05-10 16:25:35 +080010537 time_t now;
10538
10539 time(&now);
10540 if (now > radio_up_time[radioIndex])
10541 *output = now - radio_up_time[radioIndex];
10542 else {
10543 *output = 0;
10544 return RETURN_ERR;
10545 }
10546
10547 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +080010548}
10549
10550INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
10551{
10552 return RETURN_OK;
10553}
10554
10555INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
10556{
10557 return RETURN_OK;
10558}
10559
10560//To-do
10561INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
10562{
10563 char output[16]={'\0'};
10564 char config_file[MAX_BUF_SIZE] = {0};
10565
10566 if (!output_string)
10567 return RETURN_ERR;
10568
10569 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
10570 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
10571
10572 if (strlen(output) == 0)
10573 snprintf(output_string, 64, "Disabled");
10574 else if (strncmp(output, "0", 1) == 0)
10575 snprintf(output_string, 64, "Disabled");
10576 else if (strncmp(output, "1", 1) == 0)
10577 snprintf(output_string, 64, "Optional");
10578 else if (strncmp(output, "2", 1) == 0)
10579 snprintf(output_string, 64, "Required");
10580 else {
10581 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
10582 return RETURN_ERR;
10583 }
10584
10585 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
10586 return RETURN_OK;
10587}
10588INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
10589{
10590 char str[MAX_BUF_SIZE]={'\0'};
10591 char cmd[MAX_CMD_SIZE]={'\0'};
10592 struct params params;
10593 char config_file[MAX_BUF_SIZE] = {0};
10594
10595 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10596 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
10597 return RETURN_ERR;
10598
10599 params.name = "ieee80211w";
10600 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
10601 params.value = "0";
10602 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
10603 params.value = "1";
10604 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
10605 params.value = "2";
10606 else{
10607 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
10608 return RETURN_ERR;
10609 }
10610 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
10611 wifi_hostapdWrite(config_file, &params, 1);
10612 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
10613 return RETURN_OK;
10614}
10615INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
10616{
10617 char output[16]={'\0'};
10618 char config_file[MAX_BUF_SIZE] = {0};
10619
10620 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developerc0772e62023-05-18 15:10:48 +080010621 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer262f4cb2023-05-24 12:22:04 +080010622 wifi_datfileRead(config_file, "AutoChannelSelect" , output, sizeof(output));
developer72fb0bb2023-01-11 09:46:29 +080010623
developer262f4cb2023-05-24 12:22:04 +080010624 if (output == NULL)
10625 *output_bool = FALSE;
10626 else if (strncmp(output, "1", 1) == 0)
10627 *output_bool = TRUE;
10628 else if (strncmp(output, "2", 1) == 0)
10629 *output_bool = TRUE;
10630 else if (strncmp(output, "3", 1) == 0)
10631 *output_bool = TRUE;
10632 else
10633 *output_bool = FALSE;
developer72fb0bb2023-01-11 09:46:29 +080010634 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
10635
10636 return RETURN_OK;
10637}
10638
10639INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
10640{
10641 return RETURN_OK;
10642}
10643
10644INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
10645{
10646 return RETURN_OK;
10647}
10648
10649INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
10650{
10651 return RETURN_OK;
10652}
10653
10654INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
10655{
10656 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10657 char config_file[MAX_BUF_SIZE] = {0};
10658
10659 if (NULL == output)
10660 return RETURN_ERR;
10661 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
10662 wifi_hostapdRead(config_file,"hw_mode",output,64);
10663
10664 if(strcmp(output,"b")==0)
10665 sprintf(output, "%s", "1,2,5.5,11");
10666 else if (strcmp(output,"a")==0)
10667 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
10668 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
10669 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
10670
10671 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10672 return RETURN_OK;
10673}
10674
10675INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
10676{
10677 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10678 char *temp;
10679 char temp_output[128];
10680 char temp_TransmitRates[128];
10681 char config_file[MAX_BUF_SIZE] = {0};
10682
10683 if (NULL == output)
10684 return RETURN_ERR;
10685
10686 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
10687 wifi_hostapdRead(config_file,"supported_rates",output,64);
10688
10689 if (strlen(output) == 0) {
10690 wifi_getRadioSupportedDataTransmitRates(wlanIndex, output);
10691 return RETURN_OK;
10692 }
10693 strcpy(temp_TransmitRates,output);
10694 strcpy(temp_output,"");
10695 temp = strtok(temp_TransmitRates," ");
10696 while(temp!=NULL)
10697 {
10698 temp[strlen(temp)-1]=0;
10699 if((temp[0]=='5') && (temp[1]=='\0'))
10700 {
10701 temp="5.5";
10702 }
10703 strcat(temp_output,temp);
10704 temp = strtok(NULL," ");
10705 if(temp!=NULL)
10706 {
10707 strcat(temp_output,",");
10708 }
10709 }
10710 strcpy(output,temp_output);
10711 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10712
10713 return RETURN_OK;
10714}
10715
10716INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
10717{
10718 return RETURN_OK;
10719}
10720
10721
10722INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
10723{
10724 int i=0;
10725 char *temp;
10726 char temp1[128] = {0};
10727 char temp_output[128] = {0};
10728 char temp_TransmitRates[128] = {0};
10729 struct params params={'\0'};
10730 char config_file[MAX_BUF_SIZE] = {0};
10731 wifi_band band = wifi_index_to_band(wlanIndex);
10732
10733 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10734 if(NULL == output)
10735 return RETURN_ERR;
10736 strcpy(temp_TransmitRates,output);
10737
10738 for(i=0;i<strlen(temp_TransmitRates);i++)
10739 {
10740 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
10741 {
10742 continue;
10743 }
10744 else
10745 {
10746 return RETURN_ERR;
10747 }
10748 }
10749 strcpy(temp_output,"");
10750 temp = strtok(temp_TransmitRates,",");
10751 while(temp!=NULL)
10752 {
10753 strcpy(temp1,temp);
10754 if(band == band_5)
10755 {
10756 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
10757 {
10758 return RETURN_ERR;
10759 }
10760 }
10761
10762 if(strcmp(temp,"5.5")==0)
10763 {
10764 strcpy(temp1,"55");
10765 }
10766 else
10767 {
10768 strcat(temp1,"0");
10769 }
10770 strcat(temp_output,temp1);
10771 temp = strtok(NULL,",");
10772 if(temp!=NULL)
10773 {
10774 strcat(temp_output," ");
10775 }
10776 }
10777 strcpy(output,temp_output);
10778
10779 params.name = "supported_rates";
10780 params.value = output;
10781
10782 wifi_dbg_printf("\n%s:",__func__);
10783 wifi_dbg_printf("params.value=%s\n",params.value);
10784 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
10785 wifi_hostapdWrite(config_file,&params,1);
10786 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10787
10788 return RETURN_OK;
10789}
10790
10791
10792static char *sncopy(char *dst, int dst_sz, const char *src)
10793{
10794 if (src && dst && dst_sz > 0) {
10795 strncpy(dst, src, dst_sz);
10796 dst[dst_sz - 1] = '\0';
10797 }
10798 return dst;
10799}
10800
10801static int util_get_sec_chan_offset(int channel, const char* ht_mode)
10802{
10803 if (0 == strcmp(ht_mode, "HT40") ||
10804 0 == strcmp(ht_mode, "HT80") ||
10805 0 == strcmp(ht_mode, "HT160")) {
10806 switch (channel) {
10807 case 1 ... 7:
10808 case 36:
10809 case 44:
10810 case 52:
10811 case 60:
10812 case 100:
10813 case 108:
10814 case 116:
10815 case 124:
10816 case 132:
10817 case 140:
10818 case 149:
10819 case 157:
10820 return 1;
10821 case 8 ... 13:
10822 case 40:
10823 case 48:
10824 case 56:
10825 case 64:
10826 case 104:
10827 case 112:
10828 case 120:
10829 case 128:
10830 case 136:
10831 case 144:
10832 case 153:
10833 case 161:
10834 return -1;
10835 default:
10836 return -EINVAL;
10837 }
10838 }
10839
10840 return -EINVAL;
10841}
10842
10843static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
10844{
10845 int idx = channel%8;
10846 if (0 == strcmp(ht_mode, "HT40") ||
10847 0 == strcmp(ht_mode, "HT80") ||
10848 0 == strcmp(ht_mode, "HT160")) {
10849 switch (idx) {
10850 case 1:
10851 return 1;
10852 case 5:
10853 return -1;
10854 default:
10855 return -EINVAL;
10856 }
10857 }
10858
10859 return -EINVAL;
10860}
10861static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
10862{
10863 if (NULL == hw_mode) return;
10864
10865 if (0 == strcmp(hw_mode, "ac"))
10866 sncopy(bw_mode, bw_mode_len, "ht vht");
10867
10868 if (0 == strcmp(hw_mode, "n"))
10869 sncopy(bw_mode, bw_mode_len, "ht");
10870
10871 return;
10872}
10873
10874static int util_chan_to_freq(int chan)
10875{
10876 if (chan == 14)
10877 return 2484;
10878 else if (chan < 14)
10879 return 2407 + chan * 5;
10880 else if (chan >= 182 && chan <= 196)
10881 return 4000 + chan * 5;
10882 else
10883 return 5000 + chan * 5;
10884 return 0;
10885}
10886
10887static int util_6G_chan_to_freq(int chan)
10888{
10889 if (chan)
10890 return 5950 + chan * 5;
10891 else
10892 return 0;
developer69b61b02023-03-07 17:17:44 +080010893
developer72fb0bb2023-01-11 09:46:29 +080010894}
10895const int *util_unii_5g_chan2list(int chan, int width)
10896{
10897 static const int lists[] = {
10898 // <width>, <chan1>, <chan2>..., 0,
10899 20, 36, 0,
10900 20, 40, 0,
10901 20, 44, 0,
10902 20, 48, 0,
10903 20, 52, 0,
10904 20, 56, 0,
10905 20, 60, 0,
10906 20, 64, 0,
10907 20, 100, 0,
10908 20, 104, 0,
10909 20, 108, 0,
10910 20, 112, 0,
10911 20, 116, 0,
10912 20, 120, 0,
10913 20, 124, 0,
10914 20, 128, 0,
10915 20, 132, 0,
10916 20, 136, 0,
10917 20, 140, 0,
10918 20, 144, 0,
10919 20, 149, 0,
10920 20, 153, 0,
10921 20, 157, 0,
10922 20, 161, 0,
10923 20, 165, 0,
10924 40, 36, 40, 0,
10925 40, 44, 48, 0,
10926 40, 52, 56, 0,
10927 40, 60, 64, 0,
10928 40, 100, 104, 0,
10929 40, 108, 112, 0,
10930 40, 116, 120, 0,
10931 40, 124, 128, 0,
10932 40, 132, 136, 0,
10933 40, 140, 144, 0,
10934 40, 149, 153, 0,
10935 40, 157, 161, 0,
10936 80, 36, 40, 44, 48, 0,
10937 80, 52, 56, 60, 64, 0,
10938 80, 100, 104, 108, 112, 0,
10939 80, 116, 120, 124, 128, 0,
10940 80, 132, 136, 140, 144, 0,
10941 80, 149, 153, 157, 161, 0,
10942 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
10943 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
10944 -1 // final delimiter
10945 };
10946 const int *start;
10947 const int *p;
10948
10949 for (p = lists; *p != -1; p++) {
10950 if (*p == width) {
10951 for (start = ++p; *p != 0; p++) {
10952 if (*p == chan)
10953 return start;
10954 }
10955 }
10956 // move to the end of channel list of given width
10957 while (*p != 0) {
10958 p++;
10959 }
10960 }
10961
10962 return NULL;
10963}
10964
10965static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
10966{
10967 if (NULL == ht_mode)
10968 return 0;
10969
10970 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
10971 const int *chans = util_unii_5g_chan2list(channel, width);
10972 int sum = 0;
10973 int cnt = 0;
10974
10975 if (NULL == chans)
10976 return 0;
10977
10978 while (*chans) {
10979 sum += *chans;
10980 cnt++;
10981 chans++;
10982 }
10983 if (cnt == 0)
10984 return 0;
10985 return sum / cnt;
10986}
10987
10988static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
10989{
10990 if (NULL == ht_mode)
10991 return 0;
10992
10993 int width = strtol((ht_mode + 2), NULL, 10);
10994
10995 int idx = 0 ;
10996 int centerchan = 0;
10997 int chan_ofs = 1;
10998
10999 if (width == 40){
11000 idx = ((channel/4) + chan_ofs)%2;
11001 switch (idx) {
11002 case 0:
11003 centerchan = (channel - 2);
11004 break;
11005 case 1:
11006 centerchan = (channel + 2);
developer69b61b02023-03-07 17:17:44 +080011007 break;
developer72fb0bb2023-01-11 09:46:29 +080011008 default:
11009 return -EINVAL;
11010 }
11011 }else if (width == 80){
developer69b61b02023-03-07 17:17:44 +080011012 idx = ((channel/4) + chan_ofs)%4;
developer72fb0bb2023-01-11 09:46:29 +080011013 switch (idx) {
11014 case 0:
11015 centerchan = (channel - 6);
11016 break;
11017 case 1:
11018 centerchan = (channel + 6);
11019 break;
11020 case 2:
11021 centerchan = (channel + 2);
11022 break;
11023 case 3:
11024 centerchan = (channel - 2);
11025 break;
11026 default:
11027 return -EINVAL;
developer69b61b02023-03-07 17:17:44 +080011028 }
developer72fb0bb2023-01-11 09:46:29 +080011029 }else if (width == 160){
11030 switch (channel) {
11031 case 1 ... 29:
11032 centerchan = 15;
11033 break;
11034 case 33 ... 61:
11035 centerchan = 47;
11036 break;
11037 case 65 ... 93:
11038 centerchan = 79;
11039 break;
11040 case 97 ... 125:
11041 centerchan = 111;
11042 break;
11043 case 129 ... 157:
11044 centerchan = 143;
11045 break;
11046 case 161 ... 189:
11047 centerchan = 175;
11048 break;
11049 case 193 ... 221:
11050 centerchan = 207;
11051 break;
11052 default:
11053 return -EINVAL;
developer69b61b02023-03-07 17:17:44 +080011054 }
developer72fb0bb2023-01-11 09:46:29 +080011055 }
11056 return centerchan;
11057}
11058static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
11059{
11060 BOOL onlyG, onlyN, onlyA;
11061 CHAR tmp[64];
11062 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
11063 if (ret == RETURN_OK) {
11064 sncopy(hw_mode, hw_mode_size, tmp);
11065 }
11066 return ret;
11067}
11068
11069INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
11070{
11071 // Sample commands:
11072 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
11073 // hostapd_cli -i wifi0 chan_switch 30 2437
developer72fb0bb2023-01-11 09:46:29 +080011074 int freq = 0, ret = 0;
11075 char center_freq1_str[32] = ""; // center_freq1=%d
11076 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
11077 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
11078 char hw_mode[16] = ""; // n|ac
11079 char bw_mode[16] = ""; // ht|ht vht
11080 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
11081 char interface_name[16] = {0};
11082 int sec_chan_offset;
11083 int width;
11084 char config_file[64] = {0};
11085 BOOL stbcEnable = FALSE;
11086 char *ext_str = "None";
11087 wifi_band band = band_invalid;
11088 int center_chan = 0;
11089 int center_freq1 = 0;
11090
11091 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
11092
11093 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
11094 return RETURN_ERR;
11095
11096 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11097
11098 band = wifi_index_to_band(radioIndex);
11099
11100 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
11101
11102 // Get radio mode HT20|HT40|HT80 etc.
11103 if (channel){
11104 if (band == band_6){
11105 freq = util_6G_chan_to_freq(channel);
11106 }else{
11107 freq = util_chan_to_freq(channel);
11108 }
11109 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
11110
11111 // Provide bandwith if specified
11112 if (channel_width_MHz > 20) {
11113 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
11114 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
11115 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
11116
11117 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
11118 }else if (channel_width_MHz == 20){
11119 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
11120 }
11121
11122
11123 if (channel_width_MHz > 20) {
11124 if (band == band_6){
11125 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
11126 if(center_chan){
11127 center_freq1 = util_6G_chan_to_freq(center_chan);
11128 }
11129 }else{
11130 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
11131 if(center_chan){
11132 center_freq1 = util_chan_to_freq(center_chan);
11133 }
11134 }
developer69b61b02023-03-07 17:17:44 +080011135
developer72fb0bb2023-01-11 09:46:29 +080011136 if (center_freq1)
11137 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
developer69b61b02023-03-07 17:17:44 +080011138
developer72fb0bb2023-01-11 09:46:29 +080011139 }
11140
11141 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
11142 if (band == band_6){
11143 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
11144 }else{
11145 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
11146 }
11147 if (sec_chan_offset != -EINVAL)
11148 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
11149
11150 // Only the first AP, other are hanging on the same radio
developerfead3972023-05-25 20:15:02 +080011151 ret = wifi_setChannel_netlink(radioIndex, &channel, NULL);
developerd1824452023-05-18 12:30:04 +080011152 if (ret != RETURN_OK) {
developerfead3972023-05-25 20:15:02 +080011153 fprintf(stderr, "%s: wifi_setChannel return error.\n", __func__);
developerd1824452023-05-18 12:30:04 +080011154 return RETURN_ERR;
11155 }
11156 /* wifi_dbg_printf("execute: '%s'\n", cmd);
developerf6a87542023-05-16 15:47:28 +080011157 ret = _syscmd(cmd, buf, sizeof(buf));
developerd1824452023-05-18 12:30:04 +080011158 wifi_reloadAp(radioIndex); */
developer72fb0bb2023-01-11 09:46:29 +080011159
11160 ret = wifi_setRadioChannel(radioIndex, channel);
11161 if (ret != RETURN_OK) {
11162 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
11163 return RETURN_ERR;
11164 }
11165
developer262f4cb2023-05-24 12:22:04 +080011166 if (sec_chan_offset == 1)
11167 ext_str = "Above";
11168 else if (sec_chan_offset == -1)
11169 ext_str = "Below";
developer72fb0bb2023-01-11 09:46:29 +080011170
developerd1824452023-05-18 12:30:04 +080011171 /*wifi_setRadioCenterChannel(radioIndex, center_chan); */
developer72fb0bb2023-01-11 09:46:29 +080011172
11173 } else {
11174 if (channel_width_MHz > 20)
11175 ext_str = "Above";
11176 }
11177
11178 wifi_setRadioExtChannel(radioIndex, ext_str);
11179
11180 char mhz_str[16];
11181 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
11182 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
11183
11184 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11185
11186 return RETURN_OK;
11187}
11188
11189INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
11190{
11191 int index = -1;
11192 wifi_neighbor_ap2_t *scan_array = NULL;
11193 char cmd[256]={0};
11194 char buf[128]={0};
11195 char file_name[32] = {0};
11196 char filter_SSID[32] = {0};
11197 char line[256] = {0};
11198 char interface_name[16] = {0};
11199 char *ret = NULL;
11200 int freq=0;
11201 FILE *f = NULL;
11202 size_t len=0;
11203 int channels_num = 0;
11204 int vht_channel_width = 0;
11205 int get_noise_ret = RETURN_ERR;
11206 bool filter_enable = false;
11207 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
11208 int phyId = 0;
11209
11210 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
11211
11212 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
11213 f = fopen(file_name, "r");
11214 if (f != NULL) {
11215 fgets(filter_SSID, sizeof(file_name), f);
11216 if (strlen(filter_SSID) != 0)
11217 filter_enable = true;
11218 fclose(f);
11219 }
11220
11221 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
11222 return RETURN_ERR;
11223
11224 phyId = radio_index_to_phy(radio_index);
11225
11226 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
11227 _syscmd(cmd, buf, sizeof(buf));
11228 channels_num = strtol(buf, NULL, 10);
11229
11230 sprintf(cmd, "iw dev %s scan dump | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
11231 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", interface_name, interface_name);
11232 fprintf(stderr, "cmd: %s\n", cmd);
11233 if ((f = popen(cmd, "r")) == NULL) {
11234 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
11235 return RETURN_ERR;
11236 }
developer69b61b02023-03-07 17:17:44 +080011237
developer72fb0bb2023-01-11 09:46:29 +080011238 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
11239 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
developer69b61b02023-03-07 17:17:44 +080011240
developer72fb0bb2023-01-11 09:46:29 +080011241 ret = fgets(line, sizeof(line), f);
11242 while (ret != NULL) {
11243 if(strstr(line, "BSS") != NULL) { // new neighbor info
developer69b61b02023-03-07 17:17:44 +080011244 // 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 +080011245 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
11246 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
11247
11248 if (!filter_BSS) {
11249 index++;
11250 wifi_neighbor_ap2_t *tmp;
11251 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
11252 if (tmp == NULL) { // no more memory to use
11253 index--;
11254 wifi_dbg_printf("%s: realloc failed\n", __func__);
11255 break;
11256 }
11257 scan_array = tmp;
11258 }
11259 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
11260
11261 filter_BSS = false;
11262 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
11263 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
11264 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
11265 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
11266 } else if (strstr(line, "freq") != NULL) {
11267 sscanf(line," freq: %d", &freq);
11268 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
11269
11270 if (freq >= 2412 && freq <= 2484) {
11271 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
11272 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
11273 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
11274 }
11275 else if (freq >= 5160 && freq <= 5805) {
11276 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
11277 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
11278 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
11279 }
11280
11281 scan_array[index].ap_Noise = 0;
11282 if (get_noise_ret == RETURN_OK) {
11283 for (int i = 0; i < channels_num; i++) {
11284 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
11285 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
11286 break;
11287 }
11288 }
11289 }
11290 } else if (strstr(line, "beacon interval") != NULL) {
11291 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
11292 } else if (strstr(line, "signal") != NULL) {
11293 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
11294 } else if (strstr(line,"SSID") != NULL) {
11295 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
11296 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
11297 filter_BSS = true;
11298 }
11299 } else if (strstr(line, "Supported rates") != NULL) {
11300 char SRate[80] = {0}, *tmp = NULL;
11301 memset(buf, 0, sizeof(buf));
11302 strcpy(SRate, line);
11303 tmp = strtok(SRate, ":");
11304 tmp = strtok(NULL, ":");
11305 strcpy(buf, tmp);
11306 memset(SRate, 0, sizeof(SRate));
11307
11308 tmp = strtok(buf, " \n");
11309 while (tmp != NULL) {
11310 strcat(SRate, tmp);
11311 if (SRate[strlen(SRate) - 1] == '*') {
11312 SRate[strlen(SRate) - 1] = '\0';
11313 }
11314 strcat(SRate, ",");
11315
11316 tmp = strtok(NULL, " \n");
11317 }
11318 SRate[strlen(SRate) - 1] = '\0';
11319 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
11320 } else if (strstr(line, "DTIM") != NULL) {
11321 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
11322 } else if (strstr(line, "VHT capabilities") != NULL) {
11323 strcat(scan_array[index].ap_SupportedStandards, ",ac");
11324 strcpy(scan_array[index].ap_OperatingStandards, "ac");
11325 } else if (strstr(line, "HT capabilities") != NULL) {
11326 strcat(scan_array[index].ap_SupportedStandards, ",n");
11327 strcpy(scan_array[index].ap_OperatingStandards, "n");
11328 } else if (strstr(line, "VHT operation") != NULL) {
11329 ret = fgets(line, sizeof(line), f);
11330 sscanf(line," * channel width: %d", &vht_channel_width);
11331 if(vht_channel_width == 1) {
11332 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
11333 } else {
11334 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
11335 }
11336 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
11337 continue;
11338 } else if (strstr(line, "HT operation") != NULL) {
11339 ret = fgets(line, sizeof(line), f);
11340 sscanf(line," * secondary channel offset: %s", &buf);
11341 if (!strcmp(buf, "above")) {
11342 //40Mhz +
11343 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radio_index%1 ? "A": "G");
11344 }
11345 else if (!strcmp(buf, "below")) {
11346 //40Mhz -
11347 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
11348 } else {
11349 //20Mhz
11350 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radio_index%1 ? "A": "G");
11351 }
11352 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
11353 continue;
11354 } else if (strstr(line, "HE capabilities") != NULL) {
11355 strcat(scan_array[index].ap_SupportedStandards, ",ax");
11356 strcpy(scan_array[index].ap_OperatingStandards, "ax");
11357 ret = fgets(line, sizeof(line), f);
11358 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
11359 if (strstr(line, "HE40/2.4GHz") != NULL)
11360 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
11361 else
11362 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
11363 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
11364 if (strstr(line, "HE80/5GHz") != NULL) {
11365 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
11366 ret = fgets(line, sizeof(line), f);
11367 } else
11368 continue;
11369 if (strstr(line, "HE160/5GHz") != NULL)
11370 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
11371 }
11372 continue;
11373 } else if (strstr(line, "WPA") != NULL) {
11374 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
11375 } else if (strstr(line, "RSN") != NULL) {
11376 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
11377 } else if (strstr(line, "Group cipher") != NULL) {
11378 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
11379 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
11380 strcpy(scan_array[index].ap_EncryptionMode, "AES");
11381 }
11382 }
11383 ret = fgets(line, sizeof(line), f);
11384 }
11385
11386 if (!filter_BSS) {
11387 *output_array_size = index + 1;
11388 } else {
11389 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
11390 *output_array_size = index;
11391 }
11392 *neighbor_ap_array = scan_array;
11393 pclose(f);
11394 free(channels_noise_arr);
11395 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11396 return RETURN_OK;
11397}
11398
11399INT wifi_getApAssociatedDeviceStats(
11400 INT apIndex,
11401 mac_address_t *clientMacAddress,
11402 wifi_associated_dev_stats_t *associated_dev_stats,
11403 u64 *handle)
11404{
11405 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
11406 char interface_name[50] = {0};
11407 char cmd[1024] = {0};
11408 char mac_str[18] = {0};
11409 char *key = NULL;
11410 char *val = NULL;
11411 FILE *f = NULL;
11412 char *line = NULL;
11413 size_t len = 0;
11414
11415 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
11416 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
11417 return RETURN_ERR;
11418 }
11419
11420 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
11421 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
11422 if((f = popen(cmd, "r")) == NULL) {
11423 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
11424 return RETURN_ERR;
11425 }
11426
11427 while ((getline(&line, &len, f)) != -1) {
11428 key = strtok(line,":");
11429 val = strtok(NULL,":");
11430
11431 if(!strncmp(key,"rx bytes",8))
11432 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
11433 if(!strncmp(key,"tx bytes",8))
11434 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
11435 if(!strncmp(key,"rx packets",10))
11436 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
11437 if(!strncmp(key,"tx packets",10))
11438 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
11439 if(!strncmp(key,"tx retries",10))
11440 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
11441 if(!strncmp(key,"tx failed",9))
11442 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
11443 if(!strncmp(key,"rx drop misc",13))
11444 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
11445 if(!strncmp(key,"rx bitrate",10)) {
11446 val = strtok(val, " ");
11447 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
11448 }
11449 if(!strncmp(key,"tx bitrate",10)) {
11450 val = strtok(val, " ");
11451 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
11452 }
11453 }
11454 free(line);
11455 pclose(f);
11456 return RETURN_OK;
11457}
11458
11459INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
11460{
developer7e4a2a62023-04-06 19:56:03 +080011461 char interface_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +080011462 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
11463
developer7e4a2a62023-04-06 19:56:03 +080011464 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
11465
developer72fb0bb2023-01-11 09:46:29 +080011466 if (NULL == output_string)
11467 return RETURN_ERR;
11468
11469 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
11470 return RETURN_ERR;
developer7e4a2a62023-04-06 19:56:03 +080011471
11472 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 +080011473 _syscmd(cmd, buf, sizeof(buf));
11474
11475 //size of SSID name restricted to value less than 32 bytes
11476 snprintf(output_string, 32, "%s", buf);
developer7e4a2a62023-04-06 19:56:03 +080011477 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +080011478
11479 return RETURN_OK;
11480}
11481
11482INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
11483{
developer2edaf012023-05-24 14:24:53 +080011484 char *mac_arry_buf = NULL;
11485 INT policy = -1;
11486 INT buf_size = 1024;
developer72fb0bb2023-01-11 09:46:29 +080011487
developer2edaf012023-05-24 14:24:53 +080011488 mac_arry_buf = malloc(buf_size);
11489 if (!mac_arry_buf) {
11490 wifi_debug(DEBUG_ERROR,"malloc mac_arry_buf fails\n");
developer7e4a2a62023-04-06 19:56:03 +080011491 return RETURN_ERR;
developer2edaf012023-05-24 14:24:53 +080011492 }
11493 memset(mac_arry_buf, 0, buf_size);
11494 if (mtk_wifi_getApAclDevices(apIndex, mac_arry_buf, buf_size) != RETURN_OK) {
11495 wifi_debug(DEBUG_ERROR,"mtk_wifi_getApAclDevices get fails\n");
11496 goto err;
11497 }
11498 /*
11499 mtk format to get policy:
11500 "policy=1
11501 00:11:22:33:44:55
11502 00:11:22:33:44:66
11503 "
11504 */
11505 if (strlen(mac_arry_buf) < strlen("policy=1") || sscanf(mac_arry_buf, "policy=%01d", &policy) != 1) {
11506 wifi_debug(DEBUG_ERROR,"mac_arry_buf(%s) invalid\n", mac_arry_buf);
11507 goto err;
11508 }
11509 if (!(policy >=0 && policy <= 2)){
11510 wifi_debug(DEBUG_ERROR,"policy(%d) is invalid\n", policy);
11511 goto err;
11512 }
11513 *output_filterMode = policy;
11514 wifi_debug(DEBUG_NOTICE, "output_filterMode(%d), success\n", *output_filterMode);
11515 free(mac_arry_buf);
11516 mac_arry_buf = NULL;
11517 return RETURN_OK;
11518err:
11519 free(mac_arry_buf);
11520 mac_arry_buf = NULL;
11521 wifi_debug(DEBUG_NOTICE, "output_filterMode(%d), fails\n", *output_filterMode);
11522 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +080011523}
11524
developer2edaf012023-05-24 14:24:53 +080011525
developer72fb0bb2023-01-11 09:46:29 +080011526INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
11527{
11528 FILE *fp = NULL;
11529 char str[MAX_BUF_SIZE] = {0};
11530 int wificlientindex = 0 ;
11531 int count = 0;
11532 int signalstrength = 0;
11533 int arr[MACADDRESS_SIZE] = {0};
11534 unsigned char mac[MACADDRESS_SIZE] = {0};
11535 UINT wifi_count = 0;
11536 char virtual_interface_name[MAX_BUF_SIZE] = {0};
11537 char pipeCmd[MAX_CMD_SIZE] = {0};
11538
11539 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11540 *output_array_size = 0;
11541 *associated_dev_array = NULL;
11542 char interface_name[50] = {0};
11543
11544 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
11545 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
11546 return RETURN_ERR;
11547 }
11548
11549 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
11550 fp = popen(pipeCmd, "r");
11551 if (fp == NULL)
11552 {
11553 printf("Failed to run command inside function %s\n",__FUNCTION__ );
11554 return RETURN_ERR;
11555 }
11556
11557 /* Read the output a line at a time - output it. */
11558 fgets(str, sizeof(str)-1, fp);
11559 wifi_count = (unsigned int) atoi ( str );
11560 *output_array_size = wifi_count;
11561 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
11562 pclose(fp);
11563
11564 if(wifi_count == 0)
11565 {
11566 return RETURN_OK;
11567 }
11568 else
11569 {
11570 wifi_associated_dev2_t* temp = NULL;
11571 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
11572 *associated_dev_array = temp;
11573 if(temp == NULL)
11574 {
11575 printf("Error Statement. Insufficient memory \n");
11576 return RETURN_ERR;
11577 }
11578
11579 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
11580 system(pipeCmd);
11581
11582 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
11583 if(fp == NULL)
11584 {
11585 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
11586 return RETURN_ERR;
11587 }
11588 fclose(fp);
11589
11590 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
11591 fp = popen(pipeCmd, "r");
11592 if(fp)
11593 {
11594 for(count =0 ; count < wifi_count; count++)
11595 {
11596 fgets(str, MAX_BUF_SIZE, fp);
11597 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
11598 {
11599 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
11600 {
11601 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
11602
11603 }
11604 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
11605 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]);
11606 }
11607 temp[count].cli_AuthenticationState = 1; //TODO
11608 temp[count].cli_Active = 1; //TODO
11609 }
11610 pclose(fp);
11611 }
11612
11613 //Updating RSSI per client
11614 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt");
11615 fp = popen(pipeCmd, "r");
11616 if(fp)
11617 {
11618 pclose(fp);
11619 }
11620 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
11621 if(fp)
11622 {
11623 for(count =0 ; count < wifi_count ;count++)
11624 {
11625 fgets(str, MAX_BUF_SIZE, fp);
11626 signalstrength = atoi(str);
11627 temp[count].cli_RSSI = signalstrength;
11628 }
11629 pclose(fp);
11630 }
11631
11632
11633 //LastDataDownlinkRate
11634 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt");
11635 fp = popen(pipeCmd, "r");
11636 if (fp)
11637 {
11638 pclose(fp);
11639 }
11640 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
11641 if (fp)
11642 {
11643 for (count = 0; count < wifi_count; count++)
11644 {
11645 fgets(str, MAX_BUF_SIZE, fp);
11646 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
11647 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
11648 }
11649 pclose(fp);
11650 }
11651
11652 //LastDataUplinkRate
11653 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt");
11654 fp = popen(pipeCmd, "r");
11655 if (fp)
11656 {
11657 pclose(fp);
11658 }
11659 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
11660 if (fp)
11661 {
11662 for (count = 0; count < wifi_count; count++)
11663 {
11664 fgets(str, MAX_BUF_SIZE, fp);
11665 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
11666 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
11667 }
11668 pclose(fp);
11669 }
11670 }
11671 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11672 return RETURN_OK;
11673
11674}
11675
11676INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
11677{
11678#if 0
11679 /*char buf[1024] = {0};
11680 sprintf(cmd, "ifconfig %s ", interface_name);
11681 _syscmd(cmd, buf, sizeof(buf));*/
11682
11683 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
11684 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
11685 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
11686 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
11687
11688 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.
11689 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].
11690 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].
11691 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].
11692 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
11693 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
11694
11695 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
11696 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
11697 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
11698 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.
11699 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.
11700 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.
11701 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.
11702 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.
11703 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.
11704 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.
11705 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
11706#endif
11707
11708 FILE *fp = NULL;
11709 char interface_name[50] = {0};
11710 char pipeCmd[128] = {0};
11711 char str[256] = {0};
11712 wifi_ssidTrafficStats2_t *out = output_struct;
11713
11714 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
11715 if (!output_struct)
11716 return RETURN_ERR;
11717
11718 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
11719 if (wifi_GetInterfaceName(ssidIndex, interface_name) != RETURN_OK)
11720 return RETURN_ERR;
11721 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
11722
11723 fp = popen(pipeCmd, "r");
11724 if (fp == NULL) {
11725 fprintf(stderr, "%s: popen failed\n", __func__);
11726 return RETURN_ERR;
11727 }
11728 fgets(str, sizeof(str), fp);
11729 pclose(fp);
11730
11731 if (strlen(str) == 0) // interface not exist
11732 return RETURN_OK;
11733
11734 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
11735 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
11736
11737 memset(str, 0, sizeof(str));
11738 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
11739 fp = popen(pipeCmd, "r");
11740 if (fp == NULL) {
11741 fprintf(stderr, "%s: popen failed\n", __func__);
11742 return RETURN_ERR;
11743 }
11744 fgets(str, sizeof(str), fp);
11745
11746 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
11747 &out->ssid_BroadcastPacketsSent);
11748 pclose(fp);
11749
11750 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
11751 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
11752
11753 // Not supported
11754 output_struct->ssid_RetransCount = 0;
11755 output_struct->ssid_FailedRetransCount = 0;
11756 output_struct->ssid_RetryCount = 0;
11757 output_struct->ssid_MultipleRetryCount = 0;
11758 output_struct->ssid_ACKFailureCount = 0;
11759 output_struct->ssid_AggregatedPacketCount = 0;
11760
11761 return RETURN_OK;
11762}
11763
11764//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).
11765INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
11766{
11767 char output_val[16]={'\0'};
11768 char config_file[MAX_BUF_SIZE] = {0};
11769
11770 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11771 if (!output)
11772 return RETURN_ERR;
11773 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
11774 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
11775
11776 if( strcmp(output_val,"1") == 0 )
11777 *output = TRUE;
11778 else
11779 *output = FALSE;
11780 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11781
11782 return RETURN_OK;
11783}
11784
11785INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
11786{
11787 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11788 char str[MAX_BUF_SIZE]={'\0'};
11789 char string[MAX_BUF_SIZE]={'\0'};
11790 char cmd[MAX_CMD_SIZE]={'\0'};
11791 char *ch;
11792 char config_file[MAX_BUF_SIZE] = {0};
11793 struct params params;
11794
11795 if(enable == TRUE)
11796 strcpy(string,"1");
11797 else
11798 strcpy(string,"0");
11799
11800 params.name = "ap_isolate";
11801 params.value = string;
11802
11803 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
11804 wifi_hostapdWrite(config_file,&params,1);
11805 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11806
11807 return RETURN_OK;
11808}
11809
11810INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
11811{
developera1255e42023-05-13 17:45:02 +080011812 char mgmtpwr_file[32] = {0};
11813 char cmd[64] = {0};
11814 char buf[32]={0};
11815
developer72fb0bb2023-01-11 09:46:29 +080011816 if (NULL == output_dBm)
11817 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +080011818 snprintf(mgmtpwr_file, sizeof(mgmtpwr_file), "%s%d.txt", MGMT_POWER_CTRL, apIndex);
11819 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mgmtpwr_file);
11820 _syscmd(cmd, buf, sizeof(buf));
11821 if (strlen(buf) > 0)
11822 *output_dBm = strtol(buf, NULL, 10);
11823 else
11824 *output_dBm = 23;
developer72fb0bb2023-01-11 09:46:29 +080011825 return RETURN_OK;
11826}
11827
11828INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
11829{
developera1255e42023-05-13 17:45:02 +080011830 char interface_name[16] = {0};
developera1255e42023-05-13 17:45:02 +080011831 char mgmt_pwr_file[128]={0};
11832 FILE *f = NULL;
developerfead3972023-05-25 20:15:02 +080011833 int if_idx, ret = 0;
11834 struct nl_msg *msg = NULL;
11835 struct nlattr * msg_data = NULL;
11836 struct mtk_nl80211_param param;
11837 struct unl unl_ins;
11838 char power[16] = {0};
developera1255e42023-05-13 17:45:02 +080011839
11840 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11841
11842 if (wifi_GetInterfaceName(wlanIndex, interface_name) != RETURN_OK)
11843 return RETURN_ERR;
developerfead3972023-05-25 20:15:02 +080011844
11845 if_idx = if_nametoindex(interface_name);
11846 /*init mtk nl80211 vendor cmd*/
11847 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_TXPOWER;
11848 param.if_type = NL80211_ATTR_IFINDEX;
11849 param.if_idx = if_idx;
11850
11851 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
11852 if (ret) {
11853 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
11854 return RETURN_ERR;
11855 }
11856
11857 /*add mtk vendor cmd data*/
11858 snprintf(power, sizeof(power), "%d", dBm);
11859 if (nla_put(msg, MTK_NL80211_VENDOR_ATTR_TXPWR_MGMT, strlen(power), power)) {
11860 wifi_debug(DEBUG_ERROR, "Nla put attribute error\n");
11861 nlmsg_free(msg);
11862 goto err;
11863 }
11864
11865 /*send mtk nl80211 vendor msg*/
11866 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
11867 if (ret) {
11868 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
11869 goto err;
11870 }
11871
11872 /*deinit mtk nl80211 vendor msg*/
11873 mtk_nl80211_deint(&unl_ins);
11874 wifi_debug(DEBUG_NOTICE, "set cmd success.\n");
11875
developera1255e42023-05-13 17:45:02 +080011876 snprintf(mgmt_pwr_file, sizeof(mgmt_pwr_file), "%s%d.txt", MGMT_POWER_CTRL, wlanIndex);
11877 f = fopen(mgmt_pwr_file, "w");
11878 if (f == NULL) {
11879 fprintf(stderr, "%s: fopen failed\n", __func__);
11880 return RETURN_ERR;
11881 }
11882 fprintf(f, "%d", dBm);
11883 fclose(f);
developer72fb0bb2023-01-11 09:46:29 +080011884 return RETURN_OK;
developerfead3972023-05-25 20:15:02 +080011885err:
11886 mtk_nl80211_deint(&unl_ins);
11887 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
11888 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +080011889}
11890INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
11891{
11892 return RETURN_OK;
11893}
11894INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
11895{
11896 return RETURN_OK;
11897}
11898INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
11899{
11900 return RETURN_OK;
11901}
11902INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
11903{
11904 return RETURN_OK;
11905}
11906INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
11907{
11908 char config_file[MAX_BUF_SIZE] = {0};
11909 struct params list;
11910
11911 list.name = "bss_transition";
11912 list.value = activate?"1":"0";
11913 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
11914 wifi_hostapdWrite(config_file, &list, 1);
11915
11916 return RETURN_OK;
11917}
11918wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
11919
11920void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
11921{
11922 return;
11923}
11924
11925INT wifi_setApCsaDeauth(INT apIndex, INT mode)
11926{
11927 // TODO Implement me!
11928 return RETURN_OK;
11929}
11930
11931INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
11932{
11933 char file_name[128] = {0};
11934 char buf[128] = {0};
11935 FILE *f = NULL;
11936 int max_num_radios = 0;
11937
11938 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11939
11940 wifi_getMaxRadioNumber(&max_num_radios);
11941 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
11942 for (int index = 0; index < max_num_radios; index++) {
11943 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
11944 f = fopen(file_name, "w");
11945 if (f == NULL)
11946 return RETURN_ERR;
11947 // For mode == 0 is to disable filter, just don't write to the file.
11948 if (mode)
11949 fprintf(f, "%s", essid);
11950
11951 fclose(f);
11952 }
11953 } else { // special case, need to set AP's SSID as filter for each radio.
11954 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
11955 f = fopen(file_name, "w");
11956 if (f == NULL)
11957 return RETURN_ERR;
11958
11959 // For mode == 0 is to disable filter, just don't write to the file.
11960 if (mode)
11961 fprintf(f, "%s", essid);
11962
11963 fclose(f);
11964 }
11965
11966 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11967 return RETURN_OK;
11968}
11969
11970INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
11971{
11972 // TODO Implement me!
11973 //Apply wifi_pushRadioChannel() instantly
11974 return RETURN_ERR;
11975}
11976
11977INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
11978{
11979 // TODO Implement me!
11980 return RETURN_OK;
11981}
11982
11983#ifdef HAL_NETLINK_IMPL
11984static int tidStats_callback(struct nl_msg *msg, void *arg) {
11985 struct nlattr *tb[NL80211_ATTR_MAX + 1];
11986 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
11987 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
11988 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
11989 int rem , tid_index = 0;
11990
11991 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
11992 wifi_associated_dev_tid_entry_t *stats_entry;
11993
11994 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
11995 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
11996 };
11997 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
11998 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
11999 };
12000
12001 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
12002 genlmsg_attrlen(gnlh, 0), NULL);
12003
12004
12005 if (!tb[NL80211_ATTR_STA_INFO]) {
12006 fprintf(stderr, "station stats missing!\n");
12007 return NL_SKIP;
12008 }
12009
12010 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
12011 tb[NL80211_ATTR_STA_INFO],
12012 stats_policy)) {
12013 fprintf(stderr, "failed to parse nested attributes!\n");
12014 return NL_SKIP;
12015 }
12016
developer386281b2023-05-20 15:43:13 +080012017 if (sinfo[NL80211_STA_INFO_TID_STATS]) {
12018 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
12019 {
12020 stats_entry = &out->tid_array[tid_index];
developer72fb0bb2023-01-11 09:46:29 +080012021
developer386281b2023-05-20 15:43:13 +080012022 stats_entry->tid = tid_index;
12023 stats_entry->ac = _tid_ac_index_get[tid_index];
developer72fb0bb2023-01-11 09:46:29 +080012024
developer386281b2023-05-20 15:43:13 +080012025 if(sinfo[NL80211_STA_INFO_TID_STATS])
12026 {
12027 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
12028 printf("failed to parse nested stats attributes!");
12029 return NL_SKIP;
12030 }
developer72fb0bb2023-01-11 09:46:29 +080012031 }
developer386281b2023-05-20 15:43:13 +080012032 if(stats_info[NL80211_TID_STATS_TX_MSDU])
12033 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
developer72fb0bb2023-01-11 09:46:29 +080012034
developer386281b2023-05-20 15:43:13 +080012035 if(tid_index < (PS_MAX_TID - 1))
12036 tid_index++;
12037 }
developer72fb0bb2023-01-11 09:46:29 +080012038 }
12039 //ToDo: sum_time_ms, ewma_time_ms
12040 return NL_SKIP;
12041}
12042#endif
12043
12044INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
12045{
12046#ifdef HAL_NETLINK_IMPL
12047 Netlink nl;
12048 char if_name[10];
12049 char interface_name[16] = {0};
12050
12051 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
12052 return RETURN_ERR;
12053
12054 snprintf(if_name, sizeof(if_name), "%s", interface_name);
12055
12056 nl.id = initSock80211(&nl);
12057
12058 if (nl.id < 0) {
12059 fprintf(stderr, "Error initializing netlink \n");
12060 return -1;
12061 }
12062
12063 struct nl_msg* msg = nlmsg_alloc();
12064
12065 if (!msg) {
12066 fprintf(stderr, "Failed to allocate netlink message.\n");
12067 nlfree(&nl);
12068 return -2;
12069 }
12070
12071 genlmsg_put(msg,
developer8dd72532023-05-17 19:58:35 +080012072 NL_AUTO_PID,
developer72fb0bb2023-01-11 09:46:29 +080012073 NL_AUTO_SEQ,
12074 nl.id,
12075 0,
12076 0,
12077 NL80211_CMD_GET_STATION,
12078 0);
12079
12080 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
12081 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
12082 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
developer8dd72532023-05-17 19:58:35 +080012083 nl_send_auto_complete(nl.socket, msg);
developer72fb0bb2023-01-11 09:46:29 +080012084 nl_recvmsgs(nl.socket, nl.cb);
12085 nlmsg_free(msg);
12086 nlfree(&nl);
12087 return RETURN_OK;
12088#else
12089//iw implementation
12090#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
12091#define TOTAL_MAX_LINES 50
12092
12093 char buf[256] = {'\0'}; /* or other suitable maximum line size */
12094 char if_name[32] = {0};
12095 FILE *fp=NULL;
12096 char pipeCmd[1024]= {'\0'};
12097 int lines,tid_index=0;
12098 char mac_addr[20] = {'\0'};
12099
12100 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
12101 return RETURN_ERR;
12102
12103 wifi_associated_dev_tid_entry_t *stats_entry;
12104
12105 strcpy(mac_addr,clientMacAddress);
12106
12107 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
12108 fp= popen(pipeCmd,"r");
12109 if(fp == NULL)
12110 {
12111 perror("popen for station dump failed\n");
12112 return RETURN_ERR;
12113 }
12114 pclose(fp);
12115
12116 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
12117 fp=popen(pipeCmd,"r");
12118 if(fp == NULL)
12119 {
12120 perror("popen for grep station failed\n");
12121 return RETURN_ERR;
12122 }
12123 else if(fgets(buf,sizeof(buf),fp) != NULL)
12124 lines=atoi(buf);
12125 else
12126 {
12127 pclose(fp);
12128 fprintf(stderr,"No devices are connected \n");
12129 return RETURN_ERR;
12130 }
12131 pclose(fp);
12132
12133 if(lines == 1)
12134 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
12135
12136 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
12137 {
12138 stats_entry = &tid_stats->tid_array[tid_index];
12139 stats_entry->tid = tid_index;
12140
12141 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);
12142
12143 fp=popen(pipeCmd,"r");
12144 if(fp ==NULL)
12145 {
12146 perror("Failed to read from tid file \n");
12147 return RETURN_ERR;
12148 }
12149 else if(fgets(buf,sizeof(buf),fp) != NULL)
12150 stats_entry->num_msdus = atol(buf);
12151
12152 pclose(fp);
12153 stats_entry->ac = _tid_ac_index_get[tid_index];
12154// TODO:
12155// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
12156// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
12157 }
12158 return RETURN_OK;
12159#endif
12160}
12161
12162
12163INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
12164{
12165 char interface_name[16] = {0};
12166 char cmd[128]={0};
12167 char buf[128]={0};
12168 int freq = 0;
12169
12170 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12171
12172 // full mode is used to scan all channels.
12173 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
12174 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
12175 ieee80211_channel_to_frequency(chan_list[0], &freq);
12176
12177 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
12178 return RETURN_ERR;
12179
12180 if (freq)
12181 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d freq %d", interface_name, dwell_time, freq);
12182 else
12183 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d", interface_name, dwell_time);
12184
12185 _syscmd(cmd, buf, sizeof(buf));
12186 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12187
12188 return RETURN_OK;
12189}
12190
12191
12192INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
12193{
12194 // TODO Implement me!
12195 return RETURN_ERR;
12196}
12197
12198INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
12199{
12200 // TODO Implement me!
12201 return RETURN_ERR;
12202}
12203
12204INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
12205{
12206 // TODO Implement me!
12207 return RETURN_ERR;
12208}
12209
12210INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
12211{
12212 // TODO Implement me!
12213 return RETURN_ERR;
12214}
12215
12216INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
12217{
12218 // TODO Implement me!
12219 return RETURN_ERR;
12220}
12221
12222INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
12223{
12224 // TODO Implement me!
12225 return RETURN_ERR;
12226}
12227
12228INT wifi_steering_eventUnregister(void)
12229{
12230 // TODO Implement me!
12231 return RETURN_ERR;
12232}
12233
12234INT wifi_delApAclDevices(INT apIndex)
12235{
developer7e4a2a62023-04-06 19:56:03 +080012236 char inf_name[IF_NAME_SIZE] = {0};
developer2edaf012023-05-24 14:24:53 +080012237 struct unl unl_ins;
12238 int if_idx = 0, ret = 0;
12239 struct nl_msg *msg = NULL;
12240 struct nlattr * msg_data = NULL;
12241 struct mtk_nl80211_param param;
developer72fb0bb2023-01-11 09:46:29 +080012242
developer7e4a2a62023-04-06 19:56:03 +080012243 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
12244 return RETURN_ERR;
developer2edaf012023-05-24 14:24:53 +080012245 if_idx = if_nametoindex(inf_name);
12246 if (!if_idx) {
12247 wifi_debug(DEBUG_ERROR,"can't finde ifname(%s) index,ERROR\n", inf_name);
12248 return RETURN_ERR;
12249 }
12250 /*init mtk nl80211 vendor cmd*/
12251 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_ACL;
12252 param.if_type = NL80211_ATTR_IFINDEX;
12253 param.if_idx = if_idx;
12254 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
12255 if (ret) {
12256 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
12257 return RETURN_ERR;
12258 }
12259 /*add mtk vendor cmd data*/
12260 if (nla_put_flag(msg, MTK_NL80211_VENDOR_ATTR_ACL_CLEAR_ALL)) {
12261 wifi_debug(DEBUG_ERROR, "Nla put attribute error\n");
12262 nlmsg_free(msg);
12263 goto err;
12264 }
12265 /*send mtk nl80211 vendor msg*/
12266 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
12267 if (ret) {
12268 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
12269 goto err;
12270 }
12271 /*deinit mtk nl80211 vendor msg*/
12272 mtk_nl80211_deint(&unl_ins);
12273 wifi_debug(DEBUG_NOTICE, "set cmd success.\n");
12274 return RETURN_OK;
12275err:
12276 mtk_nl80211_deint(&unl_ins);
12277 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
12278 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +080012279
12280 return RETURN_OK;
12281}
12282
12283#ifdef HAL_NETLINK_IMPL
12284static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
12285 struct nlattr *tb[NL80211_ATTR_MAX + 1];
12286 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
12287 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
12288 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
12289 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
12290 char mac_addr[20],dev[20];
12291
12292 nla_parse(tb,
12293 NL80211_ATTR_MAX,
12294 genlmsg_attrdata(gnlh, 0),
12295 genlmsg_attrlen(gnlh, 0),
12296 NULL);
12297
12298 if(!tb[NL80211_ATTR_STA_INFO]) {
12299 fprintf(stderr, "sta stats missing!\n");
12300 return NL_SKIP;
12301 }
12302
12303 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
12304 fprintf(stderr, "failed to parse nested attributes!\n");
12305 return NL_SKIP;
12306 }
12307 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
12308
12309 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
12310
developer386281b2023-05-20 15:43:13 +080012311 if (sinfo[NL80211_STA_INFO_RX_BITRATE]) {
12312 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
12313 fprintf(stderr, "failed to parse nested rate attributes!");
12314 return NL_SKIP;
12315 }
developer72fb0bb2023-01-11 09:46:29 +080012316 }
12317
12318 if(sinfo[NL80211_STA_INFO_TID_STATS])
12319 {
12320 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
12321 printf("failed to parse nested stats attributes!");
12322 return NL_SKIP;
12323 }
12324 }
developer5a1194f2023-05-24 16:00:03 +080012325 if (tb[NL80211_ATTR_VHT_CAPABILITY]) {
developer72fb0bb2023-01-11 09:46:29 +080012326
developereb1ea832023-05-24 14:46:27 +080012327 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
12328 {
12329 printf("Type is VHT\n");
12330 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
12331 ((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 +080012332
developereb1ea832023-05-24 14:46:27 +080012333 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
12334 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
12335 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
12336 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
12337 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
12338 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
12339 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
12340 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
12341 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
12342 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
12343 }
12344 else
12345 {
12346 printf(" OFDM or CCK \n");
12347 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
12348 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
12349 }
12350 }
developer72fb0bb2023-01-11 09:46:29 +080012351
12352 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
12353 if(rinfo[NL80211_RATE_INFO_MCS])
12354 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
12355 }
12356 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
12357 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
12358 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
12359 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
12360
12361 if(stats_info[NL80211_TID_STATS_RX_MSDU])
12362 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
12363
12364 if (sinfo[NL80211_STA_INFO_SIGNAL])
12365 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
12366 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
12367 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
12368 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
12369 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
12370 //rssi_array need to be filled
12371 return NL_SKIP;
12372}
12373#endif
12374
12375INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
12376{
12377#ifdef HAL_NETLINK_IMPL
12378 Netlink nl;
12379 char if_name[32];
12380 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
12381 return RETURN_ERR;
12382
12383 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
12384
12385 if (*output_array_size <= 0)
12386 return RETURN_OK;
12387
12388 nl.id = initSock80211(&nl);
12389
12390 if (nl.id < 0) {
12391 fprintf(stderr, "Error initializing netlink \n");
12392 return 0;
12393 }
12394
12395 struct nl_msg* msg = nlmsg_alloc();
12396
12397 if (!msg) {
12398 fprintf(stderr, "Failed to allocate netlink message.\n");
12399 nlfree(&nl);
12400 return 0;
12401 }
12402
12403 genlmsg_put(msg,
developer8dd72532023-05-17 19:58:35 +080012404 NL_AUTO_PID,
developer72fb0bb2023-01-11 09:46:29 +080012405 NL_AUTO_SEQ,
12406 nl.id,
12407 0,
12408 0,
12409 NL80211_CMD_GET_STATION,
12410 0);
12411
12412 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
12413 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
12414 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
developer8dd72532023-05-17 19:58:35 +080012415 nl_send_auto_complete(nl.socket, msg);
developer72fb0bb2023-01-11 09:46:29 +080012416 nl_recvmsgs(nl.socket, nl.cb);
12417 nlmsg_free(msg);
12418 nlfree(&nl);
12419 return RETURN_OK;
12420#else
12421 //TODO Implement me
12422 return RETURN_OK;
12423#endif
12424}
12425
12426#ifdef HAL_NETLINK_IMPL
12427static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
12428 struct nlattr *tb[NL80211_ATTR_MAX + 1];
12429 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
12430 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
12431 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
12432 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
12433 char mac_addr[20],dev[20];
12434
12435 nla_parse(tb,
12436 NL80211_ATTR_MAX,
12437 genlmsg_attrdata(gnlh, 0),
12438 genlmsg_attrlen(gnlh, 0),
12439 NULL);
12440
12441 if(!tb[NL80211_ATTR_STA_INFO]) {
12442 fprintf(stderr, "sta stats missing!\n");
12443 return NL_SKIP;
12444 }
12445
12446 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
12447 fprintf(stderr, "failed to parse nested attributes!\n");
12448 return NL_SKIP;
12449 }
12450
12451 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
12452
12453 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
12454
developer386281b2023-05-20 15:43:13 +080012455 if (sinfo[NL80211_STA_INFO_TX_BITRATE]) {
12456 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
12457 fprintf(stderr, "failed to parse nested rate attributes!");
12458 return NL_SKIP;
12459 }
developer72fb0bb2023-01-11 09:46:29 +080012460 }
12461
12462 if(sinfo[NL80211_STA_INFO_TID_STATS])
12463 {
12464 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
12465 printf("failed to parse nested stats attributes!");
12466 return NL_SKIP;
12467 }
12468 }
developera6beea42023-05-24 16:44:05 +080012469 if (tb[NL80211_ATTR_VHT_CAPABILITY]) {
developereb1ea832023-05-24 14:46:27 +080012470 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
12471 {
12472 printf("Type is VHT\n");
12473 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
12474 ((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 +080012475
developereb1ea832023-05-24 14:46:27 +080012476 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
12477 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
12478 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
12479 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
12480 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
12481 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
12482 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
12483 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
12484 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
12485 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
12486 }
12487 else
12488 {
12489 printf(" OFDM or CCK \n");
developer72fb0bb2023-01-11 09:46:29 +080012490 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
developereb1ea832023-05-24 14:46:27 +080012491 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
12492 }
developer72fb0bb2023-01-11 09:46:29 +080012493 }
12494
12495 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
12496 if(rinfo[NL80211_RATE_INFO_MCS])
12497 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
12498 }
12499
12500 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
12501 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
12502 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
12503 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
12504
12505 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
12506 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
12507 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
12508
12509 if(stats_info[NL80211_TID_STATS_TX_MSDU])
12510 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
12511
12512 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
12513 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
12514
12515 if(sinfo[NL80211_STA_INFO_TX_FAILED])
12516 ((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]);
12517
12518 return NL_SKIP;
12519}
12520#endif
12521
12522INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
12523{
12524#ifdef HAL_NETLINK_IMPL
12525 Netlink nl;
12526 char if_name[10];
12527 char interface_name[16] = {0};
12528 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
12529 return RETURN_ERR;
12530
12531 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
12532
12533 if (*output_array_size <= 0)
12534 return RETURN_OK;
12535
12536 snprintf(if_name, sizeof(if_name), "%s", interface_name);
12537
12538 nl.id = initSock80211(&nl);
12539
12540 if(nl.id < 0) {
12541 fprintf(stderr, "Error initializing netlink \n");
12542 return 0;
12543 }
12544
12545 struct nl_msg* msg = nlmsg_alloc();
12546
12547 if(!msg) {
12548 fprintf(stderr, "Failed to allocate netlink message.\n");
12549 nlfree(&nl);
12550 return 0;
12551 }
12552
12553 genlmsg_put(msg,
developer8dd72532023-05-17 19:58:35 +080012554 NL_AUTO_PID,
developer72fb0bb2023-01-11 09:46:29 +080012555 NL_AUTO_SEQ,
12556 nl.id,
12557 0,
12558 0,
12559 NL80211_CMD_GET_STATION,
12560 0);
12561
12562 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
12563 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
12564 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
developer8dd72532023-05-17 19:58:35 +080012565 nl_send_auto_complete(nl.socket, msg);
developer72fb0bb2023-01-11 09:46:29 +080012566 nl_recvmsgs(nl.socket, nl.cb);
12567 nlmsg_free(msg);
12568 nlfree(&nl);
12569 return RETURN_OK;
12570#else
12571 //TODO Implement me
12572 return RETURN_OK;
12573#endif
12574}
12575
12576INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
12577{
12578 // TODO Implement me!
12579 char buf[MAX_BUF_SIZE] = {0};
12580 char config_file[MAX_BUF_SIZE] = {0};
12581
12582 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
12583 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
12584 *activate = (strncmp("1",buf,1) == 0);
12585
12586 return RETURN_OK;
12587}
12588
12589INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
12590{
12591 char config_file[MAX_BUF_SIZE] = {0};
12592 struct params list;
12593
12594 list.name = "rrm_neighbor_report";
12595 list.value = activate?"1":"0";
12596 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
12597 wifi_hostapdWrite(config_file, &list, 1);
12598
12599 return RETURN_OK;
12600}
12601
12602INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
12603{
12604 char buf[32] = {0};
12605 char config_file[MAX_BUF_SIZE] = {0};
12606
12607 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
12608 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
12609 *activate = (strncmp("1",buf,1) == 0);
12610
12611 return RETURN_OK;
12612}
12613#undef HAL_NETLINK_IMPL
12614#ifdef HAL_NETLINK_IMPL
12615static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
12616 struct nlattr *tb[NL80211_ATTR_MAX + 1];
12617 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
12618 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
12619 char dev[20];
12620 int freq =0 ;
12621 static int i=0;
12622
12623 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
12624
12625 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
12626 };
12627
12628 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
12629
12630 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
12631
12632 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
12633 fprintf(stderr, "survey data missing!\n");
12634 return NL_SKIP;
12635 }
12636
12637 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
12638 {
12639 fprintf(stderr, "failed to parse nested attributes!\n");
12640 return NL_SKIP;
12641 }
12642
12643
12644 if(out[0].array_size == 1 )
12645 {
12646 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
12647 {
12648 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
12649 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
12650 out[0].ch_number = ieee80211_frequency_to_channel(freq);
12651
12652 if (sinfo[NL80211_SURVEY_INFO_NOISE])
12653 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
12654 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
12655 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
12656 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
12657 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
12658 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
12659 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
12660 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
12661 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
12662 if (sinfo[NL80211_SURVEY_INFO_TIME])
12663 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
12664 return NL_STOP;
12665 }
12666 }
12667 else
12668 {
12669 if ( i <= out[0].array_size )
12670 {
12671 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
12672 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
12673 out[i].ch_number = ieee80211_frequency_to_channel(freq);
12674
12675 if (sinfo[NL80211_SURVEY_INFO_NOISE])
12676 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
12677 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
12678 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
12679 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
12680 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
12681 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
12682 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
12683 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
12684 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
12685 if (sinfo[NL80211_SURVEY_INFO_TIME])
12686 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
12687 }
12688 }
12689
12690 i++;
12691 return NL_SKIP;
12692}
12693#endif
12694
12695static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
12696{
12697 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
12698 FILE *fp;
12699
12700 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
12701 {
12702 printf("Creating Frequency-Channel Map\n");
12703 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
12704 }
12705 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
12706 if((fp = popen(command, "r")))
12707 {
12708 fgets(output, sizeof(output), fp);
12709 *freqMHz = atoi(output);
12710 pclose(fp);
12711 }
12712
12713 return 0;
12714}
12715
12716static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
12717{
12718 int freqMHz = -1;
12719 char cmd[MAX_CMD_SIZE] = {'\0'};
12720 char interface_name[16] = {0};
12721
12722 ieee80211_channel_to_frequency(channel, &freqMHz);
12723 if (freqMHz == -1) {
12724 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
12725 return -1;
12726 }
12727
12728 wifi_GetInterfaceName(radioIndex, interface_name);
12729 if (sprintf(cmd,"iw dev %s survey dump | grep -A5 %d | tr -d '\\t'", interface_name, freqMHz) < 0) {
12730 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
12731 radioIndex, freqMHz);
12732 return -1;
12733 }
12734
12735 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
12736 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
12737 return -1;
12738 }
12739
12740 return 0;
12741}
12742
12743static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
12744{
12745 const char *ptr = buf;
12746 char *key = NULL;
12747 char *val = NULL;
12748 char line[256] = { '\0' };
12749
12750 while (ptr = get_line_from_str_buf(ptr, line)) {
12751 if (strstr(line, "Frequency")) continue;
12752
12753 key = strtok(line, ":");
12754 val = strtok(NULL, " ");
12755 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
12756
12757 if (!strcmp(key, "noise")) {
12758 sscanf(val, "%d", &stats->ch_noise);
12759 if (stats->ch_noise == 0) {
12760 // Workaround for missing noise information.
12761 // Assume -95 for 2.4G and -103 for 5G
12762 if (radioIndex == 0) stats->ch_noise = -95;
12763 if (radioIndex == 1) stats->ch_noise = -103;
12764 }
12765 }
12766 else if (!strcmp(key, "channel active time")) {
12767 sscanf(val, "%llu", &stats->ch_utilization_total);
12768 }
12769 else if (!strcmp(key, "channel busy time")) {
12770 sscanf(val, "%llu", &stats->ch_utilization_busy);
12771 }
12772 else if (!strcmp(key, "channel receive time")) {
12773 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
12774 }
12775 else if (!strcmp(key, "channel transmit time")) {
12776 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
12777 }
12778 };
12779
12780 return 0;
12781}
12782
12783INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
12784{
12785 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12786#ifdef HAL_NETLINK_IMPL
12787 Netlink nl;
12788 wifi_channelStats_t_loc local[array_size];
12789 char if_name[32];
12790
12791 local[0].array_size = array_size;
12792
12793 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
12794 return RETURN_ERR;
12795
12796 nl.id = initSock80211(&nl);
12797
12798 if (nl.id < 0) {
12799 fprintf(stderr, "Error initializing netlink \n");
12800 return -1;
12801 }
12802
12803 struct nl_msg* msg = nlmsg_alloc();
12804
12805 if (!msg) {
12806 fprintf(stderr, "Failed to allocate netlink message.\n");
12807 nlfree(&nl);
12808 return -2;
12809 }
12810
12811 genlmsg_put(msg,
developer8dd72532023-05-17 19:58:35 +080012812 NL_AUTO_PID,
developer72fb0bb2023-01-11 09:46:29 +080012813 NL_AUTO_SEQ,
12814 nl.id,
12815 0,
12816 NLM_F_DUMP,
12817 NL80211_CMD_GET_SURVEY,
12818 0);
12819
12820 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
developer8dd72532023-05-17 19:58:35 +080012821 nl_send_auto_complete(nl.socket, msg);
developer72fb0bb2023-01-11 09:46:29 +080012822 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
12823 nl_recvmsgs(nl.socket, nl.cb);
12824 nlmsg_free(msg);
12825 nlfree(&nl);
12826 //Copying the Values
12827 for(int i=0;i<array_size;i++)
12828 {
12829 input_output_channelStats_array[i].ch_number = local[i].ch_number;
12830 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
12831 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
12832 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
12833 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
12834 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
12835 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
12836 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
12837 }
12838#else
12839 ULONG channel = 0;
12840 int i;
12841 int number_of_channels = array_size;
12842 char buf[512];
12843 INT ret;
12844 wifi_channelStats_t tmp_stats;
12845
12846 if (number_of_channels == 0) {
12847 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
12848 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
12849 return RETURN_ERR;
12850 }
12851 number_of_channels = 1;
12852 input_output_channelStats_array[0].ch_number = channel;
12853 }
12854
12855 for (i = 0; i < number_of_channels; i++) {
12856
12857 input_output_channelStats_array[i].ch_noise = 0;
12858 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
12859 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
12860 input_output_channelStats_array[i].ch_utilization_busy = 0;
12861 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
12862 input_output_channelStats_array[i].ch_utilization_total = 0;
12863
12864 memset(buf, 0, sizeof(buf));
12865 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
12866 return RETURN_ERR;
12867 }
12868 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
12869 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
12870 return RETURN_ERR;
12871 }
12872
12873 // XXX: fake missing 'self' counter which is not available in iw survey output
12874 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
12875 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
12876
12877 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
12878 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
12879 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
12880 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
12881 input_output_channelStats_array[i].ch_utilization_total *= 1000;
12882
12883 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",
12884 __func__,
12885 input_output_channelStats_array[i].ch_number,
12886 input_output_channelStats_array[i].ch_noise,
12887 input_output_channelStats_array[i].ch_utilization_total,
12888 input_output_channelStats_array[i].ch_utilization_busy,
12889 input_output_channelStats_array[i].ch_utilization_busy_rx,
12890 input_output_channelStats_array[i].ch_utilization_busy_tx,
12891 input_output_channelStats_array[i].ch_utilization_busy_self,
12892 input_output_channelStats_array[i].ch_utilization_busy_ext);
12893 }
12894#endif
12895 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12896 return RETURN_OK;
12897}
12898#define HAL_NETLINK_IMPL
12899
12900/* Hostapd events */
12901
12902#ifndef container_of
12903#define offset_of(st, m) ((size_t)&(((st *)0)->m))
12904#define container_of(ptr, type, member) \
12905 ((type *)((char *)ptr - offset_of(type, member)))
12906#endif /* container_of */
12907
12908struct ctrl {
12909 char sockpath[128];
12910 char sockdir[128];
12911 char bss[IFNAMSIZ];
12912 char reply[4096];
12913 int ssid_index;
12914 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
12915 void (*overrun)(struct ctrl *ctrl);
12916 struct wpa_ctrl *wpa;
12917 unsigned int ovfl;
12918 size_t reply_len;
12919 int initialized;
12920 ev_timer retry;
12921 ev_timer watchdog;
12922 ev_stat stat;
12923 ev_io io;
12924};
12925static wifi_newApAssociatedDevice_callback clients_connect_cb;
12926static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
12927static struct ctrl wpa_ctrl[MAX_APS];
12928static int initialized;
12929
12930static unsigned int ctrl_get_drops(struct ctrl *ctrl)
12931{
12932 char cbuf[256] = {};
12933 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
12934 struct cmsghdr *cmsg;
12935 unsigned int ovfl = ctrl->ovfl;
12936 unsigned int drop;
12937
12938 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
12939 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
12940 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
12941 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
12942
12943 drop = ovfl - ctrl->ovfl;
12944 ctrl->ovfl = ovfl;
12945
12946 return drop;
12947}
12948
12949static void ctrl_close(struct ctrl *ctrl)
12950{
12951 if (ctrl->io.cb)
12952 ev_io_stop(EV_DEFAULT_ &ctrl->io);
12953 if (ctrl->retry.cb)
12954 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
12955 if (!ctrl->wpa)
12956 return;
12957
12958 wpa_ctrl_detach(ctrl->wpa);
12959 wpa_ctrl_close(ctrl->wpa);
12960 ctrl->wpa = NULL;
12961 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
12962}
12963
12964static void ctrl_process(struct ctrl *ctrl)
12965{
12966 const char *str;
12967 int drops;
12968 int level;
12969 int err;
12970
12971 /* Example events:
12972 *
12973 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
12974 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
12975 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
12976 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
12977 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
12978 */
12979 if (!(str = index(ctrl->reply, '>')))
12980 return;
12981 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
12982 return;
12983
12984 str++;
12985
12986 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
12987 if (!(str = index(ctrl->reply, ' ')))
12988 return;
12989 wifi_associated_dev_t sta;
12990 memset(&sta, 0, sizeof(sta));
12991
12992 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
12993 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
12994 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
12995
12996 sta.cli_Active=true;
12997
12998 (clients_connect_cb)(ctrl->ssid_index, &sta);
12999 goto handled;
13000 }
13001
13002 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
13003 if (!(str = index(ctrl->reply, ' ')))
13004 return;
13005
13006 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
13007 goto handled;
13008 }
13009
13010 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
13011 printf("CTRL_WPA: handle TERMINATING event\n");
13012 goto retry;
13013 }
13014
13015 if (strncmp("AP-DISABLED", str, 11) == 0) {
13016 printf("CTRL_WPA: handle AP-DISABLED\n");
13017 goto retry;
13018 }
13019
13020 printf("Event not supported!!\n");
13021
13022handled:
13023
13024 if ((drops = ctrl_get_drops(ctrl))) {
13025 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
13026 if (ctrl->overrun)
13027 ctrl->overrun(ctrl);
13028 }
13029
13030 return;
13031
13032retry:
13033 printf("WPA_CTRL: closing\n");
13034 ctrl_close(ctrl);
13035 printf("WPA_CTRL: retrying from ctrl prcoess\n");
13036 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
13037}
13038
13039static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
13040{
13041 struct ctrl *ctrl = container_of(io, struct ctrl, io);
13042 int err;
13043
13044 memset(ctrl->reply, 0, sizeof(ctrl->reply));
13045 ctrl->reply_len = sizeof(ctrl->reply) - 1;
13046 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
13047 ctrl->reply[ctrl->reply_len] = 0;
13048 if (err < 0) {
13049 if (errno == EAGAIN || errno == EWOULDBLOCK)
13050 return;
13051 ctrl_close(ctrl);
13052 ev_timer_again(EV_A_ &ctrl->retry);
13053 return;
13054 }
13055
13056 ctrl_process(ctrl);
13057}
13058
13059static int ctrl_open(struct ctrl *ctrl)
13060{
13061 int fd;
13062
13063 if (ctrl->wpa)
13064 return 0;
13065
13066 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
13067 if (!ctrl->wpa)
13068 goto err;
13069
13070 if (wpa_ctrl_attach(ctrl->wpa) < 0)
13071 goto err_close;
13072
13073 fd = wpa_ctrl_get_fd(ctrl->wpa);
13074 if (fd < 0)
13075 goto err_detach;
13076
13077 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
13078 goto err_detach;
13079
13080 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
13081 ev_io_start(EV_DEFAULT_ &ctrl->io);
13082
13083 return 0;
13084
13085err_detach:
13086 wpa_ctrl_detach(ctrl->wpa);
13087err_close:
13088 wpa_ctrl_close(ctrl->wpa);
13089err:
13090 ctrl->wpa = NULL;
13091 return -1;
13092}
13093
13094static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
13095{
13096 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
13097
13098 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
13099 ctrl_open(ctrl);
13100}
13101
13102static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
13103{
13104 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
13105
13106 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
13107 if (ctrl_open(ctrl) == 0) {
13108 printf("WPA_CTRL: retry successful\n");
13109 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
13110 }
13111}
13112
13113int ctrl_enable(struct ctrl *ctrl)
13114{
13115 if (ctrl->wpa)
13116 return 0;
13117
13118 if (!ctrl->stat.cb) {
13119 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
13120 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
13121 }
13122
13123 if (!ctrl->retry.cb) {
13124 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
13125 }
13126
13127 return ctrl_open(ctrl);
13128}
13129
13130static void
13131ctrl_msg_cb(char *buf, size_t len)
13132{
13133 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
13134
13135 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
13136 ctrl_process(ctrl);
13137}
13138
13139static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
13140{
13141 int err;
13142
13143 if (!ctrl->wpa)
13144 return -1;
13145 if (*reply_len < 2)
13146 return -1;
13147
13148 (*reply_len)--;
13149 ctrl->reply_len = sizeof(ctrl->reply);
13150 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
13151 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
13152 if (err < 0)
13153 return err;
13154
13155 if (ctrl->reply_len > *reply_len)
13156 ctrl->reply_len = *reply_len;
13157
13158 *reply_len = ctrl->reply_len;
13159 memcpy(reply, ctrl->reply, *reply_len);
13160 reply[*reply_len - 1] = 0;
13161 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
13162 return 0;
13163}
13164
13165static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
13166{
13167 const char *pong = "PONG";
13168 const char *ping = "PING";
13169 char reply[1024];
13170 size_t len = sizeof(reply);
13171 int err;
13172 ULONG s, snum;
13173 INT ret;
13174 BOOL status;
13175
13176 printf("WPA_CTRL: watchdog cb\n");
13177
13178 ret = wifi_getSSIDNumberOfEntries(&snum);
13179 if (ret != RETURN_OK) {
13180 printf("%s: failed to get SSID count", __func__);
13181 return;
13182 }
13183
13184 if (snum > MAX_APS) {
13185 printf("more ssid than supported! %lu\n", snum);
13186 return;
13187 }
13188
13189 for (s = 0; s < snum; s++) {
13190 if (wifi_getApEnable(s, &status) != RETURN_OK) {
13191 printf("%s: failed to get AP Enable for index: %lu\n", __func__, s);
13192 continue;
13193 }
13194 if (status == false) continue;
13195
13196 memset(reply, 0, sizeof(reply));
13197 len = sizeof(reply);
13198 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
13199 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
13200 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
13201 continue;
13202
13203 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
13204 ctrl_close(&wpa_ctrl[s]);
13205 printf("WPA_CTRL: ev_timer_again %lu\n", s);
13206 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
13207 }
13208}
13209
13210static int init_wpa()
13211{
13212 int ret = 0, i = 0;
13213 ULONG s, snum;
13214
13215 ret = wifi_getSSIDNumberOfEntries(&snum);
13216 if (ret != RETURN_OK) {
13217 printf("%s: failed to get SSID count", __func__);
13218 return RETURN_ERR;
13219 }
13220
13221 if (snum > MAX_APS) {
13222 printf("more ssid than supported! %lu\n", snum);
13223 return RETURN_ERR;
13224 }
13225
13226 for (s = 0; s < snum; s++) {
13227 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
13228 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
13229 wpa_ctrl[s].ssid_index = s;
13230 ctrl_enable(&wpa_ctrl[s]);
13231 }
13232
13233 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
13234 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
13235
13236 initialized = 1;
13237 printf("WPA_CTRL: initialized\n");
13238
13239 return RETURN_OK;
13240}
13241
13242void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
13243{
13244 clients_connect_cb = callback_proc;
13245 if (!initialized)
13246 init_wpa();
13247}
13248
13249void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
13250{
13251 clients_disconnect_cb = callback_proc;
13252 if (!initialized)
13253 init_wpa();
13254}
13255
13256INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
13257{
13258 // TODO Implement me!
13259 return RETURN_ERR;
13260}
13261
13262INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
13263{
13264 // TODO Implement me!
13265 return RETURN_ERR;
13266}
13267
13268INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
13269{
13270 int i;
developerd1824452023-05-18 12:30:04 +080013271 int phyId = -1;
13272 char cmd[256] = {0};
13273 char channel_numbers_buf[256] = {0};
13274 char dfs_state_buf[256] = {0};
13275 char line[256] = {0};
developer72fb0bb2023-01-11 09:46:29 +080013276 const char *ptr;
developerd1824452023-05-18 12:30:04 +080013277 BOOL dfs_enable = false;
developer72fb0bb2023-01-11 09:46:29 +080013278
developerd1824452023-05-18 12:30:04 +080013279 memset(outputMap, 0, outputMapSize*sizeof(wifi_channelMap_t)); // all unused entries should be zero
developer72fb0bb2023-01-11 09:46:29 +080013280
developerd1824452023-05-18 12:30:04 +080013281 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
13282 phyId = radio_index_to_phy(radioIndex);
developer72fb0bb2023-01-11 09:46:29 +080013283
developerd1824452023-05-18 12:30:04 +080013284 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 +080013285
developerd1824452023-05-18 12:30:04 +080013286 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
13287 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
13288 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +080013289 }
13290
developerd1824452023-05-18 12:30:04 +080013291 ptr = channel_numbers_buf;
13292 i = 0;
13293 while (ptr = get_line_from_str_buf(ptr, line)) {
13294 if (i >= outputMapSize) {
13295 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
13296 return RETURN_ERR;
13297 }
13298 sscanf(line, "%d", &outputMap[i].ch_number);
13299
13300 memset(cmd, 0, sizeof(cmd));
13301 // Below command should fetch string for DFS state (usable, available or unavailable)
13302 // Example line: "DFS state: usable (for 78930 sec)"
13303 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) {
13304 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
developer72fb0bb2023-01-11 09:46:29 +080013305 return RETURN_ERR;
13306 }
13307
developerd1824452023-05-18 12:30:04 +080013308 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
13309 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
developer72fb0bb2023-01-11 09:46:29 +080013310 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
13311 return RETURN_ERR;
13312 }
13313
developerd1824452023-05-18 12:30:04 +080013314 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
developer59fda4f2023-05-16 15:47:38 +080013315
developerd1824452023-05-18 12:30:04 +080013316 if (!strcmp(dfs_state_buf, "usable")) {
13317 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
13318 } else if (!strcmp(dfs_state_buf, "available")) {
13319 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
13320 } else if (!strcmp(dfs_state_buf, "unavailable")) {
13321 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
13322 } else {
13323 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
developer72fb0bb2023-01-11 09:46:29 +080013324 }
developerd1824452023-05-18 12:30:04 +080013325 i++;
developer59fda4f2023-05-16 15:47:38 +080013326 }
developer40ba1762023-05-13 11:03:49 +080013327
developerd1824452023-05-18 12:30:04 +080013328 return RETURN_OK;
13329
developer72fb0bb2023-01-11 09:46:29 +080013330 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
13331 return RETURN_ERR;
13332}
13333
13334INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
13335{
13336 // TODO Implement me!
13337 return RETURN_ERR;
13338}
13339
13340INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
13341{
13342 return RETURN_OK;
13343}
13344
13345INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
13346{
13347 // TODO Implement me!
13348 return RETURN_ERR;
13349}
13350
13351INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
13352{
13353 // TODO API refrence Implementaion is present on RPI hal
13354 return RETURN_ERR;
13355}
13356
13357INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
13358{
developera1255e42023-05-13 17:45:02 +080013359/*
developer72fb0bb2023-01-11 09:46:29 +080013360 char interface_name[16] = {0};
13361 char cmd[128]={'\0'};
13362 char buf[128]={'\0'};
13363 char *support;
13364 int maximum_tx = 0, current_tx = 0;
developera1255e42023-05-13 17:45:02 +080013365*/ ULONG pwr_percentage = 0;
developer72fb0bb2023-01-11 09:46:29 +080013366
13367 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13368 if(txpwr_pcntg == NULL)
13369 return RETURN_ERR;
13370
developera1255e42023-05-13 17:45:02 +080013371 wifi_getRadioTransmitPower(apIndex, &pwr_percentage);
13372 *txpwr_pcntg = pwr_percentage;
13373/* if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72fb0bb2023-01-11 09:46:29 +080013374 return RETURN_ERR;
13375
13376 // Get the maximum tx power of the device
13377 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", interface_name);
13378 _syscmd(cmd, buf, sizeof(buf));
13379 maximum_tx = strtol(buf, NULL, 10);
13380
13381 // Get the current tx power
13382 memset(cmd, 0, sizeof(cmd));
13383 memset(buf, 0, sizeof(buf));
13384 snprintf(cmd, sizeof(cmd), "iw %s info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", interface_name);
13385 _syscmd(cmd, buf, sizeof(buf));
13386 current_tx = strtol(buf, NULL, 10);
13387
13388 // Get the power supported list and find the current power percentage in supported list
13389 memset(buf, 0, sizeof(buf));
13390 wifi_getRadioTransmitPowerSupported(apIndex, buf);
13391 support = strtok(buf, ",");
13392 while(true)
13393 {
13394 if(support == NULL) { // current power is not in supported list, this should not happen if the power is set by hal.
13395 *txpwr_pcntg = 100;
13396 wifi_dbg_printf("current power is not in supported list\n");
13397 return RETURN_OK;
13398 }
13399 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
13400 if (tmp == current_tx) {
13401 *txpwr_pcntg = strtol(support, NULL, 10);
13402 break;
13403 }
13404 support = strtok(NULL, ",");
13405 }
developera1255e42023-05-13 17:45:02 +080013406*/
developer72fb0bb2023-01-11 09:46:29 +080013407 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13408 return RETURN_OK;
13409}
13410
13411INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
13412{
13413 // TODO precac feature.
developerd1824452023-05-18 12:30:04 +080013414 struct params params[2] = {0};
developer72fb0bb2023-01-11 09:46:29 +080013415 char config_file[128] = {0};
developerd1824452023-05-18 12:30:04 +080013416 BOOL dfs_enable = false;
13417 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +080013418
13419 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developerd1824452023-05-18 12:30:04 +080013420 band = wifi_index_to_band(radioIndex);
13421 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
developer72fb0bb2023-01-11 09:46:29 +080013422
developerd1824452023-05-18 12:30:04 +080013423 if (dfs_enable == false) {
13424 WIFI_ENTRY_EXIT_DEBUG("Please enable DFS firstly!: %s\n", __func__);
13425 return RETURN_ERR;
13426 }
13427 params[0].name = "DfsZeroWaitDefault";
13428 params[0].value = enable?"1":"0";
13429 params[1].name = "DfsDedicatedZeroWait";
13430 params[1].value = enable?"1":"0";
13431 snprintf(config_file, sizeof(config_file), "%s%d.dat", LOGAN_DAT_FILE, band);
13432 wifi_datfileWrite(config_file, params, 2);
developerc0772e62023-05-18 15:10:48 +080013433 wifi_reloadAp(radioIndex);
developer72fb0bb2023-01-11 09:46:29 +080013434 /* TODO precac feature */
13435
13436 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13437 return RETURN_OK;
13438}
13439
13440INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
13441{
13442 char config_file[128] = {0};
developerd1824452023-05-18 12:30:04 +080013443 char buf1[32] = {0};
13444 char buf2[32] = {0};
13445 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +080013446
13447 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13448 if (NULL == enable || NULL == precac)
13449 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +080013450 band = wifi_index_to_band(radioIndex);
13451 snprintf(config_file, sizeof(config_file), "%s%d.dat", LOGAN_DAT_FILE, band);
13452 wifi_datfileRead(config_file, "DfsZeroWaitDefault", buf1, sizeof(buf1));
13453 wifi_datfileRead(config_file, "DfsDedicatedZeroWait", buf2, sizeof(buf2));
13454 if ((strncmp(buf1, "1", 1) == 0) && (strncmp(buf2, "1", 1) == 0))
developer72fb0bb2023-01-11 09:46:29 +080013455 *enable = true;
13456 else
13457 *enable = false;
13458
13459 /* TODO precac feature */
13460
13461 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13462 return RETURN_OK;
13463}
13464
13465INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
13466{
13467 *supported = TRUE;
13468 return RETURN_OK;
13469}
13470
13471INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
13472{
developera1255e42023-05-13 17:45:02 +080013473 UCHAR dat_file[64] = {0};
13474 wifi_band band = band_invalid;
13475 char cmd[128] = {0};
13476 char buf[256] = {0};
13477 char ofdmabuf[32] = {'\0'};
13478 char mimobuf[32] = {'\0'};
13479 char new_ofdmabuf[32] = {'\0'};
13480 char new_mimobuf[32] = {'\0'};
13481 struct params params[2];
13482 char *str_zero = "0;0;0;0;0;0;0;0;0;0;0;0;0;0;0";/*default 15bss per band.*/
13483 char *str_one = "1;1;1;1;1;1;1;1;1;1;1;1;1;1;1";
13484 UCHAR bss_cnt = 0;
13485 UCHAR val_cnt = 0;
13486 char *token = NULL;
developer72fb0bb2023-01-11 09:46:29 +080013487
developera1255e42023-05-13 17:45:02 +080013488 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13489 if ((mu_type < WIFI_DL_MU_TYPE_NONE)
13490 || (mu_type > WIFI_DL_MU_TYPE_OFDMA_MIMO)) {
13491 printf("%s:mu_type input Error", __func__);
13492 return RETURN_ERR;
13493 }
13494 band = wifi_index_to_band(radio_index);
13495 if (band == band_invalid) {
13496 printf("%s:Band Error\n", __func__);
13497 return RETURN_ERR;
13498 }
13499 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
13500 /*get current value in dat file*/
13501 wifi_datfileRead(dat_file, "MuOfdmaDlEnable", ofdmabuf, sizeof(ofdmabuf));
13502 wifi_datfileRead(dat_file, "MuMimoDlEnable", mimobuf, sizeof(mimobuf));
13503 WIFI_ENTRY_EXIT_DEBUG("%s:ofdma-%s, mimo-%s\n", __func__, ofdmabuf, mimobuf);
13504 get_bssnum_byindex(radio_index, &bss_cnt);
13505 val_cnt = 2*bss_cnt - 1;
13506 WIFI_ENTRY_EXIT_DEBUG("bss number: %d\n", bss_cnt);
13507 if ((val_cnt >= sizeof(new_ofdmabuf))
13508 || (val_cnt >= sizeof(new_mimobuf))) {
13509 printf("%s:bss cnt Error", __func__, bss_cnt);
13510 return RETURN_ERR;
13511 }
13512 /*translate set value*/
13513 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
13514 strncpy(new_ofdmabuf, str_zero, val_cnt);
13515 strncpy(new_mimobuf, str_zero, val_cnt);
developer72fb0bb2023-01-11 09:46:29 +080013516 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
developera1255e42023-05-13 17:45:02 +080013517 strncpy(new_ofdmabuf, str_one, val_cnt);
13518 strncpy(new_mimobuf, str_zero, val_cnt);
developer72fb0bb2023-01-11 09:46:29 +080013519 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
developera1255e42023-05-13 17:45:02 +080013520 strncpy(new_ofdmabuf, str_zero, val_cnt);
13521 strncpy(new_mimobuf, str_one, val_cnt);
13522 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO) {
13523 strncpy(new_ofdmabuf, str_one, val_cnt);
13524 strncpy(new_mimobuf, str_one, val_cnt);
developer72fb0bb2023-01-11 09:46:29 +080013525 }
developera1255e42023-05-13 17:45:02 +080013526 WIFI_ENTRY_EXIT_DEBUG("%s:new_ofdmabuf-%s, new_mimobuf-%s\n", __func__, new_ofdmabuf, new_mimobuf);
13527 /*same value, not operation*/
13528 if ((strncmp(new_mimobuf, mimobuf, 1) ==0)
13529 && (strncmp(new_ofdmabuf, ofdmabuf, 1) ==0)) {
13530 printf("%s:Reduntant value\n", __func__);
13531 return RETURN_OK;
13532 }
13533 /*modify dat file to new file*/
13534 params[0].name="MuOfdmaDlEnable";
13535 params[0].value=new_ofdmabuf;
13536 params[1].name="MuMimoDlEnable";
13537 params[1].value=new_mimobuf;
13538 wifi_datfileWrite(dat_file, params, 2);
13539 /*hostapd control restarp ap to take effect on these new value*/
13540 wifi_reloadAp(radio_index);
developer72fb0bb2023-01-11 09:46:29 +080013541 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13542 return RETURN_OK;
13543}
13544
13545INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
13546{
13547 struct params params={0};
13548 char config_file[64] = {0};
13549 char buf[64] = {0};
13550 unsigned int get_mu_type = 0;
developera1255e42023-05-13 17:45:02 +080013551 UCHAR dat_file[64] = {0};
13552 wifi_band band = band_invalid;
13553 char ofdmabuf[32] = {'\0'};
13554 char mimobuf[32] = {'\0'};
13555 char *token = NULL;
13556 UCHAR ofdma = 0;
13557 UCHAR mimo = 0;
developer72fb0bb2023-01-11 09:46:29 +080013558
13559 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13560
13561 if (mu_type == NULL)
13562 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +080013563 band = wifi_index_to_band(radio_index);
13564 if (band == band_invalid) {
13565 printf("%s:Band Error\n", __func__);
13566 return RETURN_ERR;
13567 }
13568 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
13569 /*get current value in dat file*/
13570 wifi_datfileRead(dat_file, "MuOfdmaDlEnable", ofdmabuf, sizeof(ofdmabuf));
13571 wifi_datfileRead(dat_file, "MuMimoDlEnable", mimobuf, sizeof(mimobuf));
developer72fb0bb2023-01-11 09:46:29 +080013572
developera1255e42023-05-13 17:45:02 +080013573 token = strtok(ofdmabuf, ";");
13574 ofdma = strtol(token, NULL, 10);
13575 token = strtok(mimobuf, ";");
13576 mimo = strtol(token, NULL, 10);
13577 WIFI_ENTRY_EXIT_DEBUG("%s:ofdma=%d,mimo=%d\n", __func__, ofdma, mimo);
13578 if ((ofdma == 1) && (mimo == 1))
13579 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
13580 else if ((ofdma == 0) && (mimo == 1))
13581 *mu_type = WIFI_DL_MU_TYPE_MIMO;
13582 else if ((ofdma == 1) && (mimo == 0))
13583 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
13584 else
13585 *mu_type = WIFI_DL_MU_TYPE_NONE;
developer72fb0bb2023-01-11 09:46:29 +080013586 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13587 return RETURN_OK;
13588}
13589
13590INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
13591{
13592 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
developera1255e42023-05-13 17:45:02 +080013593 UCHAR dat_file[64] = {0};
13594 wifi_band band = band_invalid;
13595 char cmd[128] = {0};
13596 char buf[256] = {0};
13597 char ofdmabuf[32] = {'\0'};
13598 char mimobuf[32] = {'\0'};
13599 char new_ofdmabuf[32] = {'\0'};
13600 char new_mimobuf[32] = {'\0'};
13601 struct params params[2];
13602 char *str_zero = "0;0;0;0;0;0;0;0;0;0;0;0;0;0;0";/*default 15bss per band.*/
13603 char *str_one = "1;1;1;1;1;1;1;1;1;1;1;1;1;1;1";
13604 UCHAR bss_cnt = 0;
13605 UCHAR val_cnt = 0;
developer72fb0bb2023-01-11 09:46:29 +080013606
developera1255e42023-05-13 17:45:02 +080013607 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13608 band = wifi_index_to_band(radio_index);
13609 if (band == band_invalid) {
13610 printf("%s:Band Error\n", __func__);
13611 return RETURN_ERR;
13612 }
13613 if ((mu_type < WIFI_UL_MU_TYPE_NONE)
13614 || (mu_type > WIFI_UL_MU_TYPE_OFDMA)) {
13615 printf("%s:mu_type input Error\n", __func__);
13616 return RETURN_ERR;
13617 }
13618 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
13619 /*get current value in dat file*/
13620 wifi_datfileRead(dat_file, "MuOfdmaUlEnable", ofdmabuf, sizeof(ofdmabuf));
13621 wifi_datfileRead(dat_file, "MuMimoUlEnable", mimobuf, sizeof(mimobuf));
13622 WIFI_ENTRY_EXIT_DEBUG("%s:ofdma-%s, mimo-%s\n", __func__, ofdmabuf, mimobuf);
13623 get_bssnum_byindex(radio_index, &bss_cnt);
13624 val_cnt = 2*bss_cnt - 1;
13625 printf("bssNumber:%d,ValCnt:%d\n", bss_cnt, val_cnt);
13626 if ((val_cnt >= sizeof(new_ofdmabuf))
13627 || (val_cnt >= sizeof(new_mimobuf))) {
13628 printf("%s:bss cnt Error\n", __func__, val_cnt);
13629 return RETURN_ERR;
13630 }
13631 /*translate set value*/
13632 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
13633 strncpy(new_ofdmabuf, str_zero, val_cnt);
13634 strncpy(new_mimobuf, str_zero, val_cnt);
developer72fb0bb2023-01-11 09:46:29 +080013635 }
developera1255e42023-05-13 17:45:02 +080013636 if (mu_type == WIFI_UL_MU_TYPE_OFDMA) {
13637 strncpy(new_ofdmabuf, str_one, val_cnt);
13638 strncpy(new_mimobuf, str_zero, val_cnt);
13639 }
13640 printf("%s:new_ofdmabuf-%s, new_mimobuf-%s\n", __func__, new_ofdmabuf, new_mimobuf);
13641 /*same value, not operation*/
13642 if ((strncmp(new_mimobuf, mimobuf, 1) ==0)
13643 && (strncmp(new_ofdmabuf, ofdmabuf, 1) ==0)) {
13644 printf("%s:Reduntant value\n", __func__);
13645 return RETURN_OK;
13646 }
13647 /*modify dat file to new file*/
13648 params[0].name="MuOfdmaUlEnable";
13649 params[0].value=new_ofdmabuf;
13650 params[1].name="MuMimoUlEnable";
13651 params[1].value=new_mimobuf;
13652 wifi_datfileWrite(dat_file, params, 2);
13653 wifi_reloadAp(radio_index);
developer72fb0bb2023-01-11 09:46:29 +080013654 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13655 return RETURN_OK;
13656}
13657
13658INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
13659{
13660 struct params params={0};
13661 char config_file[64] = {0};
13662 char buf[64] = {0};
13663 unsigned int get_mu_type = 0;
developera1255e42023-05-13 17:45:02 +080013664 UCHAR dat_file[64] = {0};
13665 wifi_band band = band_invalid;
13666 char ofdmabuf[32] = {'\0'};
13667 char mimobuf[32] = {'\0'};
13668 char *token = NULL;
13669 UCHAR ofdma = 0;
13670 UCHAR mimo = 0;
developer72fb0bb2023-01-11 09:46:29 +080013671
13672 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13673
13674 if (mu_type == NULL)
13675 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +080013676 band = wifi_index_to_band(radio_index);
13677 if (band == band_invalid) {
13678 printf("%s:Band Error", __func__);
13679 return RETURN_ERR;
13680 }
13681 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
13682 /*get current value in dat file*/
13683 wifi_datfileRead(dat_file, "MuOfdmaUlEnable", ofdmabuf, sizeof(ofdmabuf));
13684 wifi_datfileRead(dat_file, "MuMimoUlEnable", mimobuf, sizeof(mimobuf));
developer72fb0bb2023-01-11 09:46:29 +080013685
developera1255e42023-05-13 17:45:02 +080013686 token = strtok(ofdmabuf, ";");
13687 ofdma = strtol(token, NULL, 10);
13688 token = strtok(mimobuf, ";");
13689 mimo = strtol(token, NULL, 10);
13690 WIFI_ENTRY_EXIT_DEBUG("%s:ofdma=%d, mimo=%d\n", __func__, ofdma, mimo);
13691 if ((ofdma == 1) && (mimo == 0))
13692 *mu_type = WIFI_UL_MU_TYPE_OFDMA;
13693 else
13694 *mu_type = WIFI_UL_MU_TYPE_NONE;
developer72fb0bb2023-01-11 09:46:29 +080013695 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13696 return RETURN_OK;
13697}
13698
13699
13700INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
13701{
13702 char cmd[128] = {0};
13703 char buf[256] = {0};
13704 char config_file[64] = {0};
13705 char GI[8] = {0};
13706 int mode_map = 0;
13707 FILE *f = NULL;
13708 wifi_band band = band_invalid;
developera1255e42023-05-13 17:45:02 +080013709 char dat_file[64] = {'\0'};
13710 struct params params[3];
developer72fb0bb2023-01-11 09:46:29 +080013711
13712 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13713
13714 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
13715 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
13716 return RETURN_ERR;
13717 }
developera1255e42023-05-13 17:45:02 +080013718 /*sanity check*/
13719 if (((guard_interval == wifi_guard_interval_1600)
13720 || (guard_interval == wifi_guard_interval_3200))
13721 && (mode_map & (WIFI_MODE_BE | WIFI_MODE_AX) == 0)) {
13722 wifi_dbg_printf("%s: N/AC Mode not support 1600/3200ns GI\n", __func__);
13723 return RETURN_ERR;
13724 }
developer72fb0bb2023-01-11 09:46:29 +080013725 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
13726 band = wifi_index_to_band(radio_index);
13727
13728 // Hostapd are not supported HE mode GI 1600, 3200 ns.
13729 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
13730 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
13731 _syscmd(cmd, buf, sizeof(buf));
13732 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
13733 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
13734 if (strstr(buf, "[SHORT-GI-") == NULL) {
13735 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[SHORT-GI-20][SHORT-GI-40]/' %s", config_file);
13736 _syscmd(cmd, buf, sizeof(buf));
13737 }
13738 if (band == band_5) {
13739 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
13740 if (strstr(buf, "[SHORT-GI-") == NULL) {
13741 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SHORT-GI-80][SHORT-GI-160]/' %s", config_file);
13742 _syscmd(cmd, buf, sizeof(buf));
13743 }
13744 }
13745 }
developera1255e42023-05-13 17:45:02 +080013746 /*wifi_reloadAp(radio_index);
13747 caller "wifi_setRadioOperatingParameters" have done this step.
13748 */
13749 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
13750 if (guard_interval == wifi_guard_interval_400) {
13751 params[0].name = "HT_GI";
13752 params[0].value = "1";
13753 params[1].name = "VHT_SGI";
13754 params[1].value = "1";
13755 wifi_datfileWrite(dat_file, params, 2);
developer72fb0bb2023-01-11 09:46:29 +080013756 strcpy(GI, "0.4");
developera1255e42023-05-13 17:45:02 +080013757 } else {
13758 params[0].name = "HT_GI";
13759 params[0].value = "0";
13760 params[1].name = "VHT_SGI";
13761 params[1].value = "0";
13762 /*should enable FIXED_HE_GI_SUPPORT in driver*/
13763 params[2].name = "FgiFltf";
13764 if (guard_interval == wifi_guard_interval_800) {
13765 params[2].value = "800";
13766 strcpy(GI, "0.8");
13767 } else if (guard_interval == wifi_guard_interval_1600) {
13768 params[2].value = "1600";
13769 strcpy(GI, "1.6");
13770 } else if (guard_interval == wifi_guard_interval_3200) {
13771 params[2].value = "3200";
13772 strcpy(GI, "3.2");
13773 } else if (guard_interval == wifi_guard_interval_auto) {
13774 params[2].value = "0";
13775 strcpy(GI, "auto");
13776 }
13777 wifi_datfileWrite(dat_file, params, 3);
13778 }
developer72fb0bb2023-01-11 09:46:29 +080013779 // Record GI for get GI function
13780 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
13781 f = fopen(buf, "w");
13782 if (f == NULL)
13783 return RETURN_ERR;
13784 fprintf(f, "%s", GI);
13785 fclose(f);
13786 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13787 return RETURN_OK;
13788}
13789
13790INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
13791{
13792 char buf[32] = {0};
13793 char cmd[64] = {0};
13794
13795 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13796
13797 if (guard_interval == NULL)
13798 return RETURN_ERR;
13799
developera1255e42023-05-13 17:45:02 +080013800 snprintf(cmd, sizeof(cmd), "cat %s%d.txt 2> /dev/null", GUARD_INTERVAL_FILE, radio_index);
developer72fb0bb2023-01-11 09:46:29 +080013801 _syscmd(cmd, buf, sizeof(buf));
13802
13803 if (strncmp(buf, "0.4", 3) == 0)
13804 *guard_interval = wifi_guard_interval_400;
13805 else if (strncmp(buf, "0.8", 3) == 0)
13806 *guard_interval = wifi_guard_interval_800;
13807 else if (strncmp(buf, "1.6", 3) == 0)
13808 *guard_interval = wifi_guard_interval_1600;
13809 else if (strncmp(buf, "3.2", 3) == 0)
13810 *guard_interval = wifi_guard_interval_3200;
13811 else
13812 *guard_interval = wifi_guard_interval_auto;
13813
13814 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13815 return RETURN_OK;
13816}
13817
13818INT wifi_setBSSColor(INT radio_index, UCHAR color)
13819{
13820 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13821 struct params params = {0};
13822 char config_file[128] = {0};
13823 char bss_color[4] ={0};
13824
developera1255e42023-05-13 17:45:02 +080013825 if (color < 1 || color > 63) {
13826 wifi_dbg_printf("color value is err:%d.\n", color);
13827 return RETURN_ERR;
13828 }
developer72fb0bb2023-01-11 09:46:29 +080013829 params.name = "he_bss_color";
13830 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
13831 params.value = bss_color;
13832 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
13833 wifi_hostapdWrite(config_file, &params, 1);
developera1255e42023-05-13 17:45:02 +080013834 //wifi_hostapdProcessUpdate(radio_index, &params, 1);
13835 wifi_reloadAp(radio_index);
developer69b61b02023-03-07 17:17:44 +080013836
developer72fb0bb2023-01-11 09:46:29 +080013837 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13838 return RETURN_OK;
13839}
13840
13841INT wifi_getBSSColor(INT radio_index, UCHAR *color)
13842{
13843 char config_file[128] = {0};
13844 char buf[64] = {0};
13845 char temp_output[128] = {'\0'};
13846
13847 wifi_dbg_printf("\nFunc=%s\n", __func__);
13848 if (NULL == color)
13849 return RETURN_ERR;
13850
13851 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
13852 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
13853
13854 if(strlen(buf) > 0) {
13855 snprintf(temp_output, sizeof(temp_output), "%s", buf);
13856 } else {
13857 snprintf(temp_output, sizeof(temp_output), "1"); // default value
13858 }
13859
13860 *color = (UCHAR)strtoul(temp_output, NULL, 10);
13861 wifi_dbg_printf("\noutput_string=%s\n", color);
13862
13863 return RETURN_OK;
13864}
13865
13866/* multi-psk support */
13867INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
13868{
13869 char cmd[256];
13870 char interface_name[16] = {0};
13871
13872 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
13873 return RETURN_ERR;
13874
13875 sprintf(cmd, "hostapd_cli -i %s sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
13876 interface_name,
13877 mac[0],
13878 mac[1],
13879 mac[2],
13880 mac[3],
13881 mac[4],
13882 mac[5]
13883 );
13884 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
13885 _syscmd(cmd, key->wifi_keyId, 64);
13886
13887
13888 return RETURN_OK;
13889}
13890
13891INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
13892{
13893 char interface_name[16] = {0};
13894 FILE *fd = NULL;
13895 char fname[100];
13896 char cmd[128] = {0};
13897 char out[64] = {0};
13898 wifi_key_multi_psk_t * key = NULL;
13899 if(keysNumber < 0)
13900 return RETURN_ERR;
13901
13902 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
13903 fd = fopen(fname, "w");
13904 if (!fd) {
13905 return RETURN_ERR;
13906 }
13907 key= (wifi_key_multi_psk_t *) keys;
13908 for(int i=0; i<keysNumber; ++i, key++) {
13909 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
13910 }
13911 fclose(fd);
13912
13913 //reload file
13914 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
13915 return RETURN_ERR;
13916 sprintf(cmd, "hostapd_cli -i%s raw RELOAD_WPA_PSK", interface_name);
13917 _syscmd(cmd, out, 64);
13918 return RETURN_OK;
13919}
13920
13921INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
13922{
13923 FILE *fd = NULL;
13924 char fname[100];
13925 char * line = NULL;
13926 char * pos = NULL;
13927 size_t len = 0;
13928 ssize_t read = 0;
13929 INT ret = RETURN_OK;
13930 wifi_key_multi_psk_t *keys_it = NULL;
13931
13932 if (keysNumber < 1) {
13933 return RETURN_ERR;
13934 }
13935
13936 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
13937 fd = fopen(fname, "r");
13938 if (!fd) {
13939 return RETURN_ERR;
13940 }
13941
13942 if (keys == NULL) {
13943 ret = RETURN_ERR;
13944 goto close;
13945 }
13946
13947 keys_it = keys;
13948 while ((read = getline(&line, &len, fd)) != -1) {
13949 //Strip trailing new line if present
13950 if (read > 0 && line[read-1] == '\n') {
13951 line[read-1] = '\0';
13952 }
13953
13954 if(strcmp(line,"keyid=")) {
13955 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
13956 if (!(pos = index(line, ' '))) {
13957 ret = RETURN_ERR;
13958 goto close;
13959 }
13960 pos++;
13961 //Here should be 00:00:00:00:00:00
13962 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
13963 printf("Not supported MAC: %s\n", pos);
13964 }
13965 if (!(pos = index(pos, ' '))) {
13966 ret = RETURN_ERR;
13967 goto close;
13968 }
13969 pos++;
13970
13971 //The rest is PSK
13972 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
13973 keys_it++;
13974
13975 if(--keysNumber <= 0)
13976 break;
13977 }
13978 }
13979
13980close:
13981 free(line);
13982 fclose(fd);
13983 return ret;
13984}
13985/* end of multi-psk support */
13986
13987INT wifi_setNeighborReports(UINT apIndex,
13988 UINT numNeighborReports,
13989 wifi_NeighborReport_t *neighborReports)
13990{
13991 char cmd[256] = { 0 };
13992 char hex_bssid[13] = { 0 };
13993 char bssid[18] = { 0 };
13994 char nr[256] = { 0 };
13995 char ssid[256];
13996 char hex_ssid[256];
13997 char interface_name[16] = {0};
13998 INT ret;
13999
14000 /*rmeove all neighbors*/
14001 wifi_dbg_printf("\n[%s]: removing all neighbors from %s\n", __func__, interface_name);
14002 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
14003 return RETURN_ERR;
14004 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);
14005 system(cmd);
14006
14007 for(unsigned int i = 0; i < numNeighborReports; i++)
14008 {
14009 memset(ssid, 0, sizeof(ssid));
14010 ret = wifi_getSSIDName(apIndex, ssid);
14011 if (ret != RETURN_OK)
14012 return RETURN_ERR;
14013
14014 memset(hex_ssid, 0, sizeof(hex_ssid));
14015 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
14016 sprintf(hex_ssid + k,"%02x", ssid[j]);
14017
14018 snprintf(hex_bssid, sizeof(hex_bssid),
14019 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
14020 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
14021 snprintf(bssid, sizeof(bssid),
14022 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
14023 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
14024
14025 snprintf(nr, sizeof(nr),
14026 "%s" // bssid
14027 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
14028 "%02hhx" // operclass
14029 "%02hhx" // channel
14030 "%02hhx", // phy_mode
14031 hex_bssid,
14032 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
14033 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
14034 neighborReports[i].opClass,
14035 neighborReports[i].channel,
14036 neighborReports[i].phyTable);
14037
14038 snprintf(cmd, sizeof(cmd),
14039 "hostapd_cli set_neighbor "
14040 "%s " // bssid
14041 "ssid=%s " // ssid
14042 "nr=%s " // nr
14043 "-i %s",
14044 bssid,hex_ssid,nr, interface_name);
14045
14046 if (WEXITSTATUS(system(cmd)) != 0)
14047 {
14048 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
14049 }
14050 }
14051
14052 return RETURN_OK;
14053}
14054
14055INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
14056{
14057 return RETURN_OK;
14058}
14059
14060#ifdef _WIFI_HAL_TEST_
14061int main(int argc,char **argv)
14062{
14063 int index;
14064 INT ret=0;
14065 char buf[1024]="";
14066
14067 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
14068 if(argc<3)
14069 {
14070 if(argc==2)
14071 {
14072 if(!strcmp(argv[1], "init"))
14073 return wifi_init();
14074 if(!strcmp(argv[1], "reset"))
14075 return wifi_reset();
14076 if(!strcmp(argv[1], "wifi_getHalVersion"))
14077 {
14078 char buffer[64];
14079 if(wifi_getHalVersion(buffer)==RETURN_OK)
14080 printf("Version: %s\n", buffer);
14081 else
14082 printf("Error in wifi_getHalVersion\n");
14083 return RETURN_OK;
14084 }
14085 }
14086 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
14087 exit(-1);
14088 }
14089
14090 index = atoi(argv[2]);
14091 if(strstr(argv[1], "wifi_getApName")!=NULL)
14092 {
14093 wifi_getApName(index,buf);
14094 printf("Ap name is %s \n",buf);
14095 return 0;
14096 }
developerfead3972023-05-25 20:15:02 +080014097 if(strstr(argv[1], "wifi_setRadioMode")!=NULL)
14098 {
14099 UINT pureMode = atoi(argv[3]);
14100
14101 wifi_setRadioMode(index, NULL, pureMode);
14102 printf("Ap SET Radio mode 0x%x\n", pureMode);
14103 return 0;
14104 }
14105 if(strstr(argv[1], "wifi_setRadioTransmitPower")!=NULL)
14106 {
14107 ULONG TransmitPower = atoi(argv[3]);
14108
14109 wifi_setRadioTransmitPower(index, TransmitPower);
14110 printf("Ap SET TransmitPower %lu\n", TransmitPower);
14111 return 0;
14112 }
14113 if(strstr(argv[1], "wifi_setApManagementFramePowerControl")!=NULL)
14114 {
14115 INT TransmitPower = atoi(argv[3]);
14116
14117 wifi_setApManagementFramePowerControl(index, TransmitPower);
14118 printf("Ap SET Mgnt TransmitPower %d\n", TransmitPower);
14119 return 0;
14120 }
14121 if(strstr(argv[1], "wifi_setRadioBW")!=NULL)
14122 {
14123 CHAR *bandwith = argv[3];
14124
14125 wifi_setRadioOperatingChannelBandwidth(index, bandwith);
14126 printf("Ap SET bw %s\n", bandwith);
14127 return 0;
14128 }
14129 if(strstr(argv[1], "wifi_factoryResetRadio")!=NULL)
14130 {
14131 wifi_factoryResetRadio(index);
14132 printf("wifi_factoryResetRadio ok!\n");
14133 return 0;
14134 }
14135 if(strstr(argv[1], "wifi_getRadioResetCount")!=NULL)
14136 {
14137 ULONG rst_cnt;
14138 wifi_getRadioResetCount(index, &rst_cnt);
14139 printf("wifi_factoryResetRadio rst_cnt = %lu\n", rst_cnt);
14140 return 0;
14141 }
developer2edaf012023-05-24 14:24:53 +080014142 if (strncmp(argv[1], "wifi_addApAclDevice", strlen(argv[1])) == 0) {
developer49b17232023-05-19 16:35:19 +080014143 if(argc <= 3 )
14144 {
developer2edaf012023-05-24 14:24:53 +080014145 wifi_debug(DEBUG_ERROR, "Insufficient arguments \n");
developer49b17232023-05-19 16:35:19 +080014146 exit(-1);
14147 }
14148 wifi_addApAclDevice(index, argv[3]);
14149 return 0;
14150 }
developer2edaf012023-05-24 14:24:53 +080014151 if (strncmp(argv[1], "wifi_getApAclDevices", strlen(argv[1])) == 0) {
14152 wifi_getApAclDevices(index, buf, 1024);
14153 wifi_debug(DEBUG_NOTICE, "Ap acl Devices: %s\n", buf);
developer121a8e72023-05-22 09:19:39 +080014154 return 0;
14155 }
developer2edaf012023-05-24 14:24:53 +080014156 if (strncmp(argv[1], "wifi_delApAclDevice", strlen(argv[1])) == 0) {
14157 if(argc <= 3 )
14158 {
14159 wifi_debug(DEBUG_ERROR, "Insufficient arguments \n");
14160 exit(-1);
14161 }
14162 wifi_delApAclDevice(index, argv[3]);
14163 return 0;
14164 }
14165 if (strncmp(argv[1], "wifi_delApAclDevices", strlen(argv[1])) == 0) {
14166 wifi_delApAclDevices(index);
14167 return 0;
14168 }
14169 if (strncmp(argv[1], "wifi_getApAclDeviceNum", strlen(argv[1])) == 0) {
14170 int acl_num = 0;
14171 wifi_getApAclDeviceNum(index, &acl_num);
14172 wifi_debug(DEBUG_NOTICE, "Ap acl numbers: %d\n", acl_num);
14173 return 0;
14174 }
14175 if (strncmp(argv[1], "wifi_getApDenyAclDevices", strlen(argv[1])) == 0) {
14176 wifi_getApDenyAclDevices(index, buf, 1024);
14177 wifi_debug(DEBUG_NOTICE, "Ap Deny Acl Devices: %s\n", buf);
14178 return 0;
14179 }
14180 if (strncmp(argv[1], "wifi_setApMacAddressControlMode", strlen(argv[1])) == 0) {
14181 int filter_mode = 0;
14182 if(argc <= 3 )
14183 {
14184 wifi_debug(DEBUG_ERROR, "Insufficient arguments \n");
14185 exit(-1);
14186 }
14187 filter_mode = atoi(argv[3]);
14188 wifi_setApMacAddressControlMode(index,filter_mode);
14189 return 0;
14190 }
developer5cd4c862023-05-26 09:34:42 +080014191 if (strncmp(argv[1], "wifi_getRadioDeclineBARequestEnable", strlen(argv[1])) == 0) {
14192 BOOL output_bool = 0;
14193 wifi_getRadioDeclineBARequestEnable(index, &output_bool);
14194 wifi_debug(DEBUG_NOTICE, "Ap get radio ba decline enable: %d\n", output_bool);
14195 return 0;
14196 }
14197 if (strncmp(argv[1], "wifi_getRadioAutoBlockAckEnable", strlen(argv[1])) == 0) {
14198 BOOL output_bool = 0;
14199 wifi_getRadioAutoBlockAckEnable(index, &output_bool);
14200 wifi_debug(DEBUG_NOTICE, "Ap get radio auto_ba enable: %d\n", output_bool);
14201 return 0;
14202 }
14203
14204 if (strncmp(argv[1], "wifi_getApMacAddressControlMode", strlen(argv[1])) == 0) {
14205 int filter_mode = 0;
14206 wifi_getApMacAddressControlMode(index, &filter_mode);
14207 wifi_debug(DEBUG_NOTICE, "Ap MacAddress Control Mode: %d\n", filter_mode);
14208 return 0;
14209 }
14210 if (strncmp(argv[1], "wifi_setRadioIGMPSnoopingEnable", strlen(argv[1])) == 0) {
14211 int enable = 0;
14212 if(argc <= 3 )
14213 {
14214 wifi_debug(DEBUG_ERROR, "Insufficient arguments \n");
14215 exit(-1);
14216 }
14217 enable = (BOOL)atoi(argv[3]);
14218 wifi_setRadioIGMPSnoopingEnable(index, enable);
14219 wifi_debug(DEBUG_NOTICE, "Ap set IGMP Snooping Enable: %d\n", enable);
14220 return 0;
14221 }
14222
14223 if (strncmp(argv[1], "wifi_getRadioIGMPSnoopingEnable", strlen(argv[1])) == 0) {
14224 BOOL out_status = 0;
14225 wifi_getRadioIGMPSnoopingEnable(index, &out_status);
14226 wifi_debug(DEBUG_NOTICE, "Ap get IGMP Snooping Enable: %d\n", out_status);
14227 return 0;
14228 }
developer121a8e72023-05-22 09:19:39 +080014229
developer95c045d2023-05-24 19:26:28 +080014230 if (strncmp(argv[1], "wifi_setApWmmEnable", strlen(argv[1])) == 0) {
14231 int enable = 0;
14232 if(argc <= 3)
14233 {
14234 wifi_debug(DEBUG_ERROR, "Insufficient arguments \n");
14235 exit(-1);
14236 }
14237 enable = atoi(argv[3]);
14238 wifi_setApWmmEnable(index,enable);
14239 return 0;
14240 }
14241
14242 if (strncmp(argv[1], "wifi_getApWMMCapability", strlen(argv[1])) == 0) {
14243 BOOL enable = 0;
14244
14245 wifi_getApWMMCapability(index, &enable);
14246 wifi_debug(DEBUG_NOTICE, "wifi_getApWMMCapability enable: %d\n", (int)enable);
14247 return 0;
14248 }
14249
14250 if (strncmp(argv[1], "wifi_getApWmmEnable", strlen(argv[1])) == 0) {
14251 BOOL enable = 0;
14252
14253 wifi_getApWmmEnable(index, &enable);
14254 wifi_debug(DEBUG_NOTICE, "wifi_getApWmmEnable enable: %d\n", (int)enable);
14255 return 0;
14256 }
14257
developer2edaf012023-05-24 14:24:53 +080014258 if (strncmp(argv[1], "wifi_getApMacAddressControlMode", strlen(argv[1])) == 0) {
14259 int filter_mode = 0;
14260 wifi_getApMacAddressControlMode(index, &filter_mode);
14261 wifi_debug(DEBUG_NOTICE, "Ap MacAddress Control Mode: %d\n", filter_mode);
14262 return 0;
14263 }
developer0f10c772023-05-16 21:43:39 +080014264 if(strstr(argv[1], "wifi_getRadioMode")!=NULL)
14265 {
14266 int mode = 0;
14267
14268 wifi_getRadioMode(index, buf, &mode);
14269 printf("Ap Radio mode is %s , mode = 0x%x\n", buf, mode);
14270 return 0;
14271 }
developer72fb0bb2023-01-11 09:46:29 +080014272 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
14273 {
14274 BOOL b = FALSE;
14275 BOOL *output_bool = &b;
14276 wifi_getRadioAutoChannelEnable(index,output_bool);
14277 printf("Channel enabled = %d \n",b);
14278 return 0;
14279 }
14280 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
14281 {
14282 wifi_getApWpaEncryptionMode(index,buf);
14283 printf("encryption enabled = %s\n",buf);
14284 return 0;
14285 }
14286 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
14287 {
14288 BOOL b = FALSE;
14289 BOOL *output_bool = &b;
14290 wifi_getApSsidAdvertisementEnable(index,output_bool);
14291 printf("advertisment enabled = %d\n",b);
14292 return 0;
14293 }
14294 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
14295 {
14296 if(argc <= 3 )
14297 {
14298 printf("Insufficient arguments \n");
14299 exit(-1);
14300 }
14301
14302 char sta[20] = {'\0'};
14303 ULLONG handle= 0;
14304 strcpy(sta,argv[3]);
14305 mac_address_t st;
14306 mac_addr_aton(st,sta);
14307
14308 wifi_associated_dev_tid_stats_t tid_stats;
14309 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
14310 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
14311 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);
14312 }
14313
14314 if(strstr(argv[1], "getApEnable")!=NULL) {
14315 BOOL enable;
14316 ret=wifi_getApEnable(index, &enable);
14317 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
14318 }
14319 else if(strstr(argv[1], "setApEnable")!=NULL) {
14320 BOOL enable = atoi(argv[3]);
14321 ret=wifi_setApEnable(index, enable);
14322 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
14323 }
14324 else if(strstr(argv[1], "getApStatus")!=NULL) {
developer69b61b02023-03-07 17:17:44 +080014325 char status[64];
developer72fb0bb2023-01-11 09:46:29 +080014326 ret=wifi_getApStatus(index, status);
14327 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
14328 }
14329 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
14330 {
14331 wifi_getSSIDNameStatus(index,buf);
14332 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
14333 return 0;
developer2202b332023-05-24 16:23:22 +080014334 } else if(strstr(argv[1], "wifi_resetApVlanCfg")!=NULL) {
14335 wifi_resetApVlanCfg(index);
14336 printf("%s %d: wifi_resetApVlanCfg : %s\n",argv[1], index,buf);
14337 return 0;
developer72fb0bb2023-01-11 09:46:29 +080014338 }
14339 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
14340 wifi_ssidTrafficStats2_t stats={0};
14341 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
14342 printf("%s %d: returns %d\n", argv[1], index, ret);
14343 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
14344 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
14345 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
14346 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
14347 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
14348 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
14349 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
14350 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
14351 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
14352 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
14353 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
14354 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
14355 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
14356 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
14357 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
14358 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
14359 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
14360 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
14361 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
14362 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
14363 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
14364 }
14365 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
14366 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
14367 UINT array_size=0;
14368 UINT i=0;
14369 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
14370 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
developer69b61b02023-03-07 17:17:44 +080014371 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
developer72fb0bb2023-01-11 09:46:29 +080014372 printf(" neighbor %d:\n", i);
14373 printf(" ap_SSID =%s\n", pt->ap_SSID);
14374 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
14375 printf(" ap_Mode =%s\n", pt->ap_Mode);
14376 printf(" ap_Channel =%d\n", pt->ap_Channel);
14377 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
14378 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
14379 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
14380 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
14381 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
14382 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
14383 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
14384 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
14385 printf(" ap_Noise =%d\n", pt->ap_Noise);
14386 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
14387 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
14388 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
developer69b61b02023-03-07 17:17:44 +080014389 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
developer72fb0bb2023-01-11 09:46:29 +080014390 }
14391 if(neighbor_ap_array)
14392 free(neighbor_ap_array); //make sure to free the list
14393 }
14394 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
14395 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
14396 UINT array_size=0;
14397 UINT i=0;
14398 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
14399 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
developer69b61b02023-03-07 17:17:44 +080014400 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
developer72fb0bb2023-01-11 09:46:29 +080014401 printf(" associated_dev %d:\n", i);
14402 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
14403 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
14404 printf(" cli_SNR =%d\n", pt->cli_SNR);
14405 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
14406 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
14407 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
14408 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
14409 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
14410 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
14411 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
14412 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
14413 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
14414 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
14415 }
14416 if(associated_dev_array)
14417 free(associated_dev_array); //make sure to free the list
14418 }
14419
14420 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
14421 {
14422#define MAX_ARRAY_SIZE 64
14423 int i, array_size;
14424 char *p, *ch_str;
14425 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
14426
14427 if(argc != 5)
14428 {
14429 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
14430 exit(-1);
14431 }
14432 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
14433
14434 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
14435 {
14436 strtok_r(ch_str, ",", &p);
14437 input_output_channelStats_array[i].ch_number = atoi(ch_str);
14438 }
14439 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
14440 if(!array_size)
14441 array_size=1;//Need to print current channel statistics
14442 for(i=0; i<array_size; i++)
14443 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
14444 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
14445 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
14446 input_output_channelStats_array[i].ch_number,\
14447 input_output_channelStats_array[i].ch_noise,\
14448 input_output_channelStats_array[i].ch_utilization_busy_rx,\
14449 input_output_channelStats_array[i].ch_utilization_busy_tx,\
14450 input_output_channelStats_array[i].ch_utilization_busy,\
14451 input_output_channelStats_array[i].ch_utilization_busy_ext,\
14452 input_output_channelStats_array[i].ch_utilization_total);
14453 }
14454
14455 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
14456 {
14457 if(argc <= 3 )
14458 {
14459 printf("Insufficient arguments \n");
14460 exit(-1);
14461 }
14462 char mac_addr[20] = {'\0'};
14463 wifi_device_t output_struct;
14464 int dev_index = atoi(argv[3]);
14465
14466 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
14467 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
14468 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);
14469 }
14470
14471 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
14472 {
14473 if (argc <= 3)
14474 {
14475 printf("Insufficient arguments\n");
14476 exit(-1);
14477 }
14478 char args[256];
14479 wifi_NeighborReport_t *neighborReports;
14480
14481 neighborReports = calloc(argc - 2, sizeof(neighborReports));
14482 if (!neighborReports)
14483 {
14484 printf("Failed to allocate memory");
14485 exit(-1);
14486 }
14487
14488 for (int i = 3; i < argc; ++i)
14489 {
14490 char *val;
14491 int j = 0;
14492 memset(args, 0, sizeof(args));
14493 strncpy(args, argv[i], sizeof(args));
14494 val = strtok(args, ";");
14495 while (val != NULL)
14496 {
14497 if (j == 0)
14498 {
14499 mac_addr_aton(neighborReports[i - 3].bssid, val);
14500 } else if (j == 1)
14501 {
14502 neighborReports[i - 3].info = strtol(val, NULL, 16);
14503 } else if (j == 2)
14504 {
14505 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
14506 } else if (j == 3)
14507 {
14508 neighborReports[i - 3].channel = strtol(val, NULL, 16);
14509 } else if (j == 4)
14510 {
14511 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
14512 } else {
14513 printf("Insufficient arguments]n\n");
14514 exit(-1);
14515 }
14516 val = strtok(NULL, ";");
14517 j++;
14518 }
14519 }
14520
14521 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
14522 if (ret != RETURN_OK)
14523 {
14524 printf("wifi_setNeighborReports ret = %d", ret);
14525 exit(-1);
14526 }
14527 }
14528 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
14529 {
14530 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
14531 printf("%s.\n", buf);
14532 else
14533 printf("Error returned\n");
14534 }
14535 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
14536 {
14537 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
14538 printf("%s.\n", buf);
14539 else
14540 printf("Error returned\n");
14541 }
14542 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
14543 {
14544 if (argc <= 2)
14545 {
14546 printf("Insufficient arguments\n");
14547 exit(-1);
14548 }
14549 char buf[64]= {'\0'};
14550 wifi_getRadioOperatingChannelBandwidth(index,buf);
14551 printf("Current bandwidth is %s \n",buf);
14552 return 0;
14553 }
14554 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
14555 {
14556 if (argc <= 5)
14557 {
14558 printf("Insufficient arguments\n");
14559 exit(-1);
14560 }
14561 UINT channel = atoi(argv[3]);
14562 UINT width = atoi(argv[4]);
14563 UINT beacon = atoi(argv[5]);
14564 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
14565 printf("Result = %d", ret);
14566 }
14567
14568 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
14569 return 0;
14570}
14571
14572#endif
14573
14574#ifdef WIFI_HAL_VERSION_3
14575
14576INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
14577{
14578 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
14579 if (bitMap & WIFI_BITRATE_1MBPS)
14580 strcat(BasicRate, "1,");
14581 if (bitMap & WIFI_BITRATE_2MBPS)
14582 strcat(BasicRate, "2,");
14583 if (bitMap & WIFI_BITRATE_5_5MBPS)
14584 strcat(BasicRate, "5.5,");
14585 if (bitMap & WIFI_BITRATE_6MBPS)
14586 strcat(BasicRate, "6,");
14587 if (bitMap & WIFI_BITRATE_9MBPS)
14588 strcat(BasicRate, "9,");
14589 if (bitMap & WIFI_BITRATE_11MBPS)
14590 strcat(BasicRate, "11,");
14591 if (bitMap & WIFI_BITRATE_12MBPS)
14592 strcat(BasicRate, "12,");
14593 if (bitMap & WIFI_BITRATE_18MBPS)
14594 strcat(BasicRate, "18,");
14595 if (bitMap & WIFI_BITRATE_24MBPS)
14596 strcat(BasicRate, "24,");
14597 if (bitMap & WIFI_BITRATE_36MBPS)
14598 strcat(BasicRate, "36,");
14599 if (bitMap & WIFI_BITRATE_48MBPS)
14600 strcat(BasicRate, "48,");
14601 if (bitMap & WIFI_BITRATE_54MBPS)
14602 strcat(BasicRate, "54,");
14603 if (strlen(BasicRate) != 0) // remove last comma
14604 BasicRate[strlen(BasicRate) - 1] = '\0';
14605 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
14606 return RETURN_OK;
14607}
14608
14609INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
14610{
14611 UINT BitMap = 0;
14612 char *rate;
14613
14614 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
14615 rate = strtok(BasicRatesList, ",");
14616 while(rate != NULL)
14617 {
14618 if (strcmp(rate, "1") == 0)
14619 BitMap |= WIFI_BITRATE_1MBPS;
14620 else if (strcmp(rate, "2") == 0)
14621 BitMap |= WIFI_BITRATE_2MBPS;
14622 else if (strcmp(rate, "5.5") == 0)
14623 BitMap |= WIFI_BITRATE_5_5MBPS;
14624 else if (strcmp(rate, "6") == 0)
14625 BitMap |= WIFI_BITRATE_6MBPS;
14626 else if (strcmp(rate, "9") == 0)
14627 BitMap |= WIFI_BITRATE_9MBPS;
14628 else if (strcmp(rate, "11") == 0)
14629 BitMap |= WIFI_BITRATE_11MBPS;
14630 else if (strcmp(rate, "12") == 0)
14631 BitMap |= WIFI_BITRATE_12MBPS;
14632 else if (strcmp(rate, "18") == 0)
14633 BitMap |= WIFI_BITRATE_18MBPS;
14634 else if (strcmp(rate, "24") == 0)
14635 BitMap |= WIFI_BITRATE_24MBPS;
14636 else if (strcmp(rate, "36") == 0)
14637 BitMap |= WIFI_BITRATE_36MBPS;
14638 else if (strcmp(rate, "48") == 0)
14639 BitMap |= WIFI_BITRATE_48MBPS;
14640 else if (strcmp(rate, "54") == 0)
14641 BitMap |= WIFI_BITRATE_54MBPS;
14642 rate = strtok(NULL, ",");
14643 }
14644 *basicRateBitMap = BitMap;
14645 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
14646 return RETURN_OK;
14647}
14648
14649// This API is used to configured all radio operation parameter in a single set. it includes channel number, channelWidth, mode and auto chammel configuration.
14650INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
14651{
14652 char buf[128] = {0};
14653 char cmd[128] = {0};
14654 char config_file[64] = {0};
14655 int bandwidth;
14656 int set_mode = 0;
14657 wifi_radio_operationParam_t current_param;
14658
14659 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
14660
14661 multiple_set = TRUE;
14662 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
14663 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
14664 return RETURN_ERR;
14665 }
14666 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
14667 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
14668 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
14669 return RETURN_ERR;
14670 }
14671 }
14672
14673 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
14674 bandwidth = 20;
14675 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
14676 bandwidth = 40;
14677 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
14678 bandwidth = 80;
14679 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
14680 bandwidth = 160;
14681 if (operationParam->autoChannelEnabled){
14682 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
14683 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
14684 return RETURN_ERR;
14685 }
developer69b61b02023-03-07 17:17:44 +080014686 }else{
developer72fb0bb2023-01-11 09:46:29 +080014687 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
14688 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
14689 return RETURN_ERR;
14690 }
14691 }
14692
14693 if (current_param.variant != operationParam->variant) {
14694 // Two different definition bit map, so need to check every bit.
14695 if (operationParam->variant & WIFI_80211_VARIANT_A)
14696 set_mode |= WIFI_MODE_A;
14697 if (operationParam->variant & WIFI_80211_VARIANT_B)
14698 set_mode |= WIFI_MODE_B;
14699 if (operationParam->variant & WIFI_80211_VARIANT_G)
14700 set_mode |= WIFI_MODE_G;
14701 if (operationParam->variant & WIFI_80211_VARIANT_N)
14702 set_mode |= WIFI_MODE_N;
14703 if (operationParam->variant & WIFI_80211_VARIANT_AC)
14704 set_mode |= WIFI_MODE_AC;
14705 if (operationParam->variant & WIFI_80211_VARIANT_AX)
14706 set_mode |= WIFI_MODE_AX;
14707 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
14708 memset(buf, 0, sizeof(buf));
developer0f10c772023-05-16 21:43:39 +080014709 if (wifi_setRadioMode_by_dat(index, set_mode) != RETURN_OK) {
developer72fb0bb2023-01-11 09:46:29 +080014710 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
14711 return RETURN_ERR;
14712 }
14713 }
14714 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
14715 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
14716 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
14717 return RETURN_ERR;
14718 }
14719 }
14720 if (current_param.beaconInterval != operationParam->beaconInterval) {
14721 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
14722 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
14723 return RETURN_ERR;
14724 }
14725 }
14726 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
14727 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
14728 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
14729 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
14730 return RETURN_ERR;
14731 }
14732 }
14733 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
14734 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
14735 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
14736 return RETURN_ERR;
14737 }
14738 }
14739 if (current_param.guardInterval != operationParam->guardInterval) {
14740 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
14741 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
14742 return RETURN_ERR;
14743 }
14744 }
14745 if (current_param.transmitPower != operationParam->transmitPower) {
14746 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
14747 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
14748 return RETURN_ERR;
14749 }
14750 }
14751 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
14752 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
14753 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
14754 return RETURN_ERR;
14755 }
14756 }
14757 if (current_param.obssCoex != operationParam->obssCoex) {
14758 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
14759 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
14760 return RETURN_ERR;
14761 }
14762 }
14763 if (current_param.stbcEnable != operationParam->stbcEnable) {
14764 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
14765 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
14766 return RETURN_ERR;
14767 }
14768 }
14769 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
14770 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
14771 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
14772 return RETURN_ERR;
14773 }
14774 }
14775
14776 // if enable is true, then restart the radio
14777 wifi_setRadioEnable(index, FALSE);
14778 if (operationParam->enable == TRUE)
14779 wifi_setRadioEnable(index, TRUE);
14780 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
14781
14782 return RETURN_OK;
14783}
14784
14785INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
14786{
14787 char band[64] = {0};
14788 char buf[256] = {0};
14789 char config_file[64] = {0};
14790 char cmd[128] = {0};
14791 int ret = RETURN_ERR;
14792 int mode = 0;
14793 ULONG channel = 0;
14794 BOOL enabled = FALSE;
14795
14796 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
14797 printf("Entering %s index = %d\n", __func__, (int)index);
14798
14799 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
14800 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
14801 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
14802 {
14803 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
14804 return RETURN_ERR;
14805 }
14806 operationParam->enable = enabled;
14807
14808 memset(band, 0, sizeof(band));
14809 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
14810 {
14811 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
14812 return RETURN_ERR;
14813 }
14814
14815 if (!strcmp(band, "2.4GHz"))
14816 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
14817 else if (!strcmp(band, "5GHz"))
14818 operationParam->band = WIFI_FREQUENCY_5_BAND;
14819 else if (!strcmp(band, "6GHz"))
14820 operationParam->band = WIFI_FREQUENCY_6_BAND;
14821 else
14822 {
14823 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
14824 band);
14825 }
14826
14827 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
14828 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
14829 operationParam->channel = 0;
14830 operationParam->autoChannelEnabled = TRUE;
14831 } else {
14832 operationParam->channel = strtol(buf, NULL, 10);
14833 operationParam->autoChannelEnabled = FALSE;
14834 }
14835
14836 memset(buf, 0, sizeof(buf));
14837 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
14838 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
14839 return RETURN_ERR;
14840 }
14841 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
14842 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
14843 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
14844 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
14845 else
14846 {
14847 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
14848 return false;
14849 }
14850
14851 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
14852 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
14853 return RETURN_ERR;
14854 }
14855 // Two different definition bit map, so need to check every bit.
14856 if (mode & WIFI_MODE_A)
14857 operationParam->variant |= WIFI_80211_VARIANT_A;
14858 if (mode & WIFI_MODE_B)
14859 operationParam->variant |= WIFI_80211_VARIANT_B;
14860 if (mode & WIFI_MODE_G)
14861 operationParam->variant |= WIFI_80211_VARIANT_G;
14862 if (mode & WIFI_MODE_N)
14863 operationParam->variant |= WIFI_80211_VARIANT_N;
14864 if (mode & WIFI_MODE_AC)
14865 operationParam->variant |= WIFI_80211_VARIANT_AC;
14866 if (mode & WIFI_MODE_AX)
14867 operationParam->variant |= WIFI_80211_VARIANT_AX;
14868 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
14869 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
14870 return RETURN_ERR;
14871 }
14872 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
14873 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
14874 return RETURN_ERR;
14875 }
14876 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
14877 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
14878 return RETURN_ERR;
14879 }
14880
14881 memset(buf, 0, sizeof(buf));
14882 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
14883 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
14884 return RETURN_ERR;
14885 }
14886 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
14887
14888 memset(buf, 0, sizeof(buf));
14889 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
14890 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
14891 return RETURN_ERR;
14892 }
14893 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
14894
14895 memset(buf, 0, sizeof(buf));
14896 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
14897 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
14898
14899 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
14900 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
14901 return RETURN_ERR;
14902 }
developera1255e42023-05-13 17:45:02 +080014903 if (wifi_getRadioPercentageTransmitPower(index, (ULONG *)&operationParam->transmitPower) != RETURN_OK) {
developer72fb0bb2023-01-11 09:46:29 +080014904 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
14905 return RETURN_ERR;
14906 }
14907
14908 memset(buf, 0, sizeof(buf));
14909 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
14910 if (strcmp(buf, "-1") == 0) {
14911 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
14912 operationParam->ctsProtection = FALSE;
14913 } else {
14914 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
14915 operationParam->ctsProtection = TRUE;
14916 }
14917
14918 memset(buf, 0, sizeof(buf));
14919 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
14920 if (strcmp(buf, "0") == 0)
14921 operationParam->obssCoex = FALSE;
14922 else
14923 operationParam->obssCoex = TRUE;
14924
14925 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
14926 _syscmd(cmd, buf, sizeof(buf));
14927 if (strlen(buf) != 0)
14928 operationParam->stbcEnable = TRUE;
14929 else
14930 operationParam->stbcEnable = FALSE;
14931
14932 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
14933 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
14934 return RETURN_ERR;
14935 }
14936
14937 // Below value is hardcoded
14938
14939 operationParam->numSecondaryChannels = 0;
14940 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
14941 operationParam->channelSecondary[i] = 0;
14942 }
14943 operationParam->csa_beacon_count = 15;
14944 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
14945
14946 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
14947 return RETURN_OK;
14948}
14949
14950static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
14951{
14952 int max_radio_num = 0;
14953
14954 wifi_getMaxRadioNumber(&max_radio_num);
14955 if (radioIndex >= max_radio_num) {
14956 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
14957 return RETURN_ERR;
14958 }
14959
14960 return (arrayIndex * max_radio_num) + radioIndex;
14961}
14962
developer96b38512023-02-22 11:17:45 +080014963static int vap_index_to_array_index(int vapIndex, int *radioIndex, int *arrayIndex)
14964{
14965 int max_radio_num = 0;
14966
14967 if ((vapIndex < 0) || (vapIndex > MAX_NUM_VAP_PER_RADIO*MAX_NUM_RADIOS))
14968 return -1;
14969
14970 wifi_getMaxRadioNumber(&max_radio_num);
14971
14972 (*radioIndex) = vapIndex % max_radio_num;
14973 (*arrayIndex) = vapIndex / max_radio_num;
14974
14975 return 0;
14976}
14977
14978
developer72fb0bb2023-01-11 09:46:29 +080014979wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
14980 if (strncmp(beaconRate, "1Mbps", 5) == 0)
14981 return WIFI_BITRATE_1MBPS;
14982 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
14983 return WIFI_BITRATE_2MBPS;
14984 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
14985 return WIFI_BITRATE_5_5MBPS;
14986 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
14987 return WIFI_BITRATE_6MBPS;
14988 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
14989 return WIFI_BITRATE_9MBPS;
14990 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
14991 return WIFI_BITRATE_11MBPS;
14992 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
14993 return WIFI_BITRATE_12MBPS;
14994 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
14995 return WIFI_BITRATE_18MBPS;
14996 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
14997 return WIFI_BITRATE_24MBPS;
14998 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
14999 return WIFI_BITRATE_36MBPS;
15000 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
15001 return WIFI_BITRATE_48MBPS;
15002 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
15003 return WIFI_BITRATE_54MBPS;
15004 return WIFI_BITRATE_DEFAULT;
15005}
15006
15007INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
15008{
15009 if (beacon == WIFI_BITRATE_1MBPS)
15010 strcpy(beacon_str, "1Mbps");
15011 else if (beacon == WIFI_BITRATE_2MBPS)
15012 strcpy(beacon_str, "2Mbps");
15013 else if (beacon == WIFI_BITRATE_5_5MBPS)
15014 strcpy(beacon_str, "5.5Mbps");
15015 else if (beacon == WIFI_BITRATE_6MBPS)
15016 strcpy(beacon_str, "6Mbps");
15017 else if (beacon == WIFI_BITRATE_9MBPS)
15018 strcpy(beacon_str, "9Mbps");
15019 else if (beacon == WIFI_BITRATE_11MBPS)
15020 strcpy(beacon_str, "11Mbps");
15021 else if (beacon == WIFI_BITRATE_12MBPS)
15022 strcpy(beacon_str, "12Mbps");
15023 else if (beacon == WIFI_BITRATE_18MBPS)
15024 strcpy(beacon_str, "18Mbps");
15025 else if (beacon == WIFI_BITRATE_24MBPS)
15026 strcpy(beacon_str, "24Mbps");
15027 else if (beacon == WIFI_BITRATE_36MBPS)
15028 strcpy(beacon_str, "36Mbps");
15029 else if (beacon == WIFI_BITRATE_48MBPS)
15030 strcpy(beacon_str, "48Mbps");
15031 else if (beacon == WIFI_BITRATE_54MBPS)
15032 strcpy(beacon_str, "54Mbps");
15033 return RETURN_OK;
15034}
15035
15036INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
15037{
15038 INT mode = 0;
15039 INT ret = -1;
15040 INT output = 0;
15041 int i = 0;
15042 int vap_index = 0;
15043 BOOL enabled = FALSE;
15044 char buf[256] = {0};
15045 wifi_vap_security_t security = {0};
developer72fb0bb2023-01-11 09:46:29 +080015046
15047 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
15048 printf("Entering %s index = %d\n", __func__, (int)index);
15049
developerfde01262023-05-22 15:15:24 +080015050 ret = wifi_BandProfileRead(0, index, "BssidNum", buf, sizeof(buf), "0");
15051 if (ret != 0) {
15052 fprintf(stderr, "%s: wifi_BandProfileRead BssidNum failed\n", __func__);
15053 return RETURN_ERR;
15054 }
15055
15056 map->num_vaps = atoi(buf);
15057 if (map->num_vaps <= 0) {
15058 fprintf(stderr, "%s: invalid BssidNum %s\n", __func__, buf);
15059 return RETURN_ERR;
15060 }
15061
15062 for (i = 0; i < map->num_vaps; i++)
developer72fb0bb2023-01-11 09:46:29 +080015063 {
15064 map->vap_array[i].radio_index = index;
15065
15066 vap_index = array_index_to_vap_index(index, i);
15067 if (vap_index < 0)
15068 return RETURN_ERR;
15069
15070 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
15071
15072 map->vap_array[i].vap_index = vap_index;
15073
15074 memset(buf, 0, sizeof(buf));
15075 ret = wifi_getApName(vap_index, buf);
15076 if (ret != RETURN_OK) {
15077 printf("%s: wifi_getApName return error\n", __func__);
15078 return RETURN_ERR;
15079 }
15080 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
15081
15082 memset(buf, 0, sizeof(buf));
15083 ret = wifi_getSSIDName(vap_index, buf);
15084 if (ret != RETURN_OK) {
15085 printf("%s: wifi_getSSIDName return error\n", __func__);
15086 return RETURN_ERR;
15087 }
15088 snprintf(map->vap_array[i].u.bss_info.ssid, sizeof(map->vap_array[i].u.bss_info.ssid), "%s", buf);
15089
developere740c2a2023-05-23 18:34:32 +080015090#if 0
developer72fb0bb2023-01-11 09:46:29 +080015091 ret = wifi_getSSIDEnable(vap_index, &enabled);
15092 if (ret != RETURN_OK) {
15093 printf("%s: wifi_getSSIDEnable return error\n", __func__);
15094 return RETURN_ERR;
15095 }
developere740c2a2023-05-23 18:34:32 +080015096#endif
15097 map->vap_array[i].u.bss_info.enabled = true;
developer72fb0bb2023-01-11 09:46:29 +080015098
15099 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
15100 if (ret != RETURN_OK) {
15101 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
15102 return RETURN_ERR;
15103 }
15104 map->vap_array[i].u.bss_info.showSsid = enabled;
developer69b61b02023-03-07 17:17:44 +080015105
developer72fb0bb2023-01-11 09:46:29 +080015106 ret = wifi_getApIsolationEnable(vap_index, &enabled);
15107 if (ret != RETURN_OK) {
15108 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
15109 return RETURN_ERR;
15110 }
15111 map->vap_array[i].u.bss_info.isolation = enabled;
15112
15113 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
15114 if (ret != RETURN_OK) {
15115 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
15116 return RETURN_ERR;
15117 }
15118 map->vap_array[i].u.bss_info.bssMaxSta = output;
15119
15120 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
15121 if (ret != RETURN_OK) {
15122 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
15123 return RETURN_ERR;
15124 }
15125 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
15126
15127 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
15128 if (ret != RETURN_OK) {
15129 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
15130 return RETURN_ERR;
15131 }
15132 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
15133
15134 ret = wifi_getApSecurity(vap_index, &security);
15135 if (ret != RETURN_OK) {
15136 printf("%s: wifi_getApSecurity return error\n", __func__);
15137 return RETURN_ERR;
15138 }
15139 map->vap_array[i].u.bss_info.security = security;
15140
15141 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
15142 if (ret != RETURN_OK) {
15143 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
15144 return RETURN_ERR;
15145 }
developer69b61b02023-03-07 17:17:44 +080015146 if (mode == 0)
developer72fb0bb2023-01-11 09:46:29 +080015147 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
developer69b61b02023-03-07 17:17:44 +080015148 else
developer72fb0bb2023-01-11 09:46:29 +080015149 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
developer69b61b02023-03-07 17:17:44 +080015150 if (mode == 1)
developer72fb0bb2023-01-11 09:46:29 +080015151 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
developer69b61b02023-03-07 17:17:44 +080015152 else if (mode == 2)
developer72fb0bb2023-01-11 09:46:29 +080015153 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
15154
15155 ret = wifi_getApWmmEnable(vap_index, &enabled);
15156 if (ret != RETURN_OK) {
15157 printf("%s: wifi_getApWmmEnable return error\n", __func__);
15158 return RETURN_ERR;
15159 }
15160 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
15161
15162 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
15163 if (ret != RETURN_OK) {
15164 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
15165 return RETURN_ERR;
15166 }
15167 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
15168
15169 memset(buf, 0, sizeof(buf));
15170 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
15171 if (ret != RETURN_OK) {
15172 printf("%s: wifi_getApBeaconRate return error\n", __func__);
15173 return RETURN_ERR;
15174 }
15175 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
15176
15177 memset(buf, 0, sizeof(buf));
15178 ret = wifi_getBaseBSSID(vap_index, buf);
15179 if (ret != RETURN_OK) {
15180 printf("%s: wifi_getBaseBSSID return error\n", __func__);
15181 return RETURN_ERR;
15182 }
developer5b2f10c2023-05-25 17:02:21 +080015183 if (hwaddr_aton2(buf, map->vap_array[i].u.bss_info.bssid) < 0) {
15184 printf("%s: hwaddr_aton2 fail\n", __func__);
15185 return RETURN_ERR;
15186 }
developer72fb0bb2023-01-11 09:46:29 +080015187
15188 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
15189 if (ret != RETURN_OK) {
15190 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
15191 return RETURN_ERR;
15192 }
15193 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
15194
15195 // TODO: wps, noack
15196 }
15197 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
15198 return RETURN_OK;
15199}
15200
developer47cc27a2023-05-17 23:09:58 +080015201void checkVapStatus(int apIndex, BOOL *enable)
developer72fb0bb2023-01-11 09:46:29 +080015202{
15203 char if_name[16] = {0};
15204 char cmd[128] = {0};
15205 char buf[128] = {0};
15206
15207 *enable = FALSE;
15208 if (wifi_GetInterfaceName(apIndex, if_name) != RETURN_OK)
15209 return;
15210
15211 snprintf(cmd, sizeof(cmd), "cat %s | grep ^%s=1", VAP_STATUS_FILE, if_name);
15212 _syscmd(cmd, buf, sizeof(buf));
15213 if (strlen(buf) > 0)
15214 *enable = TRUE;
15215 return;
15216}
15217
15218static int prepareInterface(UINT apIndex, char *new_interface)
15219{
15220 char cur_interface[16] = {0};
15221 char config_file[128] = {0};
developer8a3bbbf2023-03-15 17:47:23 +080015222 char cmd[MAX_CMD_SIZE] = {0};
15223 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +080015224 int max_radio_num = 0;
15225 int radioIndex = -1;
15226 int phyIndex = -1;
developer8a3bbbf2023-03-15 17:47:23 +080015227 struct params params;
developer72fb0bb2023-01-11 09:46:29 +080015228
15229 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
15230 wifi_hostapdRead(config_file, "interface", cur_interface, sizeof(cur_interface));
15231
15232 if (strncmp(cur_interface, new_interface, sizeof(cur_interface)) != 0) {
developer8a3bbbf2023-03-15 17:47:23 +080015233 wifi_getMaxRadioNumber(&max_radio_num);
developer72fb0bb2023-01-11 09:46:29 +080015234 radioIndex = apIndex % max_radio_num;
15235 phyIndex = radio_index_to_phy(radioIndex);
15236 // disable and del old interface, then add new interface
15237 wifi_setApEnable(apIndex, FALSE);
developer8a3bbbf2023-03-15 17:47:23 +080015238
15239 params.name = "interface";
15240 params.value = new_interface;
15241 wifi_hostapdWrite(config_file, &params, 1);
15242
15243 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyIndex, config_file);
15244 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +080015245 }
developer8a3bbbf2023-03-15 17:47:23 +080015246
developer72fb0bb2023-01-11 09:46:29 +080015247 // update the vap status file
15248 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=1' %s", cur_interface, new_interface, VAP_STATUS_FILE);
15249 _syscmd(cmd, buf, sizeof(buf));
15250 return RETURN_OK;
15251}
15252
15253INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
15254{
15255 char interface_name[16] = {0};
15256 unsigned int i;
15257 wifi_vap_info_t *vap_info = NULL;
15258 int acl_mode;
15259 int ret = 0;
15260 char *sec_str = NULL;
15261 char buf[256] = {0};
15262 char cmd[128] = {0};
15263 char config_file[64] = {0};
15264 char bssid[32] = {0};
15265 char psk_file[64] = {0};
developer47cc27a2023-05-17 23:09:58 +080015266 BOOL enable = FALSE;
developere740c2a2023-05-23 18:34:32 +080015267 int band_idx;
15268
developer72fb0bb2023-01-11 09:46:29 +080015269
15270 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
15271 printf("Entering %s index = %d\n", __func__, (int)index);
15272 for (i = 0; i < map->num_vaps; i++)
15273 {
15274 multiple_set = TRUE;
15275 vap_info = &map->vap_array[i];
15276
15277 // Check vap status file to enable multiple ap if the system boot.
15278 checkVapStatus(vap_info->vap_index, &enable);
15279 if (vap_info->u.bss_info.enabled == FALSE && enable == FALSE)
15280 continue;
15281
15282 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
15283
developere740c2a2023-05-23 18:34:32 +080015284 band_idx = radio_index_to_band(index);
15285 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
15286 snprintf(cmd, sizeof(cmd), "cp /etc/hostapd-%s.conf %s", wifi_band_str[band_idx], config_file);
15287 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +080015288
developere740c2a2023-05-23 18:34:32 +080015289 struct params params[4];
developer72fb0bb2023-01-11 09:46:29 +080015290 params[0].name = "interface";
15291 params[0].value = vap_info->vap_name;
15292 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
15293 params[1].name = "bssid";
15294 params[1].value = bssid;
15295 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", vap_info->vap_index);
15296 params[2].name = "wpa_psk_file";
15297 params[2].value = psk_file;
developere740c2a2023-05-23 18:34:32 +080015298 params[3].name = "ssid";
15299 params[3].value = vap_info->u.bss_info.ssid;
developer72fb0bb2023-01-11 09:46:29 +080015300
15301 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
developere740c2a2023-05-23 18:34:32 +080015302 wifi_hostapdWrite(config_file, params, 4);
developer72fb0bb2023-01-11 09:46:29 +080015303
15304 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
15305 _syscmd(cmd, buf, sizeof(buf));
15306
15307 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
15308 if (ret != RETURN_OK) {
15309 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
15310 return RETURN_ERR;
15311 }
15312
15313 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
15314 if (ret != RETURN_OK) {
15315 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
15316 return RETURN_ERR;
15317 }
15318
15319 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
15320 if (ret != RETURN_OK) {
15321 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
15322 return RETURN_ERR;
15323 }
15324
15325 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
15326 if (ret != RETURN_OK) {
15327 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
15328 return RETURN_ERR;
15329 }
15330
15331 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
15332 if (ret != RETURN_OK) {
15333 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
15334 return RETURN_ERR;
15335 }
15336
15337 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
15338 if (ret != RETURN_OK) {
15339 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
15340 return RETURN_ERR;
15341 }
15342
15343 if (vap_info->u.bss_info.mac_filter_enable == false){
15344 acl_mode = 0;
15345 }else {
15346 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
15347 acl_mode = 2;
15348 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
15349 _syscmd(cmd, buf, sizeof(buf));
15350 }else{
15351 acl_mode = 1;
15352 }
15353 }
15354
15355 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
15356 if (ret != RETURN_OK) {
15357 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
15358 return RETURN_ERR;
15359 }
15360
15361 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
15362 if (ret != RETURN_OK) {
15363 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
15364 return RETURN_ERR;
15365 }
15366
developer0f10c772023-05-16 21:43:39 +080015367 memset(buf, 0, sizeof(buf));
15368 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
15369 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
15370 if (ret != RETURN_OK) {
15371 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
15372 return RETURN_ERR;
15373 }
developer72fb0bb2023-01-11 09:46:29 +080015374
15375 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
15376 if (ret != RETURN_OK) {
15377 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable\n", __func__);
15378 return RETURN_ERR;
15379 }
15380
developer72fb0bb2023-01-11 09:46:29 +080015381 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
15382 if (ret != RETURN_OK) {
15383 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
15384 return RETURN_ERR;
15385 }
15386
developer23e71282023-01-18 10:25:19 +080015387 wifi_setApEnable(vap_info->vap_index, FALSE);
15388 wifi_setApEnable(vap_info->vap_index, TRUE);
15389 multiple_set = FALSE;
15390
15391 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
developer72fb0bb2023-01-11 09:46:29 +080015392 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
15393 if (ret != RETURN_OK) {
15394 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
15395 return RETURN_ERR;
15396 }
15397
15398 // TODO mgmtPowerControl, interworking, wps
15399 }
15400 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
15401 return RETURN_OK;
15402}
15403
15404int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
15405{
15406 char *token, *next;
15407 const char s[2] = ",";
15408 int count =0;
15409
15410 /* get the first token */
15411 token = strtok_r(pchannels, s, &next);
15412
15413 /* walk through other tokens */
15414 while( token != NULL && count < MAX_CHANNELS) {
15415 chlistptr->channels_list[count++] = atoi(token);
15416 token = strtok_r(NULL, s, &next);
15417 }
15418
15419 return count;
15420}
15421
15422static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
15423{
15424 INT status;
15425 wifi_channels_list_t *chlistp;
15426 CHAR output_string[64];
15427 CHAR pchannels[128];
15428 CHAR interface_name[16] = {0};
15429 wifi_band band;
15430
15431 if(rcap == NULL)
15432 {
15433 return RETURN_ERR;
15434 }
15435
15436 rcap->numSupportedFreqBand = 1;
15437 band = wifi_index_to_band(radioIndex);
15438
15439 if (band == band_2_4)
15440 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
15441 else if (band == band_5)
15442 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
15443 else if (band == band_6)
15444 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
15445
15446 chlistp = &(rcap->channel_list[0]);
15447 memset(pchannels, 0, sizeof(pchannels));
15448
15449 /* possible number of radio channels */
15450 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
15451 {
15452 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
15453 }
15454 /* Number of channels and list*/
15455 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
15456
15457 /* autoChannelSupported */
15458 /* always ON with wifi_getRadioAutoChannelSupported */
15459 rcap->autoChannelSupported = TRUE;
15460
15461 /* DCSSupported */
15462 /* always ON with wifi_getRadioDCSSupported */
15463 rcap->DCSSupported = TRUE;
15464
15465 /* zeroDFSSupported - TBD */
15466 rcap->zeroDFSSupported = FALSE;
15467
15468 /* Supported Country List*/
15469 memset(output_string, 0, sizeof(output_string));
15470 status = wifi_getRadioCountryCode(radioIndex, output_string);
15471 if( status != 0 ) {
15472 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
15473 return RETURN_ERR;
15474 } else {
15475 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
15476 }
15477 if(!strcmp(output_string,"US")){
15478 rcap->countrySupported[0] = wifi_countrycode_US;
15479 rcap->countrySupported[1] = wifi_countrycode_CA;
15480 } else if (!strcmp(output_string,"CA")) {
15481 rcap->countrySupported[0] = wifi_countrycode_CA;
15482 rcap->countrySupported[1] = wifi_countrycode_US;
15483 } else {
15484 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
15485 }
15486
15487 rcap->numcountrySupported = 2;
15488
15489 /* csi */
15490 rcap->csi.maxDevices = 8;
15491 rcap->csi.soudingFrameSupported = TRUE;
15492
15493 wifi_GetInterfaceName(radioIndex, interface_name);
15494 snprintf(rcap->ifaceName, sizeof(interface_name), "%s",interface_name);
15495
15496 /* channelWidth - all supported bandwidths */
15497 int i=0;
15498 rcap->channelWidth[i] = 0;
15499 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
15500 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
15501 WIFI_CHANNELBANDWIDTH_40MHZ);
15502
15503 }
15504 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
15505 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
15506 WIFI_CHANNELBANDWIDTH_40MHZ |
15507 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
15508 }
15509
15510
15511 /* mode - all supported variants */
15512 // rcap->mode[i] = WIFI_80211_VARIANT_H;
15513 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
15514 rcap->mode[i] = ( WIFI_80211_VARIANT_B | WIFI_80211_VARIANT_G | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AX );
15515 }
15516 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
15517 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
15518 }
15519 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
15520 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
15521 }
15522 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
15523 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
15524
15525 /* supportedBitRate - all supported bitrates */
15526 rcap->supportedBitRate[i] = 0;
15527 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
15528 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
15529 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
15530 }
15531 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
15532 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
15533 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
15534 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
15535 }
15536
15537
15538 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
15539 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
15540 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
15541 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
15542 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
15543 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
15544 rcap->cipherSupported = 0;
15545 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
15546 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
15547
15548 return RETURN_OK;
15549}
15550
15551INT wifi_getHalCapability(wifi_hal_capability_t *cap)
15552{
15553 INT status = 0, radioIndex = 0;
15554 char cmd[MAX_BUF_SIZE] = {0}, output[MAX_BUF_SIZE] = {0};
15555 int iter = 0;
15556 unsigned int j = 0;
15557 int max_num_radios;
15558 wifi_interface_name_idex_map_t *iface_info = NULL;
15559
15560 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
15561
15562 memset(cap, 0, sizeof(wifi_hal_capability_t));
15563
15564 /* version */
15565 cap->version.major = WIFI_HAL_MAJOR_VERSION;
15566 cap->version.minor = WIFI_HAL_MINOR_VERSION;
15567
15568 /* number of radios platform property */
15569 wifi_getMaxRadioNumber(&max_num_radios);
15570 cap->wifi_prop.numRadios = max_num_radios;
15571
15572 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
15573 {
15574 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
15575 if (status != 0) {
15576 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
15577 return RETURN_ERR;
15578 }
15579
15580 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
15581 {
15582 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
15583 {
15584 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
15585 return RETURN_ERR;
15586 }
15587 iface_info = &cap->wifi_prop.interface_map[iter];
15588 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
15589 iface_info->rdk_radio_index = radioIndex;
15590 memset(output, 0, sizeof(output));
15591 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
15592 {
15593 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
15594 }
15595 // TODO: bridge name
15596 // TODO: vlan id
15597 // TODO: primary
15598 iface_info->index = array_index_to_vap_index(radioIndex, j);
15599 memset(output, 0, sizeof(output));
15600 if (wifi_getApName(iface_info->index, output) == RETURN_OK)
15601 {
15602 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
15603 }
15604 iter++;
15605 }
15606 }
15607
15608 cap->BandSteeringSupported = FALSE;
15609 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
15610 return RETURN_OK;
15611}
15612
15613INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
15614{
15615 struct params h_config={0};
15616 char config_file[64] = {0};
15617
15618 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
15619
15620 h_config.name = "okc";
15621 h_config.value = okc_enable?"1":"0";
15622
15623 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
15624 wifi_hostapdWrite(config_file, &h_config, 1);
15625 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
15626
15627 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
15628 return RETURN_OK;
15629}
15630
15631INT wifi_setSAEMFP(int ap_index, BOOL enable)
15632{
15633 struct params h_config={0};
15634 char config_file[64] = {0};
15635 char buf[128] = {0};
15636
15637 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
15638
15639 h_config.name = "sae_require_mfp";
15640 h_config.value = enable?"1":"0";
15641
15642 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
15643 wifi_hostapdWrite(config_file, &h_config, 1);
15644 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
15645
15646 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
15647 return RETURN_OK;
15648}
15649
15650INT wifi_setSAEpwe(int ap_index, int sae_pwe)
15651{
15652 struct params h_config={0};
15653 char config_file[64] = {0};
15654 char buf[128] = {0};
15655
15656 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
15657
15658 h_config.name = "sae_pwe";
15659 snprintf(buf, sizeof(buf), "%d", sae_pwe);
15660 h_config.value = buf;
15661
15662 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
15663 wifi_hostapdWrite(config_file, &h_config, 1);
15664 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
15665
15666 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
15667 return RETURN_OK;
15668}
15669
15670INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
15671{
15672 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
15673 struct params h_config={0};
15674 char config_file[64] = {0};
15675
15676 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
15677
15678 h_config.name = "wpa_disable_eapol_key_retries";
15679 h_config.value = disable_EAPOL_retries?"1":"0";
15680
15681 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
15682 wifi_hostapdWrite(config_file, &h_config, 1);
15683 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
15684
15685 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
15686 return RETURN_OK;
15687}
15688
15689INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
15690{
15691 char buf[128] = {0};
15692 char config_file[128] = {0};
developere5750452023-05-15 16:46:42 +080015693 char cmd[128] = {0};
developer72fb0bb2023-01-11 09:46:29 +080015694 char password[64] = {0};
15695 char mfp[32] = {0};
15696 char wpa_mode[32] = {0};
15697 BOOL okc_enable = FALSE;
15698 BOOL sae_MFP = FALSE;
15699 BOOL disable_EAPOL_retries = TRUE;
15700 int sae_pwe = 0;
15701 struct params params = {0};
15702 wifi_band band = band_invalid;
15703
15704 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
15705
15706 multiple_set = TRUE;
15707 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
15708 if (security->mode == wifi_security_mode_none) {
15709 strcpy(wpa_mode, "None");
15710 } else if (security->mode == wifi_security_mode_wpa_personal)
15711 strcpy(wpa_mode, "WPA-Personal");
15712 else if (security->mode == wifi_security_mode_wpa2_personal)
15713 strcpy(wpa_mode, "WPA2-Personal");
15714 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
15715 strcpy(wpa_mode, "WPA-WPA2-Personal");
15716 else if (security->mode == wifi_security_mode_wpa_enterprise)
15717 strcpy(wpa_mode, "WPA-Enterprise");
15718 else if (security->mode == wifi_security_mode_wpa2_enterprise)
15719 strcpy(wpa_mode, "WPA2-Enterprise");
15720 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
15721 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
15722 else if (security->mode == wifi_security_mode_wpa3_personal) {
15723 strcpy(wpa_mode, "WPA3-Personal");
15724 okc_enable = TRUE;
15725 sae_MFP = TRUE;
15726 sae_pwe = 2;
15727 disable_EAPOL_retries = FALSE;
15728 } else if (security->mode == wifi_security_mode_wpa3_transition) {
15729 strcpy(wpa_mode, "WPA3-Personal-Transition");
15730 okc_enable = TRUE;
15731 sae_MFP = TRUE;
15732 sae_pwe = 2;
15733 disable_EAPOL_retries = FALSE;
15734 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
15735 strcpy(wpa_mode, "WPA3-Enterprise");
15736 sae_MFP = TRUE;
15737 sae_pwe = 2;
15738 disable_EAPOL_retries = FALSE;
developerd01e3e82023-04-26 19:10:38 +080015739 } else if (security->mode == wifi_security_mode_enhanced_open) {
developer3086e2f2023-01-17 09:40:01 +080015740 strcpy(wpa_mode, "OWE");
15741 sae_MFP = TRUE;
15742 sae_pwe = 2;
15743 disable_EAPOL_retries = FALSE;
developer72fb0bb2023-01-11 09:46:29 +080015744 }
15745
15746 band = wifi_index_to_band(ap_index);
15747 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
15748 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
15749 return RETURN_ERR;
15750 }
15751
15752 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
15753 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
15754 wifi_setSAEMFP(ap_index, sae_MFP);
15755 wifi_setSAEpwe(ap_index, sae_pwe);
15756 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
15757
developerd01e3e82023-04-26 19:10:38 +080015758 if (security->mode != wifi_security_mode_none && security->mode != wifi_security_mode_enhanced_open) {
developere5750452023-05-15 16:46:42 +080015759 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) {
15760 int key_len = strlen(security->u.key.key);
15761 // wpa_psk and wpa_passphrase cann;t use at the same time, the command replace one with the other.
15762 if (key_len == 64) { // set wpa_psk
15763 strncpy(password, security->u.key.key, 64); // 64 characters
15764 password[64] = '\0';
15765 wifi_setApSecurityPreSharedKey(ap_index, password);
15766 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_passphrase=/!p' %s", config_file);
15767 } else if (key_len >= 8 && key_len < 64) { // set wpa_passphrase
15768 strncpy(password, security->u.key.key, 63);
15769 password[63] = '\0';
15770 wifi_setApSecurityKeyPassphrase(ap_index, password);
15771 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_psk=/!p' %s", config_file);
15772 } else
15773 return RETURN_ERR;
15774 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +080015775 }
15776 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
15777 params.name = "sae_password";
15778 params.value = security->u.key.key;
15779 wifi_hostapdWrite(config_file, &params, 1);
developere5750452023-05-15 16:46:42 +080015780 } else { // remove sae_password
15781 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^sae_password=/!p' %s", config_file);
15782 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +080015783 }
15784 }
15785
15786 if (security->mode != wifi_security_mode_none) {
15787 memset(&params, 0, sizeof(params));
15788 params.name = "wpa_pairwise";
15789 if (security->encr == wifi_encryption_tkip)
15790 params.value = "TKIP";
15791 else if (security->encr == wifi_encryption_aes)
15792 params.value = "CCMP";
15793 else if (security->encr == wifi_encryption_aes_tkip)
15794 params.value = "TKIP CCMP";
15795 wifi_hostapdWrite(config_file, &params, 1);
15796 }
15797
15798 if (security->mfp == wifi_mfp_cfg_disabled)
15799 strcpy(mfp, "Disabled");
15800 else if (security->mfp == wifi_mfp_cfg_optional)
15801 strcpy(mfp, "Optional");
15802 else if (security->mfp == wifi_mfp_cfg_required)
15803 strcpy(mfp, "Required");
15804 wifi_setApSecurityMFPConfig(ap_index, mfp);
15805
15806 memset(&params, 0, sizeof(params));
15807 params.name = "transition_disable";
15808 if (security->wpa3_transition_disable == TRUE)
15809 params.value = "0x01";
15810 else
15811 params.value = "0x00";
15812 wifi_hostapdWrite(config_file, &params, 1);
15813
15814 memset(&params, 0, sizeof(params));
15815 params.name = "wpa_group_rekey";
15816 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
15817 params.value = buf;
15818 wifi_hostapdWrite(config_file, &params, 1);
15819
15820 memset(&params, 0, sizeof(params));
15821 params.name = "wpa_strict_rekey";
15822 params.value = security->strict_rekey?"1":"0";
15823 wifi_hostapdWrite(config_file, &params, 1);
15824
15825 memset(&params, 0, sizeof(params));
15826 params.name = "wpa_pairwise_update_count";
developere5750452023-05-15 16:46:42 +080015827 if (security->eapol_key_retries == 0)
15828 security->eapol_key_retries = 4; // 0 is invalid, set to default value.
developer72fb0bb2023-01-11 09:46:29 +080015829 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
15830 params.value = buf;
15831 wifi_hostapdWrite(config_file, &params, 1);
15832
15833 memset(&params, 0, sizeof(params));
15834 params.name = "disable_pmksa_caching";
15835 params.value = security->disable_pmksa_caching?"1":"0";
15836 wifi_hostapdWrite(config_file, &params, 1);
15837
developer23e71282023-01-18 10:25:19 +080015838 if (multiple_set == FALSE) {
15839 wifi_setApEnable(ap_index, FALSE);
15840 wifi_setApEnable(ap_index, TRUE);
15841 }
developer72fb0bb2023-01-11 09:46:29 +080015842
15843 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
15844
15845 return RETURN_OK;
15846}
15847
15848INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
15849{
15850 char buf[256] = {0};
15851 char config_file[128] = {0};
15852 int disable = 0;
developere5750452023-05-15 16:46:42 +080015853 bool set_sae = FALSE;
developer72fb0bb2023-01-11 09:46:29 +080015854
15855 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
15856 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
15857 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
15858 security->mode = wifi_security_mode_none;
15859 if (strlen(buf) != 0) {
15860 if (!strcmp(buf, "WPA-Personal"))
15861 security->mode = wifi_security_mode_wpa_personal;
15862 else if (!strcmp(buf, "WPA2-Personal"))
15863 security->mode = wifi_security_mode_wpa2_personal;
15864 else if (!strcmp(buf, "WPA-WPA2-Personal"))
15865 security->mode = wifi_security_mode_wpa_wpa2_personal;
15866 else if (!strcmp(buf, "WPA-Enterprise"))
15867 security->mode = wifi_security_mode_wpa_enterprise;
15868 else if (!strcmp(buf, "WPA2-Enterprise"))
15869 security->mode = wifi_security_mode_wpa2_enterprise;
15870 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
15871 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
15872 else if (!strcmp(buf, "WPA3-Personal"))
15873 security->mode = wifi_security_mode_wpa3_personal;
15874 else if (!strcmp(buf, "WPA3-Personal-Transition"))
15875 security->mode = wifi_security_mode_wpa3_transition;
15876 else if (!strcmp(buf, "WPA3-Enterprise"))
15877 security->mode = wifi_security_mode_wpa3_enterprise;
developer3086e2f2023-01-17 09:40:01 +080015878 else if (!strcmp(buf, "OWE"))
developerd01e3e82023-04-26 19:10:38 +080015879 security->mode = wifi_security_mode_enhanced_open;
developer72fb0bb2023-01-11 09:46:29 +080015880 }
15881
15882 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
15883 if (security->mode == wifi_security_mode_none)
15884 security->encr = wifi_encryption_none;
15885 else {
15886 if (strcmp(buf, "TKIP") == 0)
15887 security->encr = wifi_encryption_tkip;
15888 else if (strcmp(buf, "CCMP") == 0)
15889 security->encr = wifi_encryption_aes;
15890 else
15891 security->encr = wifi_encryption_aes_tkip;
15892 }
15893
15894 if (security->mode != wifi_encryption_none) {
15895 memset(buf, 0, sizeof(buf));
15896 // wpa3 can use one or both configs as password, so we check sae_password first.
15897 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
developere5750452023-05-15 16:46:42 +080015898 if (strlen(buf) != 0) {
15899 if (security->mode == wifi_security_mode_wpa3_personal || security->mode == wifi_security_mode_wpa3_transition)
15900 security->u.key.type = wifi_security_key_type_sae;
15901 set_sae = TRUE;
15902 strncpy(security->u.key.key, buf, sizeof(buf));
15903 }
15904 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
15905 if (strlen(buf) != 0){
15906 if (set_sae == TRUE)
15907 security->u.key.type = wifi_security_key_type_psk_sae;
15908 else if (strlen(buf) == 64)
15909 security->u.key.type = wifi_security_key_type_psk;
15910 else
15911 security->u.key.type = wifi_security_key_type_pass;
15912 strncpy(security->u.key.key, buf, sizeof(security->u.key.key));
developer72fb0bb2023-01-11 09:46:29 +080015913 }
developer72fb0bb2023-01-11 09:46:29 +080015914 security->u.key.key[255] = '\0';
15915 }
15916
15917 memset(buf, 0, sizeof(buf));
15918 wifi_getApSecurityMFPConfig(ap_index, buf);
15919 if (strcmp(buf, "Disabled") == 0)
15920 security->mfp = wifi_mfp_cfg_disabled;
15921 else if (strcmp(buf, "Optional") == 0)
15922 security->mfp = wifi_mfp_cfg_optional;
15923 else if (strcmp(buf, "Required") == 0)
15924 security->mfp = wifi_mfp_cfg_required;
15925
15926 memset(buf, 0, sizeof(buf));
15927 security->wpa3_transition_disable = FALSE;
15928 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
15929 disable = strtol(buf, NULL, 16);
15930 if (disable != 0)
15931 security->wpa3_transition_disable = TRUE;
15932
15933 memset(buf, 0, sizeof(buf));
15934 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
15935 if (strlen(buf) == 0)
15936 security->rekey_interval = 86400;
15937 else
15938 security->rekey_interval = strtol(buf, NULL, 10);
15939
15940 memset(buf, 0, sizeof(buf));
15941 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
15942 if (strlen(buf) == 0)
15943 security->strict_rekey = 1;
15944 else
15945 security->strict_rekey = strtol(buf, NULL, 10);
15946
15947 memset(buf, 0, sizeof(buf));
15948 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
15949 if (strlen(buf) == 0)
15950 security->eapol_key_retries = 4;
15951 else
15952 security->eapol_key_retries = strtol(buf, NULL, 10);
15953
15954 memset(buf, 0, sizeof(buf));
15955 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
15956 if (strlen(buf) == 0)
15957 security->disable_pmksa_caching = FALSE;
15958 else
15959 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
15960
15961 /* TODO
15962 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
15963 */
15964 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
15965 security->eap_identity_req_timeout = 0;
15966 security->eap_identity_req_retries = 0;
15967 security->eap_req_timeout = 0;
15968 security->eap_req_retries = 0;
15969 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
15970 return RETURN_OK;
15971}
15972
15973#endif /* WIFI_HAL_VERSION_3 */
15974
15975#ifdef WIFI_HAL_VERSION_3_PHASE2
15976INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
15977{
15978 char interface_name[16] = {0};
15979 char cmd[128] = {0};
15980 char buf[128] = {0};
15981 char *mac_addr = NULL;
15982 BOOL status = FALSE;
15983 size_t len = 0;
15984
15985 if(ap_index > MAX_APS)
15986 return RETURN_ERR;
15987
15988 *output_numDevices = 0;
15989 wifi_getApEnable(ap_index, &status);
15990 if (status == FALSE)
15991 return RETURN_OK;
15992
15993 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
15994 return RETURN_ERR;
15995 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
15996 _syscmd(cmd, buf, sizeof(buf));
15997
15998 mac_addr = strtok(buf, "\n");
15999 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
16000 *output_numDevices = i + 1;
16001 fprintf(stderr, "mac_addr: %s\n", mac_addr);
16002 addr_ptr = output_deviceMacAddressArray[i];
16003 mac_addr_aton(addr_ptr, mac_addr);
16004 mac_addr = strtok(NULL, "\n");
16005 }
16006
16007 return RETURN_OK;
16008}
16009#else
16010INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
16011{
16012 char interface_name[16] = {0};
16013 char cmd[128];
16014 BOOL status = false;
16015
16016 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
16017 return RETURN_ERR;
16018
16019 output_buf[0] = '\0';
16020
16021 wifi_getApEnable(ap_index,&status);
16022 if (!status)
16023 return RETURN_OK;
16024
16025 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
16026 return RETURN_ERR;
16027 sprintf(cmd, "hostapd_cli -i %s list_sta | tr '\\n' ',' | sed 's/.$//'", interface_name);
16028 _syscmd(cmd, output_buf, output_buf_size);
developer69b61b02023-03-07 17:17:44 +080016029
developer72fb0bb2023-01-11 09:46:29 +080016030 return RETURN_OK;
16031}
16032#endif
16033
16034INT wifi_getProxyArp(INT apIndex, BOOL *enable)
16035{
16036 char output[16]={'\0'};
16037 char config_file[MAX_BUF_SIZE] = {0};
16038
16039 if (!enable)
16040 return RETURN_ERR;
16041
16042 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
16043 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
16044
16045 if (strlen(output) == 0)
16046 *enable = FALSE;
16047 else if (strncmp(output, "1", 1) == 0)
16048 *enable = TRUE;
16049 else
16050 *enable = FALSE;
16051
16052 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
16053 return RETURN_OK;
16054}
16055
16056INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
16057{
16058 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
16059 return RETURN_ERR;
16060 *output_enable=TRUE;
16061 return RETURN_OK;
16062}
16063
16064INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
16065{
16066 char cmd[128] = {0};
16067 char buf[128] = {0};
16068 char line[128] = {0};
16069 size_t len = 0;
16070 FILE *f = NULL;
16071 int index = 0;
16072 int exp = 0;
16073 int mantissa = 0;
16074 int duration = 0;
16075 int radio_index = 0;
16076 int max_radio_num = 0;
16077 uint twt_wake_interval = 0;
16078 int phyId = 0;
16079 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
16080
16081 wifi_getMaxRadioNumber(&max_radio_num);
16082
16083 radio_index = ap_index % max_radio_num;
16084
16085 phyId = radio_index_to_phy(radio_index);
16086 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", phyId);
16087 _syscmd(cmd, buf, sizeof(buf));
16088 *numSessionReturned = strtol(buf, NULL, 10) - 1;
16089 if (*numSessionReturned > maxNumberSessions)
16090 *numSessionReturned = maxNumberSessions;
16091 else if (*numSessionReturned < 1) {
16092 *numSessionReturned = 0;
16093 return RETURN_OK;
16094 }
16095
16096 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | tail -n %d | tr '|' ' ' | tr -s ' '", phyId, *numSessionReturned);
16097 if ((f = popen(cmd, "r")) == NULL) {
16098 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
16099 return RETURN_ERR;
16100 }
16101
16102 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
16103 while((fgets(line, sizeof(line), f)) != NULL) {
16104 char *tmp = NULL;
16105 strcpy(buf, line);
16106 tmp = strtok(buf, " ");
16107 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
16108 tmp = strtok(NULL, " ");
16109 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
16110 tmp = strtok(NULL, " ");
16111 if (strstr(tmp, "t")) {
16112 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
16113 }
16114 if (strstr(tmp, "a")) {
16115 twtSessions[index].twtParameters.operation.announced = TRUE;
16116 }
16117 tmp = strtok(NULL, " ");
16118 exp = strtol(tmp, NULL, 10);
16119 tmp = strtok(NULL, " ");
16120 mantissa = strtol(tmp, NULL, 10);
16121 tmp = strtok(NULL, " ");
16122 duration = strtol(tmp, NULL, 10);
16123
16124 // only implicit supported
16125 twtSessions[index].twtParameters.operation.implicit = TRUE;
16126 // only individual agreement supported
16127 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
16128
16129 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
16130 twt_wake_interval = mantissa * (1 << exp);
16131 if (mantissa == 0 || twt_wake_interval/mantissa != (1 << exp)) {
16132 // Overflow handling
16133 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
16134 } else {
16135 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
16136 }
16137 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
16138 index++;
16139 }
16140
16141 pclose(f);
16142 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
16143 return RETURN_OK;
16144}