blob: 02ec0542648fdd0bf6ed041a1fe5e978995bc61e [file] [log] [blame]
developer06a01d92022-09-07 16:32:39 +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*/
developerda1ed692022-09-13 13:59:20 +080037#define MTK_IMPL
developer06a01d92022-09-07 16:32:39 +080038#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>
57#include<net/if.h>
58#endif
59
60#include <ev.h>
61#include <wpa_ctrl.h>
62#include <errno.h>
63#include <time.h>
developerefb790a2023-12-26 18:58:32 +080064#include <pthread.h>
65
developer06a01d92022-09-07 16:32:39 +080066#define MAC_ALEN 6
67
developer7930d352022-12-21 17:55:42 +080068#define MAX_BUF_SIZE 256
69#define MAX_CMD_SIZE 256
70#define IF_NAME_SIZE 16
developer06a01d92022-09-07 16:32:39 +080071#define CONFIG_PREFIX "/nvram/hostapd"
developer431128d2022-12-16 15:30:41 +080072#define ACL_PREFIX "/nvram/hostapd-acl"
73#define DENY_PREFIX "/nvram/hostapd-deny"
developer06a01d92022-09-07 16:32:39 +080074//#define ACL_PREFIX "/tmp/wifi_acl_list" //RDKB convention
75#define SOCK_PREFIX "/var/run/hostapd/wifi"
developer431128d2022-12-16 15:30:41 +080076#define VAP_STATUS_FILE "/nvram/vap-status"
developera3c68b92022-09-13 15:27:29 +080077#define ESSID_FILE "/tmp/essid"
developer247302b2022-10-06 15:03:00 +080078#define GUARD_INTERVAL_FILE "/nvram/guard-interval"
developera748dcf2022-09-13 15:56:48 +080079#define CHANNEL_STATS_FILE "/tmp/channel_stats"
developer9964b5b2022-09-13 15:59:34 +080080#define DFS_ENABLE_FILE "/nvram/dfs_enable.txt"
developerf5fef612022-09-20 19:38:26 +080081#define VLAN_FILE "/nvram/hostapd.vlan"
developer431128d2022-12-16 15:30:41 +080082#define PSK_FILE "/nvram/hostapd"
developerf49437e2022-09-29 19:58:21 +080083#define MCS_FILE "/tmp/MCS"
developer6daeb3f2022-09-30 13:36:39 +080084#define NOACK_MAP_FILE "/tmp/NoAckMap"
developer454b9462022-09-13 15:29:16 +080085
developer81bf2ed2022-09-13 15:31:14 +080086#define BRIDGE_NAME "brlan0"
developer06a01d92022-09-07 16:32:39 +080087
88/*
89 MAX_APS - Number of all AP available in system
90 2x Home AP
91 2x Backhaul AP
92 2x Guest AP
93 2x Secure Onboard AP
94 2x Service AP
95
96*/
developer06a01d92022-09-07 16:32:39 +080097
developer033b37b2022-10-18 11:27:46 +080098
developera77d84b2023-02-22 16:10:50 +080099#define MAX_APS ((MAX_NUM_RADIOS)*(MAX_NUM_VAP_PER_RADIO))
developer06a01d92022-09-07 16:32:39 +0800100#ifndef AP_PREFIX
101#define AP_PREFIX "wifi"
102#endif
103
104#ifndef RADIO_PREFIX
105#define RADIO_PREFIX "wlan"
106#endif
107
developer89df4502023-02-16 20:45:02 +0800108#define MAX_ASSOCIATED_STA_NUM 2007 // hostapd default
developer06a01d92022-09-07 16:32:39 +0800109
110//Uncomment to enable debug logs
111//#define WIFI_DEBUG
112
113#ifdef WIFI_DEBUG
114#define wifi_dbg_printf printf
115#define WIFI_ENTRY_EXIT_DEBUG printf
116#else
117#define wifi_dbg_printf(format, args...) printf("")
118#define WIFI_ENTRY_EXIT_DEBUG(format, args...) printf("")
119#endif
120
121#define HOSTAPD_CONF_0 "/nvram/hostapd0.conf" //private-wifi-2g
122#define HOSTAPD_CONF_1 "/nvram/hostapd1.conf" //private-wifi-5g
123#define HOSTAPD_CONF_4 "/nvram/hostapd4.conf" //public-wifi-2g
124#define HOSTAPD_CONF_5 "/nvram/hostapd5.conf" //public-wifi-5g
125#define DEF_HOSTAPD_CONF_0 "/usr/ccsp/wifi/hostapd0.conf"
126#define DEF_HOSTAPD_CONF_1 "/usr/ccsp/wifi/hostapd1.conf"
127#define DEF_HOSTAPD_CONF_4 "/usr/ccsp/wifi/hostapd4.conf"
128#define DEF_HOSTAPD_CONF_5 "/usr/ccsp/wifi/hostapd5.conf"
129#define DEF_RADIO_PARAM_CONF "/usr/ccsp/wifi/radio_param_def.cfg"
130#define LM_DHCP_CLIENT_FORMAT "%63d %17s %63s %63s"
131
developer4fb0b922022-09-30 14:29:09 +0800132#define HOSTAPD_HT_CAPAB "[LDPC][SHORT-GI-20][SHORT-GI-40][MAX-AMSDU-7935]"
developer06a01d92022-09-07 16:32:39 +0800133
134#define BW_FNAME "/nvram/bw_file.txt"
135
136#define PS_MAX_TID 16
137
developer439baa32024-05-02 15:54:58 +0800138
139#ifdef SINGLE_WIPHY_SUPPORT
140#define single_wiphy TRUE
141#else
142#define single_wiphy FALSE
143#endif
144
developer06a01d92022-09-07 16:32:39 +0800145static wifi_radioQueueType_t _tid_ac_index_get[PS_MAX_TID] = {
146 WIFI_RADIO_QUEUE_TYPE_BE, /* 0 */
147 WIFI_RADIO_QUEUE_TYPE_BK, /* 1 */
148 WIFI_RADIO_QUEUE_TYPE_BK, /* 2 */
149 WIFI_RADIO_QUEUE_TYPE_BE, /* 3 */
150 WIFI_RADIO_QUEUE_TYPE_VI, /* 4 */
151 WIFI_RADIO_QUEUE_TYPE_VI, /* 5 */
152 WIFI_RADIO_QUEUE_TYPE_VO, /* 6 */
153 WIFI_RADIO_QUEUE_TYPE_VO, /* 7 */
154 WIFI_RADIO_QUEUE_TYPE_BE, /* 8 */
155 WIFI_RADIO_QUEUE_TYPE_BK, /* 9 */
156 WIFI_RADIO_QUEUE_TYPE_BK, /* 10 */
157 WIFI_RADIO_QUEUE_TYPE_BE, /* 11 */
158 WIFI_RADIO_QUEUE_TYPE_VI, /* 12 */
159 WIFI_RADIO_QUEUE_TYPE_VI, /* 13 */
160 WIFI_RADIO_QUEUE_TYPE_VO, /* 14 */
161 WIFI_RADIO_QUEUE_TYPE_VO, /* 15 */
162};
163
164typedef unsigned long long u64;
165
166/* Enum to define WiFi Bands */
167typedef enum
168{
169 band_invalid = -1,
170 band_2_4 = 0,
171 band_5 = 1,
developerc707e972022-09-13 15:38:02 +0800172 band_6 = 2,
developer06a01d92022-09-07 16:32:39 +0800173} wifi_band;
174
developerdb744382022-09-13 15:34:54 +0800175typedef enum {
176 WIFI_MODE_A = 0x01,
177 WIFI_MODE_B = 0x02,
178 WIFI_MODE_G = 0x04,
179 WIFI_MODE_N = 0x08,
180 WIFI_MODE_AC = 0x10,
181 WIFI_MODE_AX = 0x20,
developer7c4cd202023-03-01 10:56:29 +0800182 WIFI_MODE_BE = 0x40,
developerdb744382022-09-13 15:34:54 +0800183} wifi_ieee80211_Mode;
184
developer06a01d92022-09-07 16:32:39 +0800185#ifdef WIFI_HAL_VERSION_3
186
187// Return number of elements in array
188#ifndef ARRAY_SIZE
189#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
190#endif /* ARRAY_SIZE */
191
192#ifndef ARRAY_AND_SIZE
193#define ARRAY_AND_SIZE(x) (x),ARRAY_SIZE(x)
194#endif /* ARRAY_AND_SIZE */
195
196#define WIFI_ITEM_STR(key, str) {0, sizeof(str)-1, (int)key, (intptr_t)str}
197
198typedef struct {
199 int32_t value;
200 int32_t param;
201 intptr_t key;
202 intptr_t data;
203} wifi_secur_list;
204
developerfa41b1f2023-01-06 10:25:51 +0800205static int util_unii_5g_centerfreq(const char *ht_mode, int channel);
206static int util_unii_6g_centerfreq(const char *ht_mode, int channel);
developer72ec5572023-01-05 16:27:13 +0800207static int util_get_sec_chan_offset(int channel, const char* ht_mode);
developer06a01d92022-09-07 16:32:39 +0800208wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key);
209wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str);
210char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key);
developer63a1ef02024-05-03 16:59:38 +0800211static int ieee80211_channel_to_frequency(int chan, wifi_band band);
developer06a01d92022-09-07 16:32:39 +0800212
213static wifi_secur_list map_security[] =
214{
215 WIFI_ITEM_STR(wifi_security_mode_none, "None"),
216 WIFI_ITEM_STR(wifi_security_mode_wep_64, "WEP-64"),
217 WIFI_ITEM_STR(wifi_security_mode_wep_128, "WEP-128"),
218 WIFI_ITEM_STR(wifi_security_mode_wpa_personal, "WPA-Personal"),
219 WIFI_ITEM_STR(wifi_security_mode_wpa_enterprise, "WPA-Enterprise"),
220 WIFI_ITEM_STR(wifi_security_mode_wpa2_personal, "WPA2-Personal"),
221 WIFI_ITEM_STR(wifi_security_mode_wpa2_enterprise, "WPA2-Enterprise"),
222 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_personal, "WPA-WPA2-Personal"),
developerc0830312022-10-13 13:22:36 +0800223 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_enterprise, "WPA-WPA2-Enterprise"),
224 WIFI_ITEM_STR(wifi_security_mode_wpa3_personal, "WPA3-Personal"),
developer4a359672022-10-13 15:30:46 +0800225 WIFI_ITEM_STR(wifi_security_mode_wpa3_transition, "WPA3-Personal-Transition"),
developerc0830312022-10-13 13:22:36 +0800226 WIFI_ITEM_STR(wifi_security_mode_wpa3_enterprise, "WPA3-Enterprise")
developer06a01d92022-09-07 16:32:39 +0800227};
228
developerefb790a2023-12-26 18:58:32 +0800229typedef struct {
230 char ssid[MAX_BUF_SIZE];
231 char wpa[MAX_BUF_SIZE];
232 char wpa_key_mgmt[MAX_BUF_SIZE];
233 char wpa_passphrase[MAX_BUF_SIZE];
234 char ap_isolate[MAX_BUF_SIZE];
235 char macaddr_acl[MAX_BUF_SIZE];
236 char bss_transition[MAX_BUF_SIZE];
237 char ignore_broadcast_ssid[MAX_BUF_SIZE];
238 char max_sta[MAX_BUF_SIZE];
239} __attribute__((packed)) wifi_vap_cfg_t;
240
241pthread_t pthread_id;
242int result = 0, tflag = 0;
243wifi_vap_cfg_t vap_info[MAX_NUM_RADIOS*MAX_NUM_VAP_PER_RADIO];
244int syn_flag = 0;
245
developer06a01d92022-09-07 16:32:39 +0800246wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key)
247{
248 wifi_secur_list *item;
249 int i;
250
251 for (item = list,i = 0;i < list_sz; item++, i++) {
252 if ((int)(item->key) == key) {
253 return item;
254 }
255 }
256
257 return NULL;
258}
259
260char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key)
261{
262 wifi_secur_list *item = wifi_get_item_by_key(list, list_sz, key);
263
264 if (!item) {
265 return "";
266 }
267
268 return (char *)(item->data);
269}
270
271wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str)
272{
273 wifi_secur_list *item;
274 int i;
275
276 for (item = list,i = 0;i < list_sz; item++, i++) {
277 if (strcmp((char *)(item->data), str) == 0) {
278 return item;
279 }
280 }
281
282 return NULL;
283}
284#endif /* WIFI_HAL_VERSION_3 */
285
286#ifdef HAL_NETLINK_IMPL
287typedef struct {
288 int id;
289 struct nl_sock* socket;
290 struct nl_cb* cb;
291} Netlink;
292
293static int mac_addr_aton(unsigned char *mac_addr, char *arg)
294{
295 unsigned int mac_addr_int[6]={};
developer1d57d002022-10-12 18:03:15 +0800296 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);
developer06a01d92022-09-07 16:32:39 +0800297 mac_addr[0] = mac_addr_int[0];
298 mac_addr[1] = mac_addr_int[1];
299 mac_addr[2] = mac_addr_int[2];
300 mac_addr[3] = mac_addr_int[3];
301 mac_addr[4] = mac_addr_int[4];
302 mac_addr[5] = mac_addr_int[5];
303 return 0;
304}
305
306static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
307{
308 unsigned int mac_addr_int[6]={};
309 mac_addr_int[0] = arg[0];
310 mac_addr_int[1] = arg[1];
311 mac_addr_int[2] = arg[2];
312 mac_addr_int[3] = arg[3];
313 mac_addr_int[4] = arg[4];
314 mac_addr_int[5] = arg[5];
developer1d57d002022-10-12 18:03:15 +0800315 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]);
developer06a01d92022-09-07 16:32:39 +0800316 return;
317}
318
319static int ieee80211_frequency_to_channel(int freq)
320{
developerf5745ee2022-10-05 16:09:53 +0800321 /* see 802.11-2007 17.3.8.3.2 and Annex J */
developer06a01d92022-09-07 16:32:39 +0800322 if (freq == 2484)
323 return 14;
developerf5745ee2022-10-05 16:09:53 +0800324 /* see 802.11ax D6.1 27.3.23.2 and Annex E */
325 else if (freq == 5935)
326 return 2;
developer06a01d92022-09-07 16:32:39 +0800327 else if (freq < 2484)
328 return (freq - 2407) / 5;
329 else if (freq >= 4910 && freq <= 4980)
330 return (freq - 4000) / 5;
developerf5745ee2022-10-05 16:09:53 +0800331 else if (freq < 5950)
developer06a01d92022-09-07 16:32:39 +0800332 return (freq - 5000) / 5;
developerf5745ee2022-10-05 16:09:53 +0800333 else if (freq <= 45000) /* DMG band lower limit */
334 /* see 802.11ax D6.1 27.3.23.2 */
335 return (freq - 5950) / 5;
336 else if (freq >= 58320 && freq <= 70200)
developer06a01d92022-09-07 16:32:39 +0800337 return (freq - 56160) / 2160;
338 else
339 return 0;
340}
341
342static int initSock80211(Netlink* nl) {
343 nl->socket = nl_socket_alloc();
344 if (!nl->socket) {
345 fprintf(stderr, "Failing to allocate the sock\n");
346 return -ENOMEM;
347 }
348
349 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
350
351 if (genl_connect(nl->socket)) {
352 fprintf(stderr, "Failed to connect\n");
353 nl_close(nl->socket);
354 nl_socket_free(nl->socket);
355 return -ENOLINK;
356 }
357
358 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
359 if (nl->id< 0) {
360 fprintf(stderr, "interface not found.\n");
361 nl_close(nl->socket);
362 nl_socket_free(nl->socket);
363 return -ENOENT;
364 }
365
366 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
367 if ((!nl->cb)) {
368 fprintf(stderr, "Failed to allocate netlink callback.\n");
369 nl_close(nl->socket);
370 nl_socket_free(nl->socket);
371 return ENOMEM;
372 }
373
374 return nl->id;
375}
376
377static int nlfree(Netlink *nl)
378{
379 nl_cb_put(nl->cb);
380 nl_close(nl->socket);
381 nl_socket_free(nl->socket);
382 return 0;
383}
384
385static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
386 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
387 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
388 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
389};
390
391static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
392};
393
394static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
395};
396
397typedef struct _wifi_channelStats_loc {
398 INT array_size;
399 INT ch_number;
400 BOOL ch_in_pool;
401 INT ch_noise;
402 BOOL ch_radar_noise;
403 INT ch_max_80211_rssi;
404 INT ch_non_80211_noise;
405 INT ch_utilization;
406 ULLONG ch_utilization_total;
407 ULLONG ch_utilization_busy;
408 ULLONG ch_utilization_busy_tx;
409 ULLONG ch_utilization_busy_rx;
410 ULLONG ch_utilization_busy_self;
411 ULLONG ch_utilization_busy_ext;
412} wifi_channelStats_t_loc;
413
414typedef struct wifi_device_info {
415 INT wifi_devIndex;
416 UCHAR wifi_devMacAddress[6];
417 CHAR wifi_devIPAddress[64];
418 BOOL wifi_devAssociatedDeviceAuthentiationState;
419 INT wifi_devSignalStrength;
420 INT wifi_devTxRate;
421 INT wifi_devRxRate;
422} wifi_device_info_t;
423
424#endif
425
426//For 5g Alias Interfaces
427static BOOL priv_flag = TRUE;
428static BOOL pub_flag = TRUE;
429static BOOL Radio_flag = TRUE;
430//wifi_setApBeaconRate(1, beaconRate);
431
developer1e5aa162022-09-13 16:06:24 +0800432BOOL multiple_set = FALSE;
433
developer06a01d92022-09-07 16:32:39 +0800434struct params
435{
436 char * name;
437 char * value;
438};
439
440static int _syscmd(char *cmd, char *retBuf, int retBufSize)
441{
442 FILE *f;
443 char *ptr = retBuf;
444 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
445
446 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
447 if((f = popen(cmd, "r")) == NULL) {
448 fprintf(stderr,"\npopen %s error\n", cmd);
449 return RETURN_ERR;
450 }
451
452 while(!feof(f))
453 {
454 *ptr = 0;
455 if(bufSize>=128) {
456 bufbytes=128;
457 } else {
458 bufbytes=bufSize-1;
459 }
460
461 fgets(ptr,bufbytes,f);
462 readbytes=strlen(ptr);
463
464 if(!readbytes)
465 break;
466
467 bufSize-=readbytes;
468 ptr += readbytes;
469 }
470 cmd_ret = pclose(f);
471 retBuf[retBufSize-1]=0;
472 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
473
474 return cmd_ret >> 8;
475}
476
developer033b37b2022-10-18 11:27:46 +0800477INT radio_index_to_phy(int radioIndex)
478{
479 char cmd[128] = {0};
480 char buf[64] = {0};
481 int phyIndex = 0;
482 snprintf(cmd, sizeof(cmd), "ls /tmp | grep wifi%d | cut -d '-' -f1 | tr -d '\n'", radioIndex);
483 _syscmd(cmd, buf, sizeof(buf));
484
485 if (strlen(buf) == 0 || strstr(buf, "phy") == NULL) {
developer431128d2022-12-16 15:30:41 +0800486 fprintf(stderr, "%s: failed to get phy index with: %d\n", __func__, radioIndex);
developer033b37b2022-10-18 11:27:46 +0800487 return RETURN_ERR;
488 }
489 sscanf(buf, "phy%d", &phyIndex);
490
491 return phyIndex;
492}
developer026ac9e2022-11-07 13:46:24 +0800493
developer431128d2022-12-16 15:30:41 +0800494INT wifi_getMaxRadioNumber(INT *max_radio_num)
495{
496 char cmd[64] = {0};
497 char buf[4] = {0};
498
499 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
500
developer439baa32024-05-02 15:54:58 +0800501 snprintf(cmd, sizeof(cmd), "ls /sys/class/ieee80211 | wc -l");
developer431128d2022-12-16 15:30:41 +0800502 _syscmd(cmd, buf, sizeof(buf));
503 *max_radio_num = strtoul(buf, NULL, 10) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS:strtoul(buf, NULL, 10);
504
505 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
506
507 return RETURN_OK;
508}
509
developer59ff6de2023-02-08 17:58:14 +0800510static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
511{
512 char cmd[MAX_CMD_SIZE]={'\0'};
513 char buf[MAX_BUF_SIZE]={'\0'};
514 int ret = 0;
515
516 sprintf(cmd, "cat %s 2> /dev/null | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", conf_file, param);
517 ret = _syscmd(cmd, buf, sizeof(buf));
518 if ((ret != 0) && (strlen(buf) == 0))
519 return -1;
520 snprintf(output, output_size, "%s", buf);
521
522 return 0;
523}
524
525static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
526{
527 char cmd[MAX_CMD_SIZE]={'\0'};
528 char buf[MAX_BUF_SIZE]={'\0'};
529
530 for(int i=0;i<item_count;i++)
531 {
532 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
533 if (strlen(buf) == 0) //Insert
534 snprintf(cmd, sizeof(cmd), "echo \"%s=%s\" >> %s", list[i].name, list[i].value, conf_file);
535 else //Update
536 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=%s/\" %s", list[i].name, list[i].name, list[i].value, conf_file);
537
538 if(_syscmd(cmd, buf, sizeof(buf)))
539 return -1;
540 }
541
542 return 0;
543}
544
developer431128d2022-12-16 15:30:41 +0800545wifi_band wifi_index_to_band(int apIndex)
developerc707e972022-09-13 15:38:02 +0800546{
547 char cmd[128] = {0};
548 char buf[64] = {0};
developer59ff6de2023-02-08 17:58:14 +0800549 char config_file[128] = {0};
developer026ac9e2022-11-07 13:46:24 +0800550 int nl80211_band = 0;
developer5884e982022-10-06 10:52:50 +0800551 int i = 0;
developer026ac9e2022-11-07 13:46:24 +0800552 int phyIndex = 0;
developer431128d2022-12-16 15:30:41 +0800553 int radioIndex = 0;
554 int max_radio_num = 0;
developerc707e972022-09-13 15:38:02 +0800555 wifi_band band = band_invalid;
556
557 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer026ac9e2022-11-07 13:46:24 +0800558
developer431128d2022-12-16 15:30:41 +0800559 wifi_getMaxRadioNumber(&max_radio_num);
560 radioIndex = apIndex % max_radio_num;
developer439baa32024-05-02 15:54:58 +0800561 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
562 wifi_hostapdRead(config_file, "op_class", buf, sizeof(buf));
563 if (strlen(buf) > 0)
564 return band_6;
developer5884e982022-10-06 10:52:50 +0800565
developer439baa32024-05-02 15:54:58 +0800566 memset(buf, 0, sizeof(buf));
567 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
568 if (strncmp(buf, "a", 1) == 0)
569 return band_5;
570 else
571 return band_2_4;
developerc707e972022-09-13 15:38:02 +0800572
573 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
574 return band;
575}
576
developerd946fd62022-12-08 18:03:28 +0800577//For Getting Current Interface Name from corresponding hostapd configuration
developerac6f1142022-12-20 19:26:35 +0800578static int wifi_GetInterfaceName(int apIndex, char *interface_name)
developerd946fd62022-12-08 18:03:28 +0800579{
580 char config_file[128] = {0};
581
582 if (interface_name == NULL)
583 return RETURN_ERR;
584
585 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developerefb790a2023-12-26 18:58:32 +0800586#ifdef DYNAMIC_IF_NAME
developerd946fd62022-12-08 18:03:28 +0800587 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
588 wifi_hostapdRead(config_file, "interface", interface_name, 16);
589 if (strlen(interface_name) == 0)
590 return RETURN_ERR;
developerefb790a2023-12-26 18:58:32 +0800591#else
592 sprintf(interface_name, "%s%d",AP_PREFIX, apIndex);
593#endif
developerd946fd62022-12-08 18:03:28 +0800594 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
595 return RETURN_OK;
596}
597
developerac6f1142022-12-20 19:26:35 +0800598// wifi agent will call this function, do not change the parameter
599void GetInterfaceName(char *interface_name, char *conf_file)
600{
601 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
602 wifi_hostapdRead(conf_file,"interface",interface_name, IF_NAME_SIZE);
603 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
604}
605
developer06a01d92022-09-07 16:32:39 +0800606static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
607{
developerd946fd62022-12-08 18:03:28 +0800608 char interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +0800609 if (multiple_set == TRUE)
610 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800611 char cmd[MAX_CMD_SIZE]="", output[32]="";
612 FILE *fp;
613 int i;
614 //NOTE RELOAD should be done in ApplySSIDSettings
developerac6f1142022-12-20 19:26:35 +0800615 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +0800616 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +0800617 for(i=0; i<item_count; i++, list++)
618 {
developerd946fd62022-12-08 18:03:28 +0800619 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s SET %s %s", interface_name, list->name, list->value);
developer06a01d92022-09-07 16:32:39 +0800620 if((fp = popen(cmd, "r"))==NULL)
621 {
622 perror("popen failed");
623 return -1;
624 }
625 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
626 {
627 pclose(fp);
628 perror("fgets failed");
629 return -1;
630 }
631 pclose(fp);
632 }
633 return 0;
634}
635
636static int wifi_reloadAp(int apIndex)
637{
developerd946fd62022-12-08 18:03:28 +0800638 char interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +0800639 if (multiple_set == TRUE)
640 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800641 char cmd[MAX_CMD_SIZE]="";
642 char buf[MAX_BUF_SIZE]="";
643
developerac6f1142022-12-20 19:26:35 +0800644 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +0800645 return RETURN_ERR;
646 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s reload", interface_name);
developer06a01d92022-09-07 16:32:39 +0800647 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
648 return RETURN_ERR;
649
developerd946fd62022-12-08 18:03:28 +0800650 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s disable", interface_name);
developer06a01d92022-09-07 16:32:39 +0800651 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
652 return RETURN_ERR;
653
developerd946fd62022-12-08 18:03:28 +0800654 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s enable", interface_name);
developer06a01d92022-09-07 16:32:39 +0800655 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
656 return RETURN_ERR;
657
658 return RETURN_OK;
659}
660
developer06a01d92022-09-07 16:32:39 +0800661INT File_Reading(CHAR *file, char *Value)
662{
663 FILE *fp = NULL;
664 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
665 int count = 0;
666
667 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
668 fp = popen(file,"r");
669 if(fp == NULL)
670 return RETURN_ERR;
671
672 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
673 {
674 for(count=0;buf[count]!='\n';count++)
675 copy_buf[count]=buf[count];
676 copy_buf[count]='\0';
677 }
678 strcpy(Value,copy_buf);
679 pclose(fp);
680 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
681
682 return RETURN_OK;
683}
684
685void wifi_RestartHostapd_2G()
686{
687 int Public2GApIndex = 4;
688
689 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
690 wifi_setApEnable(Public2GApIndex, FALSE);
691 wifi_setApEnable(Public2GApIndex, TRUE);
692 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
693}
694
695void wifi_RestartHostapd_5G()
696{
697 int Public5GApIndex = 5;
698
699 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
700 wifi_setApEnable(Public5GApIndex, FALSE);
701 wifi_setApEnable(Public5GApIndex, TRUE);
702 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
703}
704
705void wifi_RestartPrivateWifi_2G()
706{
707 int PrivateApIndex = 0;
708
709 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
710 wifi_setApEnable(PrivateApIndex, FALSE);
711 wifi_setApEnable(PrivateApIndex, TRUE);
712 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
713}
714
715void wifi_RestartPrivateWifi_5G()
716{
717 int Private5GApIndex = 1;
718
719 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
720 wifi_setApEnable(Private5GApIndex, FALSE);
721 wifi_setApEnable(Private5GApIndex, TRUE);
722 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
723}
724
725static int writeBandWidth(int radioIndex,char *bw_value)
726{
727 char buf[MAX_BUF_SIZE];
728 char cmd[MAX_CMD_SIZE];
729
730 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
731 if(_syscmd(cmd, buf, sizeof(buf)))
732 {
733 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
734 _syscmd(cmd, buf, sizeof(buf));
735 return RETURN_OK;
736 }
737
738 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
739 _syscmd(cmd,buf,sizeof(buf));
740 return RETURN_OK;
741}
742
743static int readBandWidth(int radioIndex,char *bw_value)
744{
developer30423732022-12-01 16:17:49 +0800745 char buf[MAX_BUF_SIZE] = {0};
746 char cmd[MAX_CMD_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +0800747 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
748 _syscmd(cmd,buf,sizeof(buf));
749 if(NULL!=strstr(buf,"20MHz"))
developer06a01d92022-09-07 16:32:39 +0800750 strcpy(bw_value,"20MHz");
developer06a01d92022-09-07 16:32:39 +0800751 else if(NULL!=strstr(buf,"40MHz"))
developer06a01d92022-09-07 16:32:39 +0800752 strcpy(bw_value,"40MHz");
developer06a01d92022-09-07 16:32:39 +0800753 else if(NULL!=strstr(buf,"80MHz"))
developer06a01d92022-09-07 16:32:39 +0800754 strcpy(bw_value,"80MHz");
developer57fa24a2023-03-15 17:25:07 +0800755 else if(NULL!=strstr(buf,"160MHz"))
756 strcpy(bw_value,"160MHz");
757 else if(NULL!=strstr(buf,"320MHz"))
758 strcpy(bw_value,"320MHz");
developer06a01d92022-09-07 16:32:39 +0800759 else
developer06a01d92022-09-07 16:32:39 +0800760 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +0800761 return RETURN_OK;
762}
763
developer264159b2022-11-02 09:41:35 +0800764// Input could be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
developer06a01d92022-09-07 16:32:39 +0800765INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
766{
developer5f222492022-09-13 15:21:52 +0800767 struct params params={'\0'};
768 char config_file[MAX_BUF_SIZE] = {0};
769 char buf[MAX_BUF_SIZE] = {'\0'};
770
771 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer5f222492022-09-13 15:21:52 +0800772 // Copy the numeric value
developer264159b2022-11-02 09:41:35 +0800773 if (strlen (beaconRate) >= 5) {
774 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
775 buf[strlen(beaconRate) - 4] = '\0';
776 } else if (strlen(beaconRate) > 0)
777 strcpy(buf, beaconRate);
778 else
779 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +0800780
781 params.name = "beacon_rate";
782 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
783 if (strncmp(buf, "5.5", 3) == 0) {
784 snprintf(buf, sizeof(buf), "55");
785 params.value = buf;
786 } else {
787 strcat(buf, "0");
788 params.value = buf;
789 }
790
791 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
792 wifi_hostapdWrite(config_file, &params, 1);
793 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
794 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
795
796 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800797}
798
799INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
800{
developer1d57d002022-10-12 18:03:15 +0800801 char config_file[128] = {'\0'};
802 char temp_output[128] = {'\0'};
803 char buf[128] = {'\0'};
804 char cmd[128] = {'\0'};
805 int rate = 0;
developer5f222492022-09-13 15:21:52 +0800806
807 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
808 if (NULL == beaconRate)
809 return RETURN_ERR;
810
811 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
812 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
813 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
814 if(strlen(buf) > 0) {
developer1d57d002022-10-12 18:03:15 +0800815 if (strncmp(buf, "55", 2) == 0)
816 snprintf(temp_output, sizeof(temp_output), "5.5Mbps");
817 else {
818 rate = strtol(buf, NULL, 10)/10;
819 snprintf(temp_output, sizeof(temp_output), "%dMbps", rate);
820 }
developer5f222492022-09-13 15:21:52 +0800821 } else {
developer1d57d002022-10-12 18:03:15 +0800822 // config not set, so we would use lowest rate as default
developer63a1ef02024-05-03 16:59:38 +0800823 sprintf(cmd, "hostapd_cli -i wifi%d status | grep supported_rates | sed 's/=/ 0x/' | awk '{print $2}'", radioIndex);
developer1d57d002022-10-12 18:03:15 +0800824 _syscmd(cmd, buf, sizeof(buf));
developer63a1ef02024-05-03 16:59:38 +0800825 snprintf(temp_output, sizeof(temp_output), "%dMbps", strtol(buf, NULL, 0)*5/10);
developer5f222492022-09-13 15:21:52 +0800826 }
827 strncpy(beaconRate, temp_output, sizeof(temp_output));
828 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
829
830 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800831}
832
833INT wifi_setLED(INT radioIndex, BOOL enable)
834{
835 return 0;
836}
837INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
838{
839 return RETURN_OK;
840}
841/**********************************************************************************
842 *
843 * Wifi Subsystem level function prototypes
844 *
845**********************************************************************************/
846//---------------------------------------------------------------------------------------------------
847//Wifi system api
848//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
849INT wifi_getHalVersion(CHAR *output_string) //RDKB
850{
851 if(!output_string)
852 return RETURN_ERR;
853 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
854
855 return RETURN_OK;
856}
857
858
859/* wifi_factoryReset() function */
860/**
861* @description Clears internal variables to implement a factory reset of the Wi-Fi
862* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
863*
864* @param None
865*
866* @return The status of the operation.
867* @retval RETURN_OK if successful.
868* @retval RETURN_ERR if any error is detected
869*
870* @execution Synchronous
871* @sideeffect None
872*
873* @note This function must not suspend and must not invoke any blocking system
874* calls. It should probably just send a message to a driver event handler task.
875*
876*/
877INT wifi_factoryReset()
878{
879 char cmd[128];
880
881 /*delete running hostapd conf files*/
developer72ec5572023-01-05 16:27:13 +0800882 wifi_dbg_printf("\n[%s]: deleting hostapd conf file",__func__);
883 sprintf(cmd, "rm -rf /nvram/hostapd*");
developer06a01d92022-09-07 16:32:39 +0800884 system(cmd);
885 system("systemctl restart hostapd.service");
886
887 return RETURN_OK;
888}
889
890/* wifi_factoryResetRadios() function */
891/**
892* @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.
893*
894* @param None
895* @return The status of the operation
896* @retval RETURN_OK if successful
897* @retval RETURN_ERR if any error is detected
898*
899* @execution Synchronous
900*
901* @sideeffect None
902*
903* @note This function must not suspend and must not invoke any blocking system
904* calls. It should probably just send a message to a driver event handler task.
905*
906*/
907INT wifi_factoryResetRadios()
908{
developer72ec5572023-01-05 16:27:13 +0800909 int max_radio_num = 0;
910 wifi_getMaxRadioNumber(&max_radio_num);
911 for (int radioIndex = 0; radioIndex < max_radio_num; radioIndex++)
912 wifi_factoryResetRadio(radioIndex);
developer06a01d92022-09-07 16:32:39 +0800913
developer72ec5572023-01-05 16:27:13 +0800914 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800915}
916
917
918/* wifi_factoryResetRadio() function */
919/**
920* @description Restore selected radio parameters without touching access point parameters
921*
922* @param radioIndex - Index of Wi-Fi Radio channel
923*
924* @return The status of the operation.
925* @retval RETURN_OK if successful.
926* @retval RETURN_ERR if any error is detected
927*
928* @execution Synchronous.
929* @sideeffect None.
930*
931* @note This function must not suspend and must not invoke any blocking system
932* calls. It should probably just send a message to a driver event handler task.
933*
934*/
935INT wifi_factoryResetRadio(int radioIndex) //RDKB
936{
developer72ec5572023-01-05 16:27:13 +0800937 char cmd[128] = {0};
938 char buf[128] = {0};
939 int max_radio_num = 0;
940
941 wifi_getMaxRadioNumber(&max_radio_num);
942 if (radioIndex < 0 || radioIndex > max_radio_num)
943 return RETURN_ERR;
944
945 snprintf(cmd, sizeof(cmd), "systemctl stop hostapd.service");
946 _syscmd(cmd, buf, sizeof(buf));
developer5ff7f5f2022-09-13 15:12:16 +0800947
developer06a01d92022-09-07 16:32:39 +0800948 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72ec5572023-01-05 16:27:13 +0800949 snprintf(cmd, sizeof(cmd), "rm /nvram/hostapd%d* %s%d.txt", radioIndex, GUARD_INTERVAL_FILE, radioIndex);
950 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +0800951
developer72ec5572023-01-05 16:27:13 +0800952 snprintf(cmd, sizeof(cmd), "systemctl start hostapd.service");
953 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +0800954 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
955 return RETURN_OK;
956}
957
958/* wifi_initRadio() function */
959/**
960* Description: This function call initializes the specified radio.
961* Implementation specifics may dictate the functionality since
962* different hardware implementations may have different initilization requirements.
963* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
964*
965* @return The status of the operation.
966* @retval RETURN_OK if successful.
967* @retval RETURN_ERR if any error is detected
968*
969* @execution Synchronous.
970* @sideeffect None.
971*
972* @note This function must not suspend and must not invoke any blocking system
973* calls. It should probably just send a message to a driver event handler task.
974*
975*/
976INT wifi_initRadio(INT radioIndex)
977{
978 //TODO: Initializes the wifi subsystem (for specified radio)
979 return RETURN_OK;
980}
981void macfilter_init()
982{
983 char count[4]={'\0'};
984 char buf[253]={'\0'};
985 char tmp[19]={'\0'};
986 int dev_count,block,mac_entry=0;
987 char res[4]={'\0'};
988 char acl_file_path[64] = {'\0'};
989 FILE *fp = NULL;
990 int index=0;
991 char iface[10]={'\0'};
992 char config_file[MAX_BUF_SIZE] = {0};
993
994
995 sprintf(acl_file_path,"/tmp/mac_filter.sh");
996
997 fp=fopen(acl_file_path,"w+");
developer30423732022-12-01 16:17:49 +0800998 if (fp == NULL) {
999 fprintf(stderr, "%s: failed to open file %s.\n", __func__, acl_file_path);
1000 return RETURN_ERR;
1001 }
developer06a01d92022-09-07 16:32:39 +08001002 sprintf(buf,"#!/bin/sh \n");
1003 fprintf(fp,"%s\n",buf);
1004
1005 system("chmod 0777 /tmp/mac_filter.sh");
1006
1007 for(index=0;index<=1;index++)
1008 {
1009 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
1010 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
1011 sprintf(buf,"syscfg get %dcountfilter",index);
1012 _syscmd(buf,count,sizeof(count));
1013 mac_entry=atoi(count);
1014
1015 sprintf(buf,"syscfg get %dblockall",index);
1016 _syscmd(buf,res,sizeof(res));
1017 block = atoi(res);
1018
1019 //Allow only those macs mentioned in ACL
1020 if(block==1)
1021 {
1022 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1023 fprintf(fp,"%s\n",buf);
1024 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1025 {
1026 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1027 _syscmd(buf,tmp,sizeof(tmp));
1028 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
1029 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
1030 fprintf(fp,"%s\n",buf);
1031 }
1032 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
1033 fprintf(fp,"%s\n",buf);
1034 }
1035
1036 //Block all the macs mentioned in ACL
1037 else if(block==2)
1038 {
1039 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1040 fprintf(fp,"%s\n",buf);
1041
1042 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1043 {
1044 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1045 _syscmd(buf,tmp,sizeof(tmp));
1046 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
1047 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
1048 fprintf(fp,"%s\n",buf);
1049 }
1050 }
1051 }
1052 fclose(fp);
1053}
1054
1055// Initializes the wifi subsystem (all radios)
1056INT wifi_init() //RDKB
1057{
1058 char interface[MAX_BUF_SIZE]={'\0'};
1059 char bridge_name[MAX_BUF_SIZE]={'\0'};
1060 INT len=0;
1061
1062 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1063 //Not intitializing macfilter for Turris-Omnia Platform for now
1064 //macfilter_init();
1065
1066 system("/usr/sbin/iw reg set US");
developerac6f1142022-12-20 19:26:35 +08001067 // system("systemctl start hostapd.service");
developer06a01d92022-09-07 16:32:39 +08001068 sleep(2);//sleep to wait for hostapd to start
1069
1070 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1071
1072 return RETURN_OK;
1073}
1074
1075/* wifi_reset() function */
1076/**
1077* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
1078* Implementation specifics may dictate what is actualy reset since
1079* different hardware implementations may have different requirements.
1080* Parameters : None
1081*
1082* @return The status of the operation.
1083* @retval RETURN_OK if successful.
1084* @retval RETURN_ERR if any error is detected
1085*
1086* @execution Synchronous.
1087* @sideeffect None.
1088*
1089* @note This function must not suspend and must not invoke any blocking system
1090* calls. It should probably just send a message to a driver event handler task.
1091*
1092*/
1093INT wifi_reset()
1094{
1095 //TODO: resets the wifi subsystem, deletes all APs
developerb222b212022-09-13 14:01:01 +08001096 system("systemctl stop hostapd.service");
1097 sleep(2);
1098 system("systemctl start hostapd.service");
1099 sleep(5);
developer06a01d92022-09-07 16:32:39 +08001100 return RETURN_OK;
1101}
1102
1103/* wifi_down() function */
1104/**
1105* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
1106* Implementation specifics may dictate some functionality since
1107* different hardware implementations may have different requirements.
1108*
1109* @param None
1110*
1111* @return The status of the operation
1112* @retval RETURN_OK if successful
1113* @retval RETURN_ERR if any error is detected
1114*
1115* @execution Synchronous
1116* @sideeffect None
1117*
1118* @note This function must not suspend and must not invoke any blocking system
1119* calls. It should probably just send a message to a driver event handler task.
1120*
1121*/
1122INT wifi_down()
1123{
1124 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developer72ec5572023-01-05 16:27:13 +08001125 int max_num_radios = 0;
1126 wifi_getMaxRadioNumber(&max_num_radios);
1127 for (int radioIndex = 0; radioIndex < max_num_radios; radioIndex++)
1128 wifi_setRadioEnable(radioIndex, FALSE);
1129
developer06a01d92022-09-07 16:32:39 +08001130 return RETURN_OK;
1131}
1132
1133
1134/* wifi_createInitialConfigFiles() function */
1135/**
1136* @description This function creates wifi configuration files. The format
1137* and content of these files are implementation dependent. This function call is
1138* used to trigger this task if necessary. Some implementations may not need this
1139* function. If an implementation does not need to create config files the function call can
1140* do nothing and return RETURN_OK.
1141*
1142* @param None
1143*
1144* @return The status of the operation
1145* @retval RETURN_OK if successful
1146* @retval RETURN_ERR if any error is detected
1147*
1148* @execution Synchronous
1149* @sideeffect None
1150*
1151* @note This function must not suspend and must not invoke any blocking system
1152* calls. It should probably just send a message to a driver event handler task.
1153*
1154*/
1155INT wifi_createInitialConfigFiles()
1156{
1157 //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)
1158 return RETURN_OK;
1159}
1160
1161// outputs the country code to a max 64 character string
1162INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1163{
developerd946fd62022-12-08 18:03:28 +08001164 char interface_name[16] = {0};
developer7543b3b2022-09-13 13:47:17 +08001165 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer804c64f2022-10-19 13:54:40 +08001166 if(!output_string || (radioIndex >= MAX_NUM_RADIOS))
developer06a01d92022-09-07 16:32:39 +08001167 return RETURN_ERR;
developer7543b3b2022-09-13 13:47:17 +08001168
developerac6f1142022-12-20 19:26:35 +08001169 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08001170 return RETURN_ERR;
1171 sprintf(cmd,"hostapd_cli -i %s status driver | grep country | cut -d '=' -f2", interface_name);
developer7543b3b2022-09-13 13:47:17 +08001172 _syscmd(cmd, buf, sizeof(buf));
1173 if(strlen(buf) > 0)
1174 snprintf(output_string, 64, "%s", buf);
1175 else
1176 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001177
1178 return RETURN_OK;
1179}
1180
1181INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1182{
1183 //Set wifi config. Wait for wifi reset to apply
developer7543b3b2022-09-13 13:47:17 +08001184 char str[MAX_BUF_SIZE]={'\0'};
1185 char cmd[MAX_CMD_SIZE]={'\0'};
1186 struct params params;
1187 char config_file[MAX_BUF_SIZE] = {0};
1188
1189 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1190 if(NULL == CountryCode || strlen(CountryCode) >= 32 )
1191 return RETURN_ERR;
1192
developerb86c6f32022-10-07 14:34:58 +08001193 if (strlen(CountryCode) == 0)
1194 strcpy(CountryCode, "US");
1195
developer7543b3b2022-09-13 13:47:17 +08001196 params.name = "country_code";
1197 params.value = CountryCode;
1198 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, radioIndex);
1199 int ret = wifi_hostapdWrite(config_file, &params, 1);
1200 if (ret) {
1201 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
1202 ,__func__, ret);
1203 }
1204
1205 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1206 if (ret) {
1207 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
1208 ,__func__, ret);
1209 }
developer7543b3b2022-09-13 13:47:17 +08001210 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1211
developer06a01d92022-09-07 16:32:39 +08001212 return RETURN_OK;
1213}
1214
developera748dcf2022-09-13 15:56:48 +08001215INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1216{
developerd946fd62022-12-08 18:03:28 +08001217 char interface_name[16] = {0};
developera748dcf2022-09-13 15:56:48 +08001218 char channel_util_file[64] = {0};
1219 char cmd[128] = {0};
1220 char buf[128] = {0};
1221 char line[128] = {0};
1222 char *param = NULL, *value = NULL;
1223 int read = 0;
1224 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1225 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1226 size_t len = 0;
1227 FILE *f = NULL;
1228
1229 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1230
developerac6f1142022-12-20 19:26:35 +08001231 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08001232 return RETURN_ERR;
1233 snprintf(cmd, sizeof(cmd), "iw %s scan | grep signal | awk '{print $2}' | sort -n | tail -n1", interface_name);
developera748dcf2022-09-13 15:56:48 +08001234 _syscmd(cmd, buf, sizeof(buf));
1235 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1236
1237 memset(cmd, 0, sizeof(cmd));
1238 memset(buf, 0, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +08001239 snprintf(cmd, sizeof(cmd), "iw %s survey dump | grep 'in use' -A6", interface_name);
developera748dcf2022-09-13 15:56:48 +08001240 if ((f = popen(cmd, "r")) == NULL) {
1241 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1242 return RETURN_ERR;
1243 }
1244
1245 read = getline(&line, &len, f);
1246 while (read != -1) {
1247 param = strtok(line, ":\t");
1248 value = strtok(NULL, " ");
1249 if(strstr(param, "frequency") != NULL) {
1250 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1251 }
1252 if(strstr(param, "noise") != NULL) {
1253 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1254 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1255 }
1256 if(strstr(param, "channel active time") != NULL) {
1257 ActiveTime = strtol(value, NULL, 10);
1258 }
1259 if(strstr(param, "channel busy time") != NULL) {
1260 BusyTime = strtol(value, NULL, 10);
1261 }
1262 if(strstr(param, "channel transmit time") != NULL) {
1263 TransmitTime = strtol(value, NULL, 10);
1264 }
1265 read = getline(&line, &len, f);
1266 }
1267 pclose(f);
1268
1269 // The file should store the last active, busy and transmit time
1270 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1271 f = fopen(channel_util_file, "r");
1272 if (f != NULL) {
1273 read = getline(&line, &len, f);
1274 preActiveTime = strtol(line, NULL, 10);
1275 read = getline(&line, &len, f);
1276 preBusyTime = strtol(line, NULL, 10);
1277 read = getline(&line, &len, f);
1278 preTransmitTime = strtol(line, NULL, 10);
1279 fclose(f);
1280 }
1281
1282 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1283 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1284
1285 f = fopen(channel_util_file, "w");
1286 if (f != NULL) {
1287 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1288 fclose(f);
1289 }
1290 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1291 return RETURN_OK;
1292}
1293
developer06a01d92022-09-07 16:32:39 +08001294/**********************************************************************************
1295 *
1296 * Wifi radio level function prototypes
1297 *
1298**********************************************************************************/
1299
1300//Get the total number of radios in this wifi subsystem
1301INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1302{
1303 if (NULL == output)
1304 return RETURN_ERR;
developer6372c2b2022-10-27 17:39:51 +08001305 *output = MAX_NUM_RADIOS;
developer06a01d92022-09-07 16:32:39 +08001306
1307 return RETURN_OK;
1308}
1309
1310//Get the total number of SSID entries in this wifi subsystem
1311INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1312{
1313 if (NULL == output)
1314 return RETURN_ERR;
1315 *output = MAX_APS;
1316
1317 return RETURN_OK;
1318}
1319
1320//Get the Radio enable config parameter
1321INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1322{
developerd946fd62022-12-08 18:03:28 +08001323 char interface_name[16] = {0};
developer7930d352022-12-21 17:55:42 +08001324 char buf[128] = {0}, cmd[128] = {0};
developera77d84b2023-02-22 16:10:50 +08001325 int apIndex;
1326 int max_radio_num = 0;
developer06a01d92022-09-07 16:32:39 +08001327
1328 if (NULL == output_bool)
1329 return RETURN_ERR;
1330
1331 *output_bool = FALSE;
developera77d84b2023-02-22 16:10:50 +08001332
1333 wifi_getMaxRadioNumber(&max_radio_num);
1334
1335 if (radioIndex >= max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001336 return RETURN_ERR;
1337
developera77d84b2023-02-22 16:10:50 +08001338 /* loop all interface in radio, if any is enable, reture true, else return false */
1339 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
1340 {
developer643b28f2023-04-04 10:26:01 +08001341 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developera77d84b2023-02-22 16:10:50 +08001342 continue;
1343 sprintf(cmd, "hostapd_cli -i %s status | grep state | cut -d '=' -f2", interface_name);
1344 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08001345
developera77d84b2023-02-22 16:10:50 +08001346 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 ||
1347 strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0) {
1348 /* return true if any interface is eanble */
1349 *output_bool = TRUE;
1350 break;
1351 }
1352 }
developer06a01d92022-09-07 16:32:39 +08001353 return RETURN_OK;
1354}
1355
1356INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1357{
developerd946fd62022-12-08 18:03:28 +08001358 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08001359 char cmd[MAX_CMD_SIZE] = {0};
1360 char buf[MAX_CMD_SIZE] = {0};
1361 int apIndex, ret;
developer033b37b2022-10-18 11:27:46 +08001362 int max_radio_num = 0;
1363 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08001364
1365 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer033b37b2022-10-18 11:27:46 +08001366
1367 phyId = radio_index_to_phy(radioIndex);
1368
1369 wifi_getMaxRadioNumber(&max_radio_num);
1370
developer06a01d92022-09-07 16:32:39 +08001371 if(enable==FALSE)
1372 {
developera77d84b2023-02-22 16:10:50 +08001373 /* disable from max apindex to min, to avoid fail in mbss case */
1374 for(apIndex=(MAX_APS-max_radio_num+radioIndex); apIndex>=0; apIndex-=max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001375 {
developer1e125222022-12-29 09:35:25 +08001376 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72ec5572023-01-05 16:27:13 +08001377 continue;
developer1e125222022-12-29 09:35:25 +08001378
developer06a01d92022-09-07 16:32:39 +08001379 //Detaching %s%d from hostapd daemon
developerd946fd62022-12-08 18:03:28 +08001380 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08001381 _syscmd(cmd, buf, sizeof(buf));
1382 if(strncmp(buf, "OK", 2))
developerd946fd62022-12-08 18:03:28 +08001383 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
developer1e125222022-12-29 09:35:25 +08001384
developer2f18b9f2023-03-17 19:32:57 +08001385 if (!(apIndex/max_radio_num)) {
1386 snprintf(cmd, sizeof(cmd), "iw %s del", interface_name);
1387 _syscmd(cmd, buf, sizeof(buf));
1388 }
developer06a01d92022-09-07 16:32:39 +08001389 }
developer06a01d92022-09-07 16:32:39 +08001390 }
1391 else
1392 {
developer033b37b2022-10-18 11:27:46 +08001393 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001394 {
developer1e125222022-12-29 09:35:25 +08001395 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72ec5572023-01-05 16:27:13 +08001396 continue;
developer1e125222022-12-29 09:35:25 +08001397
developer643b28f2023-04-04 10:26:01 +08001398 snprintf(cmd, sizeof(cmd), "cat %s | grep %s= | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
developer06a01d92022-09-07 16:32:39 +08001399 _syscmd(cmd, buf, sizeof(buf));
developera77d84b2023-02-22 16:10:50 +08001400 if(*buf == '1') {
developer2f18b9f2023-03-17 19:32:57 +08001401 if (!(apIndex/max_radio_num)) {
1402 snprintf(cmd, sizeof(cmd), "iw phy%d interface add %s type __ap", phyId, interface_name);
1403 ret = _syscmd(cmd, buf, sizeof(buf));
1404 if ( ret == RETURN_ERR) {
1405 fprintf(stderr, "VAP interface creation failed\n");
1406 continue;
1407 }
developera77d84b2023-02-22 16:10:50 +08001408 }
developer06a01d92022-09-07 16:32:39 +08001409 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
developer439baa32024-05-02 15:54:58 +08001410 single_wiphy ? radioIndex : phyId, apIndex);
developer06a01d92022-09-07 16:32:39 +08001411 _syscmd(cmd, buf, sizeof(buf));
1412 if(strncmp(buf, "OK", 2))
developerd946fd62022-12-08 18:03:28 +08001413 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
developer06a01d92022-09-07 16:32:39 +08001414 }
1415 }
1416 }
1417
1418 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1419 return RETURN_OK;
1420}
1421
1422//Get the Radio enable status
1423INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1424{
1425 if (NULL == output_bool)
1426 return RETURN_ERR;
1427
1428 return wifi_getRadioEnable(radioIndex, output_bool);
1429}
1430
1431//Get the Radio Interface name from platform, eg "wlan0"
1432INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1433{
developer804c64f2022-10-19 13:54:40 +08001434 if (NULL == output_string || radioIndex>=MAX_NUM_RADIOS || radioIndex<0)
developer06a01d92022-09-07 16:32:39 +08001435 return RETURN_ERR;
developer7930d352022-12-21 17:55:42 +08001436 return wifi_GetInterfaceName(radioIndex, output_string);
developer06a01d92022-09-07 16:32:39 +08001437}
1438
1439//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1440//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.
1441INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1442{
developerbcc556a2022-09-22 20:02:45 +08001443 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
1444 // For max bit rate, we should always choose the best MCS
1445 char mode[64] = {0};
developerdbbd6782022-12-16 14:26:20 +08001446 char channel_bandwidth_str[64] = {0};
developerbcc556a2022-09-22 20:02:45 +08001447 char *tmp = NULL;
1448 UINT mode_map = 0;
1449 UINT num_subcarrier = 0;
1450 UINT code_bits = 0;
1451 float code_rate = 0; // use max code rate
1452 int NSS = 0;
1453 UINT Symbol_duration = 0;
1454 UINT GI_duration = 0;
1455 wifi_band band = band_invalid;
1456 wifi_guard_interval_t gi = wifi_guard_interval_auto;
1457 BOOL enable = FALSE;
1458 float bit_rate = 0;
developer06a01d92022-09-07 16:32:39 +08001459
1460 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1461 if (NULL == output_string)
1462 return RETURN_ERR;
1463
developerbcc556a2022-09-22 20:02:45 +08001464 wifi_getRadioEnable(radioIndex, &enable);
1465 if (enable == FALSE) {
1466 snprintf(output_string, 64, "0 Mb/s");
1467 return RETURN_OK;
1468 }
1469
1470 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
1471 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
1472 return RETURN_ERR;
1473 }
1474
1475 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
1476 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
1477 return RETURN_ERR;
1478 }
1479
1480 if (gi == wifi_guard_interval_3200)
1481 GI_duration = 32;
1482 else if (gi == wifi_guard_interval_1600)
1483 GI_duration = 16;
1484 else if (gi == wifi_guard_interval_800)
1485 GI_duration = 8;
1486 else // auto, 400
1487 GI_duration = 4;
developer06a01d92022-09-07 16:32:39 +08001488
developerbcc556a2022-09-22 20:02:45 +08001489 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
1490 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
1491 return RETURN_ERR;
1492 }
1493
1494 if (strstr(channel_bandwidth_str, "80+80") != NULL)
1495 strcpy(channel_bandwidth_str, "160");
1496
1497 if (mode_map & WIFI_MODE_AX) {
1498 if (strstr(channel_bandwidth_str, "160") != NULL)
1499 num_subcarrier = 1960;
1500 else if (strstr(channel_bandwidth_str, "80") != NULL)
1501 num_subcarrier = 980;
1502 else if (strstr(channel_bandwidth_str, "40") != NULL)
1503 num_subcarrier = 468;
1504 else if (strstr(channel_bandwidth_str, "20") != NULL)
1505 num_subcarrier = 234;
1506 code_bits = 10;
1507 code_rate = (float)5/6;
1508 Symbol_duration = 128;
1509 } else if (mode_map & WIFI_MODE_AC) {
1510 if (strstr(channel_bandwidth_str, "160") != NULL)
1511 num_subcarrier = 468;
1512 else if (strstr(channel_bandwidth_str, "80") != NULL)
1513 num_subcarrier = 234;
1514 else if (strstr(channel_bandwidth_str, "40") != NULL)
1515 num_subcarrier = 108;
1516 else if (strstr(channel_bandwidth_str, "20") != NULL)
1517 num_subcarrier = 52;
1518 code_bits = 8;
1519 code_rate = (float)5/6;
1520 Symbol_duration = 32;
1521 } else if (mode_map & WIFI_MODE_N) {
1522 if (strstr(channel_bandwidth_str, "160") != NULL)
1523 num_subcarrier = 468;
1524 else if (strstr(channel_bandwidth_str, "80") != NULL)
1525 num_subcarrier = 234;
1526 else if (strstr(channel_bandwidth_str, "40") != NULL)
1527 num_subcarrier = 108;
1528 else if (strstr(channel_bandwidth_str, "20") != NULL)
1529 num_subcarrier = 52;
1530 code_bits = 6;
1531 code_rate = (float)3/4;
1532 Symbol_duration = 32;
1533 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
1534 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
1535 snprintf(output_string, 64, "65 Mb/s");
1536 return RETURN_OK;
1537 } else {
1538 snprintf(output_string, 64, "0 Mb/s");
1539 return RETURN_OK;
1540 }
developer06a01d92022-09-07 16:32:39 +08001541
developerbcc556a2022-09-22 20:02:45 +08001542 // Spatial streams
1543 if (wifi_getRadioTxChainMask(radioIndex, &NSS) != RETURN_OK) {
1544 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
1545 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001546 }
developerbcc556a2022-09-22 20:02:45 +08001547
1548 // multiple 10 is to align duration unit (0.1 us)
1549 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
1550 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
1551
developer06a01d92022-09-07 16:32:39 +08001552 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1553
1554 return RETURN_OK;
1555}
1556#if 0
1557INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1558{
1559 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1560 char cmd[64];
1561 char buf[1024];
1562 int apIndex;
1563
1564 if (NULL == output_string)
1565 return RETURN_ERR;
1566
1567 apIndex=(radioIndex==0)?0:1;
1568
developerd946fd62022-12-08 18:03:28 +08001569 snprintf(cmd, sizeof(cmd), "iwconfig %s | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", interface_name);
developer06a01d92022-09-07 16:32:39 +08001570 _syscmd(cmd,buf, sizeof(buf));
1571
1572 snprintf(output_string, 64, "%s", buf);
1573 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1574 return RETURN_OK;
1575}
1576#endif
1577
1578
1579//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
1580//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.
1581INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
1582{
developer963da0c2022-09-13 15:58:27 +08001583 wifi_band band = band_invalid;
1584
developer06a01d92022-09-07 16:32:39 +08001585 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1586 if (NULL == output_string)
1587 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001588
1589 band = wifi_index_to_band(radioIndex);
1590
1591 memset(output_string, 0, 10);
1592 if (band == band_2_4)
1593 strcpy(output_string, "2.4GHz");
1594 else if (band == band_5)
1595 strcpy(output_string, "5GHz");
1596 else if (band == band_6)
1597 strcpy(output_string, "6GHz");
1598 else
1599 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001600 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1601
1602 return RETURN_OK;
1603#if 0
1604 char buf[MAX_BUF_SIZE]={'\0'};
1605 char str[MAX_BUF_SIZE]={'\0'};
1606 char cmd[MAX_CMD_SIZE]={'\0'};
1607 char *ch=NULL;
1608 char *ch2=NULL;
1609
1610 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1611 if (NULL == output_string)
1612 return RETURN_ERR;
1613
1614
1615 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1616
1617 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1618 {
1619 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1620 return RETURN_ERR;
1621 }
1622 ch=strchr(buf,'\n');
1623 *ch='\0';
1624 ch=strchr(buf,'=');
1625 if(ch==NULL)
1626 return RETURN_ERR;
1627
1628
1629 ch++;
1630
1631 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
1632 strcpy(buf,"0");
1633 if(strlen(ch) == 1)
1634 ch=strcat(buf,ch);
1635
1636
1637 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1638
1639 if(_syscmd(cmd,str,64) == RETURN_ERR)
1640 {
1641 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1642 return RETURN_ERR;
1643 }
1644
1645
1646 ch2=strchr(str,'\n');
1647 //replace \n with \0
1648 *ch2='\0';
1649 ch2=strchr(str,'=');
1650 if(ch2==NULL)
1651 {
1652 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1653 return RETURN_ERR;
1654 }
1655 else
1656 wifi_dbg_printf("%s",ch2+1);
1657
1658
1659 ch2++;
1660
1661
1662 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
1663
1664 memset(buf,'\0',sizeof(buf));
1665 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1666 {
1667 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1668 return RETURN_ERR;
1669 }
1670 if (strstr(buf,"2.4") != NULL )
1671 strcpy(output_string,"2.4GHz");
1672 else if(strstr(buf,"5.") != NULL )
1673 strcpy(output_string,"5GHz");
1674 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1675
1676 return RETURN_OK;
1677#endif
1678}
1679
1680//Get the frequency band at which the radio is operating, eg: "2.4GHz"
1681//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.
1682INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
1683{
developerb7593de2022-10-18 09:51:57 +08001684 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +08001685 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1686 if (NULL == output_string)
1687 return RETURN_ERR;
developerb7593de2022-10-18 09:51:57 +08001688 band = wifi_index_to_band(radioIndex);
1689
1690 if (band == band_2_4)
1691 snprintf(output_string, 64, "2.4GHz");
1692 else if (band == band_5)
1693 snprintf(output_string, 64, "5GHz");
1694 else if (band == band_6)
1695 snprintf(output_string, 64, "6GHz");
1696
developer06a01d92022-09-07 16:32:39 +08001697 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1698
1699 return RETURN_OK;
1700#if 0
1701 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1702 char buf[MAX_BUF_SIZE]={'\0'};
1703 char str[MAX_BUF_SIZE]={'\0'};
1704 char cmd[MAX_CMD_SIZE]={'\0'};
1705 char *ch=NULL;
1706 char *ch2=NULL;
1707 char ch1[5]="0";
1708
1709 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1710
1711 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1712 {
1713 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1714 return RETURN_ERR;
1715 }
1716
1717 ch=strchr(buf,'\n');
1718 *ch='\0';
1719 ch=strchr(buf,'=');
1720 if(ch==NULL)
1721 return RETURN_ERR;
1722 ch++;
1723
1724 if(strlen(ch)==1)
1725 {
1726 strcat(ch1,ch);
1727
1728 }
1729 else
1730 {
1731 strcpy(ch1,ch);
1732 }
1733
1734
1735
1736 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1737 if(_syscmd(cmd,str,64) == RETURN_ERR)
1738 {
1739 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1740 return RETURN_ERR;
1741 }
1742
1743
1744 ch2=strchr(str,'\n');
1745 //replace \n with \0
1746 *ch2='\0';
1747 ch2=strchr(str,'=');
1748 if(ch2==NULL)
1749 {
1750 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1751 return RETURN_ERR;
1752 }
1753 else
1754 wifi_dbg_printf("%s",ch2+1);
1755 ch2++;
1756
1757
1758 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
1759 memset(buf,'\0',sizeof(buf));
1760 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1761 {
1762 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1763 return RETURN_ERR;
1764 }
1765
1766
1767 if(strstr(buf,"2.4")!=NULL)
1768 {
1769 strcpy(output_string,"2.4GHz");
1770 }
1771 if(strstr(buf,"5.")!=NULL)
1772 {
1773 strcpy(output_string,"5GHz");
1774 }
1775 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1776 return RETURN_OK;
1777#endif
1778}
1779
1780//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
1781//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.
1782INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
1783{
developerc648f522024-05-07 16:09:35 +08001784 char cmd[256]={0};
developer963da0c2022-09-13 15:58:27 +08001785 char buf[128]={0};
1786 char temp_output[128] = {0};
1787 wifi_band band;
developere7c287f2024-05-07 10:36:38 +08001788 int phyId = 0, band_remap = 0, range_remap = 0;;
developer963da0c2022-09-13 15:58:27 +08001789
1790 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developere7c287f2024-05-07 10:36:38 +08001791 if (NULL == output_string)
developer06a01d92022-09-07 16:32:39 +08001792 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001793
1794 band = wifi_index_to_band(radioIndex);
developere7c287f2024-05-07 10:36:38 +08001795 switch (band) {
1796 case band_2_4:
1797 band_remap = 1;
1798 range_remap = 2;
1799 strcat(temp_output, "b,g,");
1800 break;
1801 case band_5:
1802 band_remap = 2;
1803 range_remap = 4;
1804 strcat(temp_output, "a,");
1805 break;
1806 case band_6:
1807 band_remap = 4;
1808 range_remap = 4;
1809 break;
developer963da0c2022-09-13 15:58:27 +08001810 }
developer033b37b2022-10-18 11:27:46 +08001811 phyId = radio_index_to_phy(radioIndex);
developer963da0c2022-09-13 15:58:27 +08001812 // ht capabilities
developere7c287f2024-05-07 10:36:38 +08001813 snprintf(cmd, sizeof(cmd),
1814 "iw phy%d info | grep 'Band \\|[^PHY|MAC|VHT].Capabilities' | sed -n '/Band %d/,/Band %d/{/Band %d/n;/Band %d/b;p}' | head -n 1 | cut -d ':' -f2 | sed 's/^.//' | tr -d '\\n'",
1815 phyId, band_remap, range_remap, band_remap, range_remap);
developer963da0c2022-09-13 15:58:27 +08001816 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001817 if (strlen(buf) >= 4 && strncmp(buf, "0x00", 4) != 0) {
developer963da0c2022-09-13 15:58:27 +08001818 strcat(temp_output, "n,");
1819 }
developer06a01d92022-09-07 16:32:39 +08001820
developer963da0c2022-09-13 15:58:27 +08001821 // vht capabilities
1822 if (band == band_5) {
developere7c287f2024-05-07 10:36:38 +08001823 snprintf(cmd, sizeof(cmd),
1824 "iw phy%d info | grep 'Band \\|VHT Capabilities' | sed -n '/Band %d/,/Band %d/{/Band %d/n;/Band %d/b;p}' | cut -d '(' -f2 | cut -c1-10 | tr -d '\\n'",
1825 phyId, band_remap, range_remap, band_remap, range_remap);
developer963da0c2022-09-13 15:58:27 +08001826 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001827 if (strlen(buf) >= 10 && strncmp(buf, "0x00000000", 10) != 0) {
developer963da0c2022-09-13 15:58:27 +08001828 strcat(temp_output, "ac,");
1829 }
1830 }
1831
1832 // he capabilities
developere7c287f2024-05-07 10:36:38 +08001833 snprintf(cmd, sizeof(cmd),
1834 "iw phy%d info | grep 'Band \\|HE MAC Capabilities' | sed -n '/Band %d/,/Band %d/{/Band %d/n;/Band %d/b;p}' | head -n 2 | tail -n 1 | cut -d '(' -f2 | cut -c1-6 | tr -d '\\n'",
1835 phyId, band_remap, range_remap, band_remap, range_remap);
developer963da0c2022-09-13 15:58:27 +08001836 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001837 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
developer963da0c2022-09-13 15:58:27 +08001838 strcat(temp_output, "ax,");
1839 }
1840
developer7c4cd202023-03-01 10:56:29 +08001841 // eht capabilities
developere7c287f2024-05-07 10:36:38 +08001842 snprintf(cmd, sizeof(cmd),
1843 "iw phy%d info | grep 'Band \\|EHT MAC Capabilities' | sed -n '/Band %d/,/Band %d/{/Band %d/n;/Band %d/b;p}' | head -n 2 | tail -n 1 | cut -d '(' -f2 | cut -c1-6 | tr -d '\\n'",
1844 phyId, band_remap, range_remap, band_remap, range_remap);
developer7c4cd202023-03-01 10:56:29 +08001845 _syscmd(cmd, buf, sizeof(buf));
1846 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
1847 strcat(temp_output, "be,");
1848 }
1849
developer963da0c2022-09-13 15:58:27 +08001850 // Remove the last comma
1851 if (strlen(temp_output) != 0)
1852 temp_output[strlen(temp_output)-1] = '\0';
1853 strncpy(output_string, temp_output, strlen(temp_output));
1854 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001855 return RETURN_OK;
1856}
1857
1858//Get the radio operating mode, and pure mode flag. eg: "ac"
1859//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.
1860INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
1861{
1862 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1863 if (NULL == output_string)
1864 return RETURN_ERR;
1865
1866 if (radioIndex == 0) {
1867 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
1868 *gOnly = FALSE;
1869 *nOnly = TRUE;
1870 *acOnly = FALSE;
1871 } else {
1872 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
1873 *gOnly = FALSE;
1874 *nOnly = FALSE;
1875 *acOnly = FALSE;
1876 }
1877 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1878
1879 return RETURN_OK;
1880#if 0
1881 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1882 char buf[64] = {0};
1883 char config_file[MAX_BUF_SIZE] = {0};
1884
1885 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
1886 return RETURN_ERR;
1887
1888 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1889 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
1890
1891 wifi_dbg_printf("\nhw_mode=%s\n",buf);
1892 if (strlen(buf) == 0)
1893 {
1894 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
1895 return RETURN_ERR;
1896 }
1897 if(strcmp(buf,"g")==0)
1898 {
1899 wifi_dbg_printf("\nG\n");
1900 *gOnly=TRUE;
1901 *nOnly=FALSE;
1902 *acOnly=FALSE;
1903 }
1904 else if(strcmp(buf,"n")==0)
1905 {
1906 wifi_dbg_printf("\nN\n");
1907 *gOnly=FALSE;
1908 *nOnly=TRUE;
1909 *acOnly=FALSE;
1910 }
1911 else if(strcmp(buf,"ac")==0)
1912 {
1913 wifi_dbg_printf("\nac\n");
1914 *gOnly=FALSE;
1915 *nOnly=FALSE;
1916 *acOnly=TRUE;
1917 }
1918 /* hostapd-5G.conf has "a" as hw_mode */
1919 else if(strcmp(buf,"a")==0)
1920 {
1921 wifi_dbg_printf("\na\n");
1922 *gOnly=FALSE;
1923 *nOnly=FALSE;
1924 *acOnly=FALSE;
1925 }
1926 else
1927 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
1928
1929 //for a,n mode
1930 if(radioIndex == 1)
1931 {
1932 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
1933 if(strcmp(buf,"1")==0)
1934 {
1935 strncpy(output_string, "n", 1);
1936 *nOnly=FALSE;
1937 }
1938 }
1939
1940 wifi_dbg_printf("\nReturning from getRadioStandard\n");
1941 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1942 return RETURN_OK;
1943#endif
1944}
1945
developerdb744382022-09-13 15:34:54 +08001946INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
1947{
1948 char cmd[128] = {0};
1949 char buf[64] = {0};
1950 char config_file[64] = {0};
1951 wifi_band band;
1952
1953 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1954 if(NULL == output_string || NULL == pureMode)
1955 return RETURN_ERR;
1956
1957 // grep all of the ieee80211 protocol config set to 1
developer30423732022-12-01 16:17:49 +08001958 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer7c4cd202023-03-01 10:56:29 +08001959 snprintf(cmd, sizeof(cmd), "cat %s | grep -E \"ieee.*=1\" | cut -d '=' -f1 | sed \"s/ieee80211\\.*/\1/\"", config_file);
developerdb744382022-09-13 15:34:54 +08001960 _syscmd(cmd, buf, sizeof(buf));
1961
1962 band = wifi_index_to_band(radioIndex);
1963 // puremode is a bit map
1964 *pureMode = 0;
1965 if (band == band_2_4) {
1966 strcat(output_string, "b,g");
1967 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
1968 if (strstr(buf, "n") != NULL) {
1969 strcat(output_string, ",n");
1970 *pureMode |= WIFI_MODE_N;
1971 }
1972 if (strstr(buf, "ax") != NULL) {
1973 strcat(output_string, ",ax");
1974 *pureMode |= WIFI_MODE_AX;
1975 }
developer7c4cd202023-03-01 10:56:29 +08001976 if (strstr(buf, "be") != NULL) {
1977 strcat(output_string, ",be");
1978 *pureMode |= WIFI_MODE_BE;
1979 }
developerdb744382022-09-13 15:34:54 +08001980 } else if (band == band_5) {
1981 strcat(output_string, "a");
1982 *pureMode |= WIFI_MODE_A;
1983 if (strstr(buf, "n") != NULL) {
1984 strcat(output_string, ",n");
1985 *pureMode |= WIFI_MODE_N;
1986 }
1987 if (strstr(buf, "ac") != NULL) {
1988 strcat(output_string, ",ac");
1989 *pureMode |= WIFI_MODE_AC;
1990 }
1991 if (strstr(buf, "ax") != NULL) {
1992 strcat(output_string, ",ax");
1993 *pureMode |= WIFI_MODE_AX;
1994 }
developer7c4cd202023-03-01 10:56:29 +08001995 if (strstr(buf, "be") != NULL) {
1996 strcat(output_string, ",be");
1997 *pureMode |= WIFI_MODE_BE;
1998 }
developerdb744382022-09-13 15:34:54 +08001999 } else if (band == band_6) {
2000 if (strstr(buf, "ax") != NULL) {
2001 strcat(output_string, "ax");
2002 *pureMode |= WIFI_MODE_AX;
2003 }
developer7c4cd202023-03-01 10:56:29 +08002004 if (strstr(buf, "be") != NULL) {
2005 strcat(output_string, ",be");
2006 *pureMode |= WIFI_MODE_BE;
2007 }
developerdb744382022-09-13 15:34:54 +08002008 }
2009
2010 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2011 return RETURN_OK;
2012}
2013
2014// Set the radio operating mode, and pure mode flag.
developer06a01d92022-09-07 16:32:39 +08002015INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
2016{
2017 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
2018 if (strcmp (channelMode,"11A") == 0)
2019 {
2020 writeBandWidth(radioIndex,"20MHz");
2021 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2022 printf("\nChannel Mode is 802.11a (5GHz)\n");
2023 }
2024 else if (strcmp (channelMode,"11NAHT20") == 0)
2025 {
2026 writeBandWidth(radioIndex,"20MHz");
2027 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2028 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
2029 }
2030 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
2031 {
2032 writeBandWidth(radioIndex,"40MHz");
2033 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2034 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
2035 }
2036 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
2037 {
2038 writeBandWidth(radioIndex,"40MHz");
2039 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2040 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
2041 }
2042 else if (strcmp (channelMode,"11ACVHT20") == 0)
2043 {
2044 writeBandWidth(radioIndex,"20MHz");
2045 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2046 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
2047 }
2048 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
2049 {
2050 writeBandWidth(radioIndex,"40MHz");
2051 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2052 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2053 }
2054 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
2055 {
2056 writeBandWidth(radioIndex,"40MHz");
2057 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2058 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2059 }
2060 else if (strcmp (channelMode,"11ACVHT80") == 0)
2061 {
2062 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
2063 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
2064 }
2065 else if (strcmp (channelMode,"11ACVHT160") == 0)
2066 {
2067 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
2068 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
2069 }
2070 else if (strcmp (channelMode,"11B") == 0)
2071 {
2072 writeBandWidth(radioIndex,"20MHz");
2073 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2074 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
2075 }
2076 else if (strcmp (channelMode,"11G") == 0)
2077 {
2078 writeBandWidth(radioIndex,"20MHz");
2079 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2080 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
2081 }
2082 else if (strcmp (channelMode,"11NGHT20") == 0)
2083 {
2084 writeBandWidth(radioIndex,"20MHz");
2085 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2086 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
2087 }
2088 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
2089 {
2090 writeBandWidth(radioIndex,"40MHz");
2091 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2092 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2093 }
2094 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
2095 {
2096 writeBandWidth(radioIndex,"40MHz");
2097 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2098 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2099 }
2100 else
2101 {
2102 return RETURN_ERR;
2103 }
2104 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2105
2106 return RETURN_OK;
2107}
2108
developerdb744382022-09-13 15:34:54 +08002109// Set the radio operating mode, and pure mode flag.
2110INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
2111{
developer7c4cd202023-03-01 10:56:29 +08002112 int num_hostapd_support_mode = 4; // n, ac, ax, be
developerdb744382022-09-13 15:34:54 +08002113 struct params list[num_hostapd_support_mode];
2114 char config_file[64] = {0};
2115 char bandwidth[16] = {0};
developer7c4cd202023-03-01 10:56:29 +08002116 char supported_mode[32] = {0};
developerdb744382022-09-13 15:34:54 +08002117 int mode_check_bit = 1 << 3; // n mode
developer7c4cd202023-03-01 10:56:29 +08002118 bool eht_support = FALSE;
developerdb744382022-09-13 15:34:54 +08002119
2120 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
2121 // Set radio mode
2122 list[0].name = "ieee80211n";
2123 list[1].name = "ieee80211ac";
2124 list[2].name = "ieee80211ax";
developer7c4cd202023-03-01 10:56:29 +08002125 list[3].name = "ieee80211be";
developerdb744382022-09-13 15:34:54 +08002126 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2127
2128 // check the bit map from n to ax, and set hostapd config
developer517a9792022-10-05 19:37:42 +08002129 if (pureMode & WIFI_MODE_N)
developerdb744382022-09-13 15:34:54 +08002130 list[0].value = "1";
2131 else
2132 list[0].value = "0";
developer517a9792022-10-05 19:37:42 +08002133 if (pureMode & WIFI_MODE_AC)
developerdb744382022-09-13 15:34:54 +08002134 list[1].value = "1";
2135 else
2136 list[1].value = "0";
developer517a9792022-10-05 19:37:42 +08002137 if (pureMode & WIFI_MODE_AX)
developerdb744382022-09-13 15:34:54 +08002138 list[2].value = "1";
2139 else
2140 list[2].value = "0";
developer7c4cd202023-03-01 10:56:29 +08002141 if (pureMode & WIFI_MODE_BE)
2142 list[3].value = "1";
2143 else
2144 list[3].value = "0";
2145
2146 wifi_getRadioSupportedStandards(radioIndex, supported_mode);
2147 if (strstr(supported_mode, "be") != NULL)
2148 eht_support = TRUE;
2149
2150 if (eht_support)
2151 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
2152 else
2153 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode-1);
developerdb744382022-09-13 15:34:54 +08002154
2155 if (channelMode == NULL || strlen(channelMode) == 0)
2156 return RETURN_OK;
2157 // Set bandwidth
2158 if (strstr(channelMode, "40") != NULL)
2159 strcpy(bandwidth, "40MHz");
2160 else if (strstr(channelMode, "80") != NULL)
2161 strcpy(bandwidth, "80MHz");
2162 else if (strstr(channelMode, "160") != NULL)
2163 strcpy(bandwidth, "160MHz");
developer7c4cd202023-03-01 10:56:29 +08002164 else if (strstr(channelMode, "320") != NULL)
2165 strcpy(bandwidth, "320MHz");
developerdb744382022-09-13 15:34:54 +08002166 else // 11A, 11B, 11G....
2167 strcpy(bandwidth, "20MHz");
2168
2169 writeBandWidth(radioIndex, bandwidth);
2170 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
2171
2172 wifi_reloadAp(radioIndex);
2173 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2174
2175 return RETURN_OK;
2176}
2177
developer1d12ebf2022-10-04 15:13:38 +08002178INT wifi_setRadioHwMode(INT radioIndex, CHAR *hw_mode) {
2179
2180 char config_file[64] = {0};
developeref938762022-10-19 17:21:01 +08002181 char buf[64] = {0};
developer1d12ebf2022-10-04 15:13:38 +08002182 struct params params = {0};
2183 wifi_band band = band_invalid;
2184
2185 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2186
2187 band = wifi_index_to_band(radioIndex);
developerc9e88f32022-10-06 17:09:56 +08002188
2189 if (strncmp(hw_mode, "a", 1) == 0 && (band != band_5 && band != band_6))
developer1d12ebf2022-10-04 15:13:38 +08002190 return RETURN_ERR;
2191 else if ((strncmp(hw_mode, "b", 1) == 0 || strncmp(hw_mode, "g", 1) == 0) && band != band_2_4)
2192 return RETURN_ERR;
developerc9e88f32022-10-06 17:09:56 +08002193 else if ((strncmp(hw_mode, "a", 1) && strncmp(hw_mode, "b", 1) && strncmp(hw_mode, "g", 1)) || band == band_invalid)
2194 return RETURN_ERR;
developer1d12ebf2022-10-04 15:13:38 +08002195
2196 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2197 params.name = "hw_mode";
2198 params.value = hw_mode;
2199 wifi_hostapdWrite(config_file, &params, 1);
2200 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2201
developeref938762022-10-19 17:21:01 +08002202 if (band == band_2_4) {
2203 if (strncmp(hw_mode, "b", 1) == 0) {
2204 wifi_setRadioMode(radioIndex, "20MHz", WIFI_MODE_B);
2205 snprintf(buf, sizeof(buf), "%s", "1,2,5.5,11");
2206 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2207 snprintf(buf, sizeof(buf), "%s", "1,2");
2208 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2209 } else {
2210 // We don't set mode here, because we don't know whitch mode should be set (g, n or ax?).
2211
2212 snprintf(buf, sizeof(buf), "%s", "6,9,12,18,24,36,48,54");
2213 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2214 snprintf(buf, sizeof(buf), "%s", "6,12,24");
2215 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2216 }
2217 }
2218
developer1d12ebf2022-10-04 15:13:38 +08002219 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2220 return RETURN_OK;
2221}
2222
developere8988ba2022-10-18 17:42:30 +08002223INT wifi_setNoscan(INT radioIndex, CHAR *noscan)
2224{
2225 char config_file[64] = {0};
2226 struct params params = {0};
2227 wifi_band band = band_invalid;
2228
2229 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2230
2231 band = wifi_index_to_band(radioIndex);
2232
2233 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2234 params.name = "noscan";
2235 params.value = noscan;
2236 wifi_hostapdWrite(config_file, &params, 1);
2237 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2238
2239 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2240 return RETURN_OK;
2241}
2242
developer06a01d92022-09-07 16:32:39 +08002243//Get the list of supported channel. eg: "1-11"
2244//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.
2245INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2246{
developer6318ed52022-09-13 15:17:58 +08002247 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002248 if (NULL == output_string)
2249 return RETURN_ERR;
developer6318ed52022-09-13 15:17:58 +08002250 char cmd[256] = {0};
2251 char buf[128] = {0};
2252 BOOL dfs_enable = false;
developer63a1ef02024-05-03 16:59:38 +08002253 int phyId = 0, band_remap = 0, range_remap = 0;
2254 wifi_band band = band_invalid;
developer033b37b2022-10-18 11:27:46 +08002255
developer63a1ef02024-05-03 16:59:38 +08002256 band = wifi_index_to_band(radioIndex);
2257 switch (band) {
2258 case band_2_4:
2259 band_remap = 1;
2260 range_remap = 2;
2261 break;
2262 case band_5:
2263 band_remap = 2;
2264 range_remap = 4;
2265 break;
2266 case band_6:
2267 band_remap = 4;
2268 range_remap = 4;
2269 break;
2270 default:
2271 break;
2272 }
developer6318ed52022-09-13 15:17:58 +08002273 // Parse possible channel number and separate them with commas.
2274 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
developer033b37b2022-10-18 11:27:46 +08002275 phyId = radio_index_to_phy(radioIndex);
developer76989232022-10-04 14:13:19 +08002276 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
developer6318ed52022-09-13 15:17:58 +08002277 if (dfs_enable)
developer63a1ef02024-05-03 16:59:38 +08002278 snprintf(cmd, sizeof(cmd),
2279 "iw phy phy%d info | grep -e '\\*.*MHz .*dBm\\|Band ' | sed -n '/Band %d/,/Band %d/{/Band %d/n;/Band %d/b;p}' | grep -v 'no IR\\|5340\\|5480' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'",
2280 phyId, band_remap, range_remap, band_remap, range_remap);
developer6318ed52022-09-13 15:17:58 +08002281 else
developer63a1ef02024-05-03 16:59:38 +08002282 snprintf(cmd, sizeof(cmd),
2283 "iw phy phy%d info | grep -e '\\*.*MHz .*dBm\\|Band ' | sed -n '/Band %d/,/Band %d/{/Band %d/n;/Band %d/b;p}' | grep -v 'radar\\|no IR\\|5340\\|5480' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'",
2284 phyId, band_remap, range_remap, band_remap, range_remap);
developer6318ed52022-09-13 15:17:58 +08002285
2286 _syscmd(cmd,buf,sizeof(buf));
2287 strncpy(output_string, buf, sizeof(buf));
2288
2289 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2290 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002291}
2292
2293//Get the list for used channel. eg: "1,6,9,11"
2294//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.
2295INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2296{
developerd946fd62022-12-08 18:03:28 +08002297 char interface_name[16] = {0};
developerf5745ee2022-10-05 16:09:53 +08002298 char cmd[128] = {0};
2299 char buf[128] = {0};
2300 char config_file[64] = {0};
2301 int channel = 0;
2302 int freq = 0;
2303 int bandwidth = 0;
2304 int center_freq = 0;
2305 int center_channel = 0;
2306 int channel_delta = 0;
2307 wifi_band band = band_invalid;
2308
2309 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2310
developer06a01d92022-09-07 16:32:39 +08002311 if (NULL == output_string)
2312 return RETURN_ERR;
2313
developerac6f1142022-12-20 19:26:35 +08002314 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08002315 return RETURN_ERR;
2316 sprintf(cmd, "iw %s info | grep channel | sed -e 's/[^0-9 ]//g'", interface_name);
developerf5745ee2022-10-05 16:09:53 +08002317 _syscmd(cmd, buf, sizeof(buf));
2318 if (strlen(buf) == 0) {
2319 fprintf(stderr, "%s: failed to get channel information from iw.\n", __func__);
2320 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002321 }
developerf5745ee2022-10-05 16:09:53 +08002322 sscanf(buf, "%d %d %d %*d %d", &channel, &freq, &bandwidth, &center_freq);
2323
2324 if (bandwidth == 20) {
2325 snprintf(output_string, 256, "%d", channel);
2326 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002327 }
developerf5745ee2022-10-05 16:09:53 +08002328
2329 center_channel = ieee80211_frequency_to_channel(center_freq);
2330
2331 band = wifi_index_to_band(radioIndex);
2332 if (band == band_2_4 && bandwidth == 40) {
2333 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2334 memset(buf, 0, sizeof(buf));
2335 wifi_halgetRadioExtChannel(config_file, buf); // read ht_capab for HT40+ or -
2336
developerf22724d2022-12-22 17:24:14 +08002337 if (strncmp(buf, "AboveControlChannel", strlen("AboveControlChannel")) == 0 && channel < 10) {
developerf5745ee2022-10-05 16:09:53 +08002338 snprintf(output_string, 256, "%d,%d", channel, channel+4);
developerf22724d2022-12-22 17:24:14 +08002339 } else if (strncmp(buf, "BelowControlChannel", strlen("BelowControlChannel")) == 0 && channel > 4) {
developerf5745ee2022-10-05 16:09:53 +08002340 snprintf(output_string, 256, "%d,%d", channel-4, channel);
2341 } else {
2342 fprintf(stderr, "%s: invalid channel %d set with %s\n.", __func__, channel, buf);
2343 return RETURN_ERR;
2344 }
2345 } else if (band == band_5 || band == band_6){
2346 // to minus 20 is an offset, because frequence of a channel have a range. We need to use offset to calculate correct channel.
developer72ec5572023-01-05 16:27:13 +08002347 // example: bandwidth 80: center is 42 (5210), channels are "36,40,44,48" (5170-5250). The delta should be 6.
developerf5745ee2022-10-05 16:09:53 +08002348 channel_delta = (bandwidth-20)/10;
developer72ec5572023-01-05 16:27:13 +08002349 memset(output_string, 0, 256);
2350 for (int i = center_channel-channel_delta; i <= center_channel+channel_delta; i+=4) {
2351 // If i is not the last channel, we add a comma.
2352 snprintf(buf, sizeof(buf), "%d%s", i, i==center_channel+channel_delta?"":",");
2353 strncat(output_string, buf, strlen(buf));
2354 }
developerf5745ee2022-10-05 16:09:53 +08002355 } else
2356 return RETURN_ERR;
2357
2358 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002359 return RETURN_OK;
2360}
2361
2362//Get the running channel number
2363INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
2364{
developer5b398df2022-11-17 20:39:48 +08002365 char channel_str[16] = {0};
2366 char config_file[128] = {0};
developer06a01d92022-09-07 16:32:39 +08002367
developer5b398df2022-11-17 20:39:48 +08002368 if (output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002369 return RETURN_ERR;
2370
developer5b398df2022-11-17 20:39:48 +08002371 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2372 wifi_hostapdRead(config_file, "channel", channel_str, sizeof(channel_str));
developer06a01d92022-09-07 16:32:39 +08002373
developer5b398df2022-11-17 20:39:48 +08002374 *output_ulong = strtoul(channel_str, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08002375
developer06a01d92022-09-07 16:32:39 +08002376 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002377}
2378
2379
2380INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2381{
2382 char cmd[1024] = {0}, buf[5] = {0};
developerdbbd6782022-12-16 14:26:20 +08002383 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08002384
2385 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2386 if (NULL == output_ulong)
2387 return RETURN_ERR;
2388
developer06a01d92022-09-07 16:32:39 +08002389 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
developerdbbd6782022-12-16 14:26:20 +08002390 if (wifi_getApName(apIndex,interface_name) != RETURN_OK)
2391 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002392 _syscmd(cmd,buf,sizeof(buf));
2393 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2394 if (*output_ulong == 0) {
2395 return RETURN_ERR;
2396 }
2397
2398 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2399 return RETURN_OK;
2400}
2401
2402//Storing the previous channel value
2403INT wifi_storeprevchanval(INT radioIndex)
2404{
2405 char buf[256] = {0};
2406 char output[4]={'\0'};
2407 char config_file[MAX_BUF_SIZE] = {0};
2408 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2409 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2410 if(radioIndex == 0)
2411 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2412 else if(radioIndex == 1)
2413 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2414 system(buf);
2415 Radio_flag = FALSE;
2416 return RETURN_OK;
2417}
2418
2419//Set the running channel number
2420INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2421{
developer76989232022-10-04 14:13:19 +08002422 // We only write hostapd config here
2423 char str_channel[8]={0};
2424 char *list_channel;
2425 char config_file[128] = {0};
2426 char possible_channels[256] = {0};
2427 int max_radio_num = 0;
2428 struct params list = {0};
developer06a01d92022-09-07 16:32:39 +08002429
developer76989232022-10-04 14:13:19 +08002430 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002431
developer76989232022-10-04 14:13:19 +08002432 // Check valid
2433 sprintf(str_channel, "%lu", channel);
developer06a01d92022-09-07 16:32:39 +08002434
developer76989232022-10-04 14:13:19 +08002435 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
2436 list_channel = strtok(possible_channels, ",");
2437 while(true)
developer06a01d92022-09-07 16:32:39 +08002438 {
developer76989232022-10-04 14:13:19 +08002439 if(list_channel == NULL) { // input not in the list
2440 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
2441 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002442 }
developer76989232022-10-04 14:13:19 +08002443 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
2444 break;
2445 list_channel = strtok(NULL, ",");
developer06a01d92022-09-07 16:32:39 +08002446 }
2447
developer76989232022-10-04 14:13:19 +08002448 list.name = "channel";
2449 list.value = str_channel;
2450 wifi_getMaxRadioNumber(&max_radio_num);
2451 for(int i=0; i<=MAX_APS/max_radio_num;i++)
developer06a01d92022-09-07 16:32:39 +08002452 {
developer76989232022-10-04 14:13:19 +08002453 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2454 wifi_hostapdWrite(config_file, &list, 1);
developer06a01d92022-09-07 16:32:39 +08002455 }
2456
developer76989232022-10-04 14:13:19 +08002457 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002458 return RETURN_OK;
developer76989232022-10-04 14:13:19 +08002459}
developer06a01d92022-09-07 16:32:39 +08002460
2461INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2462{
developer7c4cd202023-03-01 10:56:29 +08002463 struct params list[3];
2464 char str_idx[16] = {0};
2465 char supported_mode[32] = {0};
2466 char config_file[64] = {0};
developer76989232022-10-04 14:13:19 +08002467 int max_num_radios = 0;
2468 wifi_band band = band_invalid;
developer7c4cd202023-03-01 10:56:29 +08002469 bool eht_support = FALSE;
developer76989232022-10-04 14:13:19 +08002470
2471 band = wifi_index_to_band(radioIndex);
2472 if (band == band_2_4)
2473 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002474
developer7c4cd202023-03-01 10:56:29 +08002475 wifi_getRadioSupportedStandards(radioIndex, supported_mode);
2476 if (strstr(supported_mode, "be") != NULL)
2477 eht_support = TRUE;
2478
developer30423732022-12-01 16:17:49 +08002479 snprintf(str_idx, sizeof(str_idx), "%lu", channel);
developer76989232022-10-04 14:13:19 +08002480 list[0].name = "vht_oper_centr_freq_seg0_idx";
2481 list[0].value = str_idx;
2482 list[1].name = "he_oper_centr_freq_seg0_idx";
2483 list[1].value = str_idx;
developer7c4cd202023-03-01 10:56:29 +08002484 list[2].name = "eht_oper_centr_freq_seg0_idx";
2485 list[2].value = str_idx;
developer06a01d92022-09-07 16:32:39 +08002486
developer76989232022-10-04 14:13:19 +08002487 wifi_getMaxRadioNumber(&max_num_radios);
2488 for(int i=0; i<=MAX_APS/max_num_radios; i++)
developer06a01d92022-09-07 16:32:39 +08002489 {
developer76989232022-10-04 14:13:19 +08002490 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
developer7c4cd202023-03-01 10:56:29 +08002491 if (eht_support)
2492 wifi_hostapdWrite(config_file, list, 3);
developer76989232022-10-04 14:13:19 +08002493 else
2494 wifi_hostapdWrite(config_file, list, 2);
developer06a01d92022-09-07 16:32:39 +08002495 }
2496
2497 return RETURN_OK;
2498}
2499
2500//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2501//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2502INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2503{
2504 //Set to wifi config only. Wait for wifi reset to apply.
2505 char buf[256] = {0};
2506 char str_channel[256] = {0};
2507 int count = 0;
2508 ULONG Value = 0;
2509 FILE *fp = NULL;
2510 if(enable == TRUE)
2511 {
developer06a01d92022-09-07 16:32:39 +08002512 wifi_setRadioChannel(radioIndex,Value);
developer06a01d92022-09-07 16:32:39 +08002513 }
developer5884e982022-10-06 10:52:50 +08002514 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002515}
2516
developer0b246d12022-09-30 15:24:20 +08002517INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
2518{
2519 if (output_bool == NULL)
2520 return RETURN_ERR;
2521
2522 *output_bool = TRUE;
2523
2524 return RETURN_OK;
2525}
2526
developer06a01d92022-09-07 16:32:39 +08002527INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2528{
2529 if (NULL == output_bool)
2530 return RETURN_ERR;
2531 *output_bool=FALSE;
2532 return RETURN_OK;
2533}
2534
2535INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2536{
2537 if (NULL == output_bool)
2538 return RETURN_ERR;
2539 *output_bool=FALSE;
2540 return RETURN_OK;
2541}
2542
2543INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2544{
2545 //Set to wifi config only. Wait for wifi reset to apply.
2546 return RETURN_OK;
2547}
2548
2549INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2550{
2551 return RETURN_OK;
2552}
2553
2554INT wifi_factoryResetAP(int apIndex)
2555{
developer838cca92022-10-03 13:19:57 +08002556 char ap_config_file[64] = {0};
2557 char cmd[128] = {0};
developer72ec5572023-01-05 16:27:13 +08002558 char buf[128] = {0};
developer89df4502023-02-16 20:45:02 +08002559 int max_radio_num = 0;
developer838cca92022-10-03 13:19:57 +08002560
developer06a01d92022-09-07 16:32:39 +08002561 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002562
2563 wifi_setApEnable(apIndex, FALSE);
2564 sprintf(ap_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
2565 sprintf(cmd, "rm %s && sh /lib/rdk/hostapd-init.sh", ap_config_file);
developer72ec5572023-01-05 16:27:13 +08002566 _syscmd(cmd, buf, sizeof(buf));
developer89df4502023-02-16 20:45:02 +08002567 wifi_getMaxRadioNumber(&max_radio_num);
2568 if (apIndex <= max_radio_num) // The ap is default radio interface, we should default up it.
2569 wifi_setApEnable(apIndex, TRUE);
developer838cca92022-10-03 13:19:57 +08002570
developer06a01d92022-09-07 16:32:39 +08002571 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002572
developer06a01d92022-09-07 16:32:39 +08002573 return RETURN_OK;
2574}
2575
2576//To set Band Steering AP group
2577//To-do
2578INT wifi_setBandSteeringApGroup(char *ApGroup)
2579{
2580 return RETURN_OK;
2581}
2582
developer1e5aa162022-09-13 16:06:24 +08002583INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2584{
2585 char config_file[128] = {'\0'};
2586 char buf[128] = {'\0'};
2587
2588 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2589 if (dtimInterval == NULL)
2590 return RETURN_ERR;
2591
2592 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2593 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2594
2595 if (strlen(buf) == 0) {
2596 *dtimInterval = 2;
2597 } else {
2598 *dtimInterval = strtoul(buf, NULL, 10);
2599 }
2600
2601 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2602 return RETURN_OK;
2603}
2604
developer06a01d92022-09-07 16:32:39 +08002605INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2606{
developer5f222492022-09-13 15:21:52 +08002607 struct params params={0};
2608 char config_file[MAX_BUF_SIZE] = {'\0'};
2609 char buf[MAX_BUF_SIZE] = {'\0'};
2610
2611 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2612 if (dtimInterval < 1 || dtimInterval > 255) {
developer5f222492022-09-13 15:21:52 +08002613 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
developer30423732022-12-01 16:17:49 +08002614 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08002615 }
2616
2617 params.name = "dtim_period";
2618 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2619 params.value = buf;
2620
2621 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2622 wifi_hostapdWrite(config_file, &params, 1);
2623 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2624
2625 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2626 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002627}
2628
2629//Check if the driver support the Dfs
2630INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2631{
developer78a15382022-11-02 10:57:40 +08002632 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +08002633 if (NULL == output_bool)
2634 return RETURN_ERR;
developer78a15382022-11-02 10:57:40 +08002635 *output_bool=FALSE;
2636
2637 band = wifi_index_to_band(radioIndex);
2638 if (band == band_5)
2639 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08002640 return RETURN_OK;
2641}
2642
2643//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.
2644//The value of this parameter is a comma seperated list of channel number
2645INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2646{
2647 if (NULL == output_pool)
2648 return RETURN_ERR;
2649 if (radioIndex==1)
2650 return RETURN_OK;//TODO need to handle for 5GHz band, i think
2651 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2652
2653 return RETURN_OK;
2654}
2655
2656INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2657{
2658 //Set to wifi config. And apply instantly.
2659 return RETURN_OK;
2660}
2661
2662INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2663{
2664 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
2665 return RETURN_ERR;
2666 *output_interval_seconds=1800;
2667 *output_dwell_milliseconds=40;
2668
2669 return RETURN_OK;
2670}
2671
2672INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2673{
2674 //Set to wifi config. And apply instantly.
2675 return RETURN_OK;
2676}
2677
developerbfc18512022-10-05 17:54:28 +08002678INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
2679{
2680 if (output_bool == NULL)
2681 return RETURN_ERR;
2682 *output_bool = true;
2683 return RETURN_OK;
2684}
2685
2686INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
2687{
2688 return RETURN_OK;
2689}
2690
developer06a01d92022-09-07 16:32:39 +08002691//Get the Dfs enable status
2692INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2693{
developer9964b5b2022-09-13 15:59:34 +08002694 char buf[16] = {0};
2695 FILE *f = NULL;
developer9964b5b2022-09-13 15:59:34 +08002696
2697 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2698
developer30423732022-12-01 16:17:49 +08002699 if (output_bool == NULL)
2700 return RETURN_ERR;
2701
developer9964b5b2022-09-13 15:59:34 +08002702 *output_bool = TRUE; // default
developer9964b5b2022-09-13 15:59:34 +08002703 f = fopen(DFS_ENABLE_FILE, "r");
2704 if (f != NULL) {
2705 fgets(buf, 2, f);
developer76989232022-10-04 14:13:19 +08002706 if (strncmp(buf, "0", 1) == 0)
developer9964b5b2022-09-13 15:59:34 +08002707 *output_bool = FALSE;
2708 fclose(f);
2709 }
2710 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002711 return RETURN_OK;
2712}
2713
2714//Set the Dfs enable status
2715INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2716{
developer9964b5b2022-09-13 15:59:34 +08002717 char config_file[128] = {0};
2718 FILE *f = NULL;
2719 struct params params={0};
developer9964b5b2022-09-13 15:59:34 +08002720
2721 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2722
developer9964b5b2022-09-13 15:59:34 +08002723 f = fopen(DFS_ENABLE_FILE, "w");
2724 if (f == NULL)
2725 return RETURN_ERR;
2726 fprintf(f, "%d", enable);
2727 fclose(f);
2728
2729 params.name = "acs_exclude_dfs";
developer76989232022-10-04 14:13:19 +08002730 params.value = enable?"0":"1";
developer9964b5b2022-09-13 15:59:34 +08002731 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2732 wifi_hostapdWrite(config_file, &params, 1);
2733 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2734
2735 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2736
developer9964b5b2022-09-13 15:59:34 +08002737 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer76989232022-10-04 14:13:19 +08002738 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002739}
2740
2741//Check if the driver support the AutoChannelRefreshPeriod
2742INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2743{
2744 if (NULL == output_bool)
2745 return RETURN_ERR;
2746 *output_bool=FALSE; //not support
2747
2748 return RETURN_OK;
2749}
2750
2751//Get the ACS refresh period in seconds
2752INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2753{
2754 if (NULL == output_ulong)
2755 return RETURN_ERR;
2756 *output_ulong=300;
2757
2758 return RETURN_OK;
2759}
2760
2761//Set the ACS refresh period in seconds
2762INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2763{
2764 return RETURN_ERR;
2765}
2766
developer7c4cd202023-03-01 10:56:29 +08002767INT getEHT320ChannelBandwidthSet(int radioIndex, int *BandwidthSet)
2768{
2769 int center_channel = 0;
2770 char config_file[32] = {0};
2771 char buf[32] = {0};
2772
2773 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2774 wifi_hostapdRead(config_file, "eht_oper_centr_freq_seg0_idx", buf, sizeof(buf));
2775
2776 center_channel = strtoul(buf, NULL, 10);
2777 center_channel += 1; // Add 1 to become muiltiple of 16
2778 if (center_channel % 64 == 32)
2779 *BandwidthSet = WIFI_CHANNELBANDWIDTH_320_1MHZ;
2780 else if (center_channel % 64 == 0)
2781 *BandwidthSet = WIFI_CHANNELBANDWIDTH_320_2MHZ;
2782 else
2783 return RETURN_ERR;
2784 return RETURN_OK;
2785}
2786
developer06a01d92022-09-07 16:32:39 +08002787//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2788//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.
2789INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2790{
developer72ec5572023-01-05 16:27:13 +08002791 char buf[64] = {0};
developerfa41b1f2023-01-06 10:25:51 +08002792 char extchannel[128] = {0};
developer72ec5572023-01-05 16:27:13 +08002793 char config_file[128] = {0};
developer70490032022-09-13 15:45:20 +08002794 BOOL radio_enable = FALSE;
developerfa41b1f2023-01-06 10:25:51 +08002795 wifi_band band;
developer70490032022-09-13 15:45:20 +08002796
2797 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2798
developer06a01d92022-09-07 16:32:39 +08002799 if (NULL == output_string)
2800 return RETURN_ERR;
2801
developer70490032022-09-13 15:45:20 +08002802 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
2803 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002804
developer70490032022-09-13 15:45:20 +08002805 if (radio_enable != TRUE)
2806 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002807
developerfa41b1f2023-01-06 10:25:51 +08002808 band = wifi_index_to_band(radioIndex);
developer72ec5572023-01-05 16:27:13 +08002809 if (band == band_2_4) {
developerfa41b1f2023-01-06 10:25:51 +08002810 wifi_getRadioExtChannel(radioIndex, extchannel);
developer72ec5572023-01-05 16:27:13 +08002811 if (strncmp(extchannel, "Auto", 4) == 0) // Auto means that we did not set ht_capab HT40+/-
2812 snprintf(output_string, 64, "20MHz");
2813 else
2814 snprintf(output_string, 64, "40MHz");
2815
2816 } else {
2817 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2818 wifi_hostapdRead(config_file, "he_oper_chwidth", buf, sizeof(buf));
2819 if (strncmp(buf, "0", 1) == 0) { // Check whether we set central channel
2820 wifi_hostapdRead(config_file, "he_oper_centr_freq_seg0_idx", buf, sizeof(buf));
2821 if (strncmp(buf, "0", 1) == 0)
2822 snprintf(output_string, 64, "20MHz");
2823 else
2824 snprintf(output_string, 64, "40MHz");
2825
2826 } else if (strncmp(buf, "1", 1) == 0)
2827 snprintf(output_string, 64, "80MHz");
developer7c4cd202023-03-01 10:56:29 +08002828 else if (strncmp(buf, "2", 1) == 0) {
developer72ec5572023-01-05 16:27:13 +08002829 snprintf(output_string, 64, "160MHz");
developer7c4cd202023-03-01 10:56:29 +08002830 wifi_hostapdRead(config_file, "eht_oper_chwidth", buf, sizeof(buf));
2831 if (strncmp(buf, "9", 1) == 0) {
2832 int BandwidthSet = 0;
2833 if (getEHT320ChannelBandwidthSet(radioIndex, &BandwidthSet) != RETURN_OK)
2834 return RETURN_ERR;
2835 if (BandwidthSet == WIFI_CHANNELBANDWIDTH_320_1MHZ)
2836 snprintf(output_string, 64, "320-1MHz");
2837 else if (BandwidthSet == WIFI_CHANNELBANDWIDTH_320_2MHZ)
2838 snprintf(output_string, 64, "320-2MHz");
2839 }
2840 }
developer06a01d92022-09-07 16:32:39 +08002841 }
developer72ec5572023-01-05 16:27:13 +08002842
developer06a01d92022-09-07 16:32:39 +08002843 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002844
2845 return RETURN_OK;
2846}
2847
2848//Set the Operating Channel Bandwidth.
developerf7a466e2022-09-29 11:55:56 +08002849INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
developer06a01d92022-09-07 16:32:39 +08002850{
developerf7a466e2022-09-29 11:55:56 +08002851 char config_file[128];
2852 char set_value[16];
developer7c4cd202023-03-01 10:56:29 +08002853 char supported_mode[32] = {0};
2854 struct params params[3];
developerf7a466e2022-09-29 11:55:56 +08002855 int max_radio_num = 0;
developer7c4cd202023-03-01 10:56:29 +08002856 bool eht_support = FALSE;
developerf7a466e2022-09-29 11:55:56 +08002857
developer06a01d92022-09-07 16:32:39 +08002858 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002859
developerf7a466e2022-09-29 11:55:56 +08002860 if(NULL == bandwidth)
developer06a01d92022-09-07 16:32:39 +08002861 return RETURN_ERR;
2862
developer7c4cd202023-03-01 10:56:29 +08002863 if(strstr(bandwidth,"160") != NULL || strstr(bandwidth,"320") != NULL)
developerf7a466e2022-09-29 11:55:56 +08002864 strcpy(set_value, "2");
2865 else if(strstr(bandwidth,"80") != NULL)
2866 strcpy(set_value, "1");
2867 else if(strstr(bandwidth,"20") != NULL || strstr(bandwidth,"40") != NULL)
2868 strcpy(set_value, "0");
developer72ec5572023-01-05 16:27:13 +08002869 else if (strstr(bandwidth, "Auto") != NULL)
2870 return RETURN_OK;
2871 else {
developerf7a466e2022-09-29 11:55:56 +08002872 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
developer06a01d92022-09-07 16:32:39 +08002873 return RETURN_ERR;
2874 }
2875
developer7c4cd202023-03-01 10:56:29 +08002876 wifi_getRadioSupportedStandards(radioIndex, supported_mode);
2877 if (strstr(supported_mode, "be") != NULL)
2878 eht_support = TRUE;
2879
developerf7a466e2022-09-29 11:55:56 +08002880 params[0].name = "vht_oper_chwidth";
2881 params[0].value = set_value;
2882 params[1].name = "he_oper_chwidth";
2883 params[1].value = set_value;
developer7c4cd202023-03-01 10:56:29 +08002884 params[2].name = "eht_oper_chwidth";
2885 if (strstr(bandwidth,"320") != NULL) // We set oper_chwidth to 9 for EHT320
2886 params[2].value = "9";
2887 else
2888 params[2].value = set_value;
developer06a01d92022-09-07 16:32:39 +08002889
developerf7a466e2022-09-29 11:55:56 +08002890 wifi_getMaxRadioNumber(&max_radio_num);
2891 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002892 {
developer7c4cd202023-03-01 10:56:29 +08002893 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2894 if (eht_support == TRUE)
2895 wifi_hostapdWrite(config_file, params, 3);
2896 else
2897 wifi_hostapdWrite(config_file, params, 2);
developer06a01d92022-09-07 16:32:39 +08002898 }
2899
2900 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2901 return RETURN_OK;
2902}
2903
2904//Getting current radio extension channel
2905INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2906{
2907 CHAR buf[150] = {0};
2908 CHAR cmd[150] = {0};
2909 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2910 _syscmd(cmd, buf, sizeof(buf));
2911 if(NULL != strstr(buf,"HT40+"))
2912 strcpy(Value,"AboveControlChannel");
2913 else if(NULL != strstr(buf,"HT40-"))
2914 strcpy(Value,"BelowControlChannel");
2915 return RETURN_OK;
2916}
2917
2918//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
2919//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.
2920INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
2921{
developerfa41b1f2023-01-06 10:25:51 +08002922 char config_file[64] = {0};
developerfa41b1f2023-01-06 10:25:51 +08002923 wifi_band band;
developerfa41b1f2023-01-06 10:25:51 +08002924
2925 if (output_string == NULL)
developer06a01d92022-09-07 16:32:39 +08002926 return RETURN_ERR;
2927
developerfa41b1f2023-01-06 10:25:51 +08002928 band = wifi_index_to_band(radioIndex);
2929 if (band == band_invalid)
developer06a01d92022-09-07 16:32:39 +08002930 return RETURN_ERR;
developerfa41b1f2023-01-06 10:25:51 +08002931
2932 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2933
2934 snprintf(output_string, 64, "Auto");
developer72ec5572023-01-05 16:27:13 +08002935 wifi_halgetRadioExtChannel(config_file, output_string);
developer06a01d92022-09-07 16:32:39 +08002936
2937 return RETURN_OK;
2938}
2939
developer57fa24a2023-03-15 17:25:07 +08002940// This function handle 20MHz to remove HT40+/- in hostapd config, other bandwidths are handled in wifi_setRadioExtChannel.
2941INT wifi_RemoveRadioExtChannel(INT radioIndex, CHAR *ext_str)
2942{
2943 struct params params={0};
2944 char config_file[64] = {0};
2945 char ht_capab[128]={0};
2946 char buf[128] = {0};
2947 char cmd[128] = {0};
2948 int max_radio_num =0;
2949 bool stbcEnable = FALSE;
2950
2951 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2952 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
2953 _syscmd(cmd, buf, sizeof(buf));
2954 if (strlen(buf) != 0)
2955 stbcEnable = TRUE;
2956
2957 strcpy(ht_capab, HOSTAPD_HT_CAPAB);
2958 params.value = ht_capab;
2959 params.name = "ht_capab";
2960
2961 wifi_getMaxRadioNumber(&max_radio_num);
2962 for(int i=0; i<=MAX_APS/max_radio_num; i++)
2963 {
2964 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2965 wifi_hostapdWrite(config_file, &params, 1);
developer57fa24a2023-03-15 17:25:07 +08002966 }
developer8d7d0862023-05-18 16:50:23 +08002967 wifi_setRadioSTBCEnable(radioIndex, stbcEnable);
developer57fa24a2023-03-15 17:25:07 +08002968 return RETURN_OK;
2969}
2970
developer06a01d92022-09-07 16:32:39 +08002971//Set the extension channel.
2972INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
developer72ec5572023-01-05 16:27:13 +08002973{
developer06a01d92022-09-07 16:32:39 +08002974 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developerfa41b1f2023-01-06 10:25:51 +08002975 struct params params={0};
2976 char config_file[64] = {0};
2977 char ext_channel[128]={0};
2978 char buf[128] = {0};
2979 char cmd[128] = {0};
2980 int max_radio_num =0, ret = 0, bandwidth = 0;
developer72ec5572023-01-05 16:27:13 +08002981 unsigned long channel = 0;
developerfa41b1f2023-01-06 10:25:51 +08002982 bool stbcEnable = FALSE;
developer06a01d92022-09-07 16:32:39 +08002983 params.name = "ht_capab";
developerfa41b1f2023-01-06 10:25:51 +08002984 wifi_band band;
2985
2986 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2987 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
2988 _syscmd(cmd, buf, sizeof(buf));
2989 if (strlen(buf) != 0)
2990 stbcEnable = TRUE;
developer57fa24a2023-03-15 17:25:07 +08002991
2992 // readBandWidth get empty file will return error, that means we don't set new bandwidth
2993 if (readBandWidth(radioIndex, buf) != RETURN_OK) {
2994 // Get current bandwidth
2995 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, buf) != RETURN_OK)
2996 return RETURN_ERR;
2997 }
developerfa41b1f2023-01-06 10:25:51 +08002998 bandwidth = strtol(buf, NULL, 10);
2999 // TDK expected to get error with 20MHz
developer57fa24a2023-03-15 17:25:07 +08003000 // we handle 20MHz in function wifi_RemoveRadioExtChannel().
developerfa41b1f2023-01-06 10:25:51 +08003001 if (bandwidth == 20 || strstr(buf, "80+80") != NULL)
3002 return RETURN_ERR;
3003
3004 band = wifi_index_to_band(radioIndex);
3005 if (band == band_invalid)
3006 return RETURN_ERR;
3007
3008 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK)
3009 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003010
developer72ec5572023-01-05 16:27:13 +08003011 snprintf(buf, sizeof(buf), "HT%d", bandwidth);
3012 ret = util_get_sec_chan_offset(channel, buf);
3013 if (ret == -EINVAL)
3014 return RETURN_ERR;
developerfa41b1f2023-01-06 10:25:51 +08003015
3016 if(NULL!= strstr(string,"Above")) {
developer72ec5572023-01-05 16:27:13 +08003017 if ((band == band_2_4 && channel > 9) || (band == band_5 && ret == -1))
3018 return RETURN_OK;
developer033b37b2022-10-18 11:27:46 +08003019 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
developerfa41b1f2023-01-06 10:25:51 +08003020 } else if(NULL!= strstr(string,"Below")) {
developer72ec5572023-01-05 16:27:13 +08003021 if ((band == band_2_4 && channel < 5) || (band == band_5 && ret == 1))
3022 return RETURN_OK;
developer033b37b2022-10-18 11:27:46 +08003023 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
developerfa41b1f2023-01-06 10:25:51 +08003024 } else {
developer57fa24a2023-03-15 17:25:07 +08003025 fprintf(stderr, "%s: unknow extchannel %s\n", __func__, string);
3026 return RETURN_ERR;
developerfa41b1f2023-01-06 10:25:51 +08003027 }
developer06a01d92022-09-07 16:32:39 +08003028
3029 params.value = ext_channel;
developer033b37b2022-10-18 11:27:46 +08003030
3031 wifi_getMaxRadioNumber(&max_radio_num);
3032 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08003033 {
developer033b37b2022-10-18 11:27:46 +08003034 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(max_radio_num*i));
developer06a01d92022-09-07 16:32:39 +08003035 wifi_hostapdWrite(config_file, &params, 1);
3036 }
developer8d7d0862023-05-18 16:50:23 +08003037 wifi_setRadioSTBCEnable(radioIndex, stbcEnable);
developer06a01d92022-09-07 16:32:39 +08003038
3039 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
3040 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3041 return RETURN_OK;
3042}
3043
3044//Get the guard interval value. eg "400nsec" or "800nsec"
3045//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.
3046INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
3047{
developer454b9462022-09-13 15:29:16 +08003048 wifi_guard_interval_t GI;
3049
3050 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3051
3052 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
developer06a01d92022-09-07 16:32:39 +08003053 return RETURN_ERR;
developer454b9462022-09-13 15:29:16 +08003054
3055 if (GI == wifi_guard_interval_400)
3056 strcpy(output_string, "400nsec");
3057 else if (GI == wifi_guard_interval_800)
3058 strcpy(output_string, "800nsec");
3059 else if (GI == wifi_guard_interval_1600)
3060 strcpy(output_string, "1600nsec");
3061 else if (GI == wifi_guard_interval_3200)
3062 strcpy(output_string, "3200nsec");
3063 else
developer78a15382022-11-02 10:57:40 +08003064 strcpy(output_string, "Auto");
developer06a01d92022-09-07 16:32:39 +08003065
developer454b9462022-09-13 15:29:16 +08003066 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003067 return RETURN_OK;
3068}
3069
3070//Set the guard interval value.
3071INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
3072{
developer454b9462022-09-13 15:29:16 +08003073 wifi_guard_interval_t GI;
3074 int ret = 0;
3075
3076 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3077
3078 if (strcmp(string, "400nsec") == 0)
3079 GI = wifi_guard_interval_400;
developer254882b2022-09-30 17:12:31 +08003080 else if (strcmp(string , "800nsec") == 0)
developer454b9462022-09-13 15:29:16 +08003081 GI = wifi_guard_interval_800;
3082 else if (strcmp(string , "1600nsec") == 0)
3083 GI = wifi_guard_interval_1600;
3084 else if (strcmp(string , "3200nsec") == 0)
3085 GI = wifi_guard_interval_3200;
developer254882b2022-09-30 17:12:31 +08003086 else
3087 GI = wifi_guard_interval_auto;
developer454b9462022-09-13 15:29:16 +08003088
3089 ret = wifi_setGuardInterval(radioIndex, GI);
3090
3091 if (ret == RETURN_ERR) {
3092 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
3093 return RETURN_ERR;
3094 }
3095
3096 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3097 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003098}
3099
3100//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
3101INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
3102{
developerf49437e2022-09-29 19:58:21 +08003103 char buf[32]={0};
3104 char mcs_file[64] = {0};
3105 char cmd[64] = {0};
3106 int mode_bitmap = 0;
3107
3108 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3109 if(output_int == NULL)
developer06a01d92022-09-07 16:32:39 +08003110 return RETURN_ERR;
developerf49437e2022-09-29 19:58:21 +08003111 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
3112
3113 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
3114 _syscmd(cmd, buf, sizeof(buf));
3115 if (strlen(buf) > 0)
3116 *output_int = strtol(buf, NULL, 10);
3117 else {
3118 // output the max MCS for the current radio mode
3119 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
3120 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
3121 return RETURN_ERR;
3122 }
3123 if (mode_bitmap & WIFI_MODE_AX) {
3124 *output_int = 11;
3125 } else if (mode_bitmap & WIFI_MODE_AC) {
3126 *output_int = 9;
3127 } else if (mode_bitmap & WIFI_MODE_N) {
3128 *output_int = 7;
3129 }
3130 }
3131 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003132
3133 return RETURN_OK;
3134}
3135
3136//Set the Modulation Coding Scheme index
3137INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
3138{
developerf49437e2022-09-29 19:58:21 +08003139 // Only HE mode can specify MCS capability. We don't support MCS in HT mode, because that would be ambiguous (MCS code 8~11 refer to 2 NSS in HT but 1 NSS in HE adn VHT).
3140 char config_file[64] = {0};
3141 char set_value[16] = {0};
3142 char mcs_file[32] = {0};
3143 wifi_band band = band_invalid;
3144 struct params set_config = {0};
3145 FILE *f = NULL;
3146
3147 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3148
3149 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
3150
developer78a15382022-11-02 10:57:40 +08003151 // -1 means auto
3152 if (MCS > 15 || MCS < -1) {
developerf49437e2022-09-29 19:58:21 +08003153 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
3154 return RETURN_ERR;
3155 }
3156
developer78a15382022-11-02 10:57:40 +08003157 if (MCS > 9 || MCS == -1)
3158 strcpy(set_value, "2");
3159 else if (MCS > 7)
developerf49437e2022-09-29 19:58:21 +08003160 strcpy(set_value, "1");
3161 else
developer78a15382022-11-02 10:57:40 +08003162 strcpy(set_value, "0");
developerf49437e2022-09-29 19:58:21 +08003163
3164 set_config.name = "he_basic_mcs_nss_set";
3165 set_config.value = set_value;
3166
3167 wifi_hostapdWrite(config_file, &set_config, 1);
3168 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
3169
3170 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
3171 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
3172 f = fopen(mcs_file, "w");
3173 if (f == NULL) {
3174 fprintf(stderr, "%s: fopen failed\n", __func__);
3175 return RETURN_ERR;
3176 }
3177 fprintf(f, "%d", MCS);
3178 fclose(f);
3179
3180 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3181 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003182}
3183
3184//Get supported Transmit Power list, eg : "0,25,50,75,100"
3185//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.
3186INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
3187{
3188 if (NULL == output_list)
3189 return RETURN_ERR;
developer5c97d532023-09-28 11:19:30 +08003190 snprintf(output_list, 64,"0,12,25,50,75,100");
developer06a01d92022-09-07 16:32:39 +08003191 return RETURN_OK;
3192}
3193
developer5c97d532023-09-28 11:19:30 +08003194// Get current Transmit Power in percent
developer06a01d92022-09-07 16:32:39 +08003195INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
3196{
developer5c97d532023-09-28 11:19:30 +08003197 char cmd[128]={'\0'};
3198 char buf[128]={'\0'};
3199 int phyIndex = -1;
3200 bool enabled = false;
3201 int cur_tx_dbm = 0;
3202
developera5005b62022-09-13 15:43:35 +08003203 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003204
developera5005b62022-09-13 15:43:35 +08003205 if(output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08003206 return RETURN_ERR;
3207
developer5c97d532023-09-28 11:19:30 +08003208 phyIndex = radio_index_to_phy(radioIndex);
3209
3210 // Get the maximum tx power of the device
3211 snprintf(cmd, sizeof(cmd), "cat /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_info | "
developer439baa32024-05-02 15:54:58 +08003212 "grep 'Percentage Control:' | awk '{print $3}' | tr -d '\\n'", single_wiphy ? radioIndex : phyIndex);
developer06a01d92022-09-07 16:32:39 +08003213 _syscmd(cmd, buf, sizeof(buf));
developer5c97d532023-09-28 11:19:30 +08003214 if (strcmp(buf, "enable") == 0)
3215 enabled = true;
developer06a01d92022-09-07 16:32:39 +08003216
developer5c97d532023-09-28 11:19:30 +08003217 if (!enabled) {
3218 *output_ulong = 100;
3219 return RETURN_OK;
3220 }
developera5005b62022-09-13 15:43:35 +08003221
developer5c97d532023-09-28 11:19:30 +08003222 memset(cmd, 0, sizeof(cmd));
3223 memset(buf, 0, sizeof(buf));
3224 snprintf(cmd, sizeof(cmd), "cat /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_info | "
developer439baa32024-05-02 15:54:58 +08003225 "grep 'Power Drop:' | awk '{print $3}' | tr -d '\\n'", single_wiphy ? radioIndex : phyIndex);
developer5c97d532023-09-28 11:19:30 +08003226 _syscmd(cmd, buf, sizeof(buf));
3227 cur_tx_dbm = strtol(buf, NULL, 10);
3228
3229 switch (cur_tx_dbm) {
3230 case 0:
3231 *output_ulong = 100; // range 91-100
3232 break;
3233 case 1:
3234 *output_ulong = 75; // range 61-90
3235 break;
3236 case 3:
3237 *output_ulong = 50; // range 31-60
3238 break;
3239 case 6:
3240 *output_ulong = 25; // range 16-30
3241 break;
3242 case 9:
3243 *output_ulong = 12; // range 10-15
3244 break;
3245 case 12:
3246 *output_ulong = 6; // range 1-9
3247 break;
3248 default:
3249 *output_ulong = 100; // 0
3250 }
3251
developer06a01d92022-09-07 16:32:39 +08003252 return RETURN_OK;
3253}
3254
developer5c97d532023-09-28 11:19:30 +08003255// TransmitPower: the the percentage relative to the maximum power,
3256// only support 0,12,25,50,75,100, But 0 means disable Power limit,
3257// so the power is 100%
developer06a01d92022-09-07 16:32:39 +08003258INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
3259{
developerd946fd62022-12-08 18:03:28 +08003260 char interface_name[16] = {0};
developera5005b62022-09-13 15:43:35 +08003261 char *support;
developer06a01d92022-09-07 16:32:39 +08003262 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08003263 char buf[128]={0};
3264 char txpower_str[64] = {0};
developer033b37b2022-10-18 11:27:46 +08003265 int phyId = 0;
developera5005b62022-09-13 15:43:35 +08003266
3267 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003268
developerac6f1142022-12-20 19:26:35 +08003269 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003270 return RETURN_ERR;
developera5005b62022-09-13 15:43:35 +08003271
3272 // Get the Tx power supported list and check that is the input in the list
3273 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
3274 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
3275 support = strtok(buf, ",");
3276 while(true)
3277 {
3278 if(support == NULL) { // input not in the list
3279 wifi_dbg_printf("Input value is invalid.\n");
3280 return RETURN_ERR;
3281 }
3282 if (strncmp(txpower_str, support, strlen(support)) == 0) {
3283 break;
3284 }
3285 support = strtok(NULL, ",");
3286 }
developer5c97d532023-09-28 11:19:30 +08003287
developer033b37b2022-10-18 11:27:46 +08003288 phyId = radio_index_to_phy(radioIndex);
developer5c97d532023-09-28 11:19:30 +08003289 snprintf(cmd, sizeof(cmd), "echo %lu > /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_level",
developer439baa32024-05-02 15:54:58 +08003290 TransmitPower, single_wiphy ? radioIndex : phyId);
developera5005b62022-09-13 15:43:35 +08003291 _syscmd(cmd, buf, sizeof(buf));
developer5c97d532023-09-28 11:19:30 +08003292
developera5005b62022-09-13 15:43:35 +08003293 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003294
3295 return RETURN_OK;
3296}
3297
3298//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
3299INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
3300{
3301 if (NULL == Supported)
3302 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003303 *Supported = TRUE;
developer06a01d92022-09-07 16:32:39 +08003304
3305 return RETURN_OK;
3306}
3307
3308//Get 80211h feature enable
3309INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
3310{
developer3885fec2022-09-13 15:13:47 +08003311 char buf[64]={'\0'};
3312 char config_file[64] = {'\0'};
3313
3314 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3315 if(enable == NULL)
developer06a01d92022-09-07 16:32:39 +08003316 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003317
3318 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3319 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08003320
developer3885fec2022-09-13 15:13:47 +08003321 if (strncmp(buf, "1", 1) == 0)
3322 *enable = TRUE;
3323 else
3324 *enable = FALSE;
3325
3326 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003327 return RETURN_OK;
3328}
3329
3330//Set 80211h feature enable
3331INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
3332{
developer3885fec2022-09-13 15:13:47 +08003333 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3334 struct params params={'\0'};
3335 char config_file[MAX_BUF_SIZE] = {0};
3336
3337 params.name = "ieee80211h";
3338
3339 if (enable) {
3340 params.value = "1";
3341 } else {
3342 params.value = "0";
3343 }
3344
3345 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3346 wifi_hostapdWrite(config_file, &params, 1);
3347
3348 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3349 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3350 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003351}
3352
3353//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.
3354INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
3355{
3356 if (NULL == output)
3357 return RETURN_ERR;
3358 *output=100;
3359
3360 return RETURN_OK;
3361}
3362
3363//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.
3364INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
3365{
3366 if (NULL == output)
3367 return RETURN_ERR;
3368 *output = -99;
3369
3370 return RETURN_OK;
3371}
3372
3373INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
3374{
3375 return RETURN_ERR;
3376}
3377
3378
3379//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
3380INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
3381{
developerd946fd62022-12-08 18:03:28 +08003382 char interface_name[16] = {0};
developer5f222492022-09-13 15:21:52 +08003383 char cmd[MAX_BUF_SIZE]={'\0'};
3384 char buf[MAX_CMD_SIZE]={'\0'};
3385
3386 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3387 if(output == NULL)
developer06a01d92022-09-07 16:32:39 +08003388 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08003389
developerac6f1142022-12-20 19:26:35 +08003390 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003391 return RETURN_ERR;
3392 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", interface_name);
developer5f222492022-09-13 15:21:52 +08003393 _syscmd(cmd, buf, sizeof(buf));
3394 *output = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08003395
developer5f222492022-09-13 15:21:52 +08003396 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003397 return RETURN_OK;
3398}
3399
3400INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
3401{
developer5f222492022-09-13 15:21:52 +08003402 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3403 struct params params={'\0'};
3404 char buf[MAX_BUF_SIZE] = {'\0'};
3405 char config_file[MAX_BUF_SIZE] = {'\0'};
3406
developer5b398df2022-11-17 20:39:48 +08003407 if (BeaconPeriod < 15 || BeaconPeriod > 65535)
3408 return RETURN_ERR;
3409
developer5f222492022-09-13 15:21:52 +08003410 params.name = "beacon_int";
3411 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
3412 params.value = buf;
3413
3414 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3415 wifi_hostapdWrite(config_file, &params, 1);
3416
3417 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3418 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3419 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003420}
3421
3422//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.
3423INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
3424{
developer06a01d92022-09-07 16:32:39 +08003425 //TODO: need to revisit below implementation
3426 char *temp;
developere9d0abd2022-09-13 15:40:57 +08003427 char temp_output[128] = {0};
3428 char temp_TransmitRates[64] = {0};
3429 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08003430
3431 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3432 if (NULL == output)
3433 return RETURN_ERR;
3434 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
developere9d0abd2022-09-13 15:40:57 +08003435 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
3436
3437 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
3438 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
3439 } else {
3440 temp = strtok(temp_TransmitRates," ");
3441 while(temp!=NULL)
developer06a01d92022-09-07 16:32:39 +08003442 {
developere9d0abd2022-09-13 15:40:57 +08003443 // Convert 100 kbps to Mbps
3444 temp[strlen(temp)-1]=0;
3445 if((temp[0]=='5') && (temp[1]=='\0'))
3446 {
3447 temp="5.5";
3448 }
3449 strcat(temp_output,temp);
3450 temp = strtok(NULL," ");
3451 if(temp!=NULL)
3452 {
3453 strcat(temp_output,",");
3454 }
developer06a01d92022-09-07 16:32:39 +08003455 }
developere9d0abd2022-09-13 15:40:57 +08003456 strcpy(output,temp_output);
developer06a01d92022-09-07 16:32:39 +08003457 }
developer06a01d92022-09-07 16:32:39 +08003458 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003459 return RETURN_OK;
3460}
3461
3462INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
3463{
3464 char *temp;
3465 char temp1[128];
3466 char temp_output[128];
3467 char temp_TransmitRates[128];
3468 char set[128];
3469 char sub_set[128];
3470 int set_count=0,subset_count=0;
3471 int set_index=0,subset_index=0;
3472 char *token;
3473 int flag=0, i=0;
3474 struct params params={'\0'};
3475 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08003476 wifi_band band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +08003477
3478 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3479 if(NULL == TransmitRates)
3480 return RETURN_ERR;
3481 strcpy(sub_set,TransmitRates);
3482
3483 //Allow only supported Data transmit rate to be set
3484 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3485 token = strtok(sub_set,",");
3486 while( token != NULL ) /* split the basic rate to be set, by comma */
3487 {
3488 sub_set[subset_count]=atoi(token);
3489 subset_count++;
3490 token=strtok(NULL,",");
3491 }
3492 token=strtok(set,",");
3493 while(token!=NULL) /* split the supported rate by comma */
3494 {
3495 set[set_count]=atoi(token);
3496 set_count++;
3497 token=strtok(NULL,",");
3498 }
3499 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3500 {
3501 for(set_index=0;set_index < set_count;set_index++)
3502 {
3503 flag=0;
3504 if(sub_set[subset_index]==set[set_index])
3505 break;
3506 else
3507 flag=1; /* No match found */
3508 }
3509 if(flag==1)
3510 return RETURN_ERR; //If value not found return Error
3511 }
3512 strcpy(temp_TransmitRates,TransmitRates);
3513
3514 for(i=0;i<strlen(temp_TransmitRates);i++)
3515 {
3516 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
developeref938762022-10-19 17:21:01 +08003517 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08003518 {
3519 continue;
3520 }
3521 else
3522 {
3523 return RETURN_ERR;
3524 }
3525 }
3526 strcpy(temp_output,"");
3527 temp = strtok(temp_TransmitRates,",");
3528 while(temp!=NULL)
3529 {
3530 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08003531 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08003532 {
developeref938762022-10-19 17:21:01 +08003533 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08003534 {
3535 return RETURN_ERR;
3536 }
3537 }
3538
3539 if(strcmp(temp,"5.5")==0)
3540 {
3541 strcpy(temp1,"55");
3542 }
3543 else
3544 {
3545 strcat(temp1,"0");
3546 }
3547 strcat(temp_output,temp1);
3548 temp = strtok(NULL,",");
3549 if(temp!=NULL)
3550 {
3551 strcat(temp_output," ");
3552 }
3553 }
3554 strcpy(TransmitRates,temp_output);
3555
3556 params.name= "basic_rates";
3557 params.value =TransmitRates;
3558
3559 wifi_dbg_printf("\n%s:",__func__);
3560 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3561 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3562 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3563 wifi_hostapdWrite(config_file,&params,1);
3564 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3565 return RETURN_OK;
3566}
3567
3568//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
developerac6f1142022-12-20 19:26:35 +08003569INT wifi_GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
developer06a01d92022-09-07 16:32:39 +08003570{
3571 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3572 FILE *fp = NULL;
3573 char path[256] = {0}, output_string[256] = {0};
3574 int count = 0;
3575 char *interface = NULL;
3576
3577 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3578 if (fp == NULL)
3579 {
3580 printf("Failed to run command in Function %s\n", __FUNCTION__);
3581 return RETURN_ERR;
3582 }
3583 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3584 {
3585 interface = strchr(path, '=');
3586
3587 if (interface != NULL)
3588 {
3589 strcpy(output_string, interface + 1);
developer72ec5572023-01-05 16:27:13 +08003590 for (count = 0; output_string[count] != '\n' && output_string[count] != '\0'; count++)
developer06a01d92022-09-07 16:32:39 +08003591 interface_name[count] = output_string[count];
3592
3593 interface_name[count] = '\0';
3594 }
3595 }
3596 pclose(fp);
3597 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3598 return RETURN_OK;
3599}
3600
3601INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3602{
3603 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3604 output_struct->radio_BytesSent = 0;
3605 output_struct->radio_BytesReceived = 0;
3606 output_struct->radio_PacketsSent = 0;
3607 output_struct->radio_PacketsReceived = 0;
3608 output_struct->radio_ErrorsSent = 0;
3609 output_struct->radio_ErrorsReceived = 0;
3610 output_struct->radio_DiscardPacketsSent = 0;
3611 output_struct->radio_DiscardPacketsReceived = 0;
3612 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3613 return RETURN_OK;
3614}
3615
3616
3617INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3618{
3619 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer214b0592023-10-31 10:59:05 +08003620 CHAR buf[MAX_CMD_SIZE] = {0};
3621 CHAR Value[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08003622 FILE *fp = NULL;
3623
3624 if (ifname == NULL || strlen(ifname) <= 1)
3625 return RETURN_OK;
3626
developer214b0592023-10-31 10:59:05 +08003627 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
developer06a01d92022-09-07 16:32:39 +08003628 system(buf);
3629
3630 fp = fopen("/tmp/Radio_Stats.txt", "r");
3631 if(fp == NULL)
3632 {
3633 printf("/tmp/Radio_Stats.txt not exists \n");
3634 return RETURN_ERR;
3635 }
3636 fclose(fp);
3637
developer214b0592023-10-31 10:59:05 +08003638 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3639 File_Reading(buf, Value);
3640 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003641
developer214b0592023-10-31 10:59:05 +08003642 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3643 File_Reading(buf, Value);
3644 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003645
developer214b0592023-10-31 10:59:05 +08003646 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3647 File_Reading(buf, Value);
3648 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003649
developer214b0592023-10-31 10:59:05 +08003650 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3651 File_Reading(buf, Value);
3652 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003653
developer214b0592023-10-31 10:59:05 +08003654 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3655 File_Reading(buf, Value);
3656 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003657
developer214b0592023-10-31 10:59:05 +08003658 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3659 File_Reading(buf, Value);
3660 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003661
developer214b0592023-10-31 10:59:05 +08003662 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3663 File_Reading(buf, Value);
3664 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003665
developer214b0592023-10-31 10:59:05 +08003666 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3667 File_Reading(buf, Value);
3668 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003669
3670 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3671 return RETURN_OK;
3672}
3673
3674INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3675{
3676 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3677 CHAR buf[MAX_CMD_SIZE] = {0};
3678 FILE *fp = NULL;
3679 INT count = 0;
3680
3681 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3682 {
3683 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3684 File_Reading(buf, status);
3685 }
3686 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3687 return RETURN_OK;
3688}
3689
3690//Get detail radio traffic static info
3691INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3692{
3693
3694#if 0
3695 //ifconfig radio_x
3696 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3697 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3698 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3699 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3700
3701 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3702 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3703 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.
3704 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.
3705
3706 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3707 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].
3708 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3709 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.
3710 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
3711 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
3712 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
3713 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
3714 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
3715
3716 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
3717 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
3718 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
3719 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.
3720
3721 return RETURN_OK;
3722#endif
3723
developera91d99f2022-09-29 15:59:10 +08003724 CHAR interface_name[64] = {0};
developera91d99f2022-09-29 15:59:10 +08003725 BOOL iface_status = FALSE;
3726 wifi_radioTrafficStats2_t radioTrafficStats = {0};
developer7c4c40e2023-10-25 10:17:04 +08003727 INT max_radio_num = 0, apIndex = 0;
developer06a01d92022-09-07 16:32:39 +08003728
3729 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3730 if (NULL == output_struct)
3731 return RETURN_ERR;
3732
developer7c4c40e2023-10-25 10:17:04 +08003733 wifi_getMaxRadioNumber(&max_radio_num);
developer06a01d92022-09-07 16:32:39 +08003734
developer7c4c40e2023-10-25 10:17:04 +08003735 memset(output_struct, 0, sizeof(wifi_radioTrafficStats2_t));
developer06a01d92022-09-07 16:32:39 +08003736
developer7c4c40e2023-10-25 10:17:04 +08003737 for(apIndex = radioIndex; apIndex < MAX_APS; apIndex += max_radio_num) {
3738 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
3739 continue;
3740 wifi_getApEnable(radioIndex, &iface_status);
3741
3742 if (iface_status == TRUE)
3743 wifi_halGetIfStats(interface_name, &radioTrafficStats);
3744 else
3745 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
developer06a01d92022-09-07 16:32:39 +08003746
developer7c4c40e2023-10-25 10:17:04 +08003747 output_struct->radio_BytesSent += radioTrafficStats.radio_BytesSent;
3748 output_struct->radio_BytesReceived += radioTrafficStats.radio_BytesReceived;
3749 output_struct->radio_PacketsSent += radioTrafficStats.radio_PacketsSent;
3750 output_struct->radio_PacketsReceived += radioTrafficStats.radio_PacketsReceived;
3751 output_struct->radio_ErrorsSent += radioTrafficStats.radio_ErrorsSent;
3752 output_struct->radio_ErrorsReceived += radioTrafficStats.radio_ErrorsReceived;
3753 output_struct->radio_DiscardPacketsSent += radioTrafficStats.radio_DiscardPacketsSent;
3754 output_struct->radio_DiscardPacketsReceived += radioTrafficStats.radio_DiscardPacketsReceived;
3755 }
developer06a01d92022-09-07 16:32:39 +08003756
3757 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3758 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].
3759 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3760 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.
3761 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
3762 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
3763 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
3764 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
3765 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
3766
3767 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
3768 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
3769 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
3770 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.
3771
3772 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3773
3774 return RETURN_OK;
3775}
3776
3777//Set radio traffic static Measureing rules
3778INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3779{
3780 //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
3781 // Else, save the MeasuringRate and MeasuringInterval for future usage
3782
3783 return RETURN_OK;
3784}
3785
3786//To start or stop RadioTrafficStats
3787INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3788{
3789 //zqiu: If the RadioTrafficStats process running
3790 // if(enable)
3791 // return RETURN_OK.
3792 // else
3793 // Stop RadioTrafficStats process
3794 // Else
3795 // if(enable)
3796 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3797 // else
3798 // return RETURN_OK.
3799
3800 return RETURN_OK;
3801}
3802
3803//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
3804INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3805{
3806 //zqiu: Please ignor signalIndex.
3807 if (NULL == SignalLevel)
3808 return RETURN_ERR;
3809 *SignalLevel=(radioIndex==0)?-19:-19;
3810
3811 return RETURN_OK;
3812}
3813
3814//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3815INT wifi_applyRadioSettings(INT radioIndex)
3816{
3817 return RETURN_OK;
3818}
3819
3820//Get the radio index assocated with this SSID entry
3821INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3822{
developer5b398df2022-11-17 20:39:48 +08003823 if(NULL == radioIndex)
developer06a01d92022-09-07 16:32:39 +08003824 return RETURN_ERR;
developer5b398df2022-11-17 20:39:48 +08003825 int max_radio_num = 0;
3826 wifi_getMaxRadioNumber(&max_radio_num);
3827 *radioIndex = ssidIndex%max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003828 return RETURN_OK;
3829}
3830
3831//Device.WiFi.SSID.{i}.Enable
3832//Get SSID enable configuration parameters (not the SSID enable status)
3833INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3834{
3835 if (NULL == output_bool)
3836 return RETURN_ERR;
3837
developer06a01d92022-09-07 16:32:39 +08003838 return wifi_getApEnable(ssidIndex, output_bool);
3839}
3840
3841//Device.WiFi.SSID.{i}.Enable
3842//Set SSID enable configuration parameters
3843INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3844{
developer06a01d92022-09-07 16:32:39 +08003845 return wifi_setApEnable(ssidIndex, enable);
3846}
3847
3848//Device.WiFi.SSID.{i}.Status
3849//Get the SSID enable status
3850INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3851{
3852 char cmd[MAX_CMD_SIZE]={0};
3853 char buf[MAX_BUF_SIZE]={0};
3854 BOOL output_bool;
3855
3856 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3857 if (NULL == output_string)
3858 return RETURN_ERR;
developer804c64f2022-10-19 13:54:40 +08003859
developer06a01d92022-09-07 16:32:39 +08003860 wifi_getApEnable(ssidIndex,&output_bool);
3861 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3862
3863 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3864 return RETURN_OK;
3865}
3866
3867// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3868INT wifi_getSSIDName(INT apIndex, CHAR *output)
3869{
3870 char config_file[MAX_BUF_SIZE] = {0};
3871
3872 if (NULL == output)
3873 return RETURN_ERR;
3874
developerefb790a2023-12-26 18:58:32 +08003875 if (!syn_flag) {
3876 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3877 wifi_hostapdRead(config_file,"ssid",output,32);
3878 } else
developer07ded1f2024-01-10 10:30:15 +08003879 snprintf(output, 32, "%s", vap_info[apIndex].ssid);
developer06a01d92022-09-07 16:32:39 +08003880
3881 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3882 return RETURN_OK;
3883}
3884
3885// Set a max 32 byte string and sets an internal variable to the SSID name
3886INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3887{
3888 char str[MAX_BUF_SIZE]={'\0'};
3889 char cmd[MAX_CMD_SIZE]={'\0'};
3890 struct params params;
3891 char config_file[MAX_BUF_SIZE] = {0};
3892
3893 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer89df4502023-02-16 20:45:02 +08003894 if(NULL == ssid_string || strlen(ssid_string) > 32 || strlen(ssid_string) == 0 )
developer06a01d92022-09-07 16:32:39 +08003895 return RETURN_ERR;
3896
3897 params.name = "ssid";
3898 params.value = ssid_string;
3899 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3900 wifi_hostapdWrite(config_file, &params, 1);
3901 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3902 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3903
3904 return RETURN_OK;
3905}
3906
3907//Get the BSSID
3908INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3909{
3910 char cmd[MAX_CMD_SIZE]="";
3911
3912 if (NULL == output_string)
3913 return RETURN_ERR;
3914
3915 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3916 {
developer1d57d002022-10-12 18:03:15 +08003917 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep bssid | cut -d '=' -f2 | tr -d '\n'", CONFIG_PREFIX, ssidIndex);
developer06a01d92022-09-07 16:32:39 +08003918 _syscmd(cmd, output_string, 64);
3919 return RETURN_OK;
3920 }
3921 strncpy(output_string, "\0", 1);
3922
3923 return RETURN_ERR;
3924}
3925
3926//Get the MAC address associated with this Wifi SSID
3927INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3928{
3929 wifi_getBaseBSSID(ssidIndex,output_string);
3930 return RETURN_OK;
3931}
3932
3933//Get the basic SSID traffic static info
3934//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3935//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3936INT wifi_applySSIDSettings(INT ssidIndex)
3937{
developerd946fd62022-12-08 18:03:28 +08003938 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08003939 BOOL status = false;
3940 char cmd[MAX_CMD_SIZE] = {0};
3941 char buf[MAX_CMD_SIZE] = {0};
3942 int apIndex, ret;
developer033b37b2022-10-18 11:27:46 +08003943 int max_radio_num = 0;
3944 int radioIndex = 0;
3945
3946 wifi_getMaxRadioNumber(&max_radio_num);
3947
3948 radioIndex = ssidIndex % max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003949
3950 wifi_getApEnable(ssidIndex,&status);
3951 // Do not apply when ssid index is disabled
3952 if (status == false)
3953 return RETURN_OK;
3954
3955 /* Doing full remove and add for ssid Index
3956 * Not all hostapd options are supported with reload
3957 * for example macaddr_acl
3958 */
3959 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3960 return RETURN_ERR;
3961
3962 ret = wifi_setApEnable(ssidIndex,true);
3963
3964 /* Workaround for hostapd issue with multiple bss definitions
3965 * when first created interface will be removed
3966 * then all vaps other vaps on same phy are removed
3967 * after calling setApEnable to false readd all enabled vaps */
developer033b37b2022-10-18 11:27:46 +08003968 for(int i=0; i < MAX_APS/max_radio_num; i++) {
developerd946fd62022-12-08 18:03:28 +08003969 apIndex = max_radio_num*i+radioIndex;
developerac6f1142022-12-20 19:26:35 +08003970 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72ec5572023-01-05 16:27:13 +08003971 continue;
developer643b28f2023-04-04 10:26:01 +08003972 snprintf(cmd, sizeof(cmd), "cat %s | grep %s= | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
developer06a01d92022-09-07 16:32:39 +08003973 _syscmd(cmd, buf, sizeof(buf));
3974 if(*buf == '1')
3975 wifi_setApEnable(apIndex, true);
3976 }
3977
3978 return ret;
3979}
3980
developera3c68b92022-09-13 15:27:29 +08003981struct channels_noise {
3982 int channel;
3983 int noise;
3984};
3985
3986// Return noise array for each channel
3987int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3988{
developerd946fd62022-12-08 18:03:28 +08003989 char interface_name[16] = {0};
developera3c68b92022-09-13 15:27:29 +08003990 FILE *f = NULL;
3991 char cmd[128] = {0};
developer5550e242022-09-30 09:59:32 +08003992 char line[256] = {0};
developera3c68b92022-09-13 15:27:29 +08003993 size_t len = 0;
3994 ssize_t read = 0;
3995 int tmp = 0, arr_index = -1;
3996
developerac6f1142022-12-20 19:26:35 +08003997 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003998 return RETURN_ERR;
3999 sprintf(cmd, "iw dev %s survey dump | grep 'frequency\\|noise' | awk '{print $2}'", interface_name);
developera3c68b92022-09-13 15:27:29 +08004000
4001 if ((f = popen(cmd, "r")) == NULL) {
4002 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
4003 return RETURN_ERR;
4004 }
developer5550e242022-09-30 09:59:32 +08004005
4006 while(fgets(line, sizeof(line), f) != NULL) {
4007 if(arr_index < channels_num){
4008 sscanf(line, "%d", &tmp);
4009 if (tmp > 0) { // channel frequency, the first line must be frequency
4010 arr_index++;
4011 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
4012 } else { // noise
4013 channels_noise_arr[arr_index].noise = tmp;
4014 }
4015 }else{
4016 break;
developera3c68b92022-09-13 15:27:29 +08004017 }
4018 }
developera3c68b92022-09-13 15:27:29 +08004019 pclose(f);
4020 return RETURN_OK;
4021}
4022
developer06a01d92022-09-07 16:32:39 +08004023//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
4024//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
4025INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
4026{
developera3c68b92022-09-13 15:27:29 +08004027 int index = -1;
4028 wifi_neighbor_ap2_t *scan_array = NULL;
4029 char cmd[256]={0};
4030 char buf[128]={0};
4031 char file_name[32] = {0};
4032 char filter_SSID[32] = {0};
developer615510b2022-09-27 10:14:35 +08004033 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08004034 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08004035 char *ret = NULL;
developera3c68b92022-09-13 15:27:29 +08004036 int freq=0;
4037 FILE *f = NULL;
4038 size_t len=0;
developera3c68b92022-09-13 15:27:29 +08004039 int channels_num = 0;
4040 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08004041 int get_noise_ret = RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08004042 bool filter_enable = false;
4043 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08004044 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08004045
developer615510b2022-09-27 10:14:35 +08004046 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08004047
developerac6f1142022-12-20 19:26:35 +08004048 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004049 return RETURN_ERR;
4050
developera3c68b92022-09-13 15:27:29 +08004051 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
4052 f = fopen(file_name, "r");
4053 if (f != NULL) {
developer72ec5572023-01-05 16:27:13 +08004054 fgets(buf, sizeof(file_name), f);
4055 if ((strncmp(buf, "0", 1)) != 0) {
4056 fgets(filter_SSID, sizeof(file_name), f);
4057 if (strlen(filter_SSID) != 0)
4058 filter_enable = true;
4059 }
developera3c68b92022-09-13 15:27:29 +08004060 fclose(f);
4061 }
4062
developer033b37b2022-10-18 11:27:46 +08004063 phyId = radio_index_to_phy(radioIndex);
4064 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer06a01d92022-09-07 16:32:39 +08004065 _syscmd(cmd, buf, sizeof(buf));
developer615510b2022-09-27 10:14:35 +08004066 channels_num = strtol(buf, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004067
developer5550e242022-09-30 09:59:32 +08004068
developer06a01d92022-09-07 16:32:39 +08004069
developerd946fd62022-12-08 18:03:28 +08004070 sprintf(cmd, "iw dev %s scan | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
4071 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", interface_name, interface_name);
developera3c68b92022-09-13 15:27:29 +08004072 fprintf(stderr, "cmd: %s\n", cmd);
4073 if ((f = popen(cmd, "r")) == NULL) {
4074 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
4075 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08004076 }
developer5550e242022-09-30 09:59:32 +08004077
4078 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
4079 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
4080
developer615510b2022-09-27 10:14:35 +08004081 ret = fgets(line, sizeof(line), f);
4082 while (ret != NULL) {
developera3c68b92022-09-13 15:27:29 +08004083 if(strstr(line, "BSS") != NULL) { // new neighbor info
4084 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
4085 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
4086 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
developer06a01d92022-09-07 16:32:39 +08004087
developera3c68b92022-09-13 15:27:29 +08004088 if (!filter_BSS) {
4089 index++;
4090 wifi_neighbor_ap2_t *tmp;
4091 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
4092 if (tmp == NULL) { // no more memory to use
4093 index--;
4094 wifi_dbg_printf("%s: realloc failed\n", __func__);
4095 break;
4096 }
4097 scan_array = tmp;
4098 }
4099 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
4100
4101 filter_BSS = false;
4102 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
4103 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
4104 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
4105 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
4106 } else if (strstr(line, "freq") != NULL) {
4107 sscanf(line," freq: %d", &freq);
4108 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
4109
4110 if (freq >= 2412 && freq <= 2484) {
4111 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
4112 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
4113 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
4114 }
4115 else if (freq >= 5160 && freq <= 5805) {
4116 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
4117 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
4118 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
4119 }
4120
4121 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08004122 if (get_noise_ret == RETURN_OK) {
developera3c68b92022-09-13 15:27:29 +08004123 for (int i = 0; i < channels_num; i++) {
4124 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
4125 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
4126 break;
4127 }
4128 }
4129 }
4130 } else if (strstr(line, "beacon interval") != NULL) {
4131 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
4132 } else if (strstr(line, "signal") != NULL) {
4133 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
4134 } else if (strstr(line,"SSID") != NULL) {
4135 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
4136 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
4137 filter_BSS = true;
4138 }
4139 } else if (strstr(line, "Supported rates") != NULL) {
4140 char SRate[80] = {0}, *tmp = NULL;
4141 memset(buf, 0, sizeof(buf));
4142 strcpy(SRate, line);
4143 tmp = strtok(SRate, ":");
4144 tmp = strtok(NULL, ":");
4145 strcpy(buf, tmp);
4146 memset(SRate, 0, sizeof(SRate));
4147
4148 tmp = strtok(buf, " \n");
4149 while (tmp != NULL) {
4150 strcat(SRate, tmp);
4151 if (SRate[strlen(SRate) - 1] == '*') {
4152 SRate[strlen(SRate) - 1] = '\0';
4153 }
4154 strcat(SRate, ",");
4155
4156 tmp = strtok(NULL, " \n");
4157 }
4158 SRate[strlen(SRate) - 1] = '\0';
4159 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
4160 } else if (strstr(line, "DTIM") != NULL) {
4161 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
4162 } else if (strstr(line, "VHT capabilities") != NULL) {
4163 strcat(scan_array[index].ap_SupportedStandards, ",ac");
4164 strcpy(scan_array[index].ap_OperatingStandards, "ac");
4165 } else if (strstr(line, "HT capabilities") != NULL) {
4166 strcat(scan_array[index].ap_SupportedStandards, ",n");
4167 strcpy(scan_array[index].ap_OperatingStandards, "n");
4168 } else if (strstr(line, "VHT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08004169 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004170 sscanf(line," * channel width: %d", &vht_channel_width);
4171 if(vht_channel_width == 1) {
4172 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
4173 } else {
4174 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
4175 }
4176 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
4177 continue;
4178 } else if (strstr(line, "HT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08004179 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004180 sscanf(line," * secondary channel offset: %s", &buf);
4181 if (!strcmp(buf, "above")) {
4182 //40Mhz +
4183 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
4184 }
4185 else if (!strcmp(buf, "below")) {
4186 //40Mhz -
4187 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
4188 } else {
4189 //20Mhz
4190 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
4191 }
4192 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
4193 continue;
4194 } else if (strstr(line, "HE capabilities") != NULL) {
developer615510b2022-09-27 10:14:35 +08004195 strcat(scan_array[index].ap_SupportedStandards, ",ax");
4196 strcpy(scan_array[index].ap_OperatingStandards, "ax");
4197 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004198 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
4199 if (strstr(line, "HE40/2.4GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08004200 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
developera3c68b92022-09-13 15:27:29 +08004201 else
developer615510b2022-09-27 10:14:35 +08004202 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
developera3c68b92022-09-13 15:27:29 +08004203 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
developer615510b2022-09-27 10:14:35 +08004204 if (strstr(line, "HE80/5GHz") != NULL) {
4205 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
4206 ret = fgets(line, sizeof(line), f);
4207 } else
4208 continue;
developera3c68b92022-09-13 15:27:29 +08004209 if (strstr(line, "HE160/5GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08004210 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developera3c68b92022-09-13 15:27:29 +08004211 }
developer615510b2022-09-27 10:14:35 +08004212 continue;
developera3c68b92022-09-13 15:27:29 +08004213 } else if (strstr(line, "WPA") != NULL) {
4214 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
4215 } else if (strstr(line, "RSN") != NULL) {
4216 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
4217 } else if (strstr(line, "Group cipher") != NULL) {
4218 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
4219 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
4220 strcpy(scan_array[index].ap_EncryptionMode, "AES");
4221 }
4222 }
developer615510b2022-09-27 10:14:35 +08004223 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004224 }
4225
4226 if (!filter_BSS) {
4227 *output_array_size = index + 1;
4228 } else {
4229 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
4230 *output_array_size = index;
4231 }
4232 *neighbor_ap_array = scan_array;
developera3c68b92022-09-13 15:27:29 +08004233 pclose(f);
developer5550e242022-09-30 09:59:32 +08004234 free(channels_noise_arr);
developer06a01d92022-09-07 16:32:39 +08004235 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08004236 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004237}
4238
4239//>> Deprecated: used for old RDKB code.
4240INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
4241{
4242 INT status = RETURN_ERR;
4243
4244 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4245 output_struct->wifi_PLCPErrorCount = 0;
4246 output_struct->wifi_FCSErrorCount = 0;
4247 output_struct->wifi_InvalidMACCount = 0;
4248 output_struct->wifi_PacketsOtherReceived = 0;
4249 output_struct->wifi_Noise = 0;
4250 status = RETURN_OK;
4251 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4252 return status;
4253}
4254
4255INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
4256{
developerd946fd62022-12-08 18:03:28 +08004257 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08004258 char cmd[128] = {0};
4259 char buf[1280] = {0};
developer06a01d92022-09-07 16:32:39 +08004260 char *pos = NULL;
4261
4262 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4263 if (NULL == output_struct)
4264 return RETURN_ERR;
4265
developerac6f1142022-12-20 19:26:35 +08004266 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004267 return RETURN_ERR;
4268
developer06a01d92022-09-07 16:32:39 +08004269 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4270
developerd946fd62022-12-08 18:03:28 +08004271 snprintf(cmd, sizeof(cmd), "ifconfig %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004272 _syscmd(cmd, buf, sizeof(buf));
4273
4274 pos = buf;
4275 if ((pos = strstr(pos, "RX packets:")) == NULL)
4276 return RETURN_ERR;
4277 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
4278
4279 if ((pos = strstr(pos, "TX packets:")) == NULL)
4280 return RETURN_ERR;
4281 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
4282
4283 if ((pos = strstr(pos, "RX bytes:")) == NULL)
4284 return RETURN_ERR;
4285 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
4286
4287 if ((pos = strstr(pos, "TX bytes:")) == NULL)
4288 return RETURN_ERR;
4289 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
4290
developerd946fd62022-12-08 18:03:28 +08004291 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l | tr -d '\n'", interface_name);
developer06a01d92022-09-07 16:32:39 +08004292 _syscmd(cmd, buf, sizeof(buf));
4293 sscanf(buf, "%lu", &output_struct->wifi_Associations);
4294
4295#if 0
4296 //TODO: need to revisit below implementation
4297 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4298 char interface_name[MAX_BUF_SIZE] = {0};
4299 char interface_status[MAX_BUF_SIZE] = {0};
4300 char Value[MAX_BUF_SIZE] = {0};
4301 char buf[MAX_CMD_SIZE] = {0};
4302 char cmd[MAX_CMD_SIZE] = {0};
4303 FILE *fp = NULL;
4304
4305 if (NULL == output_struct) {
4306 return RETURN_ERR;
4307 }
4308
4309 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4310
4311 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
4312 {
4313 if(apIndex == 0) //private_wifi for 2.4G
4314 {
developerac6f1142022-12-20 19:26:35 +08004315 wifi_GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
developer06a01d92022-09-07 16:32:39 +08004316 }
4317 else if(apIndex == 1) //private_wifi for 5G
4318 {
developerac6f1142022-12-20 19:26:35 +08004319 wifi_GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
developer06a01d92022-09-07 16:32:39 +08004320 }
4321 else if(apIndex == 4) //public_wifi for 2.4G
4322 {
4323 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4324 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4325 {
4326 return RETURN_ERR;
4327 }
4328 if(buf[0] == '#')//tp-link
developerac6f1142022-12-20 19:26:35 +08004329 wifi_GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
developer06a01d92022-09-07 16:32:39 +08004330 else//tenda
developerac6f1142022-12-20 19:26:35 +08004331 wifi_GetInterfaceName_virtualInterfaceName_2G(interface_name);
developer06a01d92022-09-07 16:32:39 +08004332 }
4333 else if(apIndex == 5) //public_wifi for 5G
4334 {
developerac6f1142022-12-20 19:26:35 +08004335 wifi_GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
developer06a01d92022-09-07 16:32:39 +08004336 }
4337
4338 GetIfacestatus(interface_name, interface_status);
4339
4340 if(0 != strcmp(interface_status, "1"))
4341 return RETURN_ERR;
4342
4343 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4344 system(cmd);
4345
4346 fp = fopen("/tmp/SSID_Stats.txt", "r");
4347 if(fp == NULL)
4348 {
4349 printf("/tmp/SSID_Stats.txt not exists \n");
4350 return RETURN_ERR;
4351 }
4352 fclose(fp);
4353
4354 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4355 File_Reading(buf, Value);
4356 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
4357
4358 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4359 File_Reading(buf, Value);
4360 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
4361
4362 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4363 File_Reading(buf, Value);
4364 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
4365
4366 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4367 File_Reading(buf, Value);
4368 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
4369
4370 /* There is no specific parameter from caller to associate the value wifi_Associations */
4371 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
4372 //_syscmd(cmd, buf, sizeof(buf));
4373 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
4374 }
4375#endif
4376 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4377 return RETURN_OK;
4378}
4379
4380INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
4381{
4382 char interface_name[MAX_BUF_SIZE] = {0};
4383 char interface_status[MAX_BUF_SIZE] = {0};
4384 char Value[MAX_BUF_SIZE] = {0};
4385 char buf[MAX_CMD_SIZE] = {0};
4386 char cmd[MAX_CMD_SIZE] = {0};
4387 FILE *fp = NULL;
4388
4389 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4390 if (NULL == output_struct)
4391 return RETURN_ERR;
4392
4393 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
4394
developerac6f1142022-12-20 19:26:35 +08004395 if (wifi_GetInterfaceName(apIndex,interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08004396 return RETURN_ERR;
4397 GetIfacestatus(interface_name, interface_status);
developer06a01d92022-09-07 16:32:39 +08004398
developerd946fd62022-12-08 18:03:28 +08004399 if(0 != strcmp(interface_status, "1"))
4400 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08004401
developerd946fd62022-12-08 18:03:28 +08004402 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4403 system(cmd);
developer06a01d92022-09-07 16:32:39 +08004404
developerd946fd62022-12-08 18:03:28 +08004405 fp = fopen("/tmp/SSID_Stats.txt", "r");
4406 if(fp == NULL)
4407 {
4408 printf("/tmp/SSID_Stats.txt not exists \n");
4409 return RETURN_ERR;
4410 }
4411 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08004412
developerd946fd62022-12-08 18:03:28 +08004413 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4414 File_Reading(buf, Value);
4415 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004416
developerd946fd62022-12-08 18:03:28 +08004417 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4418 File_Reading(buf, Value);
4419 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004420
developerd946fd62022-12-08 18:03:28 +08004421 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4422 File_Reading(buf, Value);
4423 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004424
developerd946fd62022-12-08 18:03:28 +08004425 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4426 File_Reading(buf, Value);
4427 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004428
4429 output_struct->wifi_UnicastPacketsSent = 0;
4430 output_struct->wifi_UnicastPacketsReceived = 0;
4431 output_struct->wifi_MulticastPacketsSent = 0;
4432 output_struct->wifi_MulticastPacketsReceived = 0;
4433 output_struct->wifi_BroadcastPacketsSent = 0;
4434 output_struct->wifi_BroadcastPacketsRecevied = 0;
4435 output_struct->wifi_UnknownPacketsReceived = 0;
4436
4437 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4438 return RETURN_OK;
4439}
4440
4441INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
4442{
4443 INT status = RETURN_ERR;
4444
4445 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4446 //Below values should get updated from hal
4447 output_struct->wifi_RetransCount=0;
4448 output_struct->wifi_FailedRetransCount=0;
4449 output_struct->wifi_RetryCount=0;
4450 output_struct->wifi_MultipleRetryCount=0;
4451 output_struct->wifi_ACKFailureCount=0;
4452 output_struct->wifi_AggregatedPacketCount=0;
4453
4454 status = RETURN_OK;
4455 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4456
4457 return status;
4458}
4459
4460INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4461{
4462 INT status = RETURN_ERR;
4463 UINT index;
4464 wifi_neighbor_ap_t *pt=NULL;
4465
4466 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4467 *output_array_size=2;
4468 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4469 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4470 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4471 strcpy(pt->ap_Radio,"");
4472 strcpy(pt->ap_SSID,"");
4473 strcpy(pt->ap_BSSID,"");
4474 strcpy(pt->ap_Mode,"");
4475 pt->ap_Channel=1;
4476 pt->ap_SignalStrength=0;
4477 strcpy(pt->ap_SecurityModeEnabled,"");
4478 strcpy(pt->ap_EncryptionMode,"");
4479 strcpy(pt->ap_OperatingFrequencyBand,"");
4480 strcpy(pt->ap_SupportedStandards,"");
4481 strcpy(pt->ap_OperatingStandards,"");
4482 strcpy(pt->ap_OperatingChannelBandwidth,"");
4483 pt->ap_BeaconPeriod=1;
4484 pt->ap_Noise=0;
4485 strcpy(pt->ap_BasicDataTransferRates,"");
4486 strcpy(pt->ap_SupportedDataTransferRates,"");
4487 pt->ap_DTIMPeriod=1;
4488 pt->ap_ChannelUtilization = 1;
4489 }
4490
4491 status = RETURN_OK;
4492 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4493
4494 return status;
4495}
4496
4497//----------------- AP HAL -------------------------------
4498
4499//>> Deprecated: used for old RDKB code.
4500INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4501{
4502 if (NULL == output_ulong || NULL == output_struct)
4503 return RETURN_ERR;
4504 *output_ulong = 0;
4505 *output_struct = NULL;
4506 return RETURN_OK;
4507}
4508
4509#ifdef HAL_NETLINK_IMPL
4510static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4511 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4512 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4513 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4514 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4515 char mac_addr[20];
4516 static int count=0;
4517 int rate=0;
4518
4519 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4520
4521 nla_parse(tb,
4522 NL80211_ATTR_MAX,
4523 genlmsg_attrdata(gnlh, 0),
4524 genlmsg_attrlen(gnlh, 0),
4525 NULL);
4526
4527 if(!tb[NL80211_ATTR_STA_INFO]) {
4528 fprintf(stderr, "sta stats missing!\n");
4529 return NL_SKIP;
4530 }
4531
4532
4533 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4534 fprintf(stderr, "failed to parse nested attributes!\n");
4535 return NL_SKIP;
4536 }
4537
4538 //devIndex starts from 1
4539 if( ++count == out->wifi_devIndex )
4540 {
4541 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4542 //Getting the mac addrress
4543 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4544
4545 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4546 fprintf(stderr, "failed to parse nested rate attributes!");
4547 return NL_SKIP;
4548 }
4549
4550 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4551 if(rinfo[NL80211_RATE_INFO_BITRATE])
4552 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4553 out->wifi_devTxRate = rate/10;
4554 }
4555
4556 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4557 fprintf(stderr, "failed to parse nested rate attributes!");
4558 return NL_SKIP;
4559 }
4560
4561 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4562 if(rinfo[NL80211_RATE_INFO_BITRATE])
4563 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4564 out->wifi_devRxRate = rate/10;
4565 }
4566 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4567 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4568
4569 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4570 count = 0; //starts the count for next cycle
4571 return NL_STOP;
4572 }
4573
4574 return NL_SKIP;
4575
4576}
4577#endif
4578
4579INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4580{
4581#ifdef HAL_NETLINK_IMPL
developer30423732022-12-01 16:17:49 +08004582 Netlink nl = {0};
4583 char if_name[10] = {0};
developerd946fd62022-12-08 18:03:28 +08004584 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08004585
developer30423732022-12-01 16:17:49 +08004586 wifi_device_info_t info = {0};
developer06a01d92022-09-07 16:32:39 +08004587 info.wifi_devIndex = devIndex;
4588
developerac6f1142022-12-20 19:26:35 +08004589 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004590 return RETURN_ERR;
4591
4592 snprintf(if_name,sizeof(if_name),"%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004593
4594 nl.id = initSock80211(&nl);
4595
4596 if (nl.id < 0) {
4597 fprintf(stderr, "Error initializing netlink \n");
4598 return -1;
4599 }
4600
4601 struct nl_msg* msg = nlmsg_alloc();
4602
4603 if (!msg) {
4604 fprintf(stderr, "Failed to allocate netlink message.\n");
4605 nlfree(&nl);
4606 return -2;
4607 }
4608
4609 genlmsg_put(msg,
4610 NL_AUTO_PORT,
4611 NL_AUTO_SEQ,
4612 nl.id,
4613 0,
4614 NLM_F_DUMP,
4615 NL80211_CMD_GET_STATION,
4616 0);
4617
4618 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4619 nl_send_auto(nl.socket, msg);
4620 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4621 nl_recvmsgs(nl.socket, nl.cb);
4622 nlmsg_free(msg);
4623 nlfree(&nl);
4624
4625 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4626 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4627 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4628 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4629 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4630 return RETURN_OK;
4631#else
4632 //iw utility to retrieve station information
4633#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4634#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4635#define MACFILE "/tmp/wifi_AssoMac.txt"
4636#define TXRATEFILE "/tmp/wifi_txrate.txt"
4637#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4638 FILE *file = NULL;
4639 char if_name[10] = {'\0'};
4640 char pipeCmd[256] = {'\0'};
developer30423732022-12-01 16:17:49 +08004641 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08004642 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08004643 int count = 0, device = 0;
developer06a01d92022-09-07 16:32:39 +08004644
developerac6f1142022-12-20 19:26:35 +08004645 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004646 return RETURN_ERR;
4647
4648 snprintf(if_name,sizeof(if_name),"%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004649
4650 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4651 file = popen(pipeCmd, "r");
4652
4653 if(file == NULL)
4654 return RETURN_ERR; //popen failed
4655
4656 fgets(line, sizeof line, file);
4657 device = atoi(line);
4658 pclose(file);
4659
4660 if(device == 0)
4661 return RETURN_ERR; //No devices are connected
4662
4663 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4664 system(pipeCmd);
4665
4666 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4667
4668 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4669
4670 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4671
4672 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4673
4674 //devIndex starts from 1, ++count
4675 if((file = fopen(SIGNALFILE, "r")) != NULL )
4676 {
4677 for(count =0;fgets(line, sizeof line, file) != NULL;)
4678 {
4679 if (++count == devIndex)
4680 {
4681 output_struct->wifi_devSignalStrength = atoi(line);
4682 break;
4683 }
4684 }
4685 fclose(file);
4686 }
4687 else
4688 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4689
4690 if((file = fopen(MACFILE, "r")) != NULL )
4691 {
4692 for(count =0;fgets(line, sizeof line, file) != NULL;)
4693 {
4694 if (++count == devIndex)
4695 {
4696 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]);
4697 break;
4698 }
4699 }
4700 fclose(file);
4701 }
4702 else
4703 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4704
4705 if((file = fopen(TXRATEFILE, "r")) != NULL )
4706 {
4707 for(count =0;fgets(line, sizeof line, file) != NULL;)
4708 {
4709 if (++count == devIndex)
4710 {
4711 output_struct->wifi_devTxRate = atoi(line);
4712 break;
4713 }
4714 }
4715 fclose(file);
4716 }
4717 else
4718 fprintf(stderr,"fopen wifi_txrate.txt failed");
4719
4720 if((file = fopen(RXRATEFILE, "r")) != NULL)
4721 {
4722 for(count =0;fgets(line, sizeof line, file) != NULL;)
4723 {
4724 if (++count == devIndex)
4725 {
4726 output_struct->wifi_devRxRate = atoi(line);
4727 break;
4728 }
4729 }
4730 fclose(file);
4731 }
4732 else
4733 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4734
4735 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4736
4737 return RETURN_OK;
4738#endif
4739}
4740
4741INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4742{
4743 if (NULL == device)
4744 return RETURN_ERR;
4745 return RETURN_OK;
4746}
4747//<<
4748
4749
4750//--------------wifi_ap_hal-----------------------------
4751//enables CTS protection for the radio used by this AP
4752INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4753{
4754 //save config and Apply instantly
4755 return RETURN_ERR;
4756}
4757
4758// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4759INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4760{
developer463d39a2022-09-13 15:32:51 +08004761 char config_file[64] = {'\0'};
4762 char buf[64] = {'\0'};
4763 struct params list;
4764
4765 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4766 list.name = "ht_coex";
4767 snprintf(buf, sizeof(buf), "%d", enable);
4768 list.value = buf;
4769
4770 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4771 wifi_hostapdWrite(config_file, &list, 1);
4772 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4773
4774 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4775
4776 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004777}
4778
4779//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4780INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4781{
developerea4bcce2022-09-13 15:26:13 +08004782 char config_file[MAX_BUF_SIZE] = {'\0'};
4783 char buf[MAX_BUF_SIZE] = {'\0'};
4784 struct params list;
4785
4786 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4787 if (threshold < 256 || threshold > 2346 )
4788 return RETURN_ERR;
4789 list.name = "fragm_threshold";
4790 snprintf(buf, sizeof(buf), "%d", threshold);
4791 list.value = buf;
4792
4793 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4794 wifi_hostapdWrite(config_file, &list, 1);
4795 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developer06a01d92022-09-07 16:32:39 +08004796
developerea4bcce2022-09-13 15:26:13 +08004797 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004798
4799 return RETURN_OK;
4800}
4801
4802// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4803INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4804{
developer51a927d2022-09-13 15:42:22 +08004805 char config_file[64] = {'\0'};
developer110b8a32022-12-26 15:56:44 +08004806 char cmd[512] = {'\0'};
4807 char buf[512] = {'\0'};
developer51a927d2022-09-13 15:42:22 +08004808 char stbc_config[16] = {'\0'};
4809 wifi_band band;
4810 int iterator = 0;
4811 BOOL current_stbc = FALSE;
developer110b8a32022-12-26 15:56:44 +08004812 int ant_count = 0;
4813 int ant_bitmap = 0;
4814 struct params list;
developer51a927d2022-09-13 15:42:22 +08004815
4816 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4817
4818 band = wifi_index_to_band(radioIndex);
4819 if (band == band_invalid)
4820 return RETURN_ERR;
4821
4822 if (band == band_2_4)
4823 iterator = 1;
4824 else if (band == band_5)
4825 iterator = 2;
4826 else
4827 return RETURN_OK;
4828
developer110b8a32022-12-26 15:56:44 +08004829 wifi_getRadioTxChainMask(radioIndex, &ant_bitmap);
4830 for (; ant_bitmap > 0; ant_bitmap >>= 1)
4831 ant_count += ant_bitmap & 1;
4832
4833 if (ant_count == 1 && STBC_Enable == TRUE) {
4834 fprintf(stderr, "%s: can not enable STBC when using only one antenna\n", __func__);
4835 return RETURN_OK;
4836 }
4837
developer51a927d2022-09-13 15:42:22 +08004838 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4839
4840 // set ht and vht config
4841 for (int i = 0; i < iterator; i++) {
4842 memset(stbc_config, 0, sizeof(stbc_config));
4843 memset(cmd, 0, sizeof(cmd));
4844 memset(buf, 0, sizeof(buf));
developer110b8a32022-12-26 15:56:44 +08004845 list.name = (i == 0)?"ht_capab":"vht_capab";
4846 snprintf(stbc_config, sizeof(stbc_config), "%s", list.name);
developer51a927d2022-09-13 15:42:22 +08004847 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4848 _syscmd(cmd, buf, sizeof(buf));
4849 if (strlen(buf) != 0)
4850 current_stbc = TRUE;
4851 if (current_stbc == STBC_Enable)
4852 continue;
4853
4854 if (STBC_Enable == TRUE) {
4855 // Append the STBC flags in capab config
4856 memset(cmd, 0, sizeof(cmd));
4857 if (i == 0)
developer6372c2b2022-10-27 17:39:51 +08004858 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004859 else
developer6372c2b2022-10-27 17:39:51 +08004860 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1][RX-STBC-1]/' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004861 _syscmd(cmd, buf, sizeof(buf));
4862 } else if (STBC_Enable == FALSE) {
4863 // Remove the STBC flags and remain other flags in capab
4864 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004865 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004866 _syscmd(cmd, buf, sizeof(buf));
4867 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004868 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004869 _syscmd(cmd, buf, sizeof(buf));
4870 }
developer110b8a32022-12-26 15:56:44 +08004871 wifi_hostapdRead(config_file, list.name, buf, sizeof(buf));
4872 list.value = buf;
4873 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
developer51a927d2022-09-13 15:42:22 +08004874 }
4875
4876 wifi_reloadAp(radioIndex);
4877
4878 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4879 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004880}
4881
4882// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4883INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4884{
developerfe7aefc2022-12-23 17:13:37 +08004885 char cmd[128] = {0};
4886 char buf[128] = {0};
4887 char interface_name[16] = {0};
developer54e6b9f2022-09-28 14:41:20 +08004888
4889 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4890
4891 if(output_bool == NULL)
4892 return RETURN_ERR;
4893
developerfe7aefc2022-12-23 17:13:37 +08004894 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4895 return RETURN_ERR;
developer54e6b9f2022-09-28 14:41:20 +08004896
developerfe7aefc2022-12-23 17:13:37 +08004897 sprintf(cmd, "hostapd_cli -i %s get_amsdu | awk '{print $3}'", interface_name);
4898 _syscmd(cmd, buf, sizeof(buf));
4899
4900 if (strncmp(buf, "1", 1) == 0)
developer54e6b9f2022-09-28 14:41:20 +08004901 *output_bool = TRUE;
4902 else
4903 *output_bool = FALSE;
4904
4905 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4906 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004907}
4908
4909// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4910INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4911{
developerfe7aefc2022-12-23 17:13:37 +08004912 char config_file[128] = {0};
4913 struct params list = {0};
4914 BOOL enable;
developer54e6b9f2022-09-28 14:41:20 +08004915
4916 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4917
developerfe7aefc2022-12-23 17:13:37 +08004918 if (wifi_getRadioAMSDUEnable(radioIndex, &enable) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004919 return RETURN_ERR;
developer54e6b9f2022-09-28 14:41:20 +08004920
developerfe7aefc2022-12-23 17:13:37 +08004921 if (amsduEnable == enable)
4922 return RETURN_OK;
4923
4924 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4925 list.name = "amsdu";
4926 list.value = amsduEnable? "1":"0";
4927 wifi_hostapdWrite(config_file, &list, 1);
4928 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
4929 wifi_reloadAp(radioIndex);
developer54e6b9f2022-09-28 14:41:20 +08004930
4931 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4932 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004933}
4934
4935//P2 // outputs the number of Tx streams
4936INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4937{
developer2de97692022-09-26 14:00:03 +08004938 char buf[8] = {0};
4939 char cmd[128] = {0};
developer033b37b2022-10-18 11:27:46 +08004940 int phyId = 0;
developer2de97692022-09-26 14:00:03 +08004941
4942 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4943
developer033b37b2022-10-18 11:27:46 +08004944 phyId = radio_index_to_phy(radioIndex);
developerfe7aefc2022-12-23 17:13:37 +08004945 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Configured Antennas' | awk '{print $4}'", phyId);
developer110b8a32022-12-26 15:56:44 +08004946 _syscmd(cmd, buf, sizeof(buf));
developer2de97692022-09-26 14:00:03 +08004947
developer110b8a32022-12-26 15:56:44 +08004948 *output_int = (INT)strtol(buf, NULL, 16);
developer2de97692022-09-26 14:00:03 +08004949
4950 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4951
4952 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004953}
4954
developer110b8a32022-12-26 15:56:44 +08004955INT fitChainMask(INT radioIndex, int antcount)
4956{
4957 char buf[128] = {0};
4958 char cmd[128] = {0};
4959 char config_file[64] = {0};
4960 wifi_band band;
4961 struct params list[2] = {0};
4962
4963 band = wifi_index_to_band(radioIndex);
4964 if (band == band_invalid)
4965 return RETURN_ERR;
4966
4967 list[0].name = "he_mu_beamformer";
4968 list[1].name = "he_su_beamformer";
4969
4970 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4971 if (antcount == 1) {
4972 // remove config about multiple antennas
4973 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
4974 _syscmd(cmd, buf, sizeof(buf));
4975
4976 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SOUNDING-DIMENSION-.\\]//' %s", config_file);
4977 _syscmd(cmd, buf, sizeof(buf));
4978
4979 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SU-BEAMFORMER\\]//' %s", config_file);
4980 _syscmd(cmd, buf, sizeof(buf));
4981
4982 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[MU-BEAMFORMER\\]//' %s", config_file);
4983 _syscmd(cmd, buf, sizeof(buf));
4984
4985 list[0].value = "0";
4986 list[1].value = "0";
4987 } else {
4988 // 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.
4989 if (band == band_2_4 || band == band_5) {
4990 snprintf(cmd, sizeof(cmd), "cat %s | grep '^ht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
4991 _syscmd(cmd, buf, sizeof(buf));
4992 if (strlen(buf) > 0) {
4993 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC]/' %s", config_file);
4994 _syscmd(cmd, buf, sizeof(buf));
4995 }
4996 }
4997 if (band == band_5) {
4998 snprintf(cmd, sizeof(cmd), "cat %s | grep '^vht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
4999 _syscmd(cmd, buf, sizeof(buf));
5000 if (strlen(buf) > 0) {
5001 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1]/' %s", config_file);
5002 _syscmd(cmd, buf, sizeof(buf));
5003 }
5004 }
5005
5006 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SU-BEAMFORMER\\]'", config_file);
5007 _syscmd(cmd, buf, sizeof(buf));
5008 if (strlen(buf) == 0) {
5009 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SU-BEAMFORMER]/' %s", config_file);
5010 _syscmd(cmd, buf, sizeof(buf));
5011 }
5012
5013 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[MU-BEAMFORMER\\]'", config_file);
5014 _syscmd(cmd, buf, sizeof(buf));
5015 if (strlen(buf) == 0) {
5016 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[MU-BEAMFORMER]/' %s", config_file);
5017 _syscmd(cmd, buf, sizeof(buf));
5018 }
5019
5020 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SOUNDING-DIMENSION-.\\]'", config_file);
5021 _syscmd(cmd, buf, sizeof(buf));
5022 if (strlen(buf) == 0) {
5023 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SOUNDING-DIMENSION-%d]/' %s", antcount, config_file);
5024 } else {
5025 snprintf(cmd, sizeof(cmd), "sed -r -i 's/(SOUNDING-DIMENSION-)./\\1%d/' %s", antcount, config_file);
5026 }
5027 _syscmd(cmd, buf, sizeof(buf));
5028
5029 list[0].value = "1";
5030 list[1].value = "1";
5031 }
5032 wifi_hostapdWrite(config_file, list, 2);
5033}
5034
developer06a01d92022-09-07 16:32:39 +08005035//P2 // sets the number of Tx streams to an enviornment variable
5036INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
5037{
developer2de97692022-09-26 14:00:03 +08005038 char cmd[128] = {0};
5039 char buf[128] = {0};
developer033b37b2022-10-18 11:27:46 +08005040 int phyId = 0;
developer110b8a32022-12-26 15:56:44 +08005041 int cur_mask = 0;
5042 int antcount = 0;
5043 wifi_band band;
developer2de97692022-09-26 14:00:03 +08005044
5045 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5046
developer110b8a32022-12-26 15:56:44 +08005047 if (numStreams <= 0) {
5048 fprintf(stderr, "%s: chainmask is not supported %d.\n", __func__, numStreams);
developer2de97692022-09-26 14:00:03 +08005049 return RETURN_ERR;
5050 }
developer110b8a32022-12-26 15:56:44 +08005051
5052 wifi_getRadioTxChainMask(radioIndex, &cur_mask);
5053 if (cur_mask == numStreams)
5054 return RETURN_OK;
5055
developer2de97692022-09-26 14:00:03 +08005056 wifi_setRadioEnable(radioIndex, FALSE);
developer033b37b2022-10-18 11:27:46 +08005057
5058 phyId = radio_index_to_phy(radioIndex);
5059 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", phyId, numStreams);
developer2de97692022-09-26 14:00:03 +08005060 _syscmd(cmd, buf, sizeof(buf));
5061
5062 if (strlen(buf) > 0) {
5063 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
5064 return RETURN_ERR;
5065 }
developer2de97692022-09-26 14:00:03 +08005066
developer110b8a32022-12-26 15:56:44 +08005067 // if chain mask changed, we need to make the hostapd config valid.
5068 for (cur_mask = numStreams; cur_mask > 0; cur_mask >>= 1) {
5069 antcount += cur_mask & 1;
developer2de97692022-09-26 14:00:03 +08005070 }
developer110b8a32022-12-26 15:56:44 +08005071 fitChainMask(radioIndex, antcount);
5072
5073 wifi_setRadioEnable(radioIndex, TRUE);
5074
developer2de97692022-09-26 14:00:03 +08005075 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5076 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005077}
5078
5079//P2 // outputs the number of Rx streams
5080INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
5081{
developer110b8a32022-12-26 15:56:44 +08005082 char buf[8] = {0};
5083 char cmd[128] = {0};
5084 int phyId = 0;
5085
developer2de97692022-09-26 14:00:03 +08005086 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer110b8a32022-12-26 15:56:44 +08005087
5088 phyId = radio_index_to_phy(radioIndex);
5089 sprintf(cmd, "iw phy%d info | grep 'Configured Antennas' | awk '{print $6}'", phyId);
5090 _syscmd(cmd, buf, sizeof(buf));
5091
5092 *output_int = (INT)strtol(buf, NULL, 16);
5093
developer2de97692022-09-26 14:00:03 +08005094 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer110b8a32022-12-26 15:56:44 +08005095
developer06a01d92022-09-07 16:32:39 +08005096 return RETURN_OK;
5097}
5098
5099//P2 // sets the number of Rx streams to an enviornment variable
5100INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
5101{
developer2de97692022-09-26 14:00:03 +08005102 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5103 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
5104 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
5105 return RETURN_ERR;
5106 }
5107 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08005108 return RETURN_ERR;
5109}
5110
5111//Get radio RDG enable setting
5112INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
5113{
5114 if (NULL == output_bool)
5115 return RETURN_ERR;
5116 *output_bool = TRUE;
5117 return RETURN_OK;
5118}
5119
5120//Get radio RDG enable setting
5121INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
5122{
5123 if (NULL == output_bool)
5124 return RETURN_ERR;
5125 *output_bool = TRUE;
5126 return RETURN_OK;
5127}
5128
5129//Set radio RDG enable setting
5130INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
5131{
5132 return RETURN_ERR;
5133}
5134
5135//Get radio ADDBA enable setting
5136INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
5137{
5138 if (NULL == output_bool)
5139 return RETURN_ERR;
5140 *output_bool = TRUE;
5141 return RETURN_OK;
5142}
5143
5144//Set radio ADDBA enable setting
5145INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
5146{
5147 return RETURN_ERR;
5148}
5149
5150//Get radio auto block ack enable setting
5151INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
5152{
5153 if (NULL == output_bool)
5154 return RETURN_ERR;
5155 *output_bool = TRUE;
5156 return RETURN_OK;
5157}
5158
5159//Set radio auto block ack enable setting
5160INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
5161{
5162 return RETURN_ERR;
5163}
5164
5165//Get radio 11n pure mode enable support
5166INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
5167{
5168 if (NULL == output_bool)
5169 return RETURN_ERR;
5170 *output_bool = TRUE;
5171 return RETURN_OK;
5172}
5173
5174//Get radio 11n pure mode enable setting
5175INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
5176{
5177 if (NULL == output_bool)
5178 return RETURN_ERR;
5179 *output_bool = TRUE;
5180 return RETURN_OK;
5181}
5182
5183//Set radio 11n pure mode enable setting
5184INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
5185{
5186 return RETURN_ERR;
5187}
5188
5189//Get radio IGMP snooping enable setting
5190INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
5191{
developerd946fd62022-12-08 18:03:28 +08005192 char interface_name[16] = {0};
developer81bf2ed2022-09-13 15:31:14 +08005193 char cmd[128]={0};
5194 char buf[4]={0};
5195 bool bridge = FALSE, mac80211 = FALSE;
5196 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5197
5198 if(output_bool == NULL)
developer06a01d92022-09-07 16:32:39 +08005199 return RETURN_ERR;
developer81bf2ed2022-09-13 15:31:14 +08005200
5201 *output_bool = FALSE;
5202
5203 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
5204 _syscmd(cmd, buf, sizeof(buf));
5205 if (strncmp(buf, "1", 1) == 0)
5206 bridge = TRUE;
5207
developerac6f1142022-12-20 19:26:35 +08005208 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005209 return RETURN_ERR;
5210 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast", BRIDGE_NAME, interface_name);
developer81bf2ed2022-09-13 15:31:14 +08005211 _syscmd(cmd, buf, sizeof(buf));
5212 if (strncmp(buf, "1", 1) == 0)
5213 mac80211 = TRUE;
5214
5215 if (bridge && mac80211)
5216 *output_bool = TRUE;
5217
5218 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08005219 return RETURN_OK;
5220}
5221
5222//Set radio IGMP snooping enable setting
5223INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
5224{
developerd946fd62022-12-08 18:03:28 +08005225 char interface_name[16] = {0};
developer81bf2ed2022-09-13 15:31:14 +08005226 char cmd[128]={0};
5227 char buf[4]={0};
developer894affa2023-05-10 18:13:19 +08005228 int max_num_radios = 0;
5229 int apIndex = 0;
developer81bf2ed2022-09-13 15:31:14 +08005230 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5231
5232 // bridge
developerfb09ba62023-06-09 17:03:21 +08005233 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
developer81bf2ed2022-09-13 15:31:14 +08005234 _syscmd(cmd, buf, sizeof(buf));
5235
developer804c64f2022-10-19 13:54:40 +08005236 wifi_getMaxRadioNumber(&max_num_radios);
developer81bf2ed2022-09-13 15:31:14 +08005237 // mac80211
developer894affa2023-05-10 18:13:19 +08005238 for (int i = 0; i < MAX_NUM_VAP_PER_RADIO; i++) {
5239 apIndex = radioIndex + i*max_num_radios;
5240 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5241 continue;
developerfb09ba62023-06-09 17:03:21 +08005242 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast", enable, BRIDGE_NAME, interface_name);
developer81bf2ed2022-09-13 15:31:14 +08005243 _syscmd(cmd, buf, sizeof(buf));
5244 }
5245 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5246 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005247}
5248
5249//Get the Reset count of radio
5250INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
5251{
5252 if (NULL == output_int)
5253 return RETURN_ERR;
5254 *output_int = (radioIndex==0)? 1: 3;
5255
5256 return RETURN_OK;
5257}
5258
5259
5260//---------------------------------------------------------------------------------------------------
5261//
5262// Additional Wifi AP level APIs used for Access Point devices
5263//
5264//---------------------------------------------------------------------------------------------------
5265
5266// creates a new ap and pushes these parameters to the hardware
5267INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
5268{
developer7930d352022-12-21 17:55:42 +08005269 // Deprecated when use hal version 3, use wifi_createVap() instead.
developer06a01d92022-09-07 16:32:39 +08005270 return RETURN_OK;
5271}
5272
5273// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
5274INT wifi_deleteAp(INT apIndex)
5275{
developerd946fd62022-12-08 18:03:28 +08005276 char interface_name[16] = {0};
developer89df4502023-02-16 20:45:02 +08005277 char buf[128] = {0};
5278 char cmd[128] = {0};
developer06a01d92022-09-07 16:32:39 +08005279
developerac6f1142022-12-20 19:26:35 +08005280 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005281 return RETURN_ERR;
developera77d84b2023-02-22 16:10:50 +08005282
developer89df4502023-02-16 20:45:02 +08005283 if (wifi_setApEnable(apIndex, FALSE) != RETURN_OK)
5284 return RETURN_ERR;
5285
developer7930d352022-12-21 17:55:42 +08005286 snprintf(cmd,sizeof(cmd), "iw %s del", interface_name);
developer06a01d92022-09-07 16:32:39 +08005287 _syscmd(cmd, buf, sizeof(buf));
5288
5289 wifi_removeApSecVaribles(apIndex);
developer06a01d92022-09-07 16:32:39 +08005290 return RETURN_OK;
5291}
5292
5293// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
5294INT wifi_getApName(INT apIndex, CHAR *output_string)
5295{
developerd946fd62022-12-08 18:03:28 +08005296 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005297 if(NULL == output_string)
5298 return RETURN_ERR;
5299
developerac6f1142022-12-20 19:26:35 +08005300 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer67b8ee92022-12-20 10:48:43 +08005301 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex); // For wifiagent generating data model.
developerd946fd62022-12-08 18:03:28 +08005302 else
5303 snprintf(output_string, 16, "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08005304 return RETURN_OK;
5305}
5306
5307// Outputs the index number in that corresponds to the SSID string
5308INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
5309{
developerd946fd62022-12-08 18:03:28 +08005310 char cmd [128] = {0};
5311 char buf[32] = {0};
5312 char *apIndex_str = NULL;
developerd946fd62022-12-08 18:03:28 +08005313 bool enable = FALSE;
developer06a01d92022-09-07 16:32:39 +08005314
developerefb790a2023-12-26 18:58:32 +08005315#ifdef DYNAMIC_IF_NAME
developerd946fd62022-12-08 18:03:28 +08005316 snprintf(cmd, sizeof(cmd), "grep -rn ^interface=%s$ /nvram/hostapd*.conf | cut -d '.' -f1 | cut -d 'd' -f2 | tr -d '\\n'", inputSsidString);
5317 _syscmd(cmd, buf, sizeof(buf));
developer67b8ee92022-12-20 10:48:43 +08005318
developerac6f1142022-12-20 19:26:35 +08005319 if (strlen(buf) != 0) {
5320 apIndex_str = strtok(buf, "\n");
5321 *output_int = strtoul(apIndex_str, NULL, 10);
5322 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005323 }
developerefb790a2023-12-26 18:58:32 +08005324#endif
developer67b8ee92022-12-20 10:48:43 +08005325 // If interface name is not in hostapd config, the caller maybe wifi agent to generate data model.
5326 apIndex_str = strstr(inputSsidString, AP_PREFIX);
5327 if (apIndex_str) {
5328 sscanf(apIndex_str + strlen(AP_PREFIX), "%d", output_int);
5329 return RETURN_OK;
5330 }
developerd946fd62022-12-08 18:03:28 +08005331 *output_int = -1;
5332 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005333}
5334
5335INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
5336{
5337 return wifi_getIndexFromName(inputSsidString, output_int);
5338}
5339
5340// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
5341INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
5342{
5343 char buf[MAX_BUF_SIZE] = {0};
5344 char cmd[MAX_CMD_SIZE] = {0};
5345 char config_file[MAX_BUF_SIZE] = {0};
5346
5347 if(NULL == output_string)
5348 return RETURN_ERR;
5349
5350 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developerefb790a2023-12-26 18:58:32 +08005351 if (!syn_flag)
5352 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
5353 else
developer07ded1f2024-01-10 10:30:15 +08005354 snprintf(buf, sizeof(buf), "%s", vap_info[apIndex].wpa);
developer06a01d92022-09-07 16:32:39 +08005355 if((strcmp(buf,"3")==0))
5356 snprintf(output_string, 32, "WPAand11i");
5357 else if((strcmp(buf,"2")==0))
5358 snprintf(output_string, 32, "11i");
5359 else if((strcmp(buf,"1")==0))
5360 snprintf(output_string, 32, "WPA");
5361 else
5362 snprintf(output_string, 32, "None");
5363
5364 return RETURN_OK;
5365}
5366
5367// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
5368INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
5369{
5370 char config_file[MAX_BUF_SIZE] = {0};
5371 struct params list;
5372
5373 if (NULL == beaconTypeString)
5374 return RETURN_ERR;
5375 list.name = "wpa";
5376 list.value = "0";
5377
5378 if((strcmp(beaconTypeString,"WPAand11i")==0))
5379 list.value="3";
5380 else if((strcmp(beaconTypeString,"11i")==0))
5381 list.value="2";
5382 else if((strcmp(beaconTypeString,"WPA")==0))
5383 list.value="1";
5384
5385 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5386 wifi_hostapdWrite(config_file, &list, 1);
5387 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developerefb790a2023-12-26 18:58:32 +08005388 snprintf(vap_info[apIndex].wpa, MAX_BUF_SIZE, "%s", list.value);
developer06a01d92022-09-07 16:32:39 +08005389 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
5390 return RETURN_OK;
5391}
5392
5393// sets the beacon interval on the hardware for this AP
5394INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
5395{
developer5f222492022-09-13 15:21:52 +08005396 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5397 struct params params={'\0'};
5398 char buf[MAX_BUF_SIZE] = {'\0'};
5399 char config_file[MAX_BUF_SIZE] = {'\0'};
5400
5401 params.name = "beacon_int";
5402 snprintf(buf, sizeof(buf), "%u", beaconInterval);
5403 params.value = buf;
5404
5405 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5406 wifi_hostapdWrite(config_file, &params, 1);
5407
5408 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5409 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5410 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005411}
5412
5413INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
5414{
developer5b398df2022-11-17 20:39:48 +08005415 if (wifi_setApDTIMInterval(apIndex, dtimInterval) != RETURN_OK)
5416 return RETURN_ERR;
5417 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005418}
5419
5420// Get the packet size threshold supported.
5421INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
5422{
5423 //save config and apply instantly
5424 if (NULL == output_bool)
5425 return RETURN_ERR;
developer514406b2022-12-05 17:20:21 +08005426 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08005427 return RETURN_OK;
5428}
5429
5430// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
5431INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
5432{
developer514406b2022-12-05 17:20:21 +08005433 char buf[16] = {0};
5434 char config_file[128] = {0};
5435 struct params param = {0};
5436
5437 if (threshold > 65535) {
5438 fprintf(stderr, "%s: rts threshold %u is too big.\n", __func__, threshold);
5439 return RETURN_ERR;
5440 }
developer06a01d92022-09-07 16:32:39 +08005441
developer23e71282023-01-18 10:25:19 +08005442 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developer514406b2022-12-05 17:20:21 +08005443 snprintf(buf, sizeof(buf), "%u", threshold);
5444 param.name = "rts_threshold";
5445 param.value = buf;
5446 wifi_hostapdWrite(config_file, &param, 1);
5447 wifi_hostapdProcessUpdate(apIndex, &param, 1);
5448 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005449
5450 return RETURN_OK;
5451}
5452
5453// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5454INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
5455{
5456 if (NULL == output_string)
5457 return RETURN_ERR;
5458 snprintf(output_string, 32, "TKIPandAESEncryption");
5459 return RETURN_OK;
5460
5461}
5462
5463// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5464INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
5465{
5466 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer30423732022-12-01 16:17:49 +08005467 char *param_name = NULL;
5468 char buf[32] = {0}, config_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005469
5470 if(NULL == output_string)
5471 return RETURN_ERR;
5472
5473 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developerefb790a2023-12-26 18:58:32 +08005474 if (!syn_flag)
5475 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5476 else
developer07ded1f2024-01-10 10:30:15 +08005477 snprintf(buf, sizeof(buf), "%s", vap_info[apIndex].wpa);
developer06a01d92022-09-07 16:32:39 +08005478
5479 if(strcmp(buf,"0")==0)
5480 {
5481 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
5482 snprintf(output_string, 32, "None");
5483 return RETURN_OK;
5484 }
5485 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
5486 param_name = "rsn_pairwise";
5487 else if((strcmp(buf,"1")==0))
5488 param_name = "wpa_pairwise";
5489 else
5490 return RETURN_ERR;
5491 memset(output_string,'\0',32);
developer06a01d92022-09-07 16:32:39 +08005492 wifi_hostapdRead(config_file,param_name,output_string,32);
developer78a15382022-11-02 10:57:40 +08005493 if (strlen(output_string) == 0) { // rsn_pairwise is optional. When it is empty use wpa_pairwise instead.
5494 param_name = "wpa_pairwise";
5495 memset(output_string, '\0', 32);
5496 wifi_hostapdRead(config_file, param_name, output_string, 32);
5497 }
developer06a01d92022-09-07 16:32:39 +08005498 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
5499
developer72ec5572023-01-05 16:27:13 +08005500 if(strcmp(output_string,"TKIP CCMP") == 0)
5501 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
5502 else if(strcmp(output_string,"TKIP") == 0)
developer06a01d92022-09-07 16:32:39 +08005503 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
5504 else if(strcmp(output_string,"CCMP") == 0)
5505 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
developer06a01d92022-09-07 16:32:39 +08005506
5507 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5508 return RETURN_OK;
5509}
5510
5511// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5512INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
5513{
5514 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5515 struct params params={'\0'};
5516 char output_string[32];
developer72ec5572023-01-05 16:27:13 +08005517 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08005518
5519 memset(output_string,'\0',32);
developer72ec5572023-01-05 16:27:13 +08005520 wifi_getApBeaconType(apIndex,output_string);
developer06a01d92022-09-07 16:32:39 +08005521
5522 if(strcmp(encMode, "TKIPEncryption") == 0)
5523 params.value = "TKIP";
5524 else if(strcmp(encMode,"AESEncryption") == 0)
5525 params.value = "CCMP";
5526 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
5527 params.value = "TKIP CCMP";
5528
5529 if((strcmp(output_string,"WPAand11i")==0))
5530 {
5531 params.name = "wpa_pairwise";
5532 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5533 wifi_hostapdWrite(config_file, &params, 1);
5534 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5535
developer30423732022-12-01 16:17:49 +08005536 params.name = "rsn_pairwise";
developer06a01d92022-09-07 16:32:39 +08005537 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5538 wifi_hostapdWrite(config_file, &params, 1);
5539 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5540
5541 return RETURN_OK;
5542 }
5543 else if((strcmp(output_string,"11i")==0))
5544 {
5545 params.name = "rsn_pairwise";
5546 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5547 wifi_hostapdWrite(config_file, &params, 1);
5548 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5549 return RETURN_OK;
5550 }
5551 else if((strcmp(output_string,"WPA")==0))
5552 {
5553 params.name = "wpa_pairwise";
5554 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5555 wifi_hostapdWrite(config_file, &params, 1);
5556 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5557 return RETURN_OK;
5558 }
5559
5560 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5561 return RETURN_OK;
5562}
5563
5564// deletes internal security varable settings for this ap
5565INT wifi_removeApSecVaribles(INT apIndex)
5566{
5567 //TODO: remove the entry in hostapd config file
developerd946fd62022-12-08 18:03:28 +08005568 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s.conf//g' /tmp/conf_filename", interface_name);
developer06a01d92022-09-07 16:32:39 +08005569 //_syscmd(cmd, buf, sizeof(buf));
5570
developerd946fd62022-12-08 18:03:28 +08005571 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s//g' /tmp/conf_filename", interface_name);
developer06a01d92022-09-07 16:32:39 +08005572 //_syscmd(cmd, buf, sizeof(buf));
5573 return RETURN_ERR;
5574}
5575
5576// changes the hardware settings to disable encryption on this ap
5577INT wifi_disableApEncryption(INT apIndex)
5578{
5579 //Apply instantly
5580 return RETURN_ERR;
5581}
5582
5583// set the authorization mode on this ap
5584// mode mapping as: 1: open, 2: shared, 4:auto
5585INT wifi_setApAuthMode(INT apIndex, INT mode)
5586{
developeraf95c502022-09-13 16:18:22 +08005587 struct params params={0};
5588 char config_file[64] = {0};
5589 int ret;
5590
5591 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5592
5593 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
5594 params.name = "auth_algs";
5595
developer72ec5572023-01-05 16:27:13 +08005596 if ((mode & 1 && mode & 2) || mode & 4)
developeraf95c502022-09-13 16:18:22 +08005597 params.value = "3";
5598 else if (mode & 2)
5599 params.value = "2";
5600 else if (mode & 1)
5601 params.value = "1";
5602 else
5603 params.value = "0";
5604
5605 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5606 wifi_hostapdWrite(config_file, &params, 1);
5607 wifi_hostapdProcessUpdate(apIndex, &params, 1);
developer72ec5572023-01-05 16:27:13 +08005608 wifi_reloadAp(apIndex);
developeraf95c502022-09-13 16:18:22 +08005609 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5610
5611 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005612}
5613
5614// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5615INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5616{
5617 //save to wifi config, and wait for wifi restart to apply
5618 struct params params={'\0'};
5619 char config_file[MAX_BUF_SIZE] = {0};
5620 int ret;
5621
5622 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5623 if(authMode == NULL)
5624 return RETURN_ERR;
5625
5626 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5627 params.name = "wpa_key_mgmt";
5628
5629 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5630 params.value = "WPA-PSK";
5631 else if(strcmp(authMode,"EAPAuthentication") == 0)
5632 params.value = "WPA-EAP";
developer587c1b62022-09-27 15:58:59 +08005633 else if (strcmp(authMode, "SAEAuthentication") == 0)
5634 params.value = "SAE";
5635 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5636 params.value = "WPA-EAP-SUITE-B-192";
developer9df4e652022-10-11 11:27:38 +08005637 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
5638 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer5c9fee82023-01-13 14:44:16 +08005639 else if (strcmp(authMode, "Enhanced_Open") == 0)
5640 params.value = "OWE";
developer06a01d92022-09-07 16:32:39 +08005641 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5642 return RETURN_OK; //This is taken careof in beaconType
5643
5644 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5645 ret=wifi_hostapdWrite(config_file,&params,1);
5646 if(!ret)
5647 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
developerefb790a2023-12-26 18:58:32 +08005648 snprintf(vap_info[apIndex].wpa_key_mgmt, MAX_BUF_SIZE, "%s", params.value);
developer06a01d92022-09-07 16:32:39 +08005649 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5650
5651 return ret;
5652}
5653
5654// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5655INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5656{
5657 //save to wifi config, and wait for wifi restart to apply
5658 char BeaconType[50] = {0};
5659 char config_file[MAX_BUF_SIZE] = {0};
5660
5661 *authMode = 0;
5662 wifi_getApBeaconType(apIndex,BeaconType);
5663 printf("%s____%s \n",__FUNCTION__,BeaconType);
5664
5665 if(strcmp(BeaconType,"None") == 0)
5666 strcpy(authMode,"None");
5667 else
5668 {
5669 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developerefb790a2023-12-26 18:58:32 +08005670 if (!syn_flag)
5671 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5672 else
developer07ded1f2024-01-10 10:30:15 +08005673 snprintf(authMode, 32, "%s", vap_info[apIndex].wpa_key_mgmt);
developer06a01d92022-09-07 16:32:39 +08005674 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5675 if(strcmp(authMode,"WPA-PSK") == 0)
5676 strcpy(authMode,"SharedAuthentication");
5677 else if(strcmp(authMode,"WPA-EAP") == 0)
5678 strcpy(authMode,"EAPAuthentication");
5679 }
5680
5681 return RETURN_OK;
5682}
5683
5684// Outputs the number of stations associated per AP
5685INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5686{
developerd946fd62022-12-08 18:03:28 +08005687 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005688 char cmd[128]={0};
5689 char buf[128]={0};
5690 BOOL status = false;
5691
5692 if(apIndex > MAX_APS)
5693 return RETURN_ERR;
5694
5695 wifi_getApEnable(apIndex,&status);
5696 if (!status)
5697 return RETURN_OK;
5698
developerd946fd62022-12-08 18:03:28 +08005699 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);//alternate method
developerac6f1142022-12-20 19:26:35 +08005700 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005701 return RETURN_ERR;
5702 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08005703 _syscmd(cmd, buf, sizeof(buf));
5704 sscanf(buf,"%lu", output_ulong);
5705
5706 return RETURN_OK;
5707}
5708
5709// manually removes any active wi-fi association with the device specified on this ap
5710INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5711{
developerd946fd62022-12-08 18:03:28 +08005712 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005713 char buf[126]={'\0'};
5714
developerac6f1142022-12-20 19:26:35 +08005715 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005716 return RETURN_ERR;
5717 sprintf(buf,"hostapd_cli -i%s disassociate %s", interface_name, client_mac);
developer06a01d92022-09-07 16:32:39 +08005718 system(buf);
5719
5720 return RETURN_OK;
5721}
5722
5723// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5724INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5725{
5726 if(NULL == output_int)
5727 return RETURN_ERR;
developer5b398df2022-11-17 20:39:48 +08005728 int max_radio_num = 0;
5729 wifi_getMaxRadioNumber(&max_radio_num);
5730 *output_int = apIndex%max_radio_num;
developer06a01d92022-09-07 16:32:39 +08005731 return RETURN_OK;
5732}
5733
5734// sets the radio index for the specific ap
5735INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5736{
5737 //set to config only and wait for wifi reset to apply settings
5738 return RETURN_ERR;
5739}
5740
5741// Get the ACL MAC list per AP
5742INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5743{
developerd946fd62022-12-08 18:03:28 +08005744 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005745 char cmd[MAX_CMD_SIZE]={'\0'};
5746 int ret = 0;
5747
developerac6f1142022-12-20 19:26:35 +08005748 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005749 return RETURN_ERR;
5750 sprintf(cmd, "hostapd_cli -i %s accept_acl SHOW | awk '{print $1}'", interface_name);
developer06a01d92022-09-07 16:32:39 +08005751 ret = _syscmd(cmd,macArray,buf_size);
5752 if (ret != 0)
5753 return RETURN_ERR;
5754
5755 return RETURN_OK;
5756}
5757
developere6aafda2022-09-13 14:59:28 +08005758INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5759{
developerd946fd62022-12-08 18:03:28 +08005760 char interface_name[16] = {0};
developere6aafda2022-09-13 14:59:28 +08005761 char cmd[MAX_CMD_SIZE]={'\0'};
5762 int ret = 0;
5763
developerac6f1142022-12-20 19:26:35 +08005764 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005765 return RETURN_ERR;
5766 sprintf(cmd, "hostapd_cli -i %s deny_acl SHOW | awk '{print $1}'", interface_name);
developere6aafda2022-09-13 14:59:28 +08005767 ret = _syscmd(cmd,macArray,buf_size);
5768 if (ret != 0)
5769 return RETURN_ERR;
5770
5771 return RETURN_OK;
5772}
5773
developer06a01d92022-09-07 16:32:39 +08005774// Get the list of stations associated per AP
5775INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5776{
developerd946fd62022-12-08 18:03:28 +08005777 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005778 char cmd[128];
5779
5780 if(apIndex > 3) //Currently supporting apIndex upto 3
5781 return RETURN_ERR;
developerac6f1142022-12-20 19:26:35 +08005782 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005783 return RETURN_ERR;
5784 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
5785 //sprintf(buf,"iw dev %s station dump | grep Station | cut -d ' ' -f2", interface_name);//alternate method
developer06a01d92022-09-07 16:32:39 +08005786 _syscmd(cmd, macArray, buf_size);
5787
5788 return RETURN_OK;
5789}
5790
developer2f995fb2023-02-24 10:40:44 +08005791INT getAddressControlMode(INT apIndex, INT *mode)
5792{
5793 char buf [16] = {0};
5794 char config_file[64] = {0};
5795
5796 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developerefb790a2023-12-26 18:58:32 +08005797 if (!syn_flag)
5798 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
5799 else
developer07ded1f2024-01-10 10:30:15 +08005800 snprintf(buf, sizeof(buf), "%s", vap_info[apIndex].macaddr_acl);
developer2f995fb2023-02-24 10:40:44 +08005801
5802 *mode = -1;
5803 // 0 use deny file, 1 use accept file
5804 if (strncmp(buf, "0", 1) == 0 || strncmp(buf, "1", 1) == 0)
5805 *mode = (INT)strtol(buf, NULL, 10);
5806
5807 return RETURN_OK;
5808}
5809
developer06a01d92022-09-07 16:32:39 +08005810// adds the mac address to the filter list
5811//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5812INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5813{
5814 char cmd[MAX_CMD_SIZE]={'\0'};
5815 char buf[MAX_BUF_SIZE]={'\0'};
5816
developer2f995fb2023-02-24 10:40:44 +08005817 if (wifi_delApAclDevice(apIndex, DeviceMacAddress) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +08005818 return RETURN_ERR;
developer2f995fb2023-02-24 10:40:44 +08005819
developer06a01d92022-09-07 16:32:39 +08005820 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5821 if(_syscmd(cmd,buf,sizeof(buf)))
5822 return RETURN_ERR;
5823
5824 return RETURN_OK;
5825}
5826
developer2f995fb2023-02-24 10:40:44 +08005827INT wifi_addApDenyAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5828{
5829 char cmd[MAX_CMD_SIZE]={'\0'};
5830 char buf[MAX_BUF_SIZE]={'\0'};
5831
5832 if (wifi_delApAclDevice(apIndex, DeviceMacAddress) != RETURN_OK)
5833 return RETURN_ERR;
5834
5835 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, DENY_PREFIX, apIndex);
5836 if(_syscmd(cmd,buf,sizeof(buf)))
5837 return RETURN_ERR;
5838
5839 return RETURN_OK;
5840}
5841
developer06a01d92022-09-07 16:32:39 +08005842// deletes the mac address from the filter list
5843//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5844INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5845{
5846 char cmd[MAX_CMD_SIZE]={'\0'};
5847 char buf[MAX_BUF_SIZE]={'\0'};
5848
5849#if 0
developerd946fd62022-12-08 18:03:28 +08005850 sprintf(cmd, "hostapd_cli -i %s accept_acl DEL_MAC %s", interface_name,DeviceMacAddress);
developer06a01d92022-09-07 16:32:39 +08005851 if(_syscmd(cmd,buf,sizeof(buf)))
5852 return RETURN_ERR;
5853
5854#endif
developer2f995fb2023-02-24 10:40:44 +08005855 sprintf(cmd, "sed -i '/%s/d' %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
developer06a01d92022-09-07 16:32:39 +08005856 if(_syscmd(cmd,buf,sizeof(buf)))
5857 return RETURN_ERR;
developer2f995fb2023-02-24 10:40:44 +08005858 sprintf(cmd, "sed -i '/%s/d' %s%d", DeviceMacAddress, DENY_PREFIX, apIndex);
5859 if(_syscmd(cmd,buf,sizeof(buf)))
5860 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005861
5862 return RETURN_OK;
5863}
5864
5865// outputs the number of devices in the filter list
5866INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5867{
developere6aafda2022-09-13 14:59:28 +08005868 char cmd[MAX_BUF_SIZE]={0};
5869 char buf[MAX_CMD_SIZE]={0};
developer2f995fb2023-02-24 10:40:44 +08005870 int mode = -1;
developere6aafda2022-09-13 14:59:28 +08005871
5872 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5873 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08005874 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08005875
developer2f995fb2023-02-24 10:40:44 +08005876 getAddressControlMode(apIndex, &mode);
5877 if (mode == -1)
5878 return RETURN_OK;
5879
5880 if (mode == 0)
5881 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", DENY_PREFIX, apIndex);
5882 else if (mode == 1)
5883 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
developere6aafda2022-09-13 14:59:28 +08005884 _syscmd(cmd, buf, sizeof(buf));
5885
developer2f995fb2023-02-24 10:40:44 +08005886 *output_uint = strtol(buf, NULL, 10);
developere6aafda2022-09-13 14:59:28 +08005887
5888 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5889 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005890}
5891
5892INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5893{
5894 char cmd[128]={'\0'};
5895 char buf[128]={'\0'};
5896
5897 if(strcmp(action,"DENY")==0)
5898 {
5899 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5900 system(buf);
5901 return RETURN_OK;
5902 }
5903
5904 if(strcmp(action,"ALLOW")==0)
5905 {
5906 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5907 system(buf);
5908 return RETURN_OK;
5909 }
5910
5911 return RETURN_ERR;
5912
5913}
5914
5915// enable kick for devices on acl black list
5916INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5917{
5918 char aclArray[512] = {0}, *acl = NULL;
5919 char assocArray[512] = {0}, *asso = NULL;
5920
developere6aafda2022-09-13 14:59:28 +08005921 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005922 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5923
5924 // if there are no devices connected there is nothing to do
5925 if (strlen(assocArray) < 17)
5926 return RETURN_OK;
5927
5928 if (enable == TRUE)
5929 {
5930 //kick off the MAC which is in ACL array (deny list)
5931 acl = strtok(aclArray, "\r\n");
5932 while (acl != NULL) {
5933 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5934 wifi_kickApAssociatedDevice(apIndex, acl);
5935
5936 acl = strtok(NULL, "\r\n");
5937 }
developere6aafda2022-09-13 14:59:28 +08005938 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005939 }
5940 else
5941 {
developere6aafda2022-09-13 14:59:28 +08005942 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005943 }
5944
5945#if 0
5946 //TODO: need to revisit below implementation
5947 char aclArray[512]={0}, *acl=NULL;
5948 char assocArray[512]={0}, *asso=NULL;
5949 char buf[256]={'\0'};
5950 char action[10]={'\0'};
5951 FILE *fr=NULL;
5952 char interface[10]={'\0'};
5953 char config_file[MAX_BUF_SIZE] = {0};
5954
5955 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5956 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5957 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5958 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5959
5960 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5961 system(buf);
5962 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5963 system(buf);
5964 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5965 system(buf);
5966 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5967 system(buf);
5968 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5969 system(buf);
5970
5971 if ( enable == TRUE )
5972 {
5973 int device_count=0;
5974 strcpy(action,"DENY");
5975 //kick off the MAC which is in ACL array (deny list)
5976 acl = strtok (aclArray,",");
5977 while (acl != NULL) {
5978 if(strlen(acl)>=17)
5979 {
5980 apply_rules(apIndex, acl,action,interface);
5981 device_count++;
5982 //Register mac to be blocked ,in syscfg.db persistent storage
5983 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5984 system(buf);
5985 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5986 system(buf);
5987 system("syscfg commit");
5988
5989 wifi_kickApAssociatedDevice(apIndex, acl);
5990 }
5991 acl = strtok (NULL, ",");
5992 }
5993 }
5994 else
5995 {
5996 int device_count=0;
5997 char cmdmac[20]={'\0'};
5998 strcpy(action,"ALLOW");
5999 //kick off the MAC which is not in ACL array (allow list)
6000 acl = strtok (aclArray,",");
6001 while (acl != NULL) {
6002 if(strlen(acl)>=17)
6003 {
6004 apply_rules(apIndex, acl,action,interface);
6005 device_count++;
6006 //Register mac to be Allowed ,in syscfg.db persistent storage
6007 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
6008 system(buf);
6009 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
6010 system(buf);
6011 sprintf(cmdmac,"%s",acl);
6012 }
6013 acl = strtok (NULL, ",");
6014 }
6015 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
6016 system(buf);
6017
6018 //Disconnect the mac which is not in ACL
6019 asso = strtok (assocArray,",");
6020 while (asso != NULL) {
6021 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
6022 wifi_kickApAssociatedDevice(apIndex, asso);
6023 asso = strtok (NULL, ",");
6024 }
6025 }
6026#endif
6027 return RETURN_OK;
6028}
6029
6030INT wifi_setPreferPrivateConnection(BOOL enable)
6031{
developer06a01d92022-09-07 16:32:39 +08006032 return RETURN_OK;
6033}
6034
6035// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
6036INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
6037{
developerd946fd62022-12-08 18:03:28 +08006038 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006039 int items = 1;
6040 struct params list[2];
6041 char buf[MAX_BUF_SIZE] = {0};
6042 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08006043 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08006044
6045 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08006046
developer10adcc12022-09-13 14:39:17 +08006047 if (filterMode == 0) {
6048 sprintf(buf, "%d", 0);
6049 list[0].value = buf;
6050
developer2f995fb2023-02-24 10:40:44 +08006051 char cmd[128] = {0};
developerac6f1142022-12-20 19:26:35 +08006052 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08006053 return RETURN_ERR;
developer2f995fb2023-02-24 10:40:44 +08006054 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s deny_acl CLEAR 2> /dev/null", interface_name);
6055 _syscmd(cmd, cmd, sizeof(cmd));
developer10adcc12022-09-13 14:39:17 +08006056 memset(cmd,0,sizeof(cmd));
6057 // Delete deny_mac_file in hostapd configuration
6058 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
developer2f995fb2023-02-24 10:40:44 +08006059 _syscmd(cmd, cmd, sizeof(cmd));
developer10adcc12022-09-13 14:39:17 +08006060 }
6061 else if (filterMode == 1) {
6062 sprintf(buf, "%d", filterMode);
6063 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08006064 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
6065 list[1].name = "accept_mac_file";
6066 list[1].value = acl_file;
6067 items = 2;
developer10adcc12022-09-13 14:39:17 +08006068 } else if (filterMode == 2) {
6069 //TODO: deny_mac_file
6070 sprintf(buf, "%d", 0);
6071 list[0].value = buf;
6072 list[1].name = "deny_mac_file";
6073 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
6074 list[1].value = deny_file;
6075 items = 2;
6076 } else {
6077 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006078 }
developer10adcc12022-09-13 14:39:17 +08006079
developer06a01d92022-09-07 16:32:39 +08006080 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6081 wifi_hostapdWrite(config_file, list, items);
developer2f995fb2023-02-24 10:40:44 +08006082 if (multiple_set == FALSE) {
6083 wifi_setApEnable(apIndex, FALSE);
6084 wifi_setApEnable(apIndex, TRUE);
6085 }
developerefb790a2023-12-26 18:58:32 +08006086 snprintf(vap_info[apIndex].macaddr_acl, MAX_BUF_SIZE, "%s", list[0].value);
developer06a01d92022-09-07 16:32:39 +08006087
6088 return RETURN_OK;
6089
6090#if 0
6091 if(apIndex==0 || apIndex==1)
6092 {
6093 //set the filtermode
6094 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
6095 system(buf);
6096 system("syscfg commit");
6097
6098 if(filterMode==0)
6099 {
6100 sprintf(buf,"iptables -F WifiServices%d",apIndex);
6101 system(buf);
6102 return RETURN_OK;
6103 }
6104 }
6105 return RETURN_OK;
6106#endif
6107}
6108
6109// 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.
6110INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
6111{
6112 return RETURN_ERR;
6113}
6114
6115// gets the vlan ID for this ap from an internal enviornment variable
6116INT wifi_getApVlanID(INT apIndex, INT *output_int)
6117{
developer30423732022-12-01 16:17:49 +08006118 if(apIndex==0)
developer06a01d92022-09-07 16:32:39 +08006119 {
6120 *output_int=100;
6121 return RETURN_OK;
6122 }
6123
6124 return RETURN_ERR;
6125}
6126
6127// sets the vlan ID for this ap to an internal enviornment variable
6128INT wifi_setApVlanID(INT apIndex, INT vlanId)
6129{
6130 //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)
6131 return RETURN_ERR;
6132}
6133
6134// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
6135INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
6136{
6137 snprintf(bridgeName, 32, "brlan0");
6138 snprintf(IP, 32, "10.0.0.1");
6139 snprintf(subnet, 32, "255.255.255.0");
6140
6141 return RETURN_OK;
6142}
6143
6144//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
6145INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
6146{
6147 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
6148 return RETURN_ERR;
6149}
6150
6151// reset the vlan configuration for this ap
6152INT wifi_resetApVlanCfg(INT apIndex)
6153{
developerf5fef612022-09-20 19:38:26 +08006154 char original_config_file[64] = {0};
6155 char current_config_file[64] = {0};
6156 char buf[64] = {0};
6157 char cmd[64] = {0};
6158 char vlan_file[64] = {0};
6159 char vlan_tagged_interface[16] = {0};
6160 char vlan_bridge[16] = {0};
6161 char vlan_naming[16] = {0};
6162 struct params list[4] = {0};
6163 wifi_band band;
6164
6165 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6166
6167 band = wifi_index_to_band(apIndex);
6168 if (band == band_2_4)
6169 sprintf(original_config_file, "/etc/hostapd-2G.conf");
developer30423732022-12-01 16:17:49 +08006170 else if (band == band_5)
developerf5fef612022-09-20 19:38:26 +08006171 sprintf(original_config_file, "/etc/hostapd-5G.conf");
developer30423732022-12-01 16:17:49 +08006172 else if (band == band_6)
developerf5fef612022-09-20 19:38:26 +08006173 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6174
6175 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
6176
6177 if (strlen(vlan_file) == 0)
6178 strcpy(vlan_file, VLAN_FILE);
developer06a01d92022-09-07 16:32:39 +08006179
developerf5fef612022-09-20 19:38:26 +08006180 // The file should exist or this vap would not work.
6181 if (access(vlan_file, F_OK) != 0) {
6182 sprintf(cmd, "touch %s", vlan_file);
6183 _syscmd(cmd, buf, sizeof(buf));
6184 }
6185 list[0].name = "vlan_file";
6186 list[0].value = vlan_file;
6187
6188 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
6189 list[1].name = "vlan_tagged_interface";
6190 list[1].value = vlan_tagged_interface;
6191
6192 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
6193 list[2].name = "vlan_bridge";
6194 list[2].value = vlan_bridge;
6195
6196 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
6197 list[3].name = "vlan_naming";
6198 list[3].value = vlan_naming;
developer06a01d92022-09-07 16:32:39 +08006199
developerf5fef612022-09-20 19:38:26 +08006200 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6201 wifi_hostapdWrite(current_config_file, list, 4);
developer06a01d92022-09-07 16:32:39 +08006202 //Reapply vlan settings
developerf5fef612022-09-20 19:38:26 +08006203 // wifi_pushBridgeInfo(apIndex);
developer06a01d92022-09-07 16:32:39 +08006204
developerf5fef612022-09-20 19:38:26 +08006205 // restart this ap
6206 wifi_setApEnable(apIndex, FALSE);
6207 wifi_setApEnable(apIndex, TRUE);
6208
6209 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6210
6211 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006212}
6213
6214// 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.
6215INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
6216{
6217 return RETURN_ERR;
6218}
6219
6220// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
6221INT wifi_startHostApd()
6222{
6223 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6224 system("systemctl start hostapd.service");
6225 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6226 return RETURN_OK;
6227 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
6228}
6229
6230// stops hostapd
6231INT wifi_stopHostApd()
6232{
6233 char cmd[128] = {0};
6234 char buf[128] = {0};
6235
6236 sprintf(cmd,"systemctl stop hostapd");
6237 _syscmd(cmd, buf, sizeof(buf));
6238
6239 return RETURN_OK;
6240}
6241
6242// restart hostapd dummy function
6243INT wifi_restartHostApd()
6244{
6245 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6246 system("systemctl restart hostapd-global");
6247 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6248
6249 return RETURN_OK;
6250}
6251
6252static int align_hostapd_config(int index)
6253{
6254 ULONG lval;
6255 wifi_getRadioChannel(index%2, &lval);
6256 wifi_setRadioChannel(index%2, lval);
developer30423732022-12-01 16:17:49 +08006257 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006258}
6259
6260// sets the AP enable status variable for the specified ap.
6261INT wifi_setApEnable(INT apIndex, BOOL enable)
6262{
developerd946fd62022-12-08 18:03:28 +08006263 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006264 char config_file[MAX_BUF_SIZE] = {0};
6265 char cmd[MAX_CMD_SIZE] = {0};
6266 char buf[MAX_BUF_SIZE] = {0};
6267 BOOL status;
developer033b37b2022-10-18 11:27:46 +08006268 int max_radio_num = 0;
6269 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08006270
6271 wifi_getApEnable(apIndex,&status);
developer033b37b2022-10-18 11:27:46 +08006272
6273 wifi_getMaxRadioNumber(&max_radio_num);
developer06a01d92022-09-07 16:32:39 +08006274 if (enable == status)
6275 return RETURN_OK;
6276
developerac6f1142022-12-20 19:26:35 +08006277 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08006278 return RETURN_ERR;
6279
developer06a01d92022-09-07 16:32:39 +08006280 if (enable == TRUE) {
developer033b37b2022-10-18 11:27:46 +08006281 int radioIndex = apIndex % max_radio_num;
6282 phyId = radio_index_to_phy(radioIndex);
developer06a01d92022-09-07 16:32:39 +08006283 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6284 //Hostapd will bring up this interface
developerd946fd62022-12-08 18:03:28 +08006285 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08006286 _syscmd(cmd, buf, sizeof(buf));
developer2f18b9f2023-03-17 19:32:57 +08006287 if (!(apIndex/max_radio_num)) {
6288 sprintf(cmd, "iw %s del", interface_name);
6289 _syscmd(cmd, buf, sizeof(buf));
6290 sprintf(cmd, "iw phy phy%d interface add %s type __ap", phyId, interface_name);
6291 _syscmd(cmd, buf, sizeof(buf));
6292 }
developer439baa32024-05-02 15:54:58 +08006293 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", single_wiphy ? radioIndex : phyId, config_file);
developer06a01d92022-09-07 16:32:39 +08006294 _syscmd(cmd, buf, sizeof(buf));
6295 }
6296 else {
developerd946fd62022-12-08 18:03:28 +08006297 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08006298 _syscmd(cmd, buf, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +08006299 sprintf(cmd, "ip link set %s down", interface_name);
developer06a01d92022-09-07 16:32:39 +08006300 _syscmd(cmd, buf, sizeof(buf));
6301 }
developera77d84b2023-02-22 16:10:50 +08006302
developer431128d2022-12-16 15:30:41 +08006303 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=%d' %s",
developerd946fd62022-12-08 18:03:28 +08006304 interface_name, interface_name, enable, VAP_STATUS_FILE);
developer06a01d92022-09-07 16:32:39 +08006305 _syscmd(cmd, buf, sizeof(buf));
6306 //Wait for wifi up/down to apply
6307 return RETURN_OK;
6308}
6309
6310// Outputs the setting of the internal variable that is set by wifi_setApEnable().
6311INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
6312{
developerd946fd62022-12-08 18:03:28 +08006313 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006314 char cmd[MAX_CMD_SIZE] = {'\0'};
6315 char buf[MAX_BUF_SIZE] = {'\0'};
6316
6317 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
6318 return RETURN_ERR;
6319
6320 *output_bool = 0;
6321
6322 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
6323 {
developerac6f1142022-12-20 19:26:35 +08006324 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
developerd946fd62022-12-08 18:03:28 +08006325 *output_bool = FALSE;
6326 return RETURN_OK;
6327 }
6328 sprintf(cmd, "ifconfig %s 2> /dev/null | grep UP", interface_name);
developer06a01d92022-09-07 16:32:39 +08006329 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
6330 }
6331
6332 return RETURN_OK;
6333}
6334
6335// Outputs the AP "Enabled" "Disabled" status from driver
6336INT wifi_getApStatus(INT apIndex, CHAR *output_string)
6337{
6338 char cmd[128] = {0};
6339 char buf[128] = {0};
6340 BOOL output_bool;
6341
6342 if ( NULL == output_string)
6343 return RETURN_ERR;
6344 wifi_getApEnable(apIndex,&output_bool);
6345
6346 if(output_bool == 1)
6347 snprintf(output_string, 32, "Up");
6348 else
6349 snprintf(output_string, 32, "Disable");
6350
6351 return RETURN_OK;
6352}
6353
6354//Indicates whether or not beacons include the SSID name.
6355// outputs a 1 if SSID on the AP is enabled, else outputs 0
6356INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
6357{
6358 //get the running status
6359 char config_file[MAX_BUF_SIZE] = {0};
6360 char buf[16] = {0};
6361
6362 if (!output)
6363 return RETURN_ERR;
6364
6365 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developerefb790a2023-12-26 18:58:32 +08006366 if (!syn_flag)
6367 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
6368 else
developer07ded1f2024-01-10 10:30:15 +08006369 snprintf(buf, sizeof(buf), "%s",vap_info[apIndex].ignore_broadcast_ssid);
developer1d57d002022-10-12 18:03:15 +08006370 // default is enable
6371 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
6372 *output = TRUE;
developer06a01d92022-09-07 16:32:39 +08006373
6374 return RETURN_OK;
6375}
6376
6377// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
6378INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
6379{
6380 //store the config, apply instantly
6381 char config_file[MAX_BUF_SIZE] = {0};
6382 struct params list;
6383
6384 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6385 list.name = "ignore_broadcast_ssid";
6386 list.value = enable?"0":"1";
6387
6388 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6389 wifi_hostapdWrite(config_file, &list, 1);
6390 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6391 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08006392 wifi_reloadAp(apIndex);
developerefb790a2023-12-26 18:58:32 +08006393 snprintf(vap_info[apIndex].ignore_broadcast_ssid, MAX_BUF_SIZE, "%s", list.value);
developer06a01d92022-09-07 16:32:39 +08006394 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6395
6396 return RETURN_OK;
6397}
6398
6399//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
6400INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
6401{
6402 //get the running status
6403 if(!output_uint)
6404 return RETURN_ERR;
6405 *output_uint=16;
6406 return RETURN_OK;
6407}
6408
6409INT wifi_setApRetryLimit(INT apIndex, UINT number)
6410{
6411 //apply instantly
6412 return RETURN_ERR;
6413}
6414
6415//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
6416INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
6417{
6418 if(!output)
6419 return RETURN_ERR;
6420 *output=TRUE;
6421 return RETURN_OK;
6422}
6423
6424//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
6425INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
6426{
6427 //get the running status from driver
developer0b246d12022-09-30 15:24:20 +08006428 char cmd[128] = {0};
6429 char buf[128] = {0};
6430 int max_radio_num = 0, radioIndex = 0;
developer033b37b2022-10-18 11:27:46 +08006431 int phyId = 0;
developer3ab38042022-09-13 14:17:03 +08006432
developer0b246d12022-09-30 15:24:20 +08006433 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08006434
developer0b246d12022-09-30 15:24:20 +08006435 wifi_getMaxRadioNumber(&max_radio_num);
6436 radioIndex = apIndex % max_radio_num;
developer033b37b2022-10-18 11:27:46 +08006437 phyId = radio_index_to_phy(radioIndex);
6438 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", phyId);
developer0b246d12022-09-30 15:24:20 +08006439 _syscmd(cmd,buf, sizeof(buf));
6440
6441 if (strlen(buf) > 0)
6442 *output = true;
6443
6444 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08006445
developer06a01d92022-09-07 16:32:39 +08006446 return RETURN_OK;
6447}
6448
6449//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
6450INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
6451{
6452 //get the running status from driver
6453 if(!output)
6454 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08006455
6456 char config_file[MAX_BUF_SIZE] = {0};
6457 char buf[16] = {0};
6458
6459 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6460 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08006461 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
developer3ab38042022-09-13 14:17:03 +08006462 *output = TRUE;
6463 else
6464 *output = FALSE;
6465
developer06a01d92022-09-07 16:32:39 +08006466 return RETURN_OK;
6467}
6468
6469// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
6470INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
6471{
6472 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006473 char config_file[MAX_BUF_SIZE] = {0};
6474 struct params list;
6475
6476 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6477 list.name = "wmm_enabled";
6478 list.value = enable?"1":"0";
6479
6480 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6481 wifi_hostapdWrite(config_file, &list, 1);
6482 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6483 wifi_reloadAp(apIndex);
6484 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6485
6486 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006487}
6488
6489//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.
6490INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
6491{
6492 //get the running status from driver
6493 if(!output)
6494 return RETURN_ERR;
developer97c720c2022-11-04 17:08:12 +08006495
6496 char config_file[128] = {0};
6497 char buf[16] = {0};
6498
6499 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6500 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
6501 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
6502 *output = TRUE;
6503 else
6504 *output = FALSE;
6505
developer06a01d92022-09-07 16:32:39 +08006506 return RETURN_OK;
6507}
6508
6509// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
6510INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
6511{
6512 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006513 char config_file[MAX_BUF_SIZE] = {0};
6514 struct params list;
6515
6516 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6517 list.name = "uapsd_advertisement_enabled";
6518 list.value = enable?"1":"0";
6519
6520 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6521 wifi_hostapdWrite(config_file, &list, 1);
6522 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6523 wifi_reloadAp(apIndex);
6524 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6525
6526 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006527}
6528
developer6daeb3f2022-09-30 13:36:39 +08006529// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
developer06a01d92022-09-07 16:32:39 +08006530INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
6531{
developerd946fd62022-12-08 18:03:28 +08006532 char interface_name[16] = {0};
developer6daeb3f2022-09-30 13:36:39 +08006533 // assume class 0->BE, 1->BK, 2->VI, 3->VO
6534 char cmd[128] = {0};
6535 char buf[128] = {0};
6536 char ack_filepath[128] = {0};
6537 uint16_t bitmap = 0;
6538 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
6539 FILE *f = NULL;
6540
6541 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
6542
6543 // Get current setting
6544 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
6545 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
6546 _syscmd(cmd, buf, sizeof(buf));
6547 if (strlen(buf) > 0)
6548 bitmap = strtoul(buf, NULL, 10);
6549
6550 bitmap = strtoul(buf, NULL, 10);
6551
6552 if (ackPolicy == TRUE) { // True, unset this class
6553 bitmap &= ~class_map[class];
6554 } else { // False, set this class
6555 bitmap |= class_map[class];
6556 }
6557
6558 f = fopen(ack_filepath, "w");
6559 if (f == NULL) {
6560 fprintf(stderr, "%s: fopen failed\n", __func__);
6561 return RETURN_ERR;
6562 }
6563 fprintf(f, "%hu", bitmap);
6564 fclose(f);
6565
developerac6f1142022-12-20 19:26:35 +08006566 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08006567 return RETURN_ERR;
6568 snprintf(cmd, sizeof(cmd), "iw dev %s set noack_map 0x%04x\n", interface_name, bitmap);
developer6daeb3f2022-09-30 13:36:39 +08006569 _syscmd(cmd, buf, sizeof(buf));
6570
6571 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
6572 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006573}
6574
6575//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.
6576INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
6577{
6578 //get the running status from driver
6579 if(!output_uint)
6580 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006581
6582 char output[16]={'\0'};
6583 char config_file[MAX_BUF_SIZE] = {0};
6584
6585 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developerefb790a2023-12-26 18:58:32 +08006586 if (!syn_flag)
6587 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
6588 else
developer07ded1f2024-01-10 10:30:15 +08006589 snprintf(output, sizeof(output), "%s", vap_info[apIndex].max_sta);
developer0947e1a2022-09-13 14:15:25 +08006590 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
6591 else {
6592 int device_num = atoi(output);
6593 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
6594 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
6595 return RETURN_ERR;
6596 }
6597 else {
6598 *output_uint = device_num;
6599 }
6600 }
6601
developer06a01d92022-09-07 16:32:39 +08006602 return RETURN_OK;
6603}
6604
6605INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
6606{
6607 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08006608 char str[MAX_BUF_SIZE]={'\0'};
6609 char cmd[MAX_CMD_SIZE]={'\0'};
6610 struct params params;
6611 char config_file[MAX_BUF_SIZE] = {0};
6612
6613 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer30423732022-12-01 16:17:49 +08006614 if (number > MAX_ASSOCIATED_STA_NUM) {
developer0947e1a2022-09-13 14:15:25 +08006615 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
developer72ec5572023-01-05 16:27:13 +08006616 return RETURN_OK;
developer0947e1a2022-09-13 14:15:25 +08006617 }
6618 sprintf(str, "%d", number);
6619 params.name = "max_num_sta";
6620 params.value = str;
6621
6622 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
6623 int ret = wifi_hostapdWrite(config_file, &params, 1);
6624 if (ret) {
6625 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
6626 ,__func__, ret);
6627 }
6628
6629 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6630 if (ret) {
6631 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
6632 ,__func__, ret);
6633 }
6634 wifi_reloadAp(apIndex);
6635 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6636
6637 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006638}
6639
6640//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.
6641INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
6642{
6643 //get the current threshold
6644 if(!output_uint)
6645 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006646 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
6647 if (*output_uint == 0)
6648 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08006649 return RETURN_OK;
6650}
6651
6652INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6653{
6654 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08006655 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6656 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006657 return RETURN_ERR;
6658}
6659
6660//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.
6661INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6662{
6663 if(!output_uint)
6664 return RETURN_ERR;
6665 *output_uint = 3;
6666 return RETURN_OK;
6667}
6668
6669//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6670INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6671{
6672 if(!output_uint)
6673 return RETURN_ERR;
6674 *output_uint = 3;
6675 return RETURN_OK;
6676}
6677
6678//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.
6679INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6680{
6681 if(!output_in_seconds)
6682 return RETURN_ERR;
6683 *output_in_seconds = 0;
6684 return RETURN_OK;
6685}
6686
6687//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
6688INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6689{
6690 if(!output || apIndex>=MAX_APS)
6691 return RETURN_ERR;
6692 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006693 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
developer06a01d92022-09-07 16:32:39 +08006694 return RETURN_OK;
6695}
6696
6697//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6698INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6699{
developer587c1b62022-09-27 15:58:59 +08006700 char config_file[128] = {0};
6701 char wpa[16] = {0};
6702 char key_mgmt[64] = {0};
6703 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006704 if (!output)
6705 return RETURN_ERR;
6706
6707 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developerefb790a2023-12-26 18:58:32 +08006708 if (!syn_flag)
6709 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
6710 else
developer07ded1f2024-01-10 10:30:15 +08006711 snprintf(wpa, sizeof(wpa), "%s", vap_info[apIndex].wpa);
developer06a01d92022-09-07 16:32:39 +08006712
developer587c1b62022-09-27 15:58:59 +08006713 strcpy(output, "None");//Copying "None" to output string for default case
developerefb790a2023-12-26 18:58:32 +08006714 if (!syn_flag)
6715 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
6716 else
developer07ded1f2024-01-10 10:30:15 +08006717 snprintf(key_mgmt, sizeof(key_mgmt), "%s", vap_info[apIndex].wpa_key_mgmt);
developer4a359672022-10-13 15:30:46 +08006718 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
developer517a9792022-10-05 19:37:42 +08006719 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006720 snprintf(output, 32, "WPA-Personal");
developer517a9792022-10-05 19:37:42 +08006721 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006722 snprintf(output, 32, "WPA2-Personal");
developer517a9792022-10-05 19:37:42 +08006723 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006724 snprintf(output, 32, "WPA-WPA2-Personal");
6725
developer72ec5572023-01-05 16:27:13 +08006726 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6727 snprintf(output, 32, "WPA3-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006728 } else if (strstr(key_mgmt, "WPA-EAP")) {
developer517a9792022-10-05 19:37:42 +08006729 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006730 snprintf(output, 32, "WPA-Enterprise");
developer517a9792022-10-05 19:37:42 +08006731 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006732 snprintf(output, 32, "WPA2-Enterprise");
developer517a9792022-10-05 19:37:42 +08006733 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006734 snprintf(output, 32, "WPA-WPA2-Enterprise");
6735 } else if (strstr(key_mgmt, "SAE")) {
developer4a359672022-10-13 15:30:46 +08006736 if (strstr(key_mgmt, "WPA-PSK") == NULL)
developer587c1b62022-09-27 15:58:59 +08006737 snprintf(output, 32, "WPA3-Personal");
6738 else
developer4a359672022-10-13 15:30:46 +08006739 snprintf(output, 32, "WPA3-Personal-Transition");
developer587c1b62022-09-27 15:58:59 +08006740 }
developer06a01d92022-09-07 16:32:39 +08006741
6742 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6743 return RETURN_OK;
6744#if 0
6745 //TODO: need to revisit below implementation
6746 char securityType[32], authMode[32];
6747 int enterpriseMode=0;
6748
6749 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6750 if(!output)
6751 return RETURN_ERR;
6752
6753 wifi_getApBeaconType(apIndex, securityType);
6754 strcpy(output,"None");//By default, copying "None" to output string
6755 if (strncmp(securityType,"None", strlen("None")) == 0)
6756 return RETURN_OK;
6757
6758 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6759 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6760
6761 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6762 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6763 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6764 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6765 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6766 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6767 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6768
6769 return RETURN_OK;
6770#endif
6771}
6772
6773INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6774{
6775 char securityType[32];
6776 char authMode[32];
6777
6778 //store settings and wait for wifi up to apply
6779 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6780 if(!encMode)
6781 return RETURN_ERR;
6782
developer06a01d92022-09-07 16:32:39 +08006783 if (strcmp(encMode, "None")==0)
6784 {
6785 strcpy(securityType,"None");
6786 strcpy(authMode,"None");
6787 }
6788 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6789 {
6790 strcpy(securityType,"WPAand11i");
6791 strcpy(authMode,"PSKAuthentication");
6792 }
6793 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6794 {
6795 strcpy(securityType,"WPAand11i");
6796 strcpy(authMode,"EAPAuthentication");
6797 }
6798 else if (strcmp(encMode, "WPA-Personal")==0)
6799 {
6800 strcpy(securityType,"WPA");
6801 strcpy(authMode,"PSKAuthentication");
6802 }
6803 else if (strcmp(encMode, "WPA-Enterprise")==0)
6804 {
6805 strcpy(securityType,"WPA");
6806 strcpy(authMode,"EAPAuthentication");
6807 }
6808 else if (strcmp(encMode, "WPA2-Personal")==0)
6809 {
6810 strcpy(securityType,"11i");
6811 strcpy(authMode,"PSKAuthentication");
6812 }
6813 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6814 {
6815 strcpy(securityType,"11i");
6816 strcpy(authMode,"EAPAuthentication");
6817 }
developer587c1b62022-09-27 15:58:59 +08006818 else if (strcmp(encMode, "WPA3-Personal") == 0)
6819 {
6820 strcpy(securityType,"11i");
6821 strcpy(authMode,"SAEAuthentication");
6822 }
developer4a359672022-10-13 15:30:46 +08006823 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
developer9df4e652022-10-11 11:27:38 +08006824 {
6825 strcpy(securityType, "11i");
6826 strcpy(authMode, "PSK-SAEAuthentication");
6827 }
developer587c1b62022-09-27 15:58:59 +08006828 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6829 {
6830 strcpy(securityType,"11i");
6831 strcpy(authMode,"EAP_192-bit_Authentication");
6832 }
developer5c9fee82023-01-13 14:44:16 +08006833 else if (strcmp(encMode, "OWE") == 0)
6834 {
6835 strcpy(securityType,"11i");
6836 strcpy(authMode,"Enhanced_Open");
6837 }
developer06a01d92022-09-07 16:32:39 +08006838 else
6839 {
6840 strcpy(securityType,"None");
6841 strcpy(authMode,"None");
6842 }
6843 wifi_setApBeaconType(apIndex, securityType);
6844 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6845 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6846
6847 return RETURN_OK;
6848}
6849
6850
developer4b102122023-02-15 10:53:03 +08006851// Get PreSharedKey associated with a Access Point.
developer06a01d92022-09-07 16:32:39 +08006852//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
developer06a01d92022-09-07 16:32:39 +08006853INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6854{
developer30423732022-12-01 16:17:49 +08006855 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006856 char config_file[MAX_BUF_SIZE] = {0};
6857
6858 if(output_string==NULL)
6859 return RETURN_ERR;
6860
6861 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developerefb790a2023-12-26 18:58:32 +08006862 if (!syn_flag)
6863 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6864 else
developer07ded1f2024-01-10 10:30:15 +08006865 snprintf(buf, sizeof(buf), "%s", vap_info[apIndex].wpa);
developer06a01d92022-09-07 16:32:39 +08006866 if(strcmp(buf,"0")==0)
6867 {
6868 printf("wpa_mode is %s ......... \n",buf);
6869 return RETURN_ERR;
6870 }
6871
6872 wifi_dbg_printf("\nFunc=%s\n",__func__);
6873 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developer4b102122023-02-15 10:53:03 +08006874 wifi_hostapdRead(config_file,"wpa_psk",output_string,65);
developer06a01d92022-09-07 16:32:39 +08006875 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6876
6877 return RETURN_OK;
6878}
6879
developer4b102122023-02-15 10:53:03 +08006880// Set PreSharedKey associated with a Access Point.
6881// A literal PreSharedKey (PSK) expressed as a hexadecimal string.
developer06a01d92022-09-07 16:32:39 +08006882INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6883{
6884 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6885 struct params params={'\0'};
6886 int ret;
6887 char config_file[MAX_BUF_SIZE] = {0};
6888
6889 if(NULL == preSharedKey)
6890 return RETURN_ERR;
6891
developer4b102122023-02-15 10:53:03 +08006892 params.name = "wpa_psk";
developer06a01d92022-09-07 16:32:39 +08006893
developer4b102122023-02-15 10:53:03 +08006894 if(strlen(preSharedKey) != 64)
developer06a01d92022-09-07 16:32:39 +08006895 {
developer4b102122023-02-15 10:53:03 +08006896 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 64 chars\n");
developer06a01d92022-09-07 16:32:39 +08006897 return RETURN_ERR;
6898 }
6899 params.value = preSharedKey;
6900 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6901 ret = wifi_hostapdWrite(config_file, &params, 1);
developer4b102122023-02-15 10:53:03 +08006902 if(!ret) {
developer06a01d92022-09-07 16:32:39 +08006903 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
developer4b102122023-02-15 10:53:03 +08006904 wifi_reloadAp(apIndex);
6905 }
developer06a01d92022-09-07 16:32:39 +08006906 return ret;
6907 //TODO: call hostapd_cli for dynamic_config_control
6908}
6909
6910//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6911// outputs the passphrase, maximum 63 characters
6912INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6913{
6914 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6915
6916 wifi_dbg_printf("\nFunc=%s\n",__func__);
6917 if (NULL == output_string)
6918 return RETURN_ERR;
6919
6920 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developerefb790a2023-12-26 18:58:32 +08006921 if (!syn_flag)
6922 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6923 else
developer07ded1f2024-01-10 10:30:15 +08006924 snprintf(buf, sizeof(buf), "%s", vap_info[apIndex].wpa);
developer06a01d92022-09-07 16:32:39 +08006925 if(strcmp(buf,"0")==0)
6926 {
6927 printf("wpa_mode is %s ......... \n",buf);
6928 return RETURN_ERR;
6929 }
6930
developerefb790a2023-12-26 18:58:32 +08006931 if (!syn_flag)
6932 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6933 else
developer07ded1f2024-01-10 10:30:15 +08006934 snprintf(output_string, 64, "%s", vap_info[apIndex].wpa_passphrase);
developer06a01d92022-09-07 16:32:39 +08006935 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6936
6937 return RETURN_OK;
6938}
6939
6940// sets the passphrase enviornment variable, max 63 characters
6941INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6942{
6943 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6944 struct params params={'\0'};
6945 char config_file[MAX_BUF_SIZE] = {0};
6946 int ret;
6947
6948 if(NULL == passPhrase)
6949 return RETURN_ERR;
6950
6951 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6952 {
6953 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6954 return RETURN_ERR;
6955 }
6956 params.name = "wpa_passphrase";
6957 params.value = passPhrase;
6958 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6959 ret=wifi_hostapdWrite(config_file,&params,1);
developer4b102122023-02-15 10:53:03 +08006960 if(!ret) {
developer06a01d92022-09-07 16:32:39 +08006961 wifi_hostapdProcessUpdate(apIndex, &params, 1);
developer4b102122023-02-15 10:53:03 +08006962 wifi_reloadAp(apIndex);
6963 }
developerefb790a2023-12-26 18:58:32 +08006964 snprintf(vap_info[apIndex].wpa_passphrase, MAX_BUF_SIZE, "%s", passPhrase);
developer06a01d92022-09-07 16:32:39 +08006965
6966 return ret;
6967}
6968
6969//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.
6970INT wifi_setApSecurityReset(INT apIndex)
6971{
developer8d583982022-09-20 11:28:22 +08006972 char original_config_file[64] = {0};
6973 char current_config_file[64] = {0};
6974 char buf[64] = {0};
6975 char cmd[64] = {0};
6976 char wpa[4] = {0};
6977 char wpa_psk[64] = {0};
6978 char wpa_passphrase[64] = {0};
6979 char wpa_psk_file[128] = {0};
6980 char wpa_key_mgmt[64] = {0};
6981 char wpa_pairwise[32] = {0};
6982 wifi_band band;
6983 struct params list[6];
6984
6985 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6986
6987 band = wifi_index_to_band(apIndex);
6988 if (band == band_2_4)
6989 sprintf(original_config_file, "/etc/hostapd-2G.conf");
developer30423732022-12-01 16:17:49 +08006990 else if (band == band_5)
developer8d583982022-09-20 11:28:22 +08006991 sprintf(original_config_file, "/etc/hostapd-5G.conf");
developer30423732022-12-01 16:17:49 +08006992 else if (band == band_6)
developer8d583982022-09-20 11:28:22 +08006993 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6994 else
6995 return RETURN_ERR;
6996
6997 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6998 list[0].name = "wpa";
6999 list[0].value = wpa;
7000
7001 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
7002 list[1].name = "wpa_psk";
7003 list[1].value = wpa_psk;
7004
7005 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
7006 list[2].name = "wpa_passphrase";
7007 list[2].value = wpa_passphrase;
7008
7009 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
7010
7011 if (strlen(wpa_psk_file) == 0)
7012 strcpy(wpa_psk_file, PSK_FILE);
7013
7014 if (access(wpa_psk_file, F_OK) != 0) {
7015 sprintf(cmd, "touch %s", wpa_psk_file);
7016 _syscmd(cmd, buf, sizeof(buf));
7017 }
7018 list[3].name = "wpa_psk_file";
7019 list[3].value = wpa_psk_file;
7020
7021 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
7022 list[4].name = "wpa_key_mgmt";
7023 list[4].value = wpa_key_mgmt;
7024
7025 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
7026 list[5].name = "wpa_pairwise";
7027 list[5].value = wpa_pairwise;
7028
7029 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7030 wifi_hostapdWrite(current_config_file, list, 6);
7031
7032 wifi_setApEnable(apIndex, FALSE);
7033 wifi_setApEnable(apIndex, TRUE);
7034
7035 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7036 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08007037}
7038
7039//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).
7040INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
7041{
developer8f2ddd52022-09-13 15:39:24 +08007042 char config_file[64] = {0};
7043 char buf[64] = {0};
7044 char cmd[256] = {0};
7045
7046 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7047
developer06a01d92022-09-07 16:32:39 +08007048 if(!IP_output || !Port_output || !RadiusSecret_output)
7049 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08007050
developer8f2ddd52022-09-13 15:39:24 +08007051 // Read the first matched config
7052 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7053 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7054 _syscmd(cmd, buf, sizeof(buf));
7055 strncpy(IP_output, buf, 64);
7056
7057 memset(buf, 0, sizeof(buf));
7058 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7059 _syscmd(cmd, buf, sizeof(buf));
7060 *Port_output = atoi(buf);
7061
7062 memset(buf, 0, sizeof(buf));
7063 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7064 _syscmd(cmd, buf, sizeof(buf));
7065 strncpy(RadiusSecret_output, buf, 64);
7066
7067 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007068 return RETURN_OK;
7069}
7070
7071INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
7072{
developer8f2ddd52022-09-13 15:39:24 +08007073 char config_file[64] = {0};
7074 char port_str[8] = {0};
7075 char cmd[256] = {0};
7076 char buf[128] = {0};
7077
7078 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer4b102122023-02-15 10:53:03 +08007079 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
7080 return RETURN_ERR;
7081
7082 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
7083 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08007084
7085 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7086
7087 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
7088 _syscmd(cmd, buf, sizeof(buf));
7089 memset(cmd, 0, sizeof(cmd));
7090
7091 snprintf(port_str, sizeof(port_str), "%d", port);
7092 if (strlen(buf) == 0)
7093 // Append
7094 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
7095 "auth_server_addr=%s\\n"
7096 "auth_server_port=%s\\n"
7097 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
7098 else {
7099 // Delete the three lines setting after the "# radius 1" comment
7100 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
7101 _syscmd(cmd, buf, sizeof(buf));
7102 memset(cmd, 0, sizeof(cmd));
7103 // Use "# radius 1" comment to find the location to insert the radius setting
7104 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
7105 "# radius 1\\n"
7106 "auth_server_addr=%s\\n"
7107 "auth_server_port=%s\\n"
7108 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
7109 }
7110 if(_syscmd(cmd, buf, sizeof(buf))) {
7111 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
7112 return RETURN_ERR;
7113 }
7114
7115 wifi_reloadAp(apIndex);
7116 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7117 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08007118}
7119
7120INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
7121{
developer8f2ddd52022-09-13 15:39:24 +08007122 char config_file[64] = {0};
7123 char buf[64] = {0};
7124 char cmd[256] = {0};
7125
7126 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7127
developer06a01d92022-09-07 16:32:39 +08007128 if(!IP_output || !Port_output || !RadiusSecret_output)
7129 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08007130
7131 // Read the second matched config
7132 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7133 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7134 _syscmd(cmd, buf, sizeof(buf));
7135 strncpy(IP_output, buf, 64);
7136
7137 memset(buf, 0, sizeof(buf));
7138 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7139 _syscmd(cmd, buf, sizeof(buf));
7140 *Port_output = atoi(buf);
7141
7142 memset(buf, 0, sizeof(buf));
7143 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7144 _syscmd(cmd, buf, sizeof(buf));
7145 strncpy(RadiusSecret_output, buf, 64);
7146
7147 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007148 return RETURN_OK;
7149}
7150
7151INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
7152{
developer8f2ddd52022-09-13 15:39:24 +08007153 char config_file[64] = {0};
7154 char port_str[8] = {0};
7155 char cmd[256] = {0};
7156 char buf[128] = {0};
7157
7158 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer4b102122023-02-15 10:53:03 +08007159 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
7160 return RETURN_ERR;
7161
7162 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
7163 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08007164
7165 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7166
7167 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
7168 _syscmd(cmd, buf, sizeof(buf));
7169 memset(cmd, 0, sizeof(cmd));
7170
7171 snprintf(port_str, sizeof(port_str), "%d", port);
7172 if (strlen(buf) == 0)
7173 // Append
7174 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
7175 "auth_server_addr=%s\\n"
7176 "auth_server_port=%s\\n"
7177 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
7178 else {
7179 // Delete the three lines setting after the "# radius 2" comment
7180 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
7181 _syscmd(cmd, buf, sizeof(buf));
7182 memset(cmd, 0, sizeof(cmd));
7183 // Use "# radius 2" comment to find the location to insert the radius setting
7184 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
7185 "# radius 2\\n"
7186 "auth_server_addr=%s\\n"
7187 "auth_server_port=%s\\n"
7188 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
7189 }
7190 if(_syscmd(cmd, buf, sizeof(buf))) {
7191 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
7192 return RETURN_ERR;
7193 }
7194
7195 wifi_reloadAp(apIndex);
7196 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7197 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08007198}
7199
7200//RadiusSettings
7201INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
7202{
7203 if(!output)
7204 return RETURN_ERR;
7205
7206 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
7207 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
7208 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
7209 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
7210 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
7211 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.
7212 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
7213 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
7214 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
7215 //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.
7216
7217 return RETURN_OK;
7218}
7219
7220INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
7221{
7222 //store the paramters, and apply instantly
7223 return RETURN_ERR;
7224}
7225
7226//Device.WiFi.AccessPoint.{i}.WPS.Enable
7227//Enables or disables WPS functionality for this access point.
7228// outputs the WPS enable state of this ap in output_bool
7229INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
7230{
developerd946fd62022-12-08 18:03:28 +08007231 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007232 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer613892e2023-09-21 16:33:35 +08007233
7234 *output_bool=FALSE;
developer5b398df2022-11-17 20:39:48 +08007235 if(!output_bool)
developer06a01d92022-09-07 16:32:39 +08007236 return RETURN_ERR;
developerac6f1142022-12-20 19:26:35 +08007237 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer613892e2023-09-21 16:33:35 +08007238 return RETURN_OK;
developerd946fd62022-12-08 18:03:28 +08007239 sprintf(cmd,"hostapd_cli -i %s get_config | grep wps_state | cut -d '=' -f2", interface_name);
developer06a01d92022-09-07 16:32:39 +08007240 _syscmd(cmd, buf, sizeof(buf));
7241 if(strstr(buf, "configured"))
7242 *output_bool=TRUE;
developer06a01d92022-09-07 16:32:39 +08007243
7244 return RETURN_OK;
developer613892e2023-09-21 16:33:35 +08007245}
developer06a01d92022-09-07 16:32:39 +08007246
7247//Device.WiFi.AccessPoint.{i}.WPS.Enable
7248// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
7249INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
7250{
7251 char config_file[MAX_BUF_SIZE] = {0};
developer72ec5572023-01-05 16:27:13 +08007252 char buf[128] = {0};
developer06a01d92022-09-07 16:32:39 +08007253 struct params params;
7254
developer06a01d92022-09-07 16:32:39 +08007255 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7256 //store the paramters, and wait for wifi up to apply
7257 params.name = "wps_state";
developer72ec5572023-01-05 16:27:13 +08007258 if (enable == TRUE) {
7259 wifi_getApBeaconType(apIndex, buf);
7260 if (strncmp(buf, "None", 4) == 0) // If ap didn't set encryption
7261 params.value = "1";
7262 else // If ap set encryption
7263 params.value = "2";
7264 } else {
7265 params.value = "0";
7266 }
developer06a01d92022-09-07 16:32:39 +08007267
7268 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7269 wifi_hostapdWrite(config_file, &params, 1);
7270 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7271 wifi_reloadAp(apIndex);
7272
7273 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7274 return RETURN_OK;
7275}
7276
7277//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
7278INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
7279{
7280 if(!output)
7281 return RETURN_ERR;
7282 snprintf(output, 128, "PushButton,PIN");
7283 return RETURN_OK;
7284}
7285
7286//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
7287//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.
7288// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
7289INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
7290{
7291 if(!output)
7292 return RETURN_ERR;
7293 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
7294
7295 return RETURN_OK;
7296}
7297
7298//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
7299// 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
7300INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
7301{
7302 //apply instantly. No setting need to be stored.
7303 char methods[MAX_BUF_SIZE], *token, *next_token;
7304 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
7305 struct params params;
7306
developer5b398df2022-11-17 20:39:48 +08007307 if(!methodString)
developer06a01d92022-09-07 16:32:39 +08007308 return RETURN_ERR;
7309 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7310 //store the paramters, and wait for wifi up to apply
7311
7312 snprintf(methods, sizeof(methods), "%s", methodString);
7313 for(token=methods; *token; token=next_token)
7314 {
7315 strtok_r(token, ",", &next_token);
7316 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
7317 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
7318 else if(*token=='E')
7319 {
7320 if(!strcmp(methods, "Ethernet"))
7321 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
7322 else if(!strcmp(methods, "ExternalNFCToken"))
7323 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
7324 else
7325 printf("%s: Unknown WpsConfigMethod\n", __func__);
7326 }
7327 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
7328 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
7329 else if(*token=='N' && !strcmp(token, "NFCInterface"))
7330 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
7331 else if(*token=='P' )
7332 {
7333 if(!strcmp(token, "PushButton"))
developer894affa2023-05-10 18:13:19 +08007334 snprintf(config_methods, sizeof(config_methods), "%s ", "push_button");
developer06a01d92022-09-07 16:32:39 +08007335 else if(!strcmp(token, "PIN"))
7336 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
7337 else
7338 printf("%s: Unknown WpsConfigMethod\n", __func__);
7339 }
7340 else
7341 printf("%s: Unknown WpsConfigMethod\n", __func__);
7342 }
7343 params.name = "config_methods";
7344 params.value = config_methods;
7345 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7346 wifi_hostapdWrite(config_file, &params, 1);
7347 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7348 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7349
7350 return RETURN_OK;
7351}
7352
7353// outputs the pin value, ulong_pin must be allocated by the caller
7354INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
7355{
7356 char buf[MAX_BUF_SIZE] = {0};
7357 char cmd[MAX_CMD_SIZE] = {0};
7358
developer5b398df2022-11-17 20:39:48 +08007359 if(!output_ulong)
developer06a01d92022-09-07 16:32:39 +08007360 return RETURN_ERR;
7361 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
7362 _syscmd(cmd, buf, sizeof(buf));
7363 if(strlen(buf) > 0)
7364 *output_ulong=strtoul(buf, NULL, 10);
7365
7366 return RETURN_OK;
7367}
7368
7369// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
7370INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
7371{
7372 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
7373 char ap_pin[16] = {0};
7374 char buf[MAX_BUF_SIZE] = {0};
7375 char config_file[MAX_BUF_SIZE] = {0};
7376 ULONG prev_pin = 0;
7377 struct params params;
7378
developer06a01d92022-09-07 16:32:39 +08007379 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7380 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
7381 params.name = "ap_pin";
7382 params.value = ap_pin;
7383 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7384 wifi_hostapdWrite(config_file, &params, 1);
7385 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7386 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7387
7388 return RETURN_OK;
7389}
7390
7391// Output string is either Not configured or Configured, max 32 characters
7392INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
7393{
developerd946fd62022-12-08 18:03:28 +08007394 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007395 char cmd[MAX_CMD_SIZE];
7396 char buf[MAX_BUF_SIZE]={0};
7397
developer5b398df2022-11-17 20:39:48 +08007398 if(!output_string)
developer06a01d92022-09-07 16:32:39 +08007399 return RETURN_ERR;
7400 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7401 snprintf(output_string, 32, "Not configured");
developerac6f1142022-12-20 19:26:35 +08007402 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007403 return RETURN_ERR;
7404 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep wps_state | cut -d'=' -f2", interface_name);
developer06a01d92022-09-07 16:32:39 +08007405 _syscmd(cmd, buf, sizeof(buf));
7406
developer348e3d92022-09-13 14:48:41 +08007407 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08007408 snprintf(output_string, 32, "Configured");
7409 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7410
7411 return RETURN_OK;
7412}
7413
7414// sets the WPS pin for this AP
7415INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
7416{
developerd946fd62022-12-08 18:03:28 +08007417 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007418 char cmd[MAX_CMD_SIZE];
7419 char buf[MAX_BUF_SIZE]={0};
7420 BOOL enable;
7421
developer06a01d92022-09-07 16:32:39 +08007422 wifi_getApEnable(apIndex, &enable);
7423 if (!enable)
7424 return RETURN_ERR;
7425 wifi_getApWpsEnable(apIndex, &enable);
7426 if (!enable)
7427 return RETURN_ERR;
7428
developerac6f1142022-12-20 19:26:35 +08007429 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007430 return RETURN_ERR;
7431 snprintf(cmd, 64, "hostapd_cli -i%s wps_pin any %s", interface_name, pin);
developer06a01d92022-09-07 16:32:39 +08007432 _syscmd(cmd, buf, sizeof(buf));
7433 if((strstr(buf, "OK"))!=NULL)
7434 return RETURN_OK;
7435
7436 return RETURN_ERR;
7437}
7438
7439// This function is called when the WPS push button has been pressed for this AP
7440INT wifi_setApWpsButtonPush(INT apIndex)
7441{
7442 char cmd[MAX_CMD_SIZE];
7443 char buf[MAX_BUF_SIZE]={0};
developerd946fd62022-12-08 18:03:28 +08007444 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007445 BOOL enable=FALSE;
7446
developer06a01d92022-09-07 16:32:39 +08007447 wifi_getApEnable(apIndex, &enable);
7448 if (!enable)
7449 return RETURN_ERR;
7450
7451 wifi_getApWpsEnable(apIndex, &enable);
7452 if (!enable)
7453 return RETURN_ERR;
7454
developerac6f1142022-12-20 19:26:35 +08007455 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007456 return RETURN_ERR;
7457
developer900e2b72023-05-23 10:23:48 +08007458 snprintf(cmd, sizeof(cmd), "sleep 1 && hostapd_cli -i%s wps_cancel && hostapd_cli -i%s wps_pbc", interface_name, interface_name);
developer06a01d92022-09-07 16:32:39 +08007459 _syscmd(cmd, buf, sizeof(buf));
7460
7461 if((strstr(buf, "OK"))!=NULL)
7462 return RETURN_OK;
7463 return RETURN_ERR;
7464}
7465
7466// cancels WPS mode for this AP
7467INT wifi_cancelApWPS(INT apIndex)
7468{
developerd946fd62022-12-08 18:03:28 +08007469 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007470 char cmd[MAX_CMD_SIZE];
7471 char buf[MAX_BUF_SIZE]={0};
7472
developerac6f1142022-12-20 19:26:35 +08007473 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007474 return RETURN_ERR;
7475 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel", interface_name);
developer06a01d92022-09-07 16:32:39 +08007476 _syscmd(cmd,buf, sizeof(buf));
7477
7478 if((strstr(buf, "OK"))!=NULL)
7479 return RETURN_OK;
7480 return RETURN_ERR;
7481}
7482
7483//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
7484//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
7485INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
7486{
developerd946fd62022-12-08 18:03:28 +08007487 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08007488 FILE *f = NULL;
developer06a01d92022-09-07 16:32:39 +08007489 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
developer30423732022-12-01 16:17:49 +08007490 char cmd[256] = {0}, buf[2048] = {0};
7491 char *param = NULL, *value = NULL, *line=NULL;
developer06a01d92022-09-07 16:32:39 +08007492 size_t len = 0;
developer30423732022-12-01 16:17:49 +08007493 ssize_t nread = 0;
developer06a01d92022-09-07 16:32:39 +08007494 wifi_associated_dev_t *dev=NULL;
7495
7496 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7497 *associated_dev_array = NULL;
developerac6f1142022-12-20 19:26:35 +08007498 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007499 return RETURN_ERR;
7500 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08007501 _syscmd(cmd,buf,sizeof(buf));
7502 *output_array_size = atoi(buf);
7503
7504 if (*output_array_size <= 0)
7505 return RETURN_OK;
7506
7507 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
7508 *associated_dev_array = dev;
developerd946fd62022-12-08 18:03:28 +08007509 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt" , interface_name);
developer06a01d92022-09-07 16:32:39 +08007510 _syscmd(cmd,buf,sizeof(buf));
7511 f = fopen("/tmp/connected_devices.txt", "r");
7512 if (f==NULL)
7513 {
7514 *output_array_size=0;
7515 return RETURN_ERR;
7516 }
developer30423732022-12-01 16:17:49 +08007517 while ((getline(&line, &len, f)) != -1)
developer06a01d92022-09-07 16:32:39 +08007518 {
7519 param = strtok(line,"=");
7520 value = strtok(NULL,"=");
7521
7522 if( strcmp("flags",param) == 0 )
7523 {
7524 value[strlen(value)-1]='\0';
7525 if(strstr (value,"AUTHORIZED") != NULL )
7526 {
7527 dev[auth_temp].cli_AuthenticationState = 1;
7528 dev[auth_temp].cli_Active = 1;
7529 auth_temp++;
7530 read_flag=1;
7531 }
7532 }
7533 if(read_flag==1)
7534 {
7535 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7536 {
7537 value[strlen(value)-1]='\0';
7538 sscanf(value, "%x:%x:%x:%x:%x:%x",
7539 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7540 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7541 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7542 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7543 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7544 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7545 mac_temp++;
7546 read_flag=0;
7547 }
7548 }
7549 }
7550 *output_array_size = auth_temp;
7551 auth_temp=0;
7552 mac_temp=0;
7553 free(line);
7554 fclose(f);
7555 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7556 return RETURN_OK;
7557}
7558
7559#define MACADDRESS_SIZE 6
7560
7561INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7562{
7563 FILE *fp = NULL;
7564 char str[MAX_BUF_SIZE] = {0};
7565 int wificlientindex = 0 ;
7566 int count = 0;
7567 int signalstrength = 0;
7568 int arr[MACADDRESS_SIZE] = {0};
7569 unsigned char mac[MACADDRESS_SIZE] = {0};
7570 UINT wifi_count = 0;
7571 char virtual_interface_name[MAX_BUF_SIZE] = {0};
7572 char pipeCmd[MAX_CMD_SIZE] = {0};
7573
7574 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7575 *output_array_size = 0;
7576 *associated_dev_array = NULL;
7577
7578 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
7579 fp = popen(pipeCmd, "r");
7580 if (fp == NULL)
7581 {
7582 printf("Failed to run command inside function %s\n",__FUNCTION__ );
7583 return RETURN_ERR;
7584 }
7585
7586 /* Read the output a line at a time - output it. */
7587 fgets(str, sizeof(str)-1, fp);
7588 wifi_count = (unsigned int) atoi ( str );
7589 *output_array_size = wifi_count;
7590 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
7591 pclose(fp);
7592
7593 if(wifi_count == 0)
7594 {
7595 return RETURN_OK;
7596 }
7597 else
7598 {
7599 wifi_associated_dev3_t* temp = NULL;
7600 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
7601 if(temp == NULL)
7602 {
7603 printf("Error Statement. Insufficient memory \n");
7604 return RETURN_ERR;
7605 }
7606
7607 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
7608 system(pipeCmd);
7609 memset(pipeCmd,0,sizeof(pipeCmd));
7610 if(apIndex == 0)
7611 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
7612 else if(apIndex == 1)
7613 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
7614 system(pipeCmd);
7615
7616 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
7617 if(fp == NULL)
7618 {
7619 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
developerd946fd62022-12-08 18:03:28 +08007620 free(temp);
developer06a01d92022-09-07 16:32:39 +08007621 return RETURN_ERR;
7622 }
7623 fclose(fp);
7624
developer30423732022-12-01 16:17:49 +08007625 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08007626 fp = popen(pipeCmd, "r");
7627 if(fp)
7628 {
7629 for(count =0 ; count < wifi_count; count++)
7630 {
7631 fgets(str, MAX_BUF_SIZE, fp);
7632 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7633 {
7634 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7635 {
7636 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7637
7638 }
7639 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7640 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]);
7641 }
7642 temp[count].cli_AuthenticationState = 1; //TODO
7643 temp[count].cli_Active = 1; //TODO
7644 }
7645 pclose(fp);
7646 }
7647
developer30423732022-12-01 16:17:49 +08007648 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt");
developer06a01d92022-09-07 16:32:39 +08007649 fp = popen(pipeCmd, "r");
7650 if(fp)
7651 {
7652 pclose(fp);
7653 }
7654 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
7655 if(fp)
7656 {
7657 for(count =0 ; count < wifi_count ;count++)
7658 {
7659 fgets(str, MAX_BUF_SIZE, fp);
7660 signalstrength = atoi(str);
7661 temp[count].cli_SignalStrength = signalstrength;
7662 temp[count].cli_RSSI = signalstrength;
7663 temp[count].cli_SNR = signalstrength + 95;
7664 }
7665 pclose(fp);
7666 }
7667
7668
7669 if((apIndex == 0) || (apIndex == 4))
7670 {
7671 for(count =0 ; count < wifi_count ;count++)
7672 {
7673 strcpy(temp[count].cli_OperatingStandard,"g");
7674 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
7675 }
7676
7677 //BytesSent
developer30423732022-12-01 16:17:49 +08007678 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt");
developer06a01d92022-09-07 16:32:39 +08007679 fp = popen(pipeCmd, "r");
7680 if(fp)
7681 {
7682 pclose(fp);
7683 }
7684 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
7685 if(fp)
7686 {
7687 for (count = 0; count < wifi_count; count++)
7688 {
7689 fgets(str, MAX_BUF_SIZE, fp);
7690 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
7691 }
7692 pclose(fp);
7693 }
7694
7695 //BytesReceived
developer30423732022-12-01 16:17:49 +08007696 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt");
developer06a01d92022-09-07 16:32:39 +08007697 fp = popen(pipeCmd, "r");
7698 if (fp)
7699 {
7700 pclose(fp);
7701 }
7702 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
7703 if (fp)
7704 {
7705 for (count = 0; count < wifi_count; count++)
7706 {
7707 fgets(str, MAX_BUF_SIZE, fp);
7708 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7709 }
7710 pclose(fp);
7711 }
7712
7713 //PacketsSent
developer30423732022-12-01 16:17:49 +08007714 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt");
developer06a01d92022-09-07 16:32:39 +08007715 fp = popen(pipeCmd, "r");
7716 if (fp)
7717 {
7718 pclose(fp);
7719 }
7720
7721 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7722 if (fp)
7723 {
7724 for (count = 0; count < wifi_count; count++)
7725 {
7726 fgets(str, MAX_BUF_SIZE, fp);
7727 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7728 }
7729 pclose(fp);
7730 }
7731
7732 //PacketsReceived
developer30423732022-12-01 16:17:49 +08007733 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt");
developer06a01d92022-09-07 16:32:39 +08007734 fp = popen(pipeCmd, "r");
7735 if (fp)
7736 {
7737 pclose(fp);
7738 }
7739 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7740 if (fp)
7741 {
7742 for (count = 0; count < wifi_count; count++)
7743 {
7744 fgets(str, MAX_BUF_SIZE, fp);
7745 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7746 }
7747 pclose(fp);
7748 }
7749
7750 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007751 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt");
developer06a01d92022-09-07 16:32:39 +08007752 fp = popen(pipeCmd, "r");
7753 if (fp)
7754 {
7755 pclose(fp);
7756 }
7757 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7758 if (fp)
7759 {
7760 for (count = 0; count < wifi_count; count++)
7761 {
7762 fgets(str, MAX_BUF_SIZE, fp);
7763 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7764 }
7765 pclose(fp);
7766 }
7767
7768 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007769 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt");
developer06a01d92022-09-07 16:32:39 +08007770 fp = popen(pipeCmd, "r");
7771 if (fp)
7772 {
7773 pclose(fp);
7774 }
7775 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7776 if (fp)
7777 {
7778 for (count = 0; count < wifi_count; count++)
7779 {
7780 fgets(str, MAX_BUF_SIZE, fp);
7781 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7782 }
7783 pclose(fp);
7784 }
7785
7786 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08007787 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt");
developer06a01d92022-09-07 16:32:39 +08007788 fp = popen(pipeCmd, "r");
7789 if (fp)
7790 {
7791 pclose(fp);
7792 }
7793 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7794 if (fp)
7795 {
7796 for (count = 0; count < wifi_count; count++)
7797 {
7798 fgets(str, MAX_BUF_SIZE, fp);
7799 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7800 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7801 }
7802 pclose(fp);
7803 }
7804
7805 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08007806 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt");
developer06a01d92022-09-07 16:32:39 +08007807 fp = popen(pipeCmd, "r");
7808 if (fp)
7809 {
7810 pclose(fp);
7811 }
7812 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7813 if (fp)
7814 {
7815 for (count = 0; count < wifi_count; count++)
7816 {
7817 fgets(str, MAX_BUF_SIZE, fp);
7818 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7819 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7820 }
7821 pclose(fp);
7822 }
7823
7824 }
7825 else if ((apIndex == 1) || (apIndex == 5))
7826 {
7827 for (count = 0; count < wifi_count; count++)
7828 {
7829 strcpy(temp[count].cli_OperatingStandard, "a");
7830 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7831 temp[count].cli_BytesSent = 0;
7832 temp[count].cli_BytesReceived = 0;
7833 temp[count].cli_LastDataUplinkRate = 0;
7834 temp[count].cli_LastDataDownlinkRate = 0;
7835 temp[count].cli_PacketsSent = 0;
7836 temp[count].cli_PacketsReceived = 0;
7837 temp[count].cli_ErrorsSent = 0;
7838 }
7839 }
7840
7841 for (count = 0; count < wifi_count; count++)
7842 {
7843 temp[count].cli_Retransmissions = 0;
7844 temp[count].cli_DataFramesSentAck = 0;
7845 temp[count].cli_DataFramesSentNoAck = 0;
7846 temp[count].cli_MinRSSI = 0;
7847 temp[count].cli_MaxRSSI = 0;
7848 strncpy(temp[count].cli_InterferenceSources, "", 64);
7849 memset(temp[count].cli_IPAddress, 0, 64);
7850 temp[count].cli_RetransCount = 0;
7851 temp[count].cli_FailedRetransCount = 0;
7852 temp[count].cli_RetryCount = 0;
7853 temp[count].cli_MultipleRetryCount = 0;
7854 }
7855 *associated_dev_array = temp;
7856 }
7857 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7858 return RETURN_OK;
7859}
7860
7861int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7862{
7863 FILE *fp = NULL;
7864 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7865 char cmd[MAX_CMD_SIZE];
7866 int count = 0;
7867
7868 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7869 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7870 fp = popen(cmd,"r");
7871 if(fp == NULL)
7872 {
7873 printf("Failed to run command in Function %s\n",__FUNCTION__);
7874 return 0;
7875 }
7876 if(fgets(path, sizeof(path)-1, fp) != NULL)
7877 {
7878 for(count=0;path[count]!='\n';count++)
7879 status[count]=path[count];
7880 status[count]='\0';
7881 }
7882 strcpy(wifi_status,status);
7883 pclose(fp);
7884 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7885 return RETURN_OK;
7886}
7887
7888/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7889struct hostapd_sta_param {
7890 char key[50];
7891 char value[100];
7892}
7893
7894static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7895 int i = 0;
7896
7897 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7898 if (strncmp(params[i].key,key,50) == 0){
7899 return &params[i].value;
7900 }
7901 i++;
7902 }
7903 return NULL;
7904
7905} */
7906
7907static unsigned int count_occurences(const char *buf, const char *word)
7908{
7909 unsigned int n = 0;
7910 char *ptr = strstr(buf, word);
7911
7912 while (ptr++) {
7913 n++;
7914 ptr = strstr(ptr, word);
7915 }
7916
7917 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7918 return n;
7919}
7920
7921static const char *get_line_from_str_buf(const char *buf, char *line)
7922{
7923 int i;
7924 int n = strlen(buf);
7925
7926 for (i = 0; i < n; i++) {
7927 line[i] = buf[i];
7928 if (buf[i] == '\n') {
7929 line[i] = '\0';
7930 return &buf[i + 1];
7931 }
7932 }
7933
7934 return NULL;
7935}
7936
developer9a9f46e2023-11-09 09:22:42 +08007937static INT wifi_getAssocConnectMode(INT apIndex, CHAR *input_string, CHAR *OperatingStandard)
7938{
7939 wifi_band band;
7940 int ieee80211_mode = 0;
7941
7942 if (!input_string || !OperatingStandard)
7943 return RETURN_ERR;
7944
7945 band = wifi_index_to_band(apIndex);
7946
7947 if (strstr(input_string, "HE"))
7948 ieee80211_mode = WIFI_MODE_AX;
7949 else if (strstr(input_string, "VHT"))
7950 ieee80211_mode = WIFI_MODE_AC;
7951 else if (strstr(input_string, "EHT"))
7952 ieee80211_mode = WIFI_MODE_BE;
7953
7954 switch (ieee80211_mode) {
7955 case WIFI_MODE_AC:
7956 strncpy(OperatingStandard, "ac", 2);
7957 break;
7958 case WIFI_MODE_AX:
7959 strncpy(OperatingStandard, "ax", 2);
7960 break;
7961 case WIFI_MODE_BE:
7962 strncpy(OperatingStandard, "be", 2);
7963 break;
7964 default:
7965 if(band == band_2_4)
7966 strncpy(OperatingStandard,"b,g,n", 5);
7967 else if(band == band_5)
7968 strncpy(OperatingStandard,"a,n", 3);
7969 else if(band == band_6)
7970 strncpy(OperatingStandard,"ax", 2);
7971 else {
7972 wifi_dbg_printf("%s: failed to parse band %d\n", __FUNCTION__, band);
7973 return RETURN_ERR;
7974 }
7975 }
7976
7977
7978 return RETURN_OK;
7979}
7980
developer06a01d92022-09-07 16:32:39 +08007981INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7982{
7983 unsigned int assoc_cnt = 0;
7984 char interface_name[50] = {0};
7985 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7986 char cmd[MAX_CMD_SIZE] = {'\0'};
7987 char line[256] = {'\0'};
7988 int i = 0;
7989 int ret = 0;
7990 const char *ptr = NULL;
7991 char *key = NULL;
7992 char *val = NULL;
7993 wifi_associated_dev3_t *temp = NULL;
7994 int rssi;
7995
7996 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7997
7998 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7999 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8000 return RETURN_ERR;
8001 }
8002
8003 // Example filtered output of 'iw dev' command:
8004 // Station 0a:69:72:10:d2:fa (on wifi0)
8005 // signal avg:-67 [-71, -71] dBm
8006 // Station 28:c2:1f:25:5f:99 (on wifi0)
8007 // signal avg:-67 [-71, -70] dBm
developer9a9f46e2023-11-09 09:22:42 +08008008 if (sprintf(cmd,"iw dev %s station dump | tr -d '\t' | grep -E 'Station|signal avg"
8009 "|tx bitrate|rx bitrate'", interface_name) < 0) {
8010 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
developer06a01d92022-09-07 16:32:39 +08008011 return RETURN_ERR;
8012 }
8013
8014 ret = _syscmd(cmd, buf, sizeof(buf));
8015 if (ret == RETURN_ERR) {
8016 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
8017 return RETURN_ERR;
8018 }
8019
8020 *output_array_size = count_occurences(buf, "Station");
8021 if (*output_array_size == 0) return RETURN_OK;
8022
8023 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
8024 if (temp == NULL) {
8025 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
8026 return RETURN_ERR;
8027 }
8028 *associated_dev_array = temp;
8029
8030 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
8031 ptr = get_line_from_str_buf(buf, line);
8032 i = -1;
8033 while (ptr) {
8034 if (strstr(line, "Station")) {
8035 i++;
8036 key = strtok(line, " ");
8037 val = strtok(NULL, " ");
8038 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
8039 &temp[i].cli_MACAddress[0],
8040 &temp[i].cli_MACAddress[1],
8041 &temp[i].cli_MACAddress[2],
8042 &temp[i].cli_MACAddress[3],
8043 &temp[i].cli_MACAddress[4],
8044 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
8045 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
8046 free(*associated_dev_array);
8047 return RETURN_ERR;
8048 }
8049 }
8050 else if (i < 0) {
developer9a9f46e2023-11-09 09:22:42 +08008051 wifi_dbg_printf("%s: not find station\n", __FUNCTION__);
developer06a01d92022-09-07 16:32:39 +08008052 ptr = get_line_from_str_buf(ptr, line);
8053 continue; // We didn't detect 'station' entry yet
8054 }
8055 else if (strstr(line, "signal avg")) {
8056 key = strtok(line, ":");
8057 val = strtok(NULL, " ");
8058 if (sscanf(val, "%d", &rssi) <= 0 ) {
8059 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
8060 free(*associated_dev_array);
8061 return RETURN_ERR;
8062 }
8063 temp[i].cli_RSSI = rssi;
8064 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
8065 }
developer9a9f46e2023-11-09 09:22:42 +08008066 else if (strstr(line, "tx bitrate")) {
8067 ret = wifi_getAssocConnectMode(apIndex, line, temp[i].cli_OperatingStandard);
8068 if (ret == RETURN_ERR) {
8069 wifi_dbg_printf("%s: failed to execute tx get assoc connect mode command.\n", __FUNCTION__);
8070 return ret;
8071 }
8072 }
8073 else if (strstr(line, "rx bitrate")) {
8074 /* if tx get ac, ax, be mode, need not get mode from rx */
8075 if (strncmp(temp[i].cli_OperatingStandard,"ac", 2) &&
8076 strncmp(temp[i].cli_OperatingStandard,"ax", 2) &&
8077 strncmp(temp[i].cli_OperatingStandard,"be", 2)) {
8078 ret = wifi_getAssocConnectMode(apIndex, line, temp[i].cli_OperatingStandard);
8079 if (ret == RETURN_ERR) {
8080 wifi_dbg_printf("%s: failed to execute rx get assoc connect mode command.\n", __FUNCTION__);
8081 return ret;
8082 }
8083 }
8084 }
developer06a01d92022-09-07 16:32:39 +08008085 // Here other fields can be parsed if added to filter of 'iw dev' command
developer06a01d92022-09-07 16:32:39 +08008086 ptr = get_line_from_str_buf(ptr, line);
developer9a9f46e2023-11-09 09:22:42 +08008087 }
developer06a01d92022-09-07 16:32:39 +08008088
8089 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008090 return RETURN_OK;
8091}
8092
8093#if 0
8094//To-do
8095INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8096{
8097 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8098
8099 //Using different approach to get required WiFi Parameters from system available commands
8100#if 0
8101 FILE *f;
8102 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
8103 char cmd[256], buf[2048];
8104 char *param , *value, *line=NULL;
8105 size_t len = 0;
8106 ssize_t nread;
8107 wifi_associated_dev3_t *dev=NULL;
8108 *associated_dev_array = NULL;
developerd946fd62022-12-08 18:03:28 +08008109 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08008110 _syscmd(cmd,buf,sizeof(buf));
8111 *output_array_size = atoi(buf);
8112
8113 if (*output_array_size <= 0)
8114 return RETURN_OK;
8115
8116 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
8117 *associated_dev_array = dev;
developerd946fd62022-12-08 18:03:28 +08008118 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt", interface_name);
developer06a01d92022-09-07 16:32:39 +08008119 _syscmd(cmd,buf,sizeof(buf));
8120 f = fopen("/tmp/connected_devices.txt", "r");
8121 if (f==NULL)
8122 {
8123 *output_array_size=0;
8124 return RETURN_ERR;
8125 }
8126 while ((nread = getline(&line, &len, f)) != -1)
8127 {
8128 param = strtok(line,"=");
8129 value = strtok(NULL,"=");
8130
8131 if( strcmp("flags",param) == 0 )
8132 {
8133 value[strlen(value)-1]='\0';
8134 if(strstr (value,"AUTHORIZED") != NULL )
8135 {
8136 dev[auth_temp].cli_AuthenticationState = 1;
8137 dev[auth_temp].cli_Active = 1;
8138 auth_temp++;
8139 read_flag=1;
8140 }
8141 }
8142 if(read_flag==1)
8143 {
8144 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
8145 {
8146 value[strlen(value)-1]='\0';
8147 sscanf(value, "%x:%x:%x:%x:%x:%x",
8148 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
8149 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
8150 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
8151 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
8152 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
8153 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
8154
8155 }
8156 else if( strcmp("rx_packets",param) == 0 )
8157 {
8158 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
8159 }
8160
8161 else if( strcmp("tx_packets",param) == 0 )
8162 {
8163 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
8164 }
8165
8166 else if( strcmp("rx_bytes",param) == 0 )
8167 {
8168 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
8169 }
8170
8171 else if( strcmp("tx_bytes",param) == 0 )
8172 {
8173 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
8174 mac_temp++;
8175 read_flag=0;
8176 }
8177 }
8178 }
8179
8180 *output_array_size = auth_temp;
8181 auth_temp=0;
8182 mac_temp=0;
8183 free(line);
8184 fclose(f);
8185#endif
8186 char interface_name[MAX_BUF_SIZE] = {0};
8187 char wifi_status[MAX_BUF_SIZE] = {0};
8188 char hostapdconf[MAX_BUF_SIZE] = {0};
8189
8190 wifi_associated_dev3_t *dev_array = NULL;
8191 ULONG wifi_count = 0;
8192
8193 *associated_dev_array = NULL;
8194 *output_array_size = 0;
8195
8196 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
8197 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
8198 {
8199 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
8200
developerac6f1142022-12-20 19:26:35 +08008201 wifi_GetInterfaceName(interface_name, hostapdconf);
developer06a01d92022-09-07 16:32:39 +08008202
8203 if(strlen(interface_name) > 1)
8204 {
8205 wifihal_interfacestatus(wifi_status,interface_name);
8206 if(strcmp(wifi_status,"RUNNING") == 0)
8207 {
8208 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
8209
8210 *associated_dev_array = dev_array;
8211 *output_array_size = wifi_count;
8212 }
8213 else
8214 {
8215 *associated_dev_array = NULL;
8216 }
8217 }
8218 }
8219
8220 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8221 return RETURN_OK;
8222}
8223#endif
8224
8225/* getIPAddress function */
8226/**
8227* @description Returning IpAddress of the Matched String
8228*
8229* @param
8230* @str Having MacAddress
8231* @ipaddr Having ipaddr
8232* @return The status of the operation
8233* @retval RETURN_OK if successful
8234* @retval RETURN_ERR if any error is detected
8235*
8236*/
8237
8238INT getIPAddress(char *str,char *ipaddr)
8239{
8240 FILE *fp = NULL;
8241 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
8242 int LeaseTime = 0,ret = 0;
8243 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
8244 {
8245 return RETURN_ERR;
8246 }
8247
8248 while ( fgets(buf, sizeof(buf), fp)!= NULL )
8249 {
8250 /*
8251 Sample:sss
8252 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
8253 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
8254 */
8255 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
developerd946fd62022-12-08 18:03:28 +08008256 &(LeaseTime),
8257 phyAddr,
8258 ipAddr,
8259 hostName
8260 );
developer06a01d92022-09-07 16:32:39 +08008261 if(ret != 4)
8262 continue;
8263 if(strcmp(str,phyAddr) == 0)
developerd946fd62022-12-08 18:03:28 +08008264 strcpy(ipaddr,ipAddr);
developer06a01d92022-09-07 16:32:39 +08008265 }
developerd946fd62022-12-08 18:03:28 +08008266 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08008267 return RETURN_OK;
8268}
8269
8270/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
8271/**
8272* @description Returning Inactive wireless connected clients informations
8273*
8274* @param
8275* @filename Holding private_wifi 2g/5g content files
8276* @associated_dev_array Having inactiv wireless clients informations
8277* @output_array_size Returning Inactive wireless counts
8278* @return The status of the operation
8279* @retval RETURN_OK if successful
8280* @retval RETURN_ERR if any error is detected
8281*
8282*/
8283
8284INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8285{
8286 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8287 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
8288 FILE *fp = NULL;
8289 int arr[MACADDRESS_SIZE] = {0};
8290 unsigned char mac[MACADDRESS_SIZE] = {0};
8291 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
8292 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
8293 fp = popen(buf,"r");
8294 if(fp == NULL)
8295 return RETURN_ERR;
8296 else
8297 {
8298 fgets(path,sizeof(path),fp);
8299 maccount = atoi(path);
8300 }
8301 pclose(fp);
8302 *output_array_size = maccount;
8303 wifi_associated_dev3_t* temp = NULL;
8304 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
8305 *associated_dev_array = temp;
8306 if(temp == NULL)
8307 {
8308 printf("Error Statement. Insufficient memory \n");
8309 return RETURN_ERR;
8310 }
8311 memset(buf,0,sizeof(buf));
8312 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
8313 fp = popen(buf,"r");
developer30423732022-12-01 16:17:49 +08008314 if (fp == NULL) {
8315 fprintf(stderr, "%s: failed pipe command %s.\n", __func__, buf);
8316 return RETURN_ERR;
8317 }
developer06a01d92022-09-07 16:32:39 +08008318 for(count = 0; count < maccount ; count++)
8319 {
8320 fgets(path,sizeof(path),fp);
8321 for(i = 0; path[i]!='\n';i++)
8322 str[i]=path[i];
8323 str[i]='\0';
8324 getIPAddress(str,ipaddr);
8325 memset(buf,0,sizeof(buf));
8326 if(strlen(ipaddr) > 0)
8327 {
8328 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
8329 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
8330 {
8331 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8332 {
8333 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8334 {
8335 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8336
8337 }
8338 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8339 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]);
8340 }
8341 temp[count].cli_AuthenticationState = 0; //TODO
8342 temp[count].cli_Active = 0; //TODO
8343 temp[count].cli_SignalStrength = 0;
8344 }
8345 else //Active wireless clients info
8346 {
8347 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8348 {
8349 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8350 {
8351 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8352
8353 }
8354 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8355 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]);
8356 }
8357 temp[count].cli_Active = 1;
8358 }
8359 }
8360 memset(ipaddr,0,sizeof(ipaddr));
8361 }
8362 pclose(fp);
8363 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8364 return RETURN_OK;
8365}
8366//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
8367//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
8368//To get Band Steering Capability
8369INT wifi_getBandSteeringCapability(BOOL *support)
8370{
8371 *support = FALSE;
8372 return RETURN_OK;
8373}
8374
8375
8376//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
8377//To get Band Steering enable status
8378INT wifi_getBandSteeringEnable(BOOL *enable)
8379{
8380 *enable = FALSE;
8381 return RETURN_OK;
8382}
8383
8384//To turn on/off Band steering
8385INT wifi_setBandSteeringEnable(BOOL enable)
8386{
8387 return RETURN_OK;
8388}
8389
8390//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
8391//To get Band Steering AP group
8392INT wifi_getBandSteeringApGroup(char *output_ApGroup)
8393{
8394 if (NULL == output_ApGroup)
8395 return RETURN_ERR;
8396
8397 strcpy(output_ApGroup, "1,2");
8398 return RETURN_OK;
8399}
8400
8401//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
8402//to set and read the band steering BandUtilizationThreshold parameters
8403INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
8404{
8405 return RETURN_ERR;
8406}
8407
8408INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
8409{
8410 return RETURN_ERR;
8411}
8412
8413//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
8414//to set and read the band steering RSSIThreshold parameters
8415INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
8416{
8417 return RETURN_ERR;
8418}
8419
8420INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
8421{
8422 return RETURN_ERR;
8423}
8424
8425
8426//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
8427//to set and read the band steering physical modulation rate threshold parameters
8428INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
8429{
8430 //If chip is not support, return -1
8431 return RETURN_ERR;
8432}
8433
8434INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
8435{
8436 //If chip is not support, return -1
8437 return RETURN_ERR;
8438}
8439
8440//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
8441//to set and read the inactivity time (in seconds) for steering under overload condition
8442INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
8443{
8444 return RETURN_ERR;
8445}
8446
8447INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
8448{
8449 return RETURN_ERR;
8450}
8451
8452//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
8453//to set and read the inactivity time (in seconds) for steering under Idle condition
8454INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
8455{
8456 return RETURN_ERR;
8457}
8458
8459INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
8460{
8461 return RETURN_ERR;
8462}
8463
8464//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
8465//pClientMAC[64]
8466//pSourceSSIDIndex[64]
8467//pDestSSIDIndex[64]
8468//pSteeringReason[256]
8469INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
8470{
8471 //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
8472 *pSteeringTime=time(NULL);
8473 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
8474 return RETURN_OK;
8475}
8476
8477INT wifi_ifConfigDown(INT apIndex)
8478{
8479 INT status = RETURN_OK;
8480 char cmd[64];
8481
8482 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
8483 printf("%s: %s\n", __func__, cmd);
8484 system(cmd);
8485
8486 return status;
8487}
8488
8489INT wifi_ifConfigUp(INT apIndex)
8490{
developerd946fd62022-12-08 18:03:28 +08008491 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008492 char cmd[128];
8493 char buf[1024];
8494
developerac6f1142022-12-20 19:26:35 +08008495 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008496 return RETURN_ERR;
8497 snprintf(cmd, sizeof(cmd), "ifconfig %s up 2>/dev/null", interface_name);
developer06a01d92022-09-07 16:32:39 +08008498 _syscmd(cmd, buf, sizeof(buf));
8499 return 0;
8500}
8501
8502//>> Deprecated. Replace with wifi_applyRadioSettings
8503INT wifi_pushBridgeInfo(INT apIndex)
8504{
developerd946fd62022-12-08 18:03:28 +08008505 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08008506 char ip[32] = {0};
8507 char subnet[32] = {0};
8508 char bridge[32] = {0};
8509 int vlanId = 0;
8510 char cmd[128] = {0};
8511 char buf[1024] = {0};
developer06a01d92022-09-07 16:32:39 +08008512
8513 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
8514 wifi_getApVlanID(apIndex,&vlanId);
8515
developerac6f1142022-12-20 19:26:35 +08008516 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008517 return RETURN_ERR;
8518 snprintf(cmd, sizeof(cmd), "cfgVlan %s %s %d %s ", interface_name, bridge, vlanId, ip);
developer06a01d92022-09-07 16:32:39 +08008519 _syscmd(cmd,buf, sizeof(buf));
8520
8521 return 0;
8522}
8523
8524INT wifi_pushChannel(INT radioIndex, UINT channel)
8525{
developerd946fd62022-12-08 18:03:28 +08008526 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008527 char cmd[128];
8528 char buf[1024];
8529 int apIndex;
8530
8531 apIndex=(radioIndex==0)?0:1;
developerac6f1142022-12-20 19:26:35 +08008532 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008533 return RETURN_ERR;
8534 snprintf(cmd, sizeof(cmd), "iwconfig %s freq %d",interface_name,channel);
developer06a01d92022-09-07 16:32:39 +08008535 _syscmd(cmd,buf, sizeof(buf));
8536
8537 return 0;
8538}
8539
8540INT wifi_pushChannelMode(INT radioIndex)
8541{
8542 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
8543 return RETURN_ERR;
8544}
8545
8546INT wifi_pushDefaultValues(INT radioIndex)
8547{
8548 //Apply Comcast specified default radio settings instantly
8549 //AMPDU=1
8550 //AMPDUFrames=32
8551 //AMPDULim=50000
8552 //txqueuelen=1000
8553
8554 return RETURN_ERR;
8555}
8556
8557INT wifi_pushTxChainMask(INT radioIndex)
8558{
8559 //Apply default TxChainMask instantly
8560 return RETURN_ERR;
8561}
8562
8563INT wifi_pushRxChainMask(INT radioIndex)
8564{
8565 //Apply default RxChainMask instantly
8566 return RETURN_ERR;
8567}
8568
8569INT wifi_pushSSID(INT apIndex, CHAR *ssid)
8570{
8571 INT status;
8572
8573 status = wifi_setSSIDName(apIndex,ssid);
8574 wifi_setApEnable(apIndex,FALSE);
8575 wifi_setApEnable(apIndex,TRUE);
8576
8577 return status;
8578}
8579
8580INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
8581{
8582 //Apply default Ssid Advertisement instantly
8583 return RETURN_ERR;
8584}
8585
8586INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
8587{
8588 INT status = RETURN_ERR;
8589 *output = 0;
8590 return RETURN_ERR;
8591}
8592
8593INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
8594{
8595 return RETURN_OK;
8596}
8597
8598INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
8599{
8600 return RETURN_OK;
8601}
8602
8603//To-do
8604INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
8605{
developereb199ae2022-09-13 14:04:27 +08008606 char output[16]={'\0'};
8607 char config_file[MAX_BUF_SIZE] = {0};
8608
8609 if (!output_string)
8610 return RETURN_ERR;
8611
8612 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8613 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
8614
8615 if (strlen(output) == 0)
8616 snprintf(output_string, 64, "Disabled");
8617 else if (strncmp(output, "0", 1) == 0)
8618 snprintf(output_string, 64, "Disabled");
8619 else if (strncmp(output, "1", 1) == 0)
8620 snprintf(output_string, 64, "Optional");
8621 else if (strncmp(output, "2", 1) == 0)
8622 snprintf(output_string, 64, "Required");
8623 else {
8624 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
8625 return RETURN_ERR;
8626 }
8627
8628 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08008629 return RETURN_OK;
8630}
8631INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
8632{
developereb199ae2022-09-13 14:04:27 +08008633 char str[MAX_BUF_SIZE]={'\0'};
8634 char cmd[MAX_CMD_SIZE]={'\0'};
8635 struct params params;
8636 char config_file[MAX_BUF_SIZE] = {0};
8637
8638 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8639 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
8640 return RETURN_ERR;
8641
8642 params.name = "ieee80211w";
8643 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
8644 params.value = "0";
8645 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
8646 params.value = "1";
8647 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
8648 params.value = "2";
8649 else{
8650 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
8651 return RETURN_ERR;
8652 }
8653 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8654 wifi_hostapdWrite(config_file, &params, 1);
8655 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008656 return RETURN_OK;
8657}
8658INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
8659{
8660 char output[16]={'\0'};
8661 char config_file[MAX_BUF_SIZE] = {0};
8662
8663 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8664 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
8665 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
8666
8667 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
8668 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8669
8670 return RETURN_OK;
8671}
8672
8673INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
8674{
8675 return RETURN_OK;
8676}
8677
8678INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
8679{
8680 return RETURN_OK;
8681}
8682
8683INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
8684{
8685 return RETURN_OK;
8686}
8687
8688INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8689{
8690 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8691 char config_file[MAX_BUF_SIZE] = {0};
8692
8693 if (NULL == output)
8694 return RETURN_ERR;
8695 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8696 wifi_hostapdRead(config_file,"hw_mode",output,64);
8697
8698 if(strcmp(output,"b")==0)
8699 sprintf(output, "%s", "1,2,5.5,11");
8700 else if (strcmp(output,"a")==0)
8701 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
8702 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
8703 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
8704
8705 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8706 return RETURN_OK;
8707}
8708
8709INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8710{
8711 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8712 char *temp;
8713 char temp_output[128];
8714 char temp_TransmitRates[128];
8715 char config_file[MAX_BUF_SIZE] = {0};
8716
8717 if (NULL == output)
8718 return RETURN_ERR;
8719
8720 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8721 wifi_hostapdRead(config_file,"supported_rates",output,64);
8722
developer5b398df2022-11-17 20:39:48 +08008723 if (strlen(output) == 0) {
8724 wifi_getRadioSupportedDataTransmitRates(wlanIndex, output);
8725 return RETURN_OK;
8726 }
developer06a01d92022-09-07 16:32:39 +08008727 strcpy(temp_TransmitRates,output);
8728 strcpy(temp_output,"");
8729 temp = strtok(temp_TransmitRates," ");
8730 while(temp!=NULL)
8731 {
8732 temp[strlen(temp)-1]=0;
8733 if((temp[0]=='5') && (temp[1]=='\0'))
8734 {
8735 temp="5.5";
8736 }
8737 strcat(temp_output,temp);
8738 temp = strtok(NULL," ");
8739 if(temp!=NULL)
8740 {
8741 strcat(temp_output,",");
8742 }
8743 }
8744 strcpy(output,temp_output);
8745 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8746
8747 return RETURN_OK;
8748}
8749
8750INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8751{
8752 return RETURN_OK;
8753}
8754
8755
8756INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8757{
8758 int i=0;
8759 char *temp;
developeref938762022-10-19 17:21:01 +08008760 char temp1[128] = {0};
8761 char temp_output[128] = {0};
8762 char temp_TransmitRates[128] = {0};
developer06a01d92022-09-07 16:32:39 +08008763 struct params params={'\0'};
8764 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08008765 wifi_band band = wifi_index_to_band(wlanIndex);
developer06a01d92022-09-07 16:32:39 +08008766
8767 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8768 if(NULL == output)
8769 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08008770 strcpy(temp_TransmitRates,output);
8771
8772 for(i=0;i<strlen(temp_TransmitRates);i++)
8773 {
developeref938762022-10-19 17:21:01 +08008774 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08008775 {
8776 continue;
8777 }
8778 else
8779 {
8780 return RETURN_ERR;
8781 }
8782 }
8783 strcpy(temp_output,"");
developeref938762022-10-19 17:21:01 +08008784 temp = strtok(temp_TransmitRates,",");
developer06a01d92022-09-07 16:32:39 +08008785 while(temp!=NULL)
8786 {
8787 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08008788 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08008789 {
developeref938762022-10-19 17:21:01 +08008790 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08008791 {
8792 return RETURN_ERR;
8793 }
8794 }
8795
8796 if(strcmp(temp,"5.5")==0)
8797 {
8798 strcpy(temp1,"55");
8799 }
8800 else
8801 {
8802 strcat(temp1,"0");
8803 }
8804 strcat(temp_output,temp1);
developeref938762022-10-19 17:21:01 +08008805 temp = strtok(NULL,",");
developer06a01d92022-09-07 16:32:39 +08008806 if(temp!=NULL)
8807 {
8808 strcat(temp_output," ");
8809 }
8810 }
8811 strcpy(output,temp_output);
8812
developer06a01d92022-09-07 16:32:39 +08008813 params.name = "supported_rates";
8814 params.value = output;
8815
8816 wifi_dbg_printf("\n%s:",__func__);
8817 wifi_dbg_printf("params.value=%s\n",params.value);
8818 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8819 wifi_hostapdWrite(config_file,&params,1);
8820 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8821
8822 return RETURN_OK;
8823}
8824
8825
8826static char *sncopy(char *dst, int dst_sz, const char *src)
8827{
8828 if (src && dst && dst_sz > 0) {
8829 strncpy(dst, src, dst_sz);
8830 dst[dst_sz - 1] = '\0';
8831 }
8832 return dst;
8833}
8834
8835static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8836{
8837 if (0 == strcmp(ht_mode, "HT40") ||
8838 0 == strcmp(ht_mode, "HT80") ||
developer7c4cd202023-03-01 10:56:29 +08008839 0 == strcmp(ht_mode, "HT160") ||
8840 0 == strcmp(ht_mode, "HT320")) {
developer06a01d92022-09-07 16:32:39 +08008841 switch (channel) {
developer9a520b12023-09-21 16:01:43 +08008842 case 0 ... 7:
developer06a01d92022-09-07 16:32:39 +08008843 case 36:
8844 case 44:
8845 case 52:
8846 case 60:
8847 case 100:
8848 case 108:
8849 case 116:
8850 case 124:
8851 case 132:
8852 case 140:
8853 case 149:
8854 case 157:
8855 return 1;
8856 case 8 ... 13:
8857 case 40:
8858 case 48:
8859 case 56:
8860 case 64:
8861 case 104:
8862 case 112:
8863 case 120:
8864 case 128:
8865 case 136:
8866 case 144:
8867 case 153:
8868 case 161:
8869 return -1;
8870 default:
8871 return -EINVAL;
8872 }
8873 }
8874
8875 return -EINVAL;
8876}
8877
developerb7593de2022-10-18 09:51:57 +08008878static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
8879{
8880 int idx = channel%8;
8881 if (0 == strcmp(ht_mode, "HT40") ||
8882 0 == strcmp(ht_mode, "HT80") ||
developer7c4cd202023-03-01 10:56:29 +08008883 0 == strcmp(ht_mode, "HT160") ||
8884 0 == strcmp(ht_mode, "HT320")) {
developerb7593de2022-10-18 09:51:57 +08008885 switch (idx) {
8886 case 1:
8887 return 1;
8888 case 5:
8889 return -1;
8890 default:
8891 return -EINVAL;
8892 }
8893 }
8894
8895 return -EINVAL;
8896}
developer06a01d92022-09-07 16:32:39 +08008897static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8898{
8899 if (NULL == hw_mode) return;
8900
8901 if (0 == strcmp(hw_mode, "ac"))
8902 sncopy(bw_mode, bw_mode_len, "ht vht");
8903
8904 if (0 == strcmp(hw_mode, "n"))
8905 sncopy(bw_mode, bw_mode_len, "ht");
8906
8907 return;
8908}
8909
8910static int util_chan_to_freq(int chan)
8911{
8912 if (chan == 14)
8913 return 2484;
8914 else if (chan < 14)
8915 return 2407 + chan * 5;
8916 else if (chan >= 182 && chan <= 196)
8917 return 4000 + chan * 5;
8918 else
8919 return 5000 + chan * 5;
8920 return 0;
8921}
8922
developerb7593de2022-10-18 09:51:57 +08008923static int util_6G_chan_to_freq(int chan)
8924{
8925 if (chan)
8926 return 5950 + chan * 5;
8927 else
8928 return 0;
8929
8930}
developer06a01d92022-09-07 16:32:39 +08008931const int *util_unii_5g_chan2list(int chan, int width)
8932{
8933 static const int lists[] = {
8934 // <width>, <chan1>, <chan2>..., 0,
developer8b2f01f2024-03-01 14:50:27 +08008935 20, 36, 0,
8936 20, 40, 0,
8937 20, 44, 0,
8938 20, 48, 0,
8939 20, 52, 0,
8940 20, 56, 0,
8941 20, 60, 0,
8942 20, 64, 0,
developer06a01d92022-09-07 16:32:39 +08008943 20, 100, 0,
8944 20, 104, 0,
8945 20, 108, 0,
8946 20, 112, 0,
8947 20, 116, 0,
8948 20, 120, 0,
8949 20, 124, 0,
8950 20, 128, 0,
8951 20, 132, 0,
8952 20, 136, 0,
8953 20, 140, 0,
8954 20, 144, 0,
8955 20, 149, 0,
8956 20, 153, 0,
8957 20, 157, 0,
8958 20, 161, 0,
8959 20, 165, 0,
developer8b2f01f2024-03-01 14:50:27 +08008960 20, 169, 0,
8961 20, 173, 0,
8962 20, 177, 0,
8963 40, 36, 40, 0,
8964 40, 44, 48, 0,
8965 40, 52, 56, 0,
8966 40, 60, 64, 0,
developer06a01d92022-09-07 16:32:39 +08008967 40, 100, 104, 0,
8968 40, 108, 112, 0,
8969 40, 116, 120, 0,
8970 40, 124, 128, 0,
8971 40, 132, 136, 0,
8972 40, 140, 144, 0,
8973 40, 149, 153, 0,
8974 40, 157, 161, 0,
developer8b2f01f2024-03-01 14:50:27 +08008975 40, 165, 169, 0,
8976 40, 173, 177, 0,
8977 80, 36, 40, 44, 48, 0,
8978 80, 52, 56, 60, 64, 0,
developer06a01d92022-09-07 16:32:39 +08008979 80, 100, 104, 108, 112, 0,
8980 80, 116, 120, 124, 128, 0,
8981 80, 132, 136, 140, 144, 0,
8982 80, 149, 153, 157, 161, 0,
developer8b2f01f2024-03-01 14:50:27 +08008983 80, 165, 169, 173, 177, 0,
8984 160,36, 40, 44, 48, 52, 56, 60, 64, 0,
8985 160,100, 104, 108, 112, 116, 120, 124, 128, 0,
8986 160,149, 153, 157, 161, 165, 169, 173, 177, 0,
developer06a01d92022-09-07 16:32:39 +08008987 -1 // final delimiter
8988 };
8989 const int *start;
8990 const int *p;
8991
8992 for (p = lists; *p != -1; p++) {
8993 if (*p == width) {
8994 for (start = ++p; *p != 0; p++) {
8995 if (*p == chan)
8996 return start;
8997 }
8998 }
8999 // move to the end of channel list of given width
9000 while (*p != 0) {
9001 p++;
9002 }
9003 }
9004
9005 return NULL;
9006}
9007
9008static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
9009{
9010 if (NULL == ht_mode)
9011 return 0;
9012
9013 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
9014 const int *chans = util_unii_5g_chan2list(channel, width);
9015 int sum = 0;
9016 int cnt = 0;
9017
9018 if (NULL == chans)
9019 return 0;
9020
9021 while (*chans) {
9022 sum += *chans;
9023 cnt++;
9024 chans++;
9025 }
developer30423732022-12-01 16:17:49 +08009026 if (cnt == 0)
9027 return 0;
developer06a01d92022-09-07 16:32:39 +08009028 return sum / cnt;
9029}
9030
developerb7593de2022-10-18 09:51:57 +08009031static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
9032{
9033 if (NULL == ht_mode)
9034 return 0;
9035
9036 int width = strtol((ht_mode + 2), NULL, 10);
9037
9038 int idx = 0 ;
9039 int centerchan = 0;
9040 int chan_ofs = 1;
9041
9042 if (width == 40){
9043 idx = ((channel/4) + chan_ofs)%2;
9044 switch (idx) {
9045 case 0:
9046 centerchan = (channel - 2);
9047 break;
9048 case 1:
9049 centerchan = (channel + 2);
9050 break;
9051 default:
9052 return -EINVAL;
9053 }
9054 }else if (width == 80){
9055 idx = ((channel/4) + chan_ofs)%4;
9056 switch (idx) {
9057 case 0:
9058 centerchan = (channel - 6);
9059 break;
9060 case 1:
9061 centerchan = (channel + 6);
9062 break;
9063 case 2:
9064 centerchan = (channel + 2);
9065 break;
9066 case 3:
9067 centerchan = (channel - 2);
9068 break;
9069 default:
9070 return -EINVAL;
9071 }
9072 }else if (width == 160){
9073 switch (channel) {
9074 case 1 ... 29:
9075 centerchan = 15;
9076 break;
9077 case 33 ... 61:
9078 centerchan = 47;
9079 break;
9080 case 65 ... 93:
9081 centerchan = 79;
9082 break;
9083 case 97 ... 125:
9084 centerchan = 111;
9085 break;
9086 case 129 ... 157:
9087 centerchan = 143;
9088 break;
9089 case 161 ... 189:
9090 centerchan = 175;
9091 break;
9092 case 193 ... 221:
9093 centerchan = 207;
9094 break;
9095 default:
9096 return -EINVAL;
9097 }
developer7c4cd202023-03-01 10:56:29 +08009098 }else if (width == 320){
9099 switch (channel) {
9100 case 1 ... 29:
9101 centerchan = 31;
9102 break;
9103 case 33 ... 93:
9104 centerchan = 63;
9105 break;
9106 case 97 ... 157:
9107 centerchan = 127;
9108 break;
9109 case 161 ... 221:
9110 centerchan = 191;
9111 break;
9112 default:
9113 return -EINVAL;
9114 }
developerb7593de2022-10-18 09:51:57 +08009115 }
9116 return centerchan;
9117}
developer06a01d92022-09-07 16:32:39 +08009118static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
9119{
9120 BOOL onlyG, onlyN, onlyA;
9121 CHAR tmp[64];
9122 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
9123 if (ret == RETURN_OK) {
9124 sncopy(hw_mode, hw_mode_size, tmp);
9125 }
9126 return ret;
9127}
9128
9129INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
9130{
9131 // Sample commands:
9132 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
9133 // hostapd_cli -i wifi0 chan_switch 30 2437
9134 char cmd[MAX_CMD_SIZE] = {0};
9135 char buf[MAX_BUF_SIZE] = {0};
9136 int freq = 0, ret = 0;
9137 char center_freq1_str[32] = ""; // center_freq1=%d
9138 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
9139 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
9140 char hw_mode[16] = ""; // n|ac
9141 char bw_mode[16] = ""; // ht|ht vht
9142 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
developerd946fd62022-12-08 18:03:28 +08009143 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08009144 int sec_chan_offset;
9145 int width;
developer4fb0b922022-09-30 14:29:09 +08009146 char config_file[64] = {0};
9147 BOOL stbcEnable = FALSE;
developer7c4cd202023-03-01 10:56:29 +08009148 BOOL setEHT320 = FALSE;
developer5884e982022-10-06 10:52:50 +08009149 char *ext_str = "None";
developerb7593de2022-10-18 09:51:57 +08009150 wifi_band band = band_invalid;
9151 int center_chan = 0;
9152 int center_freq1 = 0;
developer5884e982022-10-06 10:52:50 +08009153
developer4fb0b922022-09-30 14:29:09 +08009154 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08009155
developerac6f1142022-12-20 19:26:35 +08009156 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009157 return RETURN_ERR;
9158
developer06a01d92022-09-07 16:32:39 +08009159 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9160
developerb7593de2022-10-18 09:51:57 +08009161 band = wifi_index_to_band(radioIndex);
9162
developer5884e982022-10-06 10:52:50 +08009163 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
developer06a01d92022-09-07 16:32:39 +08009164
9165 // Get radio mode HT20|HT40|HT80 etc.
developer5884e982022-10-06 10:52:50 +08009166 if (channel){
developerb7593de2022-10-18 09:51:57 +08009167 if (band == band_6){
9168 freq = util_6G_chan_to_freq(channel);
9169 }else{
9170 freq = util_chan_to_freq(channel);
9171 }
developer7c4cd202023-03-01 10:56:29 +08009172 if (width == 320) {
9173 width = 160; // We should set HE central channel as 160, and additionally modify EHT central channel with 320
9174 setEHT320 = TRUE;
9175 }
developer5884e982022-10-06 10:52:50 +08009176 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
developer06a01d92022-09-07 16:32:39 +08009177
developer5884e982022-10-06 10:52:50 +08009178 // Provide bandwith if specified
9179 if (channel_width_MHz > 20) {
9180 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
9181 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
9182 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
developer06a01d92022-09-07 16:32:39 +08009183
developer5884e982022-10-06 10:52:50 +08009184 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
9185 }else if (channel_width_MHz == 20){
9186 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
9187 }
developer06a01d92022-09-07 16:32:39 +08009188
developerb7593de2022-10-18 09:51:57 +08009189
developer5884e982022-10-06 10:52:50 +08009190 if (channel_width_MHz > 20) {
developerb7593de2022-10-18 09:51:57 +08009191 if (band == band_6){
9192 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
9193 if(center_chan){
9194 center_freq1 = util_6G_chan_to_freq(center_chan);
9195 }
9196 }else{
9197 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
9198 if(center_chan){
9199 center_freq1 = util_chan_to_freq(center_chan);
9200 }
developer5884e982022-10-06 10:52:50 +08009201 }
developerb7593de2022-10-18 09:51:57 +08009202
9203 if (center_freq1)
9204 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
9205
9206 }
9207
9208 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
9209 if (band == band_6){
9210 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
9211 }else{
9212 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
developer06a01d92022-09-07 16:32:39 +08009213 }
developerb7593de2022-10-18 09:51:57 +08009214 if (sec_chan_offset != -EINVAL)
9215 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
developer06a01d92022-09-07 16:32:39 +08009216
developer5884e982022-10-06 10:52:50 +08009217 // Only the first AP, other are hanging on the same radio
9218 int apIndex = radioIndex;
developerd946fd62022-12-08 18:03:28 +08009219 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s chan_switch %d %d %s %s %s",
9220 interface_name, csa_beacon_count, freq,
developer5884e982022-10-06 10:52:50 +08009221 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
9222 wifi_dbg_printf("execute: '%s'\n", cmd);
9223 ret = _syscmd(cmd, buf, sizeof(buf));
developerfa41b1f2023-01-06 10:25:51 +08009224 wifi_reloadAp(radioIndex);
developer06a01d92022-09-07 16:32:39 +08009225
developer5884e982022-10-06 10:52:50 +08009226 ret = wifi_setRadioChannel(radioIndex, channel);
9227 if (ret != RETURN_OK) {
9228 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
9229 return RETURN_ERR;
9230 }
9231
9232 if (sec_chan_offset == 1) ext_str = "Above";
9233 else if (sec_chan_offset == -1) ext_str = "Below";
9234
9235 wifi_setRadioCenterChannel(radioIndex, center_chan);
developer06a01d92022-09-07 16:32:39 +08009236
developer5884e982022-10-06 10:52:50 +08009237 } else {
9238 if (channel_width_MHz > 20)
9239 ext_str = "Above";
9240 }
developer4fb0b922022-09-30 14:29:09 +08009241
developer06a01d92022-09-07 16:32:39 +08009242 char mhz_str[16];
9243 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
developer7c4cd202023-03-01 10:56:29 +08009244 if (setEHT320 == TRUE)
9245 wifi_setRadioOperatingChannelBandwidth(radioIndex, "320MHz");
9246 else
9247 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
developer06a01d92022-09-07 16:32:39 +08009248
developer57fa24a2023-03-15 17:25:07 +08009249 writeBandWidth(radioIndex, mhz_str);
9250 if (band == band_2_4 || band == band_5) {
9251 if (width == 20)
9252 wifi_RemoveRadioExtChannel(radioIndex, ext_str);
9253 else
9254 wifi_setRadioExtChannel(radioIndex, ext_str);
9255 }
developer06a01d92022-09-07 16:32:39 +08009256 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9257
9258 return RETURN_OK;
9259}
9260
9261INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
9262{
developer615510b2022-09-27 10:14:35 +08009263 int index = -1;
developer06a01d92022-09-07 16:32:39 +08009264 wifi_neighbor_ap2_t *scan_array = NULL;
developer615510b2022-09-27 10:14:35 +08009265 char cmd[256]={0};
9266 char buf[128]={0};
9267 char file_name[32] = {0};
9268 char filter_SSID[32] = {0};
9269 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08009270 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08009271 char *ret = NULL;
developer06a01d92022-09-07 16:32:39 +08009272 int freq=0;
developer06a01d92022-09-07 16:32:39 +08009273 FILE *f = NULL;
developer615510b2022-09-27 10:14:35 +08009274 size_t len=0;
9275 int channels_num = 0;
developer06a01d92022-09-07 16:32:39 +08009276 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08009277 int get_noise_ret = RETURN_ERR;
developer615510b2022-09-27 10:14:35 +08009278 bool filter_enable = false;
9279 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08009280 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08009281
developer615510b2022-09-27 10:14:35 +08009282 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009283
developer615510b2022-09-27 10:14:35 +08009284 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
9285 f = fopen(file_name, "r");
9286 if (f != NULL) {
developer72ec5572023-01-05 16:27:13 +08009287 fgets(buf, sizeof(file_name), f);
9288 if ((strncmp(buf, "0", 1)) != 0) {
9289 fgets(filter_SSID, sizeof(file_name), f);
9290 if (strlen(filter_SSID) != 0)
9291 filter_enable = true;
9292 }
developer615510b2022-09-27 10:14:35 +08009293 fclose(f);
9294 }
9295
developerac6f1142022-12-20 19:26:35 +08009296 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009297 return RETURN_ERR;
9298
developer033b37b2022-10-18 11:27:46 +08009299 phyId = radio_index_to_phy(radio_index);
9300
9301 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer615510b2022-09-27 10:14:35 +08009302 _syscmd(cmd, buf, sizeof(buf));
9303 channels_num = strtol(buf, NULL, 10);
9304
developerd946fd62022-12-08 18:03:28 +08009305 sprintf(cmd, "iw dev %s scan dump | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
9306 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", interface_name, interface_name);
developer615510b2022-09-27 10:14:35 +08009307 fprintf(stderr, "cmd: %s\n", cmd);
9308 if ((f = popen(cmd, "r")) == NULL) {
developer06a01d92022-09-07 16:32:39 +08009309 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9310 return RETURN_ERR;
9311 }
developer5550e242022-09-30 09:59:32 +08009312
9313 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
9314 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
9315
developer615510b2022-09-27 10:14:35 +08009316 ret = fgets(line, sizeof(line), f);
9317 while (ret != NULL) {
9318 if(strstr(line, "BSS") != NULL) { // new neighbor info
9319 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
9320 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
9321 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
9322
9323 if (!filter_BSS) {
9324 index++;
9325 wifi_neighbor_ap2_t *tmp;
9326 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
9327 if (tmp == NULL) { // no more memory to use
9328 index--;
9329 wifi_dbg_printf("%s: realloc failed\n", __func__);
9330 break;
9331 }
9332 scan_array = tmp;
9333 }
9334 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
developer06a01d92022-09-07 16:32:39 +08009335
developer615510b2022-09-27 10:14:35 +08009336 filter_BSS = false;
9337 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
9338 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
9339 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
9340 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
9341 } else if (strstr(line, "freq") != NULL) {
developer06a01d92022-09-07 16:32:39 +08009342 sscanf(line," freq: %d", &freq);
developer615510b2022-09-27 10:14:35 +08009343 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
developer06a01d92022-09-07 16:32:39 +08009344
developer615510b2022-09-27 10:14:35 +08009345 if (freq >= 2412 && freq <= 2484) {
9346 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
9347 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
9348 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
9349 }
9350 else if (freq >= 5160 && freq <= 5805) {
9351 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
9352 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
9353 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
9354 }
developer06a01d92022-09-07 16:32:39 +08009355
developer615510b2022-09-27 10:14:35 +08009356 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08009357 if (get_noise_ret == RETURN_OK) {
developer615510b2022-09-27 10:14:35 +08009358 for (int i = 0; i < channels_num; i++) {
9359 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
9360 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
9361 break;
9362 }
9363 }
developer06a01d92022-09-07 16:32:39 +08009364 }
developer615510b2022-09-27 10:14:35 +08009365 } else if (strstr(line, "beacon interval") != NULL) {
9366 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
9367 } else if (strstr(line, "signal") != NULL) {
9368 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
9369 } else if (strstr(line,"SSID") != NULL) {
9370 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
9371 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
9372 filter_BSS = true;
developer06a01d92022-09-07 16:32:39 +08009373 }
developer615510b2022-09-27 10:14:35 +08009374 } else if (strstr(line, "Supported rates") != NULL) {
9375 char SRate[80] = {0}, *tmp = NULL;
9376 memset(buf, 0, sizeof(buf));
9377 strcpy(SRate, line);
9378 tmp = strtok(SRate, ":");
9379 tmp = strtok(NULL, ":");
9380 strcpy(buf, tmp);
9381 memset(SRate, 0, sizeof(SRate));
developer06a01d92022-09-07 16:32:39 +08009382
developer615510b2022-09-27 10:14:35 +08009383 tmp = strtok(buf, " \n");
9384 while (tmp != NULL) {
9385 strcat(SRate, tmp);
9386 if (SRate[strlen(SRate) - 1] == '*') {
9387 SRate[strlen(SRate) - 1] = '\0';
9388 }
9389 strcat(SRate, ",");
developer06a01d92022-09-07 16:32:39 +08009390
developer615510b2022-09-27 10:14:35 +08009391 tmp = strtok(NULL, " \n");
developer06a01d92022-09-07 16:32:39 +08009392 }
developer615510b2022-09-27 10:14:35 +08009393 SRate[strlen(SRate) - 1] = '\0';
9394 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
9395 } else if (strstr(line, "DTIM") != NULL) {
9396 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
9397 } else if (strstr(line, "VHT capabilities") != NULL) {
9398 strcat(scan_array[index].ap_SupportedStandards, ",ac");
9399 strcpy(scan_array[index].ap_OperatingStandards, "ac");
9400 } else if (strstr(line, "HT capabilities") != NULL) {
9401 strcat(scan_array[index].ap_SupportedStandards, ",n");
9402 strcpy(scan_array[index].ap_OperatingStandards, "n");
9403 } else if (strstr(line, "VHT operation") != NULL) {
9404 ret = fgets(line, sizeof(line), f);
9405 sscanf(line," * channel width: %d", &vht_channel_width);
9406 if(vht_channel_width == 1) {
9407 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
9408 } else {
9409 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
9410 }
9411 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
9412 continue;
9413 } else if (strstr(line, "HT operation") != NULL) {
9414 ret = fgets(line, sizeof(line), f);
9415 sscanf(line," * secondary channel offset: %s", &buf);
9416 if (!strcmp(buf, "above")) {
developer06a01d92022-09-07 16:32:39 +08009417 //40Mhz +
developer615510b2022-09-27 10:14:35 +08009418 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radio_index%1 ? "A": "G");
developer06a01d92022-09-07 16:32:39 +08009419 }
developer615510b2022-09-27 10:14:35 +08009420 else if (!strcmp(buf, "below")) {
developer06a01d92022-09-07 16:32:39 +08009421 //40Mhz -
developer615510b2022-09-27 10:14:35 +08009422 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
9423 } else {
9424 //20Mhz
9425 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radio_index%1 ? "A": "G");
developer06a01d92022-09-07 16:32:39 +08009426 }
developer615510b2022-09-27 10:14:35 +08009427 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
developer06a01d92022-09-07 16:32:39 +08009428 continue;
developer615510b2022-09-27 10:14:35 +08009429 } else if (strstr(line, "HE capabilities") != NULL) {
9430 strcat(scan_array[index].ap_SupportedStandards, ",ax");
9431 strcpy(scan_array[index].ap_OperatingStandards, "ax");
9432 ret = fgets(line, sizeof(line), f);
9433 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
9434 if (strstr(line, "HE40/2.4GHz") != NULL)
9435 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
9436 else
9437 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
9438 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
9439 if (strstr(line, "HE80/5GHz") != NULL) {
9440 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
9441 ret = fgets(line, sizeof(line), f);
9442 } else
9443 continue;
9444 if (strstr(line, "HE160/5GHz") != NULL)
9445 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developer06a01d92022-09-07 16:32:39 +08009446 }
developer615510b2022-09-27 10:14:35 +08009447 continue;
9448 } else if (strstr(line, "WPA") != NULL) {
9449 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
9450 } else if (strstr(line, "RSN") != NULL) {
9451 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
9452 } else if (strstr(line, "Group cipher") != NULL) {
9453 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
9454 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
9455 strcpy(scan_array[index].ap_EncryptionMode, "AES");
developer06a01d92022-09-07 16:32:39 +08009456 }
developer06a01d92022-09-07 16:32:39 +08009457 }
developer615510b2022-09-27 10:14:35 +08009458 ret = fgets(line, sizeof(line), f);
9459 }
9460
9461 if (!filter_BSS) {
9462 *output_array_size = index + 1;
9463 } else {
9464 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
9465 *output_array_size = index;
developer06a01d92022-09-07 16:32:39 +08009466 }
developer06a01d92022-09-07 16:32:39 +08009467 *neighbor_ap_array = scan_array;
developer06a01d92022-09-07 16:32:39 +08009468 pclose(f);
developer5550e242022-09-30 09:59:32 +08009469 free(channels_noise_arr);
developer615510b2022-09-27 10:14:35 +08009470 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009471 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009472}
developer615510b2022-09-27 10:14:35 +08009473
developer06a01d92022-09-07 16:32:39 +08009474INT wifi_getApAssociatedDeviceStats(
9475 INT apIndex,
9476 mac_address_t *clientMacAddress,
9477 wifi_associated_dev_stats_t *associated_dev_stats,
9478 u64 *handle)
9479{
9480 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
9481 char interface_name[50] = {0};
9482 char cmd[1024] = {0};
9483 char mac_str[18] = {0};
9484 char *key = NULL;
9485 char *val = NULL;
9486 FILE *f = NULL;
9487 char *line = NULL;
9488 size_t len = 0;
developer06a01d92022-09-07 16:32:39 +08009489
9490 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9491 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9492 return RETURN_ERR;
9493 }
9494
9495 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
9496 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
9497 if((f = popen(cmd, "r")) == NULL) {
9498 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9499 return RETURN_ERR;
9500 }
9501
developer30423732022-12-01 16:17:49 +08009502 while ((getline(&line, &len, f)) != -1) {
developer06a01d92022-09-07 16:32:39 +08009503 key = strtok(line,":");
9504 val = strtok(NULL,":");
9505
9506 if(!strncmp(key,"rx bytes",8))
9507 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
9508 if(!strncmp(key,"tx bytes",8))
9509 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
9510 if(!strncmp(key,"rx packets",10))
9511 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9512 if(!strncmp(key,"tx packets",10))
9513 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9514 if(!strncmp(key,"tx retries",10))
9515 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
9516 if(!strncmp(key,"tx failed",9))
9517 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
9518 if(!strncmp(key,"rx drop misc",13))
9519 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
9520 if(!strncmp(key,"rx bitrate",10)) {
9521 val = strtok(val, " ");
9522 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
9523 }
9524 if(!strncmp(key,"tx bitrate",10)) {
9525 val = strtok(val, " ");
9526 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
9527 }
9528 }
9529 free(line);
9530 pclose(f);
9531 return RETURN_OK;
9532}
9533
9534INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
9535{
developerd946fd62022-12-08 18:03:28 +08009536 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08009537 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
9538
9539 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9540 if (NULL == output_string)
9541 return RETURN_ERR;
9542
developerac6f1142022-12-20 19:26:35 +08009543 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009544 return RETURN_ERR;
9545 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep ^ssid | cut -d '=' -f2 | tr -d '\n'", interface_name);
developer06a01d92022-09-07 16:32:39 +08009546 _syscmd(cmd, buf, sizeof(buf));
9547
9548 //size of SSID name restricted to value less than 32 bytes
9549 snprintf(output_string, 32, "%s", buf);
9550 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
9551
9552 return RETURN_OK;
9553}
9554
9555INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
9556{
9557 //char cmd[MAX_CMD_SIZE] = {0};
9558 char config_file[MAX_BUF_SIZE] = {0};
9559 char buf[32] = {0};
9560
9561 if (!output_filterMode)
9562 return RETURN_ERR;
9563
9564 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
9565 //_syscmd(cmd, buf, sizeof(buf));
9566 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developerefb790a2023-12-26 18:58:32 +08009567 if (!syn_flag)
9568 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
9569 else
developer07ded1f2024-01-10 10:30:15 +08009570 snprintf(buf, sizeof(buf), "%s", vap_info[apIndex].macaddr_acl);
developer10adcc12022-09-13 14:39:17 +08009571 if(strlen(buf) == 0) {
9572 *output_filterMode = 0;
9573 }
9574 else {
9575 int macaddr_acl_mode = strtol(buf, NULL, 10);
9576 if (macaddr_acl_mode == 1) {
9577 *output_filterMode = 1;
9578 } else if (macaddr_acl_mode == 0) {
9579 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
9580 if (strlen(buf) == 0) {
9581 *output_filterMode = 0;
9582 } else {
9583 *output_filterMode = 2;
9584 }
9585 } else {
9586 return RETURN_ERR;
9587 }
9588 }
developer06a01d92022-09-07 16:32:39 +08009589
9590 return RETURN_OK;
9591}
9592
9593INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
9594{
9595 FILE *fp = NULL;
9596 char str[MAX_BUF_SIZE] = {0};
9597 int wificlientindex = 0 ;
9598 int count = 0;
9599 int signalstrength = 0;
9600 int arr[MACADDRESS_SIZE] = {0};
9601 unsigned char mac[MACADDRESS_SIZE] = {0};
9602 UINT wifi_count = 0;
9603 char virtual_interface_name[MAX_BUF_SIZE] = {0};
9604 char pipeCmd[MAX_CMD_SIZE] = {0};
9605
9606 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9607 *output_array_size = 0;
9608 *associated_dev_array = NULL;
9609 char interface_name[50] = {0};
9610
9611 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9612 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9613 return RETURN_ERR;
9614 }
9615
9616 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
9617 fp = popen(pipeCmd, "r");
9618 if (fp == NULL)
9619 {
9620 printf("Failed to run command inside function %s\n",__FUNCTION__ );
9621 return RETURN_ERR;
9622 }
9623
9624 /* Read the output a line at a time - output it. */
9625 fgets(str, sizeof(str)-1, fp);
9626 wifi_count = (unsigned int) atoi ( str );
9627 *output_array_size = wifi_count;
9628 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
9629 pclose(fp);
9630
9631 if(wifi_count == 0)
9632 {
9633 return RETURN_OK;
9634 }
9635 else
9636 {
9637 wifi_associated_dev2_t* temp = NULL;
9638 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
9639 *associated_dev_array = temp;
9640 if(temp == NULL)
9641 {
9642 printf("Error Statement. Insufficient memory \n");
9643 return RETURN_ERR;
9644 }
9645
9646 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
9647 system(pipeCmd);
9648
9649 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
9650 if(fp == NULL)
9651 {
9652 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
9653 return RETURN_ERR;
9654 }
9655 fclose(fp);
9656
developer30423732022-12-01 16:17:49 +08009657 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08009658 fp = popen(pipeCmd, "r");
9659 if(fp)
9660 {
9661 for(count =0 ; count < wifi_count; count++)
9662 {
9663 fgets(str, MAX_BUF_SIZE, fp);
9664 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
9665 {
9666 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
9667 {
9668 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
9669
9670 }
9671 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
9672 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]);
9673 }
9674 temp[count].cli_AuthenticationState = 1; //TODO
9675 temp[count].cli_Active = 1; //TODO
9676 }
9677 pclose(fp);
9678 }
9679
9680 //Updating RSSI per client
developer30423732022-12-01 16:17:49 +08009681 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt");
developer06a01d92022-09-07 16:32:39 +08009682 fp = popen(pipeCmd, "r");
9683 if(fp)
9684 {
9685 pclose(fp);
9686 }
9687 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
9688 if(fp)
9689 {
9690 for(count =0 ; count < wifi_count ;count++)
9691 {
9692 fgets(str, MAX_BUF_SIZE, fp);
9693 signalstrength = atoi(str);
9694 temp[count].cli_RSSI = signalstrength;
9695 }
9696 pclose(fp);
9697 }
9698
9699
9700 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08009701 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt");
developer06a01d92022-09-07 16:32:39 +08009702 fp = popen(pipeCmd, "r");
9703 if (fp)
9704 {
9705 pclose(fp);
9706 }
9707 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
9708 if (fp)
9709 {
9710 for (count = 0; count < wifi_count; count++)
9711 {
9712 fgets(str, MAX_BUF_SIZE, fp);
9713 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
9714 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
9715 }
9716 pclose(fp);
9717 }
9718
9719 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08009720 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt");
developer06a01d92022-09-07 16:32:39 +08009721 fp = popen(pipeCmd, "r");
9722 if (fp)
9723 {
9724 pclose(fp);
9725 }
9726 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
9727 if (fp)
9728 {
9729 for (count = 0; count < wifi_count; count++)
9730 {
9731 fgets(str, MAX_BUF_SIZE, fp);
9732 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
9733 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
9734 }
9735 pclose(fp);
9736 }
9737 }
9738 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9739 return RETURN_OK;
9740
9741}
9742
9743INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
9744{
9745#if 0
9746 /*char buf[1024] = {0};
developerd946fd62022-12-08 18:03:28 +08009747 sprintf(cmd, "ifconfig %s ", interface_name);
developer06a01d92022-09-07 16:32:39 +08009748 _syscmd(cmd, buf, sizeof(buf));*/
9749
9750 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
9751 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
9752 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
9753 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
9754
9755 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.
9756 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].
9757 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].
9758 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].
9759 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
9760 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
9761
9762 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
9763 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9764 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9765 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.
9766 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.
9767 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.
9768 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.
9769 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.
9770 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.
9771 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.
9772 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
9773#endif
9774
9775 FILE *fp = NULL;
developer06a01d92022-09-07 16:32:39 +08009776 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08009777 char pipeCmd[128] = {0};
9778 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08009779 wifi_ssidTrafficStats2_t *out = output_struct;
9780
developerce736392022-09-13 15:24:34 +08009781 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009782 if (!output_struct)
9783 return RETURN_ERR;
9784
developerce736392022-09-13 15:24:34 +08009785 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
developerac6f1142022-12-20 19:26:35 +08009786 if (wifi_GetInterfaceName(ssidIndex, interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08009787 return RETURN_ERR;
developerce736392022-09-13 15:24:34 +08009788 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009789
developer06a01d92022-09-07 16:32:39 +08009790 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009791 if (fp == NULL) {
9792 fprintf(stderr, "%s: popen failed\n", __func__);
9793 return RETURN_ERR;
9794 }
9795 fgets(str, sizeof(str), fp);
developerd946fd62022-12-08 18:03:28 +08009796 pclose(fp);
developer06a01d92022-09-07 16:32:39 +08009797
developerce736392022-09-13 15:24:34 +08009798 if (strlen(str) == 0) // interface not exist
9799 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009800
developerce736392022-09-13 15:24:34 +08009801 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
9802 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009803
developerce736392022-09-13 15:24:34 +08009804 memset(str, 0, sizeof(str));
9805 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08009806 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009807 if (fp == NULL) {
9808 fprintf(stderr, "%s: popen failed\n", __func__);
9809 return RETURN_ERR;
9810 }
9811 fgets(str, sizeof(str), fp);
9812
9813 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
9814 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009815 pclose(fp);
developerce736392022-09-13 15:24:34 +08009816
9817 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
9818 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
9819
9820 // Not supported
9821 output_struct->ssid_RetransCount = 0;
9822 output_struct->ssid_FailedRetransCount = 0;
9823 output_struct->ssid_RetryCount = 0;
9824 output_struct->ssid_MultipleRetryCount = 0;
9825 output_struct->ssid_ACKFailureCount = 0;
9826 output_struct->ssid_AggregatedPacketCount = 0;
9827
developer06a01d92022-09-07 16:32:39 +08009828 return RETURN_OK;
9829}
9830
9831//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).
9832INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
9833{
9834 char output_val[16]={'\0'};
9835 char config_file[MAX_BUF_SIZE] = {0};
9836
9837 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9838 if (!output)
9839 return RETURN_ERR;
9840 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developerefb790a2023-12-26 18:58:32 +08009841 if (!syn_flag)
9842 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
9843 else
developer07ded1f2024-01-10 10:30:15 +08009844 snprintf(output_val, sizeof(output_val), "%s", vap_info[apIndex].ap_isolate);
developer06a01d92022-09-07 16:32:39 +08009845 if( strcmp(output_val,"1") == 0 )
9846 *output = TRUE;
9847 else
9848 *output = FALSE;
9849 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9850
9851 return RETURN_OK;
9852}
9853
9854INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
9855{
9856 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9857 char str[MAX_BUF_SIZE]={'\0'};
9858 char string[MAX_BUF_SIZE]={'\0'};
9859 char cmd[MAX_CMD_SIZE]={'\0'};
9860 char *ch;
9861 char config_file[MAX_BUF_SIZE] = {0};
9862 struct params params;
9863
9864 if(enable == TRUE)
9865 strcpy(string,"1");
9866 else
9867 strcpy(string,"0");
9868
9869 params.name = "ap_isolate";
9870 params.value = string;
9871
9872 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9873 wifi_hostapdWrite(config_file,&params,1);
developerefb790a2023-12-26 18:58:32 +08009874 snprintf(vap_info[apIndex].ap_isolate, sizeof(vap_info[apIndex].ap_isolate), "%s", params.value);
developer06a01d92022-09-07 16:32:39 +08009875 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9876
9877 return RETURN_OK;
9878}
9879
9880INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
9881{
9882 if (NULL == output_dBm)
9883 return RETURN_ERR;
9884
9885 *output_dBm = 0;
9886 return RETURN_OK;
9887}
9888
9889INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
9890{
9891 return RETURN_OK;
9892}
9893INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
9894{
9895 return RETURN_OK;
9896}
9897INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
9898{
9899 return RETURN_OK;
9900}
9901INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
9902{
9903 return RETURN_OK;
9904}
9905INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
9906{
9907 return RETURN_OK;
9908}
9909INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
9910{
9911 char config_file[MAX_BUF_SIZE] = {0};
9912 struct params list;
9913
9914 list.name = "bss_transition";
9915 list.value = activate?"1":"0";
9916 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
9917 wifi_hostapdWrite(config_file, &list, 1);
developerefb790a2023-12-26 18:58:32 +08009918 snprintf(vap_info[apIndex].bss_transition, MAX_BUF_SIZE, "%s", list.value);
developer06a01d92022-09-07 16:32:39 +08009919
9920 return RETURN_OK;
9921}
9922wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
9923
9924void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
9925{
9926 return;
9927}
9928
9929INT wifi_setApCsaDeauth(INT apIndex, INT mode)
9930{
9931 // TODO Implement me!
9932 return RETURN_OK;
9933}
9934
9935INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
9936{
developera3c68b92022-09-13 15:27:29 +08009937 char file_name[128] = {0};
developera3c68b92022-09-13 15:27:29 +08009938 FILE *f = NULL;
9939
developer72ec5572023-01-05 16:27:13 +08009940 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08009941
developer72ec5572023-01-05 16:27:13 +08009942 if (essid == NULL)
9943 return RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08009944
developer72ec5572023-01-05 16:27:13 +08009945 if (strlen(essid) == 0 || apIndex == -1) {
9946 // When essid is blank (apIndex==-1), the configured SSID on that interface is used.
9947 wifi_getSSIDName(apIndex, essid);
developera3c68b92022-09-13 15:27:29 +08009948 }
9949
developer72ec5572023-01-05 16:27:13 +08009950 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
9951 f = fopen(file_name, "w");
9952 if (f == NULL)
9953 return RETURN_ERR;
9954
9955 // For mode == 0 is to disable filter, just don't write ssid to the file.
9956 fprintf(f, "%d\n%s", mode, mode?essid:"");
9957 fclose(f);
9958 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009959 return RETURN_OK;
9960}
9961
9962INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
9963{
9964 // TODO Implement me!
9965 //Apply wifi_pushRadioChannel() instantly
9966 return RETURN_ERR;
9967}
9968
9969INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9970{
9971 // TODO Implement me!
9972 return RETURN_OK;
9973}
9974
9975#ifdef HAL_NETLINK_IMPL
9976static int tidStats_callback(struct nl_msg *msg, void *arg) {
9977 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9978 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9979 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9980 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9981 int rem , tid_index = 0;
9982
9983 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9984 wifi_associated_dev_tid_entry_t *stats_entry;
9985
9986 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9987 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9988 };
9989 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9990 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9991 };
9992
9993 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9994 genlmsg_attrlen(gnlh, 0), NULL);
9995
9996
9997 if (!tb[NL80211_ATTR_STA_INFO]) {
9998 fprintf(stderr, "station stats missing!\n");
9999 return NL_SKIP;
10000 }
10001
10002 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
10003 tb[NL80211_ATTR_STA_INFO],
10004 stats_policy)) {
10005 fprintf(stderr, "failed to parse nested attributes!\n");
10006 return NL_SKIP;
10007 }
10008
10009 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
10010 {
10011 stats_entry = &out->tid_array[tid_index];
10012
10013 stats_entry->tid = tid_index;
10014 stats_entry->ac = _tid_ac_index_get[tid_index];
10015
10016 if(sinfo[NL80211_STA_INFO_TID_STATS])
10017 {
10018 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
10019 printf("failed to parse nested stats attributes!");
10020 return NL_SKIP;
10021 }
10022 }
10023 if(stats_info[NL80211_TID_STATS_TX_MSDU])
10024 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
10025
10026 if(tid_index < (PS_MAX_TID - 1))
10027 tid_index++;
10028 }
10029 //ToDo: sum_time_ms, ewma_time_ms
10030 return NL_SKIP;
10031}
10032#endif
10033
10034INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
10035{
10036#ifdef HAL_NETLINK_IMPL
10037 Netlink nl;
10038 char if_name[10];
developerd946fd62022-12-08 18:03:28 +080010039 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080010040
developerac6f1142022-12-20 19:26:35 +080010041 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010042 return RETURN_ERR;
10043
10044 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +080010045
10046 nl.id = initSock80211(&nl);
10047
10048 if (nl.id < 0) {
10049 fprintf(stderr, "Error initializing netlink \n");
10050 return -1;
10051 }
10052
10053 struct nl_msg* msg = nlmsg_alloc();
10054
10055 if (!msg) {
10056 fprintf(stderr, "Failed to allocate netlink message.\n");
10057 nlfree(&nl);
10058 return -2;
10059 }
10060
10061 genlmsg_put(msg,
10062 NL_AUTO_PORT,
10063 NL_AUTO_SEQ,
10064 nl.id,
10065 0,
10066 0,
10067 NL80211_CMD_GET_STATION,
10068 0);
10069
10070 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
10071 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10072 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
10073 nl_send_auto(nl.socket, msg);
10074 nl_recvmsgs(nl.socket, nl.cb);
10075 nlmsg_free(msg);
10076 nlfree(&nl);
10077 return RETURN_OK;
10078#else
10079//iw implementation
10080#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
10081#define TOTAL_MAX_LINES 50
10082
10083 char buf[256] = {'\0'}; /* or other suitable maximum line size */
developerd946fd62022-12-08 18:03:28 +080010084 char if_name[32] = {0};
developer06a01d92022-09-07 16:32:39 +080010085 FILE *fp=NULL;
10086 char pipeCmd[1024]= {'\0'};
10087 int lines,tid_index=0;
10088 char mac_addr[20] = {'\0'};
10089
developerac6f1142022-12-20 19:26:35 +080010090 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010091 return RETURN_ERR;
10092
developer06a01d92022-09-07 16:32:39 +080010093 wifi_associated_dev_tid_entry_t *stats_entry;
10094
developer06a01d92022-09-07 16:32:39 +080010095 strcpy(mac_addr,clientMacAddress);
10096
10097 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
10098 fp= popen(pipeCmd,"r");
10099 if(fp == NULL)
10100 {
10101 perror("popen for station dump failed\n");
10102 return RETURN_ERR;
10103 }
10104 pclose(fp);
10105
10106 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
10107 fp=popen(pipeCmd,"r");
10108 if(fp == NULL)
10109 {
10110 perror("popen for grep station failed\n");
10111 return RETURN_ERR;
10112 }
10113 else if(fgets(buf,sizeof(buf),fp) != NULL)
10114 lines=atoi(buf);
10115 else
10116 {
10117 pclose(fp);
10118 fprintf(stderr,"No devices are connected \n");
10119 return RETURN_ERR;
10120 }
10121 pclose(fp);
10122
10123 if(lines == 1)
10124 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
10125
10126 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
10127 {
10128 stats_entry = &tid_stats->tid_array[tid_index];
10129 stats_entry->tid = tid_index;
10130
10131 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);
10132
10133 fp=popen(pipeCmd,"r");
10134 if(fp ==NULL)
10135 {
10136 perror("Failed to read from tid file \n");
10137 return RETURN_ERR;
10138 }
10139 else if(fgets(buf,sizeof(buf),fp) != NULL)
10140 stats_entry->num_msdus = atol(buf);
10141
10142 pclose(fp);
10143 stats_entry->ac = _tid_ac_index_get[tid_index];
10144// TODO:
10145// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
10146// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
10147 }
10148 return RETURN_OK;
10149#endif
10150}
10151
10152
10153INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
10154{
developerd946fd62022-12-08 18:03:28 +080010155 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +080010156 char cmd[128]={0};
10157 char buf[128]={0};
10158 int freq = 0;
developer63a1ef02024-05-03 16:59:38 +080010159 wifi_band band = band_invalid;
developer615510b2022-09-27 10:14:35 +080010160
10161 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10162
developer63a1ef02024-05-03 16:59:38 +080010163 band = wifi_index_to_band(apIndex);
developer615510b2022-09-27 10:14:35 +080010164 // full mode is used to scan all channels.
10165 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
10166 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
developer63a1ef02024-05-03 16:59:38 +080010167 freq = ieee80211_channel_to_frequency(chan_list[0], band);
developer615510b2022-09-27 10:14:35 +080010168
developerac6f1142022-12-20 19:26:35 +080010169 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010170 return RETURN_ERR;
10171
developer615510b2022-09-27 10:14:35 +080010172 if (freq)
developerd946fd62022-12-08 18:03:28 +080010173 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d freq %d", interface_name, dwell_time, freq);
developer615510b2022-09-27 10:14:35 +080010174 else
developerd946fd62022-12-08 18:03:28 +080010175 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d", interface_name, dwell_time);
developer615510b2022-09-27 10:14:35 +080010176
10177 _syscmd(cmd, buf, sizeof(buf));
10178 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10179
developer06a01d92022-09-07 16:32:39 +080010180 return RETURN_OK;
10181}
10182
10183
10184INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
10185{
10186 // TODO Implement me!
10187 return RETURN_ERR;
10188}
10189
10190INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
10191{
10192 // TODO Implement me!
10193 return RETURN_ERR;
10194}
10195
10196INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
10197{
10198 // TODO Implement me!
10199 return RETURN_ERR;
10200}
10201
10202INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
10203{
10204 // TODO Implement me!
10205 return RETURN_ERR;
10206}
10207
10208INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
10209{
10210 // TODO Implement me!
10211 return RETURN_ERR;
10212}
10213
10214INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
10215{
10216 // TODO Implement me!
10217 return RETURN_ERR;
10218}
10219
10220INT wifi_steering_eventUnregister(void)
10221{
10222 // TODO Implement me!
10223 return RETURN_ERR;
10224}
10225
10226INT wifi_delApAclDevices(INT apIndex)
10227{
10228#if 0
10229 char cmd[MAX_BUF_SIZE] = {0};
10230 char buf[MAX_BUF_SIZE] = {0};
10231
10232 /* Not reset proof solution */
developerd946fd62022-12-08 18:03:28 +080010233 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s accept_acl CLEAR", interface_name);
developer06a01d92022-09-07 16:32:39 +080010234 if(_syscmd(cmd,buf,sizeof(buf)))
10235 return RETURN_ERR;
10236#endif
developer9988c232023-03-06 14:57:08 +080010237 char cmd[256]={0};
10238 char buf[64]={0};
developer06a01d92022-09-07 16:32:39 +080010239
developere6aafda2022-09-13 14:59:28 +080010240 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer9988c232023-03-06 14:57:08 +080010241 sprintf(cmd, "rm %s%d %s%d 2>&1 && touch %s%d %s%d", ACL_PREFIX, apIndex, DENY_PREFIX, apIndex, ACL_PREFIX, apIndex, DENY_PREFIX, apIndex);
developere6aafda2022-09-13 14:59:28 +080010242 if(_syscmd(cmd, buf, sizeof(buf)))
10243 return RETURN_ERR;
10244 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080010245
10246 return RETURN_OK;
10247}
10248
10249#ifdef HAL_NETLINK_IMPL
10250static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
10251 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10252 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10253 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10254 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
10255 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
10256 char mac_addr[20],dev[20];
10257
10258 nla_parse(tb,
10259 NL80211_ATTR_MAX,
10260 genlmsg_attrdata(gnlh, 0),
10261 genlmsg_attrlen(gnlh, 0),
10262 NULL);
10263
10264 if(!tb[NL80211_ATTR_STA_INFO]) {
10265 fprintf(stderr, "sta stats missing!\n");
10266 return NL_SKIP;
10267 }
10268
10269 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
10270 fprintf(stderr, "failed to parse nested attributes!\n");
10271 return NL_SKIP;
10272 }
10273 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
10274
10275 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10276
10277 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
10278 fprintf(stderr, "failed to parse nested rate attributes!");
10279 return NL_SKIP;
10280 }
10281
10282 if(sinfo[NL80211_STA_INFO_TID_STATS])
10283 {
10284 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
10285 printf("failed to parse nested stats attributes!");
10286 return NL_SKIP;
10287 }
10288 }
10289
10290 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
10291 {
10292 printf("Type is VHT\n");
10293 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
10294 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
10295
10296 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
10297 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
10298 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
10299 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10300 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
10301 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10302 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
10303 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10304 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
10305 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
10306 }
10307 else
10308 {
10309 printf(" OFDM or CCK \n");
10310 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
10311 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
10312 }
10313
10314 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
10315 if(rinfo[NL80211_RATE_INFO_MCS])
10316 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
10317 }
10318 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
10319 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
10320 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
10321 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
10322
10323 if(stats_info[NL80211_TID_STATS_RX_MSDU])
10324 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
10325
10326 if (sinfo[NL80211_STA_INFO_SIGNAL])
10327 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
10328 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
10329 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
10330 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
10331 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
10332 //rssi_array need to be filled
10333 return NL_SKIP;
10334}
10335#endif
10336
10337INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10338{
10339#ifdef HAL_NETLINK_IMPL
10340 Netlink nl;
developerd946fd62022-12-08 18:03:28 +080010341 char if_name[32];
developerac6f1142022-12-20 19:26:35 +080010342 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010343 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010344
10345 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
10346
10347 if (*output_array_size <= 0)
10348 return RETURN_OK;
10349
developer06a01d92022-09-07 16:32:39 +080010350 nl.id = initSock80211(&nl);
10351
10352 if (nl.id < 0) {
10353 fprintf(stderr, "Error initializing netlink \n");
10354 return 0;
10355 }
10356
10357 struct nl_msg* msg = nlmsg_alloc();
10358
10359 if (!msg) {
10360 fprintf(stderr, "Failed to allocate netlink message.\n");
10361 nlfree(&nl);
10362 return 0;
10363 }
10364
10365 genlmsg_put(msg,
10366 NL_AUTO_PORT,
10367 NL_AUTO_SEQ,
10368 nl.id,
10369 0,
10370 0,
10371 NL80211_CMD_GET_STATION,
10372 0);
10373
10374 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
10375 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10376 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
10377 nl_send_auto(nl.socket, msg);
10378 nl_recvmsgs(nl.socket, nl.cb);
10379 nlmsg_free(msg);
10380 nlfree(&nl);
10381 return RETURN_OK;
10382#else
10383 //TODO Implement me
10384 return RETURN_OK;
10385#endif
10386}
10387
10388#ifdef HAL_NETLINK_IMPL
10389static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
10390 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10391 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10392 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10393 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
10394 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
10395 char mac_addr[20],dev[20];
10396
10397 nla_parse(tb,
10398 NL80211_ATTR_MAX,
10399 genlmsg_attrdata(gnlh, 0),
10400 genlmsg_attrlen(gnlh, 0),
10401 NULL);
10402
10403 if(!tb[NL80211_ATTR_STA_INFO]) {
10404 fprintf(stderr, "sta stats missing!\n");
10405 return NL_SKIP;
10406 }
10407
10408 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
10409 fprintf(stderr, "failed to parse nested attributes!\n");
10410 return NL_SKIP;
10411 }
10412
10413 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
10414
10415 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10416
10417 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
10418 fprintf(stderr, "failed to parse nested rate attributes!");
10419 return NL_SKIP;
10420 }
10421
10422 if(sinfo[NL80211_STA_INFO_TID_STATS])
10423 {
10424 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
10425 printf("failed to parse nested stats attributes!");
10426 return NL_SKIP;
10427 }
10428 }
10429 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
10430 {
10431 printf("Type is VHT\n");
10432 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
10433 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
10434
10435 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
10436 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
10437 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
10438 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10439 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
10440 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10441 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
10442 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10443 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
10444 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
10445 }
10446 else
10447 {
10448 printf(" OFDM or CCK \n");
10449 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
10450 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
10451 }
10452
10453 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
10454 if(rinfo[NL80211_RATE_INFO_MCS])
10455 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
10456 }
10457
10458 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
10459 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
10460 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
10461 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
10462
10463 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
10464 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10465 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10466
10467 if(stats_info[NL80211_TID_STATS_TX_MSDU])
10468 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
10469
10470 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
10471 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
10472
10473 if(sinfo[NL80211_STA_INFO_TX_FAILED])
10474 ((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]);
10475
10476 return NL_SKIP;
10477}
10478#endif
10479
10480INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10481{
10482#ifdef HAL_NETLINK_IMPL
10483 Netlink nl;
10484 char if_name[10];
developerd946fd62022-12-08 18:03:28 +080010485 char interface_name[16] = {0};
developerac6f1142022-12-20 19:26:35 +080010486 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010487 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010488
10489 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
10490
10491 if (*output_array_size <= 0)
10492 return RETURN_OK;
10493
developerd946fd62022-12-08 18:03:28 +080010494 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +080010495
10496 nl.id = initSock80211(&nl);
10497
10498 if(nl.id < 0) {
10499 fprintf(stderr, "Error initializing netlink \n");
10500 return 0;
10501 }
10502
10503 struct nl_msg* msg = nlmsg_alloc();
10504
10505 if(!msg) {
10506 fprintf(stderr, "Failed to allocate netlink message.\n");
10507 nlfree(&nl);
10508 return 0;
10509 }
10510
10511 genlmsg_put(msg,
10512 NL_AUTO_PORT,
10513 NL_AUTO_SEQ,
10514 nl.id,
10515 0,
10516 0,
10517 NL80211_CMD_GET_STATION,
10518 0);
10519
10520 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
10521 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10522 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
10523 nl_send_auto(nl.socket, msg);
10524 nl_recvmsgs(nl.socket, nl.cb);
10525 nlmsg_free(msg);
10526 nlfree(&nl);
10527 return RETURN_OK;
10528#else
10529 //TODO Implement me
10530 return RETURN_OK;
10531#endif
10532}
10533
10534INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
10535{
10536 // TODO Implement me!
10537 char buf[MAX_BUF_SIZE] = {0};
10538 char config_file[MAX_BUF_SIZE] = {0};
10539
10540 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developerefb790a2023-12-26 18:58:32 +080010541 if (!syn_flag)
10542 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
10543 else
developer07ded1f2024-01-10 10:30:15 +080010544 snprintf(buf, sizeof(buf), "%s", vap_info[apIndex].bss_transition);
developer06a01d92022-09-07 16:32:39 +080010545 *activate = (strncmp("1",buf,1) == 0);
10546
10547 return RETURN_OK;
10548}
10549
10550INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
10551{
10552 char config_file[MAX_BUF_SIZE] = {0};
10553 struct params list;
10554
10555 list.name = "rrm_neighbor_report";
10556 list.value = activate?"1":"0";
10557 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10558 wifi_hostapdWrite(config_file, &list, 1);
10559
10560 return RETURN_OK;
10561}
10562
10563INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
10564{
10565 char buf[32] = {0};
10566 char config_file[MAX_BUF_SIZE] = {0};
10567
10568 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10569 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
10570 *activate = (strncmp("1",buf,1) == 0);
10571
10572 return RETURN_OK;
10573}
10574#undef HAL_NETLINK_IMPL
10575#ifdef HAL_NETLINK_IMPL
10576static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
10577 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10578 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10579 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
10580 char dev[20];
10581 int freq =0 ;
10582 static int i=0;
10583
10584 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
10585
10586 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
10587 };
10588
10589 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
10590
10591 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10592
10593 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
10594 fprintf(stderr, "survey data missing!\n");
10595 return NL_SKIP;
10596 }
10597
10598 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
10599 {
10600 fprintf(stderr, "failed to parse nested attributes!\n");
10601 return NL_SKIP;
10602 }
10603
10604
10605 if(out[0].array_size == 1 )
10606 {
10607 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
10608 {
10609 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10610 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10611 out[0].ch_number = ieee80211_frequency_to_channel(freq);
10612
10613 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10614 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10615 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10616 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10617 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10618 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10619 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10620 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10621 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10622 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10623 if (sinfo[NL80211_SURVEY_INFO_TIME])
10624 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10625 return NL_STOP;
10626 }
10627 }
10628 else
10629 {
10630 if ( i <= out[0].array_size )
10631 {
10632 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10633 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10634 out[i].ch_number = ieee80211_frequency_to_channel(freq);
10635
10636 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10637 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10638 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10639 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10640 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10641 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10642 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10643 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10644 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10645 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10646 if (sinfo[NL80211_SURVEY_INFO_TIME])
10647 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10648 }
10649 }
10650
10651 i++;
10652 return NL_SKIP;
10653}
10654#endif
10655
developer63a1ef02024-05-03 16:59:38 +080010656static int ieee80211_channel_to_frequency(int chan, wifi_band band)
developer06a01d92022-09-07 16:32:39 +080010657{
developer63a1ef02024-05-03 16:59:38 +080010658 /* see 802.11 17.3.8.3.2 and Annex J
10659 * there are overlapping channel numbers in 5GHz and 2GHz bands */
10660 if (chan <= 0)
10661 return -1; /* not supported */
10662 switch (band) {
10663 case band_2_4:
10664 if (chan == 14)
10665 return 2484;
10666 else if (chan < 14)
10667 return (2407 + chan * 5);
10668 break;
10669 case band_5:
10670 if (chan >= 182 && chan <= 196)
10671 return (4000 + chan * 5);
10672 else
10673 return (5000 + chan * 5);
10674 break;
10675 case band_6:
10676 /* see 802.11ax D6.1 27.3.23.2 */
10677 if (chan == 2)
10678 return 5935;
10679 if (chan <= 233)
10680 return (5950 + chan * 5);
10681 break;
10682 default:
10683 return -1;
10684 break;
developer06a01d92022-09-07 16:32:39 +080010685 }
developer06a01d92022-09-07 16:32:39 +080010686}
10687
10688static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
10689{
10690 int freqMHz = -1;
10691 char cmd[MAX_CMD_SIZE] = {'\0'};
developer7930d352022-12-21 17:55:42 +080010692 char interface_name[16] = {0};
developer63a1ef02024-05-03 16:59:38 +080010693 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +080010694
developer63a1ef02024-05-03 16:59:38 +080010695 band = wifi_index_to_band(radioIndex);
10696 freqMHz = ieee80211_channel_to_frequency(channel, band);
developer06a01d92022-09-07 16:32:39 +080010697 if (freqMHz == -1) {
10698 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
10699 return -1;
10700 }
10701
developer7930d352022-12-21 17:55:42 +080010702 wifi_GetInterfaceName(radioIndex, interface_name);
10703 if (sprintf(cmd,"iw dev %s survey dump | grep -A5 %d | tr -d '\\t'", interface_name, freqMHz) < 0) {
developer06a01d92022-09-07 16:32:39 +080010704 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
10705 radioIndex, freqMHz);
10706 return -1;
10707 }
10708
10709 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
10710 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
10711 return -1;
10712 }
10713
10714 return 0;
10715}
10716
10717static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
10718{
10719 const char *ptr = buf;
10720 char *key = NULL;
10721 char *val = NULL;
10722 char line[256] = { '\0' };
10723
10724 while (ptr = get_line_from_str_buf(ptr, line)) {
10725 if (strstr(line, "Frequency")) continue;
10726
10727 key = strtok(line, ":");
10728 val = strtok(NULL, " ");
10729 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
10730
10731 if (!strcmp(key, "noise")) {
10732 sscanf(val, "%d", &stats->ch_noise);
10733 if (stats->ch_noise == 0) {
10734 // Workaround for missing noise information.
10735 // Assume -95 for 2.4G and -103 for 5G
10736 if (radioIndex == 0) stats->ch_noise = -95;
10737 if (radioIndex == 1) stats->ch_noise = -103;
10738 }
10739 }
10740 else if (!strcmp(key, "channel active time")) {
10741 sscanf(val, "%llu", &stats->ch_utilization_total);
10742 }
10743 else if (!strcmp(key, "channel busy time")) {
10744 sscanf(val, "%llu", &stats->ch_utilization_busy);
10745 }
10746 else if (!strcmp(key, "channel receive time")) {
10747 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
10748 }
10749 else if (!strcmp(key, "channel transmit time")) {
10750 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
10751 }
10752 };
10753
10754 return 0;
10755}
10756
10757INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
10758{
10759 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10760#ifdef HAL_NETLINK_IMPL
10761 Netlink nl;
10762 wifi_channelStats_t_loc local[array_size];
developerd946fd62022-12-08 18:03:28 +080010763 char if_name[32];
developer06a01d92022-09-07 16:32:39 +080010764
10765 local[0].array_size = array_size;
10766
developerac6f1142022-12-20 19:26:35 +080010767 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010768 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010769
10770 nl.id = initSock80211(&nl);
10771
10772 if (nl.id < 0) {
10773 fprintf(stderr, "Error initializing netlink \n");
10774 return -1;
10775 }
10776
10777 struct nl_msg* msg = nlmsg_alloc();
10778
10779 if (!msg) {
10780 fprintf(stderr, "Failed to allocate netlink message.\n");
10781 nlfree(&nl);
10782 return -2;
10783 }
10784
10785 genlmsg_put(msg,
10786 NL_AUTO_PORT,
10787 NL_AUTO_SEQ,
10788 nl.id,
10789 0,
10790 NLM_F_DUMP,
10791 NL80211_CMD_GET_SURVEY,
10792 0);
10793
10794 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10795 nl_send_auto(nl.socket, msg);
10796 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
10797 nl_recvmsgs(nl.socket, nl.cb);
10798 nlmsg_free(msg);
10799 nlfree(&nl);
10800 //Copying the Values
10801 for(int i=0;i<array_size;i++)
10802 {
10803 input_output_channelStats_array[i].ch_number = local[i].ch_number;
10804 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
10805 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
10806 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
10807 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
10808 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
10809 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
10810 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
10811 }
10812#else
10813 ULONG channel = 0;
10814 int i;
10815 int number_of_channels = array_size;
10816 char buf[512];
10817 INT ret;
10818 wifi_channelStats_t tmp_stats;
10819
10820 if (number_of_channels == 0) {
10821 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
10822 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
10823 return RETURN_ERR;
10824 }
10825 number_of_channels = 1;
10826 input_output_channelStats_array[0].ch_number = channel;
10827 }
10828
10829 for (i = 0; i < number_of_channels; i++) {
10830
10831 input_output_channelStats_array[i].ch_noise = 0;
10832 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
10833 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
10834 input_output_channelStats_array[i].ch_utilization_busy = 0;
10835 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
10836 input_output_channelStats_array[i].ch_utilization_total = 0;
10837
10838 memset(buf, 0, sizeof(buf));
10839 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
10840 return RETURN_ERR;
10841 }
10842 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
10843 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
10844 return RETURN_ERR;
10845 }
10846
10847 // XXX: fake missing 'self' counter which is not available in iw survey output
10848 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
10849 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
10850
10851 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
10852 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
10853 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
10854 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
10855 input_output_channelStats_array[i].ch_utilization_total *= 1000;
10856
10857 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",
10858 __func__,
10859 input_output_channelStats_array[i].ch_number,
10860 input_output_channelStats_array[i].ch_noise,
10861 input_output_channelStats_array[i].ch_utilization_total,
10862 input_output_channelStats_array[i].ch_utilization_busy,
10863 input_output_channelStats_array[i].ch_utilization_busy_rx,
10864 input_output_channelStats_array[i].ch_utilization_busy_tx,
10865 input_output_channelStats_array[i].ch_utilization_busy_self,
10866 input_output_channelStats_array[i].ch_utilization_busy_ext);
10867 }
10868#endif
10869 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10870 return RETURN_OK;
10871}
10872#define HAL_NETLINK_IMPL
10873
10874/* Hostapd events */
10875
10876#ifndef container_of
10877#define offset_of(st, m) ((size_t)&(((st *)0)->m))
10878#define container_of(ptr, type, member) \
10879 ((type *)((char *)ptr - offset_of(type, member)))
10880#endif /* container_of */
10881
10882struct ctrl {
10883 char sockpath[128];
10884 char sockdir[128];
10885 char bss[IFNAMSIZ];
10886 char reply[4096];
10887 int ssid_index;
10888 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
10889 void (*overrun)(struct ctrl *ctrl);
10890 struct wpa_ctrl *wpa;
10891 unsigned int ovfl;
10892 size_t reply_len;
10893 int initialized;
10894 ev_timer retry;
10895 ev_timer watchdog;
10896 ev_stat stat;
10897 ev_io io;
10898};
10899static wifi_newApAssociatedDevice_callback clients_connect_cb;
10900static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
10901static struct ctrl wpa_ctrl[MAX_APS];
10902static int initialized;
10903
10904static unsigned int ctrl_get_drops(struct ctrl *ctrl)
10905{
10906 char cbuf[256] = {};
10907 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
10908 struct cmsghdr *cmsg;
10909 unsigned int ovfl = ctrl->ovfl;
10910 unsigned int drop;
10911
10912 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
10913 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
10914 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
10915 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
10916
10917 drop = ovfl - ctrl->ovfl;
10918 ctrl->ovfl = ovfl;
10919
10920 return drop;
10921}
10922
10923static void ctrl_close(struct ctrl *ctrl)
10924{
10925 if (ctrl->io.cb)
10926 ev_io_stop(EV_DEFAULT_ &ctrl->io);
10927 if (ctrl->retry.cb)
10928 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10929 if (!ctrl->wpa)
10930 return;
10931
10932 wpa_ctrl_detach(ctrl->wpa);
10933 wpa_ctrl_close(ctrl->wpa);
10934 ctrl->wpa = NULL;
10935 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
10936}
10937
10938static void ctrl_process(struct ctrl *ctrl)
10939{
10940 const char *str;
10941 int drops;
10942 int level;
10943 int err;
10944
10945 /* Example events:
10946 *
10947 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
10948 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
10949 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
10950 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
10951 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
10952 */
10953 if (!(str = index(ctrl->reply, '>')))
10954 return;
10955 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
10956 return;
10957
10958 str++;
10959
10960 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
10961 if (!(str = index(ctrl->reply, ' ')))
10962 return;
10963 wifi_associated_dev_t sta;
10964 memset(&sta, 0, sizeof(sta));
10965
10966 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10967 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
10968 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
10969
10970 sta.cli_Active=true;
10971
10972 (clients_connect_cb)(ctrl->ssid_index, &sta);
10973 goto handled;
10974 }
10975
10976 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
10977 if (!(str = index(ctrl->reply, ' ')))
10978 return;
10979
10980 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
10981 goto handled;
10982 }
10983
10984 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
10985 printf("CTRL_WPA: handle TERMINATING event\n");
10986 goto retry;
10987 }
10988
10989 if (strncmp("AP-DISABLED", str, 11) == 0) {
10990 printf("CTRL_WPA: handle AP-DISABLED\n");
10991 goto retry;
10992 }
10993
10994 printf("Event not supported!!\n");
10995
10996handled:
10997
10998 if ((drops = ctrl_get_drops(ctrl))) {
10999 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
11000 if (ctrl->overrun)
11001 ctrl->overrun(ctrl);
11002 }
11003
11004 return;
11005
11006retry:
11007 printf("WPA_CTRL: closing\n");
11008 ctrl_close(ctrl);
11009 printf("WPA_CTRL: retrying from ctrl prcoess\n");
11010 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
11011}
11012
11013static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
11014{
11015 struct ctrl *ctrl = container_of(io, struct ctrl, io);
11016 int err;
11017
11018 memset(ctrl->reply, 0, sizeof(ctrl->reply));
11019 ctrl->reply_len = sizeof(ctrl->reply) - 1;
11020 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
11021 ctrl->reply[ctrl->reply_len] = 0;
11022 if (err < 0) {
11023 if (errno == EAGAIN || errno == EWOULDBLOCK)
11024 return;
11025 ctrl_close(ctrl);
11026 ev_timer_again(EV_A_ &ctrl->retry);
11027 return;
11028 }
11029
11030 ctrl_process(ctrl);
11031}
11032
11033static int ctrl_open(struct ctrl *ctrl)
11034{
11035 int fd;
11036
11037 if (ctrl->wpa)
11038 return 0;
11039
11040 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
11041 if (!ctrl->wpa)
11042 goto err;
11043
11044 if (wpa_ctrl_attach(ctrl->wpa) < 0)
11045 goto err_close;
11046
11047 fd = wpa_ctrl_get_fd(ctrl->wpa);
11048 if (fd < 0)
11049 goto err_detach;
11050
11051 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
11052 goto err_detach;
11053
11054 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
11055 ev_io_start(EV_DEFAULT_ &ctrl->io);
11056
11057 return 0;
11058
11059err_detach:
11060 wpa_ctrl_detach(ctrl->wpa);
11061err_close:
11062 wpa_ctrl_close(ctrl->wpa);
11063err:
11064 ctrl->wpa = NULL;
11065 return -1;
11066}
11067
11068static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
11069{
11070 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
11071
11072 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
11073 ctrl_open(ctrl);
11074}
11075
11076static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
11077{
11078 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
11079
11080 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
11081 if (ctrl_open(ctrl) == 0) {
11082 printf("WPA_CTRL: retry successful\n");
11083 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
11084 }
11085}
11086
11087int ctrl_enable(struct ctrl *ctrl)
11088{
11089 if (ctrl->wpa)
11090 return 0;
11091
11092 if (!ctrl->stat.cb) {
11093 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
11094 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
11095 }
11096
11097 if (!ctrl->retry.cb) {
11098 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
11099 }
11100
11101 return ctrl_open(ctrl);
11102}
11103
11104static void
11105ctrl_msg_cb(char *buf, size_t len)
11106{
11107 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
11108
11109 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
11110 ctrl_process(ctrl);
11111}
11112
11113static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
11114{
11115 int err;
11116
11117 if (!ctrl->wpa)
11118 return -1;
11119 if (*reply_len < 2)
11120 return -1;
11121
11122 (*reply_len)--;
11123 ctrl->reply_len = sizeof(ctrl->reply);
11124 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
11125 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
11126 if (err < 0)
11127 return err;
11128
11129 if (ctrl->reply_len > *reply_len)
11130 ctrl->reply_len = *reply_len;
11131
11132 *reply_len = ctrl->reply_len;
11133 memcpy(reply, ctrl->reply, *reply_len);
11134 reply[*reply_len - 1] = 0;
11135 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
11136 return 0;
11137}
11138
11139static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
11140{
11141 const char *pong = "PONG";
11142 const char *ping = "PING";
11143 char reply[1024];
11144 size_t len = sizeof(reply);
11145 int err;
11146 ULONG s, snum;
11147 INT ret;
11148 BOOL status;
11149
11150 printf("WPA_CTRL: watchdog cb\n");
11151
11152 ret = wifi_getSSIDNumberOfEntries(&snum);
11153 if (ret != RETURN_OK) {
11154 printf("%s: failed to get SSID count", __func__);
11155 return;
11156 }
11157
11158 if (snum > MAX_APS) {
11159 printf("more ssid than supported! %lu\n", snum);
11160 return;
11161 }
11162
11163 for (s = 0; s < snum; s++) {
11164 if (wifi_getApEnable(s, &status) != RETURN_OK) {
developer30423732022-12-01 16:17:49 +080011165 printf("%s: failed to get AP Enable for index: %lu\n", __func__, s);
developer06a01d92022-09-07 16:32:39 +080011166 continue;
11167 }
11168 if (status == false) continue;
11169
11170 memset(reply, 0, sizeof(reply));
11171 len = sizeof(reply);
11172 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
11173 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
11174 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
11175 continue;
11176
11177 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
11178 ctrl_close(&wpa_ctrl[s]);
developer30423732022-12-01 16:17:49 +080011179 printf("WPA_CTRL: ev_timer_again %lu\n", s);
developer06a01d92022-09-07 16:32:39 +080011180 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
11181 }
11182}
11183
11184static int init_wpa()
11185{
11186 int ret = 0, i = 0;
11187 ULONG s, snum;
11188
11189 ret = wifi_getSSIDNumberOfEntries(&snum);
11190 if (ret != RETURN_OK) {
11191 printf("%s: failed to get SSID count", __func__);
11192 return RETURN_ERR;
11193 }
11194
11195 if (snum > MAX_APS) {
11196 printf("more ssid than supported! %lu\n", snum);
11197 return RETURN_ERR;
11198 }
11199
11200 for (s = 0; s < snum; s++) {
11201 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
11202 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
11203 wpa_ctrl[s].ssid_index = s;
11204 ctrl_enable(&wpa_ctrl[s]);
11205 }
11206
11207 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
11208 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
11209
11210 initialized = 1;
11211 printf("WPA_CTRL: initialized\n");
11212
11213 return RETURN_OK;
11214}
11215
11216void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
11217{
11218 clients_connect_cb = callback_proc;
11219 if (!initialized)
11220 init_wpa();
11221}
11222
11223void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
11224{
11225 clients_disconnect_cb = callback_proc;
11226 if (!initialized)
11227 init_wpa();
11228}
11229
11230INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
11231{
11232 // TODO Implement me!
11233 return RETURN_ERR;
11234}
11235
11236INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
11237{
11238 // TODO Implement me!
11239 return RETURN_ERR;
11240}
11241
11242INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
11243{
11244 int i;
developer63a1ef02024-05-03 16:59:38 +080011245 int phyId = -1, band_remap = 0, range_remap = 0;
developer4b102122023-02-15 10:53:03 +080011246 char cmd[256] = {0};
11247 char channel_numbers_buf[256] = {0};
11248 char dfs_state_buf[256] = {0};
11249 char line[256] = {0};
developer06a01d92022-09-07 16:32:39 +080011250 const char *ptr;
developer4b102122023-02-15 10:53:03 +080011251 BOOL dfs_enable = false;
developer63a1ef02024-05-03 16:59:38 +080011252 wifi_band band = band_invalid;
11253
11254 band = wifi_index_to_band(radioIndex);
11255 switch (band) {
11256 case band_2_4:
11257 band_remap = 1;
11258 range_remap = 2;
11259 break;
11260 case band_5:
11261 band_remap = 2;
11262 range_remap = 4;
11263 break;
11264 case band_6:
11265 band_remap = 4;
11266 range_remap = 4;
11267 break;
11268 default:
11269 break;
11270 }
developer06a01d92022-09-07 16:32:39 +080011271
developer4b102122023-02-15 10:53:03 +080011272 memset(outputMap, 0, outputMapSize*sizeof(wifi_channelMap_t)); // all unused entries should be zero
developer06a01d92022-09-07 16:32:39 +080011273
developer4b102122023-02-15 10:53:03 +080011274 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
11275 phyId = radio_index_to_phy(radioIndex);
developer06a01d92022-09-07 16:32:39 +080011276
developer63a1ef02024-05-03 16:59:38 +080011277 snprintf(cmd, sizeof (cmd),
11278 "iw phy phy%d info | grep -e '\\*.*MHz .*dBm\\|Band ' | sed -n '/Band %d/,/Band %d/{/Band %d/n;/Band %d/b;p}' | grep -v '%sno IR\\|5340\\|5480' | awk '{print $4}' | tr -d '[]'",
11279 phyId, band_remap, range_remap, band_remap, range_remap, dfs_enable?"":"radar\\|");
developer06a01d92022-09-07 16:32:39 +080011280
developer4b102122023-02-15 10:53:03 +080011281 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
11282 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
11283 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011284 }
11285
developer4b102122023-02-15 10:53:03 +080011286 ptr = channel_numbers_buf;
11287 i = 0;
11288 while (ptr = get_line_from_str_buf(ptr, line)) {
11289 if (i >= outputMapSize) {
11290 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
11291 return RETURN_ERR;
11292 }
11293 sscanf(line, "%d", &outputMap[i].ch_number);
11294
11295 memset(cmd, 0, sizeof(cmd));
11296 // Below command should fetch string for DFS state (usable, available or unavailable)
11297 // Example line: "DFS state: usable (for 78930 sec)"
11298 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) {
11299 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
developer06a01d92022-09-07 16:32:39 +080011300 return RETURN_ERR;
11301 }
11302
developer4b102122023-02-15 10:53:03 +080011303 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
11304 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
developer06a01d92022-09-07 16:32:39 +080011305 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
11306 return RETURN_ERR;
11307 }
11308
developer4b102122023-02-15 10:53:03 +080011309 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
developer06a01d92022-09-07 16:32:39 +080011310
developer4b102122023-02-15 10:53:03 +080011311 if (!strcmp(dfs_state_buf, "usable")) {
11312 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
11313 } else if (!strcmp(dfs_state_buf, "available")) {
11314 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
11315 } else if (!strcmp(dfs_state_buf, "unavailable")) {
11316 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
11317 } else {
11318 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
developer06a01d92022-09-07 16:32:39 +080011319 }
developer4b102122023-02-15 10:53:03 +080011320 i++;
developer06a01d92022-09-07 16:32:39 +080011321 }
11322
developer4b102122023-02-15 10:53:03 +080011323 return RETURN_OK;
11324
developer06a01d92022-09-07 16:32:39 +080011325 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
11326 return RETURN_ERR;
11327}
11328
11329INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
11330{
11331 // TODO Implement me!
11332 return RETURN_ERR;
11333}
11334
11335INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
11336{
11337 return RETURN_OK;
11338}
11339
11340INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
11341{
11342 // TODO Implement me!
11343 return RETURN_ERR;
11344}
11345
11346INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
11347{
11348 // TODO API refrence Implementaion is present on RPI hal
11349 return RETURN_ERR;
11350}
11351
developerfeab1d12023-09-27 11:29:38 +080011352
developer06a01d92022-09-07 16:32:39 +080011353INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
11354{
developera5005b62022-09-13 15:43:35 +080011355 char cmd[128]={'\0'};
11356 char buf[128]={'\0'};
developerfeab1d12023-09-27 11:29:38 +080011357 int radioIndex = -1;
11358 int phyIndex = -1;
11359 bool enabled = false;
11360 int cur_tx_dbm = 0;
developera5005b62022-09-13 15:43:35 +080011361
11362 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developerfeab1d12023-09-27 11:29:38 +080011363
developera5005b62022-09-13 15:43:35 +080011364 if(txpwr_pcntg == NULL)
11365 return RETURN_ERR;
11366
developerfeab1d12023-09-27 11:29:38 +080011367 // The API name as getRadioXXX, I think the input index should be radioIndex,
11368 // but current we not change the name, but use it as radioIndex
11369 radioIndex = apIndex;
11370 phyIndex = radio_index_to_phy(radioIndex);
developerd946fd62022-12-08 18:03:28 +080011371
developera5005b62022-09-13 15:43:35 +080011372 // Get the maximum tx power of the device
developerfeab1d12023-09-27 11:29:38 +080011373 snprintf(cmd, sizeof(cmd), "cat /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_info | "
developer439baa32024-05-02 15:54:58 +080011374 "grep 'Percentage Control:' | awk '{print $3}' | tr -d '\\n'", single_wiphy ? radioIndex : phyIndex);
developera5005b62022-09-13 15:43:35 +080011375 _syscmd(cmd, buf, sizeof(buf));
developerfeab1d12023-09-27 11:29:38 +080011376 if (strcmp(buf, "enable") == 0)
11377 enabled = true;
developera5005b62022-09-13 15:43:35 +080011378
developerfeab1d12023-09-27 11:29:38 +080011379 if (!enabled) {
11380 *txpwr_pcntg = 100;
11381 return RETURN_OK;
11382 }
11383
developera5005b62022-09-13 15:43:35 +080011384 memset(cmd, 0, sizeof(cmd));
11385 memset(buf, 0, sizeof(buf));
developerfeab1d12023-09-27 11:29:38 +080011386 snprintf(cmd, sizeof(cmd), "cat /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_info | "
developer439baa32024-05-02 15:54:58 +080011387 "grep 'Power Drop:' | awk '{print $3}' | tr -d '\\n'", single_wiphy ? radioIndex : phyIndex);
developera5005b62022-09-13 15:43:35 +080011388 _syscmd(cmd, buf, sizeof(buf));
developerfeab1d12023-09-27 11:29:38 +080011389 cur_tx_dbm = strtol(buf, NULL, 10);
developera5005b62022-09-13 15:43:35 +080011390
developerfeab1d12023-09-27 11:29:38 +080011391 switch (cur_tx_dbm) {
11392 case 0:
11393 *txpwr_pcntg = 100; // range 91-100
developera5005b62022-09-13 15:43:35 +080011394 break;
developerfeab1d12023-09-27 11:29:38 +080011395 case 1:
11396 *txpwr_pcntg = 75; // range 61-90
11397 break;
11398 case 3:
11399 *txpwr_pcntg = 50; // range 31-60
11400 break;
11401 case 6:
11402 *txpwr_pcntg = 25; // range 16-30
11403 break;
11404 case 9:
11405 *txpwr_pcntg = 12; // range 10-15
11406 break;
11407 case 12:
11408 *txpwr_pcntg = 6; // range 1-9
11409 break;
11410 default:
11411 *txpwr_pcntg = 100; // 0
developera5005b62022-09-13 15:43:35 +080011412 }
developerfeab1d12023-09-27 11:29:38 +080011413
developer06a01d92022-09-07 16:32:39 +080011414 return RETURN_OK;
11415}
11416
11417INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
11418{
developer58599c22022-09-13 16:40:34 +080011419 // TODO precac feature.
11420 struct params params = {0};
11421 char config_file[128] = {0};
11422
11423 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11424
11425 params.name = "enable_background_radar";
11426 params.value = enable?"1":"0";
11427 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
11428 wifi_hostapdWrite(config_file, &params, 1);
11429 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
11430
11431 /* TODO precac feature */
11432
11433 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11434 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011435}
11436
11437INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
11438{
developer58599c22022-09-13 16:40:34 +080011439 char config_file[128] = {0};
11440 char buf[64] = {0};
11441
11442 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11443 if (NULL == enable || NULL == precac)
11444 return RETURN_ERR;
11445
11446 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
11447 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
developerf7e92b62023-05-04 17:06:52 +080011448 if (strncmp(buf, "1", 1) == 0) {
developer58599c22022-09-13 16:40:34 +080011449 *enable = true;
developerf7e92b62023-05-04 17:06:52 +080011450 *precac = true;
11451 } else {
developer58599c22022-09-13 16:40:34 +080011452 *enable = false;
developerf7e92b62023-05-04 17:06:52 +080011453 *precac = false;
11454 }
developer58599c22022-09-13 16:40:34 +080011455
11456 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11457 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011458}
11459
11460INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
11461{
developer58599c22022-09-13 16:40:34 +080011462 *supported = TRUE;
11463 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011464}
11465
developera7149722023-01-11 11:36:21 +080011466bool check_is_hemu_vendor_new_patch() {
11467 char cmd[128] = {0};
11468 char buf[128] = {0};
11469
11470 snprintf(cmd, sizeof(cmd), "hostapd_cli -h 2>&1 | grep set_hemu");
11471 _syscmd(cmd, buf, sizeof(buf));
11472
11473 if (strlen(buf) > 0)
11474 return FALSE;
11475 else
11476 return TRUE;
11477}
11478
developer3e6b1692022-09-30 18:04:05 +080011479INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
11480{
11481 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11482 struct params params = {0};
11483 char config_file[64] = {0};
11484 char buf[64] = {0};
developera7149722023-01-11 11:36:21 +080011485 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011486 unsigned int set_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011487 bool new_vendor_patch = FALSE;
developer3e6b1692022-09-30 18:04:05 +080011488 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11489
developera7149722023-01-11 11:36:21 +080011490 wifi_getDownlinkMuType(radio_index, &set_mu_type);
developer3e6b1692022-09-30 18:04:05 +080011491
11492 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
11493 set_mu_type &= ~0x05; // unset bit 0, 2
11494 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11495 set_mu_type |= 0x01;
11496 set_mu_type &= ~0x04;
11497 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
11498 set_mu_type &= ~0x01;
11499 set_mu_type |= 0x04;
11500 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
11501 set_mu_type |= 0x05; // set bit 0, 2
11502 }
11503
developera7149722023-01-11 11:36:21 +080011504 new_vendor_patch = check_is_hemu_vendor_new_patch();
11505 if (new_vendor_patch)
11506 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11507 else
11508 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11509
11510 params.name = hemu_vendor_cmd;
developer3e6b1692022-09-30 18:04:05 +080011511 sprintf(buf, "%u", set_mu_type);
11512 params.value = buf;
11513 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11514 wifi_hostapdWrite(config_file, &params, 1);
11515 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developera7149722023-01-11 11:36:21 +080011516 wifi_reloadAp(radio_index);
developer3e6b1692022-09-30 18:04:05 +080011517
11518 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11519 return RETURN_OK;
11520}
11521
11522INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
11523{
11524 struct params params={0};
11525 char config_file[64] = {0};
11526 char buf[64] = {0};
11527 unsigned int get_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011528 bool new_vendor_patch = FALSE;
11529 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011530
11531 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11532
11533 if (mu_type == NULL)
11534 return RETURN_ERR;
11535
developera7149722023-01-11 11:36:21 +080011536 new_vendor_patch = check_is_hemu_vendor_new_patch();
11537
11538 if (new_vendor_patch)
11539 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11540 else
11541 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11542
developer3e6b1692022-09-30 18:04:05 +080011543 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
developera7149722023-01-11 11:36:21 +080011544 wifi_hostapdRead(config_file, hemu_vendor_cmd, buf, sizeof(buf));
developer3e6b1692022-09-30 18:04:05 +080011545 get_mu_type = strtol(buf, NULL, 10);
11546
11547 if (get_mu_type & 0x04 && get_mu_type & 0x01)
11548 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
11549 else if (get_mu_type & 0x04)
11550 *mu_type = WIFI_DL_MU_TYPE_MIMO;
11551 else if (get_mu_type & 0x01)
11552 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11553 else
11554 *mu_type = WIFI_DL_MU_TYPE_NONE;
11555
11556 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11557 return RETURN_OK;
11558}
11559
11560INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
11561{
11562 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11563 struct params params={0};
11564 char config_file[64] = {0};
11565 char buf[64] = {0};
11566 unsigned int set_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011567 bool new_vendor_patch = FALSE;
11568 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011569 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11570
developera7149722023-01-11 11:36:21 +080011571 wifi_getUplinkMuType(radio_index, &set_mu_type);
developer3e6b1692022-09-30 18:04:05 +080011572
11573 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
11574 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
11575 set_mu_type &= ~0x0a;
11576 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11577 set_mu_type |= 0x02;
11578 set_mu_type &= ~0x08;
11579 }
11580
developera7149722023-01-11 11:36:21 +080011581 new_vendor_patch = check_is_hemu_vendor_new_patch();
11582
11583 if (new_vendor_patch)
11584 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11585 else
11586 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11587
11588 params.name = hemu_vendor_cmd;
developer3e6b1692022-09-30 18:04:05 +080011589 sprintf(buf, "%u", set_mu_type);
11590 params.value = buf;
11591 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11592 wifi_hostapdWrite(config_file, &params, 1);
11593 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developera7149722023-01-11 11:36:21 +080011594 wifi_reloadAp(radio_index);
developer3e6b1692022-09-30 18:04:05 +080011595
11596 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11597 return RETURN_OK;
11598}
11599
11600INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
11601{
11602 struct params params={0};
11603 char config_file[64] = {0};
11604 char buf[64] = {0};
11605 unsigned int get_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011606 bool new_vendor_patch = FALSE;
11607 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011608
11609 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11610
developera7149722023-01-11 11:36:21 +080011611 new_vendor_patch = check_is_hemu_vendor_new_patch();
11612
11613 if (new_vendor_patch)
11614 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11615 else
11616 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11617
developer3e6b1692022-09-30 18:04:05 +080011618 if (mu_type == NULL)
11619 return RETURN_ERR;
11620
11621 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
developera7149722023-01-11 11:36:21 +080011622 wifi_hostapdRead(config_file, hemu_vendor_cmd, buf, sizeof(buf));
developer3e6b1692022-09-30 18:04:05 +080011623
11624 get_mu_type = strtol(buf, NULL, 10);
11625 if (get_mu_type & 0x02)
11626 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11627 else
11628 *mu_type = WIFI_DL_MU_TYPE_NONE;
11629
11630 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11631 return RETURN_OK;
11632}
11633
11634
developer454b9462022-09-13 15:29:16 +080011635INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
11636{
11637 char cmd[128] = {0};
developer254882b2022-09-30 17:12:31 +080011638 char buf[256] = {0};
11639 char config_file[64] = {0};
developer454b9462022-09-13 15:29:16 +080011640 char GI[8] = {0};
developer254882b2022-09-30 17:12:31 +080011641 int mode_map = 0;
developer454b9462022-09-13 15:29:16 +080011642 FILE *f = NULL;
developer254882b2022-09-30 17:12:31 +080011643 wifi_band band = band_invalid;
developer454b9462022-09-13 15:29:16 +080011644
11645 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11646
developer254882b2022-09-30 17:12:31 +080011647 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
developer454b9462022-09-13 15:29:16 +080011648 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
11649 return RETURN_ERR;
11650 }
developer454b9462022-09-13 15:29:16 +080011651
developer254882b2022-09-30 17:12:31 +080011652 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer454b9462022-09-13 15:29:16 +080011653 band = wifi_index_to_band(radio_index);
developer454b9462022-09-13 15:29:16 +080011654
developer254882b2022-09-30 17:12:31 +080011655 // Hostapd are not supported HE mode GI 1600, 3200 ns.
11656 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
developer6372c2b2022-10-27 17:39:51 +080011657 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
developer254882b2022-09-30 17:12:31 +080011658 _syscmd(cmd, buf, sizeof(buf));
11659 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
11660 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
11661 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011662 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[SHORT-GI-20][SHORT-GI-40]/' %s", config_file);
developer254882b2022-09-30 17:12:31 +080011663 _syscmd(cmd, buf, sizeof(buf));
11664 }
11665 if (band == band_5) {
11666 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
11667 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011668 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SHORT-GI-80][SHORT-GI-160]/' %s", config_file);
developer254882b2022-09-30 17:12:31 +080011669 _syscmd(cmd, buf, sizeof(buf));
11670 }
11671 }
11672 }
11673 wifi_reloadAp(radio_index);
developer454b9462022-09-13 15:29:16 +080011674
developer254882b2022-09-30 17:12:31 +080011675 if (guard_interval == wifi_guard_interval_400)
11676 strcpy(GI, "0.4");
11677 else if (guard_interval == wifi_guard_interval_800)
11678 strcpy(GI, "0.8");
11679 else if (guard_interval == wifi_guard_interval_1600)
11680 strcpy(GI, "1.6");
11681 else if (guard_interval == wifi_guard_interval_3200)
11682 strcpy(GI, "3.2");
11683 else if (guard_interval == wifi_guard_interval_auto)
11684 strcpy(GI, "auto");
developer454b9462022-09-13 15:29:16 +080011685 // Record GI for get GI function
11686 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11687 f = fopen(buf, "w");
developer254882b2022-09-30 17:12:31 +080011688 if (f == NULL)
11689 return RETURN_ERR;
11690 fprintf(f, "%s", GI);
developer454b9462022-09-13 15:29:16 +080011691 fclose(f);
11692 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11693 return RETURN_OK;
11694}
11695
11696INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
11697{
11698 char buf[32] = {0};
11699 char cmd[64] = {0};
11700
11701 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11702
11703 if (guard_interval == NULL)
11704 return RETURN_ERR;
11705
developer7c4cd202023-03-01 10:56:29 +080011706 snprintf(cmd, sizeof(cmd), "cat %s%d.txt 2> /dev/null", GUARD_INTERVAL_FILE, radio_index);
developer454b9462022-09-13 15:29:16 +080011707 _syscmd(cmd, buf, sizeof(buf));
11708
11709 if (strncmp(buf, "0.4", 3) == 0)
11710 *guard_interval = wifi_guard_interval_400;
11711 else if (strncmp(buf, "0.8", 3) == 0)
11712 *guard_interval = wifi_guard_interval_800;
11713 else if (strncmp(buf, "1.6", 3) == 0)
11714 *guard_interval = wifi_guard_interval_1600;
11715 else if (strncmp(buf, "3.2", 3) == 0)
11716 *guard_interval = wifi_guard_interval_3200;
11717 else
11718 *guard_interval = wifi_guard_interval_auto;
11719
11720 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11721 return RETURN_OK;
11722}
11723
developer3cc61d12022-09-13 16:36:05 +080011724INT wifi_setBSSColor(INT radio_index, UCHAR color)
11725{
11726 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11727 struct params params = {0};
11728 char config_file[128] = {0};
11729 char bss_color[4] ={0};
developer2acb9632023-03-14 14:58:31 +080011730 UCHAR *color_list;
11731 int color_num = 0;
11732 int maxNumberColors = 64;
11733 BOOL color_is_aval = FALSE;
11734
developerbf0b9dc2023-07-06 14:30:54 +080011735 if (color > 63 || color == 0)
developer2acb9632023-03-14 14:58:31 +080011736 return RETURN_ERR;
11737
developer517f3be2023-05-08 10:02:39 +080011738 color_list = calloc(maxNumberColors, sizeof(UCHAR));
11739 if (wifi_getAvailableBSSColor(radio_index, maxNumberColors, color_list, &color_num) != RETURN_OK) {
11740 free(color_list);
developer2acb9632023-03-14 14:58:31 +080011741 return RETURN_ERR;
developer517f3be2023-05-08 10:02:39 +080011742 }
developer2acb9632023-03-14 14:58:31 +080011743
11744 for (int i = 0; i < color_num; i++) {
11745 if (color_list[i] == color) {
11746 color_is_aval = TRUE;
11747 break;
11748 }
11749 }
11750 if (color_is_aval == FALSE) {
developer517f3be2023-05-08 10:02:39 +080011751 free(color_list);
developer2acb9632023-03-14 14:58:31 +080011752 fprintf(stderr, "%s: color %hhu is not avaliable.\n", __func__, color);
11753 return RETURN_ERR;
11754 }
developer3cc61d12022-09-13 16:36:05 +080011755
11756 params.name = "he_bss_color";
11757 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
11758 params.value = bss_color;
developer2acb9632023-03-14 14:58:31 +080011759 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer3cc61d12022-09-13 16:36:05 +080011760 wifi_hostapdWrite(config_file, &params, 1);
11761 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developer2acb9632023-03-14 14:58:31 +080011762 wifi_reloadAp(radio_index);
11763
developer517f3be2023-05-08 10:02:39 +080011764 free(color_list);
developer3cc61d12022-09-13 16:36:05 +080011765 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11766 return RETURN_OK;
11767}
11768
11769INT wifi_getBSSColor(INT radio_index, UCHAR *color)
11770{
developer3cc61d12022-09-13 16:36:05 +080011771 char buf[64] = {0};
developer2acb9632023-03-14 14:58:31 +080011772 char cmd[128] = {0};
11773 char interface_name[16] = {0};
developer3cc61d12022-09-13 16:36:05 +080011774
developer3cc61d12022-09-13 16:36:05 +080011775 if (NULL == color)
11776 return RETURN_ERR;
11777
developer2acb9632023-03-14 14:58:31 +080011778 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
11779 return RETURN_ERR;
developer3cc61d12022-09-13 16:36:05 +080011780
developer2acb9632023-03-14 14:58:31 +080011781 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_bss_color | cut -d '=' -f2", interface_name);
11782 _syscmd(cmd, buf, sizeof(buf));
11783 *color = (UCHAR)strtoul(buf, NULL, 10);
developer3cc61d12022-09-13 16:36:05 +080011784
developer2acb9632023-03-14 14:58:31 +080011785 return RETURN_OK;
11786}
11787
11788INT wifi_getAvailableBSSColor(INT radio_index, INT maxNumberColors, UCHAR* colorList, INT *numColorReturned)
11789{
11790 char buf[64] = {0};
11791 char cmd[128] = {0};
11792 char interface_name[16] = {0};
11793 unsigned long long color_bitmap = 0;
developer3cc61d12022-09-13 16:36:05 +080011794
developer2acb9632023-03-14 14:58:31 +080011795 if (NULL == colorList || NULL == numColorReturned)
11796 return RETURN_ERR;
11797
11798 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
11799 return RETURN_ERR;
11800
11801 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_color_bmp | head -n 1 | cut -d '=' -f2", interface_name);
11802 _syscmd(cmd, buf, sizeof(buf));
11803 color_bitmap = strtoull(buf, NULL, 16);
11804
11805 *numColorReturned = 0;
11806 for (int i = 0; i < maxNumberColors; i++) {
11807 if (color_bitmap & 1) {
11808 colorList[*numColorReturned] = i;
11809 (*numColorReturned) += 1;
11810 }
11811 color_bitmap >>= 1;
11812 }
developer3cc61d12022-09-13 16:36:05 +080011813 return RETURN_OK;
11814}
11815
developer06a01d92022-09-07 16:32:39 +080011816/* multi-psk support */
11817INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
11818{
11819 char cmd[256];
developerd946fd62022-12-08 18:03:28 +080011820 char interface_name[16] = {0};
11821
developerac6f1142022-12-20 19:26:35 +080011822 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011823 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011824
developerd946fd62022-12-08 18:03:28 +080011825 sprintf(cmd, "hostapd_cli -i %s sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
11826 interface_name,
developer06a01d92022-09-07 16:32:39 +080011827 mac[0],
11828 mac[1],
11829 mac[2],
11830 mac[3],
11831 mac[4],
11832 mac[5]
11833 );
11834 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
11835 _syscmd(cmd, key->wifi_keyId, 64);
11836
11837
11838 return RETURN_OK;
11839}
11840
11841INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11842{
developerd946fd62022-12-08 18:03:28 +080011843 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011844 FILE *fd = NULL;
11845 char fname[100];
11846 char cmd[128] = {0};
11847 char out[64] = {0};
11848 wifi_key_multi_psk_t * key = NULL;
11849 if(keysNumber < 0)
11850 return RETURN_ERR;
11851
developer431128d2022-12-16 15:30:41 +080011852 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011853 fd = fopen(fname, "w");
11854 if (!fd) {
11855 return RETURN_ERR;
11856 }
11857 key= (wifi_key_multi_psk_t *) keys;
11858 for(int i=0; i<keysNumber; ++i, key++) {
11859 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
11860 }
11861 fclose(fd);
11862
11863 //reload file
developerac6f1142022-12-20 19:26:35 +080011864 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011865 return RETURN_ERR;
11866 sprintf(cmd, "hostapd_cli -i%s raw RELOAD_WPA_PSK", interface_name);
developer06a01d92022-09-07 16:32:39 +080011867 _syscmd(cmd, out, 64);
11868 return RETURN_OK;
11869}
11870
11871INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11872{
11873 FILE *fd = NULL;
11874 char fname[100];
11875 char * line = NULL;
11876 char * pos = NULL;
11877 size_t len = 0;
11878 ssize_t read = 0;
11879 INT ret = RETURN_OK;
11880 wifi_key_multi_psk_t *keys_it = NULL;
11881
11882 if (keysNumber < 1) {
11883 return RETURN_ERR;
11884 }
11885
developer431128d2022-12-16 15:30:41 +080011886 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011887 fd = fopen(fname, "r");
11888 if (!fd) {
11889 return RETURN_ERR;
11890 }
11891
11892 if (keys == NULL) {
11893 ret = RETURN_ERR;
11894 goto close;
11895 }
11896
11897 keys_it = keys;
11898 while ((read = getline(&line, &len, fd)) != -1) {
11899 //Strip trailing new line if present
11900 if (read > 0 && line[read-1] == '\n') {
11901 line[read-1] = '\0';
11902 }
11903
11904 if(strcmp(line,"keyid=")) {
11905 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
11906 if (!(pos = index(line, ' '))) {
11907 ret = RETURN_ERR;
11908 goto close;
11909 }
11910 pos++;
11911 //Here should be 00:00:00:00:00:00
11912 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
11913 printf("Not supported MAC: %s\n", pos);
11914 }
11915 if (!(pos = index(pos, ' '))) {
11916 ret = RETURN_ERR;
11917 goto close;
11918 }
11919 pos++;
11920
11921 //The rest is PSK
11922 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
11923 keys_it++;
11924
11925 if(--keysNumber <= 0)
11926 break;
11927 }
11928 }
11929
11930close:
11931 free(line);
11932 fclose(fd);
11933 return ret;
11934}
11935/* end of multi-psk support */
11936
11937INT wifi_setNeighborReports(UINT apIndex,
11938 UINT numNeighborReports,
11939 wifi_NeighborReport_t *neighborReports)
11940{
11941 char cmd[256] = { 0 };
11942 char hex_bssid[13] = { 0 };
11943 char bssid[18] = { 0 };
11944 char nr[256] = { 0 };
11945 char ssid[256];
11946 char hex_ssid[256];
developerd946fd62022-12-08 18:03:28 +080011947 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011948 INT ret;
11949
11950 /*rmeove all neighbors*/
developerd946fd62022-12-08 18:03:28 +080011951 wifi_dbg_printf("\n[%s]: removing all neighbors from %s\n", __func__, interface_name);
developerac6f1142022-12-20 19:26:35 +080011952 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011953 return RETURN_ERR;
11954 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);
developer06a01d92022-09-07 16:32:39 +080011955 system(cmd);
11956
11957 for(unsigned int i = 0; i < numNeighborReports; i++)
11958 {
11959 memset(ssid, 0, sizeof(ssid));
11960 ret = wifi_getSSIDName(apIndex, ssid);
11961 if (ret != RETURN_OK)
11962 return RETURN_ERR;
11963
11964 memset(hex_ssid, 0, sizeof(hex_ssid));
11965 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
11966 sprintf(hex_ssid + k,"%02x", ssid[j]);
11967
11968 snprintf(hex_bssid, sizeof(hex_bssid),
11969 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
11970 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11971 snprintf(bssid, sizeof(bssid),
11972 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
11973 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11974
11975 snprintf(nr, sizeof(nr),
11976 "%s" // bssid
11977 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
11978 "%02hhx" // operclass
11979 "%02hhx" // channel
11980 "%02hhx", // phy_mode
11981 hex_bssid,
11982 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
11983 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
11984 neighborReports[i].opClass,
11985 neighborReports[i].channel,
11986 neighborReports[i].phyTable);
11987
11988 snprintf(cmd, sizeof(cmd),
11989 "hostapd_cli set_neighbor "
11990 "%s " // bssid
11991 "ssid=%s " // ssid
11992 "nr=%s " // nr
developerd946fd62022-12-08 18:03:28 +080011993 "-i %s",
11994 bssid,hex_ssid,nr, interface_name);
developer06a01d92022-09-07 16:32:39 +080011995
11996 if (WEXITSTATUS(system(cmd)) != 0)
11997 {
11998 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
11999 }
12000 }
12001
12002 return RETURN_OK;
12003}
12004
12005INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
12006{
12007 return RETURN_OK;
12008}
12009
12010#ifdef _WIFI_HAL_TEST_
12011int main(int argc,char **argv)
12012{
12013 int index;
12014 INT ret=0;
12015 char buf[1024]="";
12016
12017 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12018 if(argc<3)
12019 {
12020 if(argc==2)
12021 {
12022 if(!strcmp(argv[1], "init"))
12023 return wifi_init();
12024 if(!strcmp(argv[1], "reset"))
12025 return wifi_reset();
12026 if(!strcmp(argv[1], "wifi_getHalVersion"))
12027 {
12028 char buffer[64];
12029 if(wifi_getHalVersion(buffer)==RETURN_OK)
12030 printf("Version: %s\n", buffer);
12031 else
12032 printf("Error in wifi_getHalVersion\n");
12033 return RETURN_OK;
12034 }
12035 }
12036 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
12037 exit(-1);
12038 }
12039
12040 index = atoi(argv[2]);
12041 if(strstr(argv[1], "wifi_getApName")!=NULL)
12042 {
12043 wifi_getApName(index,buf);
12044 printf("Ap name is %s \n",buf);
12045 return 0;
12046 }
12047 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
12048 {
12049 BOOL b = FALSE;
12050 BOOL *output_bool = &b;
12051 wifi_getRadioAutoChannelEnable(index,output_bool);
12052 printf("Channel enabled = %d \n",b);
12053 return 0;
12054 }
12055 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
12056 {
12057 wifi_getApWpaEncryptionMode(index,buf);
12058 printf("encryption enabled = %s\n",buf);
12059 return 0;
12060 }
12061 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
12062 {
12063 BOOL b = FALSE;
12064 BOOL *output_bool = &b;
12065 wifi_getApSsidAdvertisementEnable(index,output_bool);
12066 printf("advertisment enabled = %d\n",b);
12067 return 0;
12068 }
12069 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
12070 {
12071 if(argc <= 3 )
12072 {
12073 printf("Insufficient arguments \n");
12074 exit(-1);
12075 }
12076
12077 char sta[20] = {'\0'};
12078 ULLONG handle= 0;
12079 strcpy(sta,argv[3]);
12080 mac_address_t st;
12081 mac_addr_aton(st,sta);
12082
12083 wifi_associated_dev_tid_stats_t tid_stats;
12084 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
12085 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
12086 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);
12087 }
12088
12089 if(strstr(argv[1], "getApEnable")!=NULL) {
12090 BOOL enable;
12091 ret=wifi_getApEnable(index, &enable);
12092 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
12093 }
12094 else if(strstr(argv[1], "setApEnable")!=NULL) {
12095 BOOL enable = atoi(argv[3]);
12096 ret=wifi_setApEnable(index, enable);
12097 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
12098 }
12099 else if(strstr(argv[1], "getApStatus")!=NULL) {
12100 char status[64];
12101 ret=wifi_getApStatus(index, status);
12102 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
12103 }
12104 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
12105 {
12106 wifi_getSSIDNameStatus(index,buf);
12107 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
12108 return 0;
12109 }
12110 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
12111 wifi_ssidTrafficStats2_t stats={0};
12112 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
12113 printf("%s %d: returns %d\n", argv[1], index, ret);
12114 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
12115 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
12116 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
12117 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
12118 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
12119 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
12120 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
12121 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
12122 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
12123 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
12124 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
12125 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
12126 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
12127 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
12128 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
12129 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
12130 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
12131 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
12132 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
12133 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
12134 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
12135 }
12136 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
12137 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
12138 UINT array_size=0;
12139 UINT i=0;
12140 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
12141 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
12142 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
12143 printf(" neighbor %d:\n", i);
12144 printf(" ap_SSID =%s\n", pt->ap_SSID);
12145 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
12146 printf(" ap_Mode =%s\n", pt->ap_Mode);
12147 printf(" ap_Channel =%d\n", pt->ap_Channel);
12148 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
12149 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
12150 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
12151 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
12152 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
12153 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
12154 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
12155 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
12156 printf(" ap_Noise =%d\n", pt->ap_Noise);
12157 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
12158 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
12159 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
12160 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
12161 }
12162 if(neighbor_ap_array)
12163 free(neighbor_ap_array); //make sure to free the list
12164 }
12165 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
12166 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
12167 UINT array_size=0;
12168 UINT i=0;
12169 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
12170 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
12171 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
12172 printf(" associated_dev %d:\n", i);
12173 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
12174 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
12175 printf(" cli_SNR =%d\n", pt->cli_SNR);
12176 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
12177 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
12178 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
12179 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
12180 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
12181 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
12182 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
12183 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
12184 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
12185 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
12186 }
12187 if(associated_dev_array)
12188 free(associated_dev_array); //make sure to free the list
12189 }
12190
12191 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
12192 {
12193#define MAX_ARRAY_SIZE 64
12194 int i, array_size;
12195 char *p, *ch_str;
12196 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
12197
12198 if(argc != 5)
12199 {
12200 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
12201 exit(-1);
12202 }
12203 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
12204
12205 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
12206 {
12207 strtok_r(ch_str, ",", &p);
12208 input_output_channelStats_array[i].ch_number = atoi(ch_str);
12209 }
12210 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
12211 if(!array_size)
12212 array_size=1;//Need to print current channel statistics
12213 for(i=0; i<array_size; i++)
12214 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
12215 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
12216 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
12217 input_output_channelStats_array[i].ch_number,\
12218 input_output_channelStats_array[i].ch_noise,\
12219 input_output_channelStats_array[i].ch_utilization_busy_rx,\
12220 input_output_channelStats_array[i].ch_utilization_busy_tx,\
12221 input_output_channelStats_array[i].ch_utilization_busy,\
12222 input_output_channelStats_array[i].ch_utilization_busy_ext,\
12223 input_output_channelStats_array[i].ch_utilization_total);
12224 }
12225
12226 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
12227 {
12228 if(argc <= 3 )
12229 {
12230 printf("Insufficient arguments \n");
12231 exit(-1);
12232 }
12233 char mac_addr[20] = {'\0'};
12234 wifi_device_t output_struct;
12235 int dev_index = atoi(argv[3]);
12236
12237 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
12238 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
12239 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);
12240 }
12241
12242 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
12243 {
12244 if (argc <= 3)
12245 {
12246 printf("Insufficient arguments\n");
12247 exit(-1);
12248 }
12249 char args[256];
12250 wifi_NeighborReport_t *neighborReports;
12251
12252 neighborReports = calloc(argc - 2, sizeof(neighborReports));
12253 if (!neighborReports)
12254 {
12255 printf("Failed to allocate memory");
12256 exit(-1);
12257 }
12258
12259 for (int i = 3; i < argc; ++i)
12260 {
12261 char *val;
12262 int j = 0;
12263 memset(args, 0, sizeof(args));
12264 strncpy(args, argv[i], sizeof(args));
12265 val = strtok(args, ";");
12266 while (val != NULL)
12267 {
12268 if (j == 0)
12269 {
12270 mac_addr_aton(neighborReports[i - 3].bssid, val);
12271 } else if (j == 1)
12272 {
12273 neighborReports[i - 3].info = strtol(val, NULL, 16);
12274 } else if (j == 2)
12275 {
12276 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
12277 } else if (j == 3)
12278 {
12279 neighborReports[i - 3].channel = strtol(val, NULL, 16);
12280 } else if (j == 4)
12281 {
12282 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
12283 } else {
12284 printf("Insufficient arguments]n\n");
12285 exit(-1);
12286 }
12287 val = strtok(NULL, ";");
12288 j++;
12289 }
12290 }
12291
12292 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
12293 if (ret != RETURN_OK)
12294 {
12295 printf("wifi_setNeighborReports ret = %d", ret);
12296 exit(-1);
12297 }
12298 }
12299 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
12300 {
12301 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
12302 printf("%s.\n", buf);
12303 else
12304 printf("Error returned\n");
12305 }
12306 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
12307 {
12308 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
12309 printf("%s.\n", buf);
12310 else
12311 printf("Error returned\n");
12312 }
12313 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
12314 {
12315 if (argc <= 2)
12316 {
12317 printf("Insufficient arguments\n");
12318 exit(-1);
12319 }
12320 char buf[64]= {'\0'};
12321 wifi_getRadioOperatingChannelBandwidth(index,buf);
12322 printf("Current bandwidth is %s \n",buf);
12323 return 0;
12324 }
12325 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
12326 {
12327 if (argc <= 5)
12328 {
12329 printf("Insufficient arguments\n");
12330 exit(-1);
12331 }
12332 UINT channel = atoi(argv[3]);
12333 UINT width = atoi(argv[4]);
12334 UINT beacon = atoi(argv[5]);
12335 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
12336 printf("Result = %d", ret);
12337 }
12338
12339 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12340 return 0;
12341}
12342
12343#endif
12344
12345#ifdef WIFI_HAL_VERSION_3
12346
developer1e5aa162022-09-13 16:06:24 +080012347INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
12348{
12349 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12350 if (bitMap & WIFI_BITRATE_1MBPS)
12351 strcat(BasicRate, "1,");
12352 if (bitMap & WIFI_BITRATE_2MBPS)
12353 strcat(BasicRate, "2,");
12354 if (bitMap & WIFI_BITRATE_5_5MBPS)
12355 strcat(BasicRate, "5.5,");
12356 if (bitMap & WIFI_BITRATE_6MBPS)
12357 strcat(BasicRate, "6,");
12358 if (bitMap & WIFI_BITRATE_9MBPS)
12359 strcat(BasicRate, "9,");
12360 if (bitMap & WIFI_BITRATE_11MBPS)
12361 strcat(BasicRate, "11,");
12362 if (bitMap & WIFI_BITRATE_12MBPS)
12363 strcat(BasicRate, "12,");
12364 if (bitMap & WIFI_BITRATE_18MBPS)
12365 strcat(BasicRate, "18,");
12366 if (bitMap & WIFI_BITRATE_24MBPS)
12367 strcat(BasicRate, "24,");
12368 if (bitMap & WIFI_BITRATE_36MBPS)
12369 strcat(BasicRate, "36,");
12370 if (bitMap & WIFI_BITRATE_48MBPS)
12371 strcat(BasicRate, "48,");
12372 if (bitMap & WIFI_BITRATE_54MBPS)
12373 strcat(BasicRate, "54,");
12374 if (strlen(BasicRate) != 0) // remove last comma
12375 BasicRate[strlen(BasicRate) - 1] = '\0';
12376 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12377 return RETURN_OK;
12378}
12379
12380INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
12381{
12382 UINT BitMap = 0;
12383 char *rate;
12384
12385 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12386 rate = strtok(BasicRatesList, ",");
12387 while(rate != NULL)
12388 {
12389 if (strcmp(rate, "1") == 0)
12390 BitMap |= WIFI_BITRATE_1MBPS;
12391 else if (strcmp(rate, "2") == 0)
12392 BitMap |= WIFI_BITRATE_2MBPS;
12393 else if (strcmp(rate, "5.5") == 0)
12394 BitMap |= WIFI_BITRATE_5_5MBPS;
12395 else if (strcmp(rate, "6") == 0)
12396 BitMap |= WIFI_BITRATE_6MBPS;
12397 else if (strcmp(rate, "9") == 0)
12398 BitMap |= WIFI_BITRATE_9MBPS;
12399 else if (strcmp(rate, "11") == 0)
12400 BitMap |= WIFI_BITRATE_11MBPS;
12401 else if (strcmp(rate, "12") == 0)
12402 BitMap |= WIFI_BITRATE_12MBPS;
12403 else if (strcmp(rate, "18") == 0)
12404 BitMap |= WIFI_BITRATE_18MBPS;
12405 else if (strcmp(rate, "24") == 0)
12406 BitMap |= WIFI_BITRATE_24MBPS;
12407 else if (strcmp(rate, "36") == 0)
12408 BitMap |= WIFI_BITRATE_36MBPS;
12409 else if (strcmp(rate, "48") == 0)
12410 BitMap |= WIFI_BITRATE_48MBPS;
12411 else if (strcmp(rate, "54") == 0)
12412 BitMap |= WIFI_BITRATE_54MBPS;
12413 rate = strtok(NULL, ",");
12414 }
12415 *basicRateBitMap = BitMap;
12416 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12417 return RETURN_OK;
12418}
12419
developer7c4cd202023-03-01 10:56:29 +080012420INT setEHT320CentrlChannel(UINT radioIndex, int channel, wifi_channelBandwidth_t bandwidth)
12421{
12422 int center_channel = 0;
12423 char central_channel_str[16] = {0};
12424 char config_file[32] = {0};
12425 struct params param = {0};
12426
12427 center_channel = util_unii_6g_centerfreq("HT320", channel);
12428 if (bandwidth == WIFI_CHANNELBANDWIDTH_320_1MHZ) {
12429 if (channel >= 193)
12430 return RETURN_ERR;
12431 if (channel >= 33) {
12432 if (channel > center_channel)
12433 center_channel += 32;
12434 else
12435 center_channel -= 32;
12436 }
12437 } else if (bandwidth == WIFI_CHANNELBANDWIDTH_320_2MHZ) {
12438 if (channel <= 29)
12439 return RETURN_ERR;
12440 }
12441 snprintf(central_channel_str, sizeof(central_channel_str), "%d", center_channel);
12442 param.name = "eht_oper_centr_freq_seg0_idx";
12443 param.value = central_channel_str;
12444 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12445 wifi_hostapdWrite(config_file, &param, 1);
12446
12447 return RETURN_OK;
12448}
12449
12450INT wifi_setRadioOpclass(INT radioIndex, INT bandwidth)
12451{
12452 int op_class = 0;
12453 char config_file[32] = {0};
12454 char op_class_str[8] = {0};
12455 struct params param = {0};
12456
12457 if (bandwidth == 20)
12458 op_class = 131;
12459 else if (bandwidth == 40)
12460 op_class = 132;
12461 else if (bandwidth == 80)
12462 op_class = 133;
12463 else if (bandwidth == 160)
12464 op_class = 134;
12465 else if (bandwidth == 320)
12466 op_class = 137;
12467 else
12468 return RETURN_ERR;
12469 snprintf(op_class_str, sizeof(op_class_str), "%d", op_class);
12470 param.name = "op_class";
12471 param.value = op_class_str;
12472 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12473 wifi_hostapdWrite(config_file, &param, 1);
12474 return RETURN_OK;
12475}
12476
12477INT wifi_getRadioOpclass(INT radioIndex, UINT *class)
12478{
12479 char config_file[32] = {0};
12480 char buf [16] = {0};
12481
12482 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12483 if (wifi_hostapdRead(config_file, "op_class", buf, sizeof(buf)) != 0)
12484 return RETURN_ERR; // 6g band should set op_class
12485 *class = (UINT)strtoul(buf, NULL, 10);
12486
12487 return RETURN_OK;
12488}
12489
developer1e5aa162022-09-13 16:06:24 +080012490// This API is used to configured all radio operation parameter in a single set. it includes channel number, channelWidth, mode and auto chammel configuration.
developer06a01d92022-09-07 16:32:39 +080012491INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
12492{
developer1e5aa162022-09-13 16:06:24 +080012493 char buf[128] = {0};
12494 char cmd[128] = {0};
12495 char config_file[64] = {0};
12496 int bandwidth;
developer517a9792022-10-05 19:37:42 +080012497 int set_mode = 0;
developer1e5aa162022-09-13 16:06:24 +080012498 wifi_radio_operationParam_t current_param;
12499
12500 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12501
12502 multiple_set = TRUE;
12503 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
12504 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
12505 return RETURN_ERR;
12506 }
12507 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
12508 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
12509 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
12510 return RETURN_ERR;
12511 }
12512 }
developer5884e982022-10-06 10:52:50 +080012513
12514 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
12515 bandwidth = 20;
12516 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
12517 bandwidth = 40;
12518 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
12519 bandwidth = 80;
12520 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
12521 bandwidth = 160;
developer7c4cd202023-03-01 10:56:29 +080012522 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_2MHZ)
12523 bandwidth = 320;
developer5884e982022-10-06 10:52:50 +080012524 if (operationParam->autoChannelEnabled){
12525 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
12526 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
12527 return RETURN_ERR;
12528 }
12529 }else{
developer1e5aa162022-09-13 16:06:24 +080012530 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
12531 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
12532 return RETURN_ERR;
12533 }
12534 }
developer5884e982022-10-06 10:52:50 +080012535
developer7c4cd202023-03-01 10:56:29 +080012536 // if set EHT 320. We need to overide the central channel config set by wifi_pushRadioChannel2.
12537 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_2MHZ) {
12538 if (setEHT320CentrlChannel(index, operationParam->channel, operationParam->channelWidth) != RETURN_OK) {
12539 fprintf(stderr, "%s: failed to set EHT 320 bandwidth with channel %d and %s setting\n", __func__, operationParam->channel, \
12540 (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ) ? "EHT320-1" : "EHT320-2");
12541 return RETURN_ERR;
12542 }
12543 }
12544
12545 if (operationParam->band == WIFI_FREQUENCY_6_BAND) {
12546 if (wifi_setRadioOpclass(index, bandwidth) != RETURN_OK) {
12547 fprintf(stderr, "%s: wifi_setRadioOpclass return error.\n", __func__);
12548 return RETURN_ERR;
12549 }
12550 }
12551
developer1e5aa162022-09-13 16:06:24 +080012552 if (current_param.variant != operationParam->variant) {
12553 // Two different definition bit map, so need to check every bit.
12554 if (operationParam->variant & WIFI_80211_VARIANT_A)
12555 set_mode |= WIFI_MODE_A;
12556 if (operationParam->variant & WIFI_80211_VARIANT_B)
12557 set_mode |= WIFI_MODE_B;
12558 if (operationParam->variant & WIFI_80211_VARIANT_G)
12559 set_mode |= WIFI_MODE_G;
12560 if (operationParam->variant & WIFI_80211_VARIANT_N)
12561 set_mode |= WIFI_MODE_N;
12562 if (operationParam->variant & WIFI_80211_VARIANT_AC)
12563 set_mode |= WIFI_MODE_AC;
12564 if (operationParam->variant & WIFI_80211_VARIANT_AX)
12565 set_mode |= WIFI_MODE_AX;
developer7c4cd202023-03-01 10:56:29 +080012566 if (operationParam->variant & WIFI_80211_VARIANT_BE)
12567 set_mode |= WIFI_MODE_BE;
developer1e5aa162022-09-13 16:06:24 +080012568 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
12569 memset(buf, 0, sizeof(buf));
12570 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
12571 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
12572 return RETURN_ERR;
12573 }
12574 }
12575 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
12576 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
12577 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
12578 return RETURN_ERR;
12579 }
12580 }
12581 if (current_param.beaconInterval != operationParam->beaconInterval) {
12582 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
12583 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
12584 return RETURN_ERR;
12585 }
12586 }
12587 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
12588 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
12589 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12590 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
12591 return RETURN_ERR;
12592 }
12593 }
12594 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
12595 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
12596 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
12597 return RETURN_ERR;
12598 }
12599 }
12600 if (current_param.guardInterval != operationParam->guardInterval) {
12601 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
12602 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
12603 return RETURN_ERR;
12604 }
12605 }
12606 if (current_param.transmitPower != operationParam->transmitPower) {
12607 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
12608 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
12609 return RETURN_ERR;
12610 }
12611 }
12612 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
12613 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
12614 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
12615 return RETURN_ERR;
12616 }
12617 }
12618 if (current_param.obssCoex != operationParam->obssCoex) {
12619 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
12620 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
12621 return RETURN_ERR;
12622 }
12623 }
12624 if (current_param.stbcEnable != operationParam->stbcEnable) {
12625 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
12626 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
12627 return RETURN_ERR;
12628 }
12629 }
developer5735d092023-09-19 20:12:26 +080012630 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
12631 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
12632 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
12633 return RETURN_ERR;
12634 }
12635 }
developer1e5aa162022-09-13 16:06:24 +080012636
12637 // if enable is true, then restart the radio
12638 wifi_setRadioEnable(index, FALSE);
12639 if (operationParam->enable == TRUE)
12640 wifi_setRadioEnable(index, TRUE);
12641 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12642
developer06a01d92022-09-07 16:32:39 +080012643 return RETURN_OK;
12644}
12645
12646INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
12647{
developer1e5aa162022-09-13 16:06:24 +080012648 char band[64] = {0};
12649 char buf[256] = {0};
12650 char config_file[64] = {0};
12651 char cmd[128] = {0};
12652 int ret = RETURN_ERR;
12653 int mode = 0;
12654 ULONG channel = 0;
12655 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080012656
12657 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12658 printf("Entering %s index = %d\n", __func__, (int)index);
12659
developer1e5aa162022-09-13 16:06:24 +080012660 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
12661 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
12662 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012663 {
developer1e5aa162022-09-13 16:06:24 +080012664 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012665 return RETURN_ERR;
12666 }
12667 operationParam->enable = enabled;
12668
12669 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080012670 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012671 {
developer1e5aa162022-09-13 16:06:24 +080012672 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012673 return RETURN_ERR;
12674 }
12675
12676 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080012677 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080012678 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080012679 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080012680 else if (!strcmp(band, "6GHz"))
12681 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080012682 else
12683 {
developer1e5aa162022-09-13 16:06:24 +080012684 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080012685 band);
12686 }
12687
developer1e5aa162022-09-13 16:06:24 +080012688 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
12689 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
12690 operationParam->channel = 0;
12691 operationParam->autoChannelEnabled = TRUE;
12692 } else {
12693 operationParam->channel = strtol(buf, NULL, 10);
12694 operationParam->autoChannelEnabled = FALSE;
12695 }
12696
developer06a01d92022-09-07 16:32:39 +080012697 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080012698 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
12699 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
12700 return RETURN_ERR;
12701 }
developer06a01d92022-09-07 16:32:39 +080012702 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
12703 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
12704 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer87d5a782022-10-07 13:23:27 +080012705 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
developer7c4cd202023-03-01 10:56:29 +080012706 else if (!strcmp(buf, "320-1MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_320_1MHZ;
12707 else if (!strcmp(buf, "320-2MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_320_2MHZ;
developer06a01d92022-09-07 16:32:39 +080012708 else
12709 {
developer1e5aa162022-09-13 16:06:24 +080012710 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
12711 return false;
developer06a01d92022-09-07 16:32:39 +080012712 }
12713
developer7c4cd202023-03-01 10:56:29 +080012714 if (operationParam->band == WIFI_FREQUENCY_6_BAND) {
12715 if (wifi_getRadioOpclass(index, &operationParam->op_class) != RETURN_OK) {
12716 fprintf(stderr, "%s: op_class is not set.\n", __func__);
12717 return RETURN_ERR;
12718 }
12719 }
12720
developer1e5aa162022-09-13 16:06:24 +080012721 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
12722 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
12723 return RETURN_ERR;
12724 }
12725 // Two different definition bit map, so need to check every bit.
12726 if (mode & WIFI_MODE_A)
12727 operationParam->variant |= WIFI_80211_VARIANT_A;
12728 if (mode & WIFI_MODE_B)
12729 operationParam->variant |= WIFI_80211_VARIANT_B;
12730 if (mode & WIFI_MODE_G)
12731 operationParam->variant |= WIFI_80211_VARIANT_G;
12732 if (mode & WIFI_MODE_N)
12733 operationParam->variant |= WIFI_80211_VARIANT_N;
12734 if (mode & WIFI_MODE_AC)
12735 operationParam->variant |= WIFI_80211_VARIANT_AC;
12736 if (mode & WIFI_MODE_AX)
12737 operationParam->variant |= WIFI_80211_VARIANT_AX;
developer7c4cd202023-03-01 10:56:29 +080012738 if (mode & WIFI_MODE_BE)
12739 operationParam->variant |= WIFI_80211_VARIANT_BE;
developer1e5aa162022-09-13 16:06:24 +080012740 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
12741 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
12742 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012743 }
developer1e5aa162022-09-13 16:06:24 +080012744 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
12745 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
12746 return RETURN_ERR;
12747 }
12748 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
12749 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
12750 return RETURN_ERR;
12751 }
developer06a01d92022-09-07 16:32:39 +080012752
developer1e5aa162022-09-13 16:06:24 +080012753 memset(buf, 0, sizeof(buf));
12754 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
12755 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
12756 return RETURN_ERR;
12757 }
12758 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
12759
12760 memset(buf, 0, sizeof(buf));
12761 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12762 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
12763 return RETURN_ERR;
12764 }
12765 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
12766
12767 memset(buf, 0, sizeof(buf));
12768 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
12769 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
12770
12771 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
12772 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
12773 return RETURN_ERR;
12774 }
12775 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
12776 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
12777 return RETURN_ERR;
12778 }
12779
12780 memset(buf, 0, sizeof(buf));
12781 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
12782 if (strcmp(buf, "-1") == 0) {
12783 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
12784 operationParam->ctsProtection = FALSE;
12785 } else {
12786 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
12787 operationParam->ctsProtection = TRUE;
12788 }
12789
12790 memset(buf, 0, sizeof(buf));
12791 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
12792 if (strcmp(buf, "0") == 0)
12793 operationParam->obssCoex = FALSE;
12794 else
12795 operationParam->obssCoex = TRUE;
12796
12797 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
12798 _syscmd(cmd, buf, sizeof(buf));
12799 if (strlen(buf) != 0)
12800 operationParam->stbcEnable = TRUE;
12801 else
12802 operationParam->stbcEnable = FALSE;
12803
developer5735d092023-09-19 20:12:26 +080012804 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
12805 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
12806 return RETURN_ERR;
12807 }
developer1e5aa162022-09-13 16:06:24 +080012808
12809 // Below value is hardcoded
12810
12811 operationParam->numSecondaryChannels = 0;
12812 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
12813 operationParam->channelSecondary[i] = 0;
12814 }
12815 operationParam->csa_beacon_count = 15;
12816 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080012817
12818 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12819 return RETURN_OK;
12820}
12821
12822static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
12823{
developerc086fb72022-10-04 10:18:22 +080012824 int max_radio_num = 0;
12825
12826 wifi_getMaxRadioNumber(&max_radio_num);
developer30423732022-12-01 16:17:49 +080012827 if (radioIndex >= max_radio_num) {
developerc086fb72022-10-04 10:18:22 +080012828 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
12829 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012830 }
12831
developerc086fb72022-10-04 10:18:22 +080012832 return (arrayIndex * max_radio_num) + radioIndex;
12833}
developer06a01d92022-09-07 16:32:39 +080012834
developerc086fb72022-10-04 10:18:22 +080012835wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
12836 if (strncmp(beaconRate, "1Mbps", 5) == 0)
12837 return WIFI_BITRATE_1MBPS;
12838 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
12839 return WIFI_BITRATE_2MBPS;
12840 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
12841 return WIFI_BITRATE_5_5MBPS;
12842 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
12843 return WIFI_BITRATE_6MBPS;
12844 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
12845 return WIFI_BITRATE_9MBPS;
12846 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
12847 return WIFI_BITRATE_11MBPS;
12848 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
12849 return WIFI_BITRATE_12MBPS;
12850 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
12851 return WIFI_BITRATE_18MBPS;
12852 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
12853 return WIFI_BITRATE_24MBPS;
12854 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
12855 return WIFI_BITRATE_36MBPS;
12856 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
12857 return WIFI_BITRATE_48MBPS;
12858 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
12859 return WIFI_BITRATE_54MBPS;
12860 return WIFI_BITRATE_DEFAULT;
developer06a01d92022-09-07 16:32:39 +080012861}
12862
developer1d57d002022-10-12 18:03:15 +080012863INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
12864{
12865 if (beacon == WIFI_BITRATE_1MBPS)
12866 strcpy(beacon_str, "1Mbps");
12867 else if (beacon == WIFI_BITRATE_2MBPS)
12868 strcpy(beacon_str, "2Mbps");
12869 else if (beacon == WIFI_BITRATE_5_5MBPS)
12870 strcpy(beacon_str, "5.5Mbps");
12871 else if (beacon == WIFI_BITRATE_6MBPS)
12872 strcpy(beacon_str, "6Mbps");
12873 else if (beacon == WIFI_BITRATE_9MBPS)
12874 strcpy(beacon_str, "9Mbps");
12875 else if (beacon == WIFI_BITRATE_11MBPS)
12876 strcpy(beacon_str, "11Mbps");
12877 else if (beacon == WIFI_BITRATE_12MBPS)
12878 strcpy(beacon_str, "12Mbps");
12879 else if (beacon == WIFI_BITRATE_18MBPS)
12880 strcpy(beacon_str, "18Mbps");
12881 else if (beacon == WIFI_BITRATE_24MBPS)
12882 strcpy(beacon_str, "24Mbps");
12883 else if (beacon == WIFI_BITRATE_36MBPS)
12884 strcpy(beacon_str, "36Mbps");
12885 else if (beacon == WIFI_BITRATE_48MBPS)
12886 strcpy(beacon_str, "48Mbps");
12887 else if (beacon == WIFI_BITRATE_54MBPS)
12888 strcpy(beacon_str, "54Mbps");
12889 return RETURN_OK;
12890}
12891
developer74ed4192023-09-21 17:15:17 +080012892void checkVapStatus(int apIndex, bool *enable)
12893{
12894 char if_name[16] = {0};
12895 char cmd[128] = {0};
12896 char buf[128] = {0};
12897
12898 *enable = FALSE;
12899 if (wifi_GetInterfaceName(apIndex, if_name) != RETURN_OK)
12900 return;
12901
12902 snprintf(cmd, sizeof(cmd), "cat %s | grep ^%s=1", VAP_STATUS_FILE, if_name);
12903 _syscmd(cmd, buf, sizeof(buf));
12904 if (strlen(buf) > 0)
12905 *enable = TRUE;
12906 return;
12907}
12908
developerefb790a2023-12-26 18:58:32 +080012909INT wifi_getVapInfoMisc(int vap_index)
12910{
12911 char config_file[MAX_BUF_SIZE] = {0};
12912
12913 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX,vap_index);
12914 wifi_hostapdRead(config_file,"ssid",vap_info[vap_index].ssid, MAX_BUF_SIZE);
12915 wifi_hostapdRead(config_file,"wpa", vap_info[vap_index].wpa, MAX_BUF_SIZE);
12916 wifi_hostapdRead(config_file,"wpa_key_mgmt", vap_info[vap_index].wpa_key_mgmt, MAX_BUF_SIZE);
12917 wifi_hostapdRead(config_file,"wpa_passphrase", vap_info[vap_index].wpa_passphrase, MAX_BUF_SIZE);
12918 wifi_hostapdRead(config_file,"ap_isolate", vap_info[vap_index].ap_isolate, MAX_BUF_SIZE);
12919 wifi_hostapdRead(config_file,"macaddr_acl", vap_info[vap_index].macaddr_acl, MAX_BUF_SIZE);
12920 wifi_hostapdRead(config_file,"bss_transition", vap_info[vap_index].bss_transition, MAX_BUF_SIZE);
12921 wifi_hostapdRead(config_file,"ignore_broadcast_ssid", vap_info[vap_index].ignore_broadcast_ssid, MAX_BUF_SIZE);
12922 wifi_hostapdRead(config_file, "max_num_sta", vap_info[vap_index].max_sta, MAX_BUF_SIZE);
12923 return RETURN_OK;
12924}
12925
12926int wifi_Syncthread(void *arg)
12927{
12928 int radio_idx = 0, i = 0;
12929 int vap_index = 0;
developera2af46a2024-01-04 19:11:23 +080012930 int max_radio = 0;
developerefb790a2023-12-26 18:58:32 +080012931
developera2af46a2024-01-04 19:11:23 +080012932 wifi_getMaxRadioNumber(&max_radio);
developerefb790a2023-12-26 18:58:32 +080012933 while (1)
12934 {
12935 sleep(5);
developera2af46a2024-01-04 19:11:23 +080012936 for (radio_idx = 0; radio_idx < max_radio; radio_idx++)
developerefb790a2023-12-26 18:58:32 +080012937 {
12938 for (i = 0; i < MAX_NUM_VAP_PER_RADIO; i++)
12939 {
12940 vap_index = array_index_to_vap_index(radio_idx, i);
12941 if (vap_index >= 0)
12942 wifi_getVapInfoMisc(vap_index);
12943 }
12944 }
12945 syn_flag = 1;
12946 }
12947 return 0;
12948}
12949
developer06a01d92022-09-07 16:32:39 +080012950INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12951{
developerc086fb72022-10-04 10:18:22 +080012952 INT mode = 0;
12953 INT ret = -1;
12954 INT output = 0;
12955 int i = 0;
12956 int vap_index = 0;
12957 BOOL enabled = FALSE;
12958 char buf[256] = {0};
developer30423732022-12-01 16:17:49 +080012959 wifi_vap_security_t security = {0};
developera77d84b2023-02-22 16:10:50 +080012960
developer06a01d92022-09-07 16:32:39 +080012961
12962 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12963 printf("Entering %s index = %d\n", __func__, (int)index);
12964
developera77d84b2023-02-22 16:10:50 +080012965 for (i = 0; i < MAX_NUM_VAP_PER_RADIO; i++)
developer06a01d92022-09-07 16:32:39 +080012966 {
developerc086fb72022-10-04 10:18:22 +080012967 map->vap_array[i].radio_index = index;
12968
developer06a01d92022-09-07 16:32:39 +080012969 vap_index = array_index_to_vap_index(index, i);
12970 if (vap_index < 0)
developer06a01d92022-09-07 16:32:39 +080012971 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012972
developerc086fb72022-10-04 10:18:22 +080012973 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
developer06a01d92022-09-07 16:32:39 +080012974
12975 map->vap_array[i].vap_index = vap_index;
12976
12977 memset(buf, 0, sizeof(buf));
developerc086fb72022-10-04 10:18:22 +080012978 ret = wifi_getApName(vap_index, buf);
12979 if (ret != RETURN_OK) {
developera77d84b2023-02-22 16:10:50 +080012980 printf("%s: wifi_getApName return error. vap_index=%d\n", __func__, vap_index);
12981
developerc086fb72022-10-04 10:18:22 +080012982 return RETURN_ERR;
12983 }
12984 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
12985
12986 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012987 ret = wifi_getSSIDName(vap_index, buf);
developerc086fb72022-10-04 10:18:22 +080012988 if (ret != RETURN_OK) {
developer1d57d002022-10-12 18:03:15 +080012989 printf("%s: wifi_getSSIDName return error\n", __func__);
developerc086fb72022-10-04 10:18:22 +080012990 return RETURN_ERR;
12991 }
12992 snprintf(map->vap_array[i].u.bss_info.ssid, sizeof(map->vap_array[i].u.bss_info.ssid), "%s", buf);
developer06a01d92022-09-07 16:32:39 +080012993
developer74ed4192023-09-21 17:15:17 +080012994 checkVapStatus(vap_index, &enabled);
developer06a01d92022-09-07 16:32:39 +080012995 map->vap_array[i].u.bss_info.enabled = enabled;
12996
developerc086fb72022-10-04 10:18:22 +080012997 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
12998 if (ret != RETURN_OK) {
12999 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
13000 return RETURN_ERR;
13001 }
developer06a01d92022-09-07 16:32:39 +080013002 map->vap_array[i].u.bss_info.showSsid = enabled;
developerc086fb72022-10-04 10:18:22 +080013003
13004 ret = wifi_getApIsolationEnable(vap_index, &enabled);
13005 if (ret != RETURN_OK) {
13006 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
13007 return RETURN_ERR;
13008 }
13009 map->vap_array[i].u.bss_info.isolation = enabled;
13010
13011 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
13012 if (ret != RETURN_OK) {
13013 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
13014 return RETURN_ERR;
13015 }
13016 map->vap_array[i].u.bss_info.bssMaxSta = output;
13017
13018 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
13019 if (ret != RETURN_OK) {
13020 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
13021 return RETURN_ERR;
13022 }
13023 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080013024
developerc086fb72022-10-04 10:18:22 +080013025 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
13026 if (ret != RETURN_OK) {
13027 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
13028 return RETURN_ERR;
13029 }
13030 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080013031
developerc086fb72022-10-04 10:18:22 +080013032 ret = wifi_getApSecurity(vap_index, &security);
13033 if (ret != RETURN_OK) {
13034 printf("%s: wifi_getApSecurity return error\n", __func__);
13035 return RETURN_ERR;
13036 }
13037 map->vap_array[i].u.bss_info.security = security;
developer06a01d92022-09-07 16:32:39 +080013038
developerc086fb72022-10-04 10:18:22 +080013039 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
13040 if (ret != RETURN_OK) {
13041 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
13042 return RETURN_ERR;
13043 }
13044 if (mode == 0)
13045 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
13046 else
13047 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
13048 if (mode == 1)
13049 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
13050 else if (mode == 2)
13051 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
developer06a01d92022-09-07 16:32:39 +080013052
developerc086fb72022-10-04 10:18:22 +080013053 ret = wifi_getApWmmEnable(vap_index, &enabled);
13054 if (ret != RETURN_OK) {
13055 printf("%s: wifi_getApWmmEnable return error\n", __func__);
13056 return RETURN_ERR;
13057 }
13058 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
developer06a01d92022-09-07 16:32:39 +080013059
developerc086fb72022-10-04 10:18:22 +080013060 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
13061 if (ret != RETURN_OK) {
13062 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080013063 return RETURN_ERR;
13064 }
developerc086fb72022-10-04 10:18:22 +080013065 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
developer06a01d92022-09-07 16:32:39 +080013066
13067 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080013068 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
developerc086fb72022-10-04 10:18:22 +080013069 if (ret != RETURN_OK) {
13070 printf("%s: wifi_getApBeaconRate return error\n", __func__);
13071 return RETURN_ERR;
13072 }
13073 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
developer06a01d92022-09-07 16:32:39 +080013074
developerc086fb72022-10-04 10:18:22 +080013075 memset(buf, 0, sizeof(buf));
13076 ret = wifi_getBaseBSSID(vap_index, buf);
13077 if (ret != RETURN_OK) {
13078 printf("%s: wifi_getBaseBSSID return error\n", __func__);
13079 return RETURN_ERR;
13080 }
13081 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
13082 &map->vap_array[i].u.bss_info.bssid[0],
13083 &map->vap_array[i].u.bss_info.bssid[1],
13084 &map->vap_array[i].u.bss_info.bssid[2],
13085 &map->vap_array[i].u.bss_info.bssid[3],
13086 &map->vap_array[i].u.bss_info.bssid[4],
13087 &map->vap_array[i].u.bss_info.bssid[5]);
developer1d57d002022-10-12 18:03:15 +080013088 // fprintf(stderr, "%s index %d: mac: %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n", __func__, vap_index, map->vap_array[i].u.bss_info.bssid[0], map->vap_array[i].u.bss_info.bssid[1], map->vap_array[i].u.bss_info.bssid[2], map->vap_array[i].u.bss_info.bssid[3], map->vap_array[i].u.bss_info.bssid[4], map->vap_array[i].u.bss_info.bssid[5]);
13089
13090 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
13091 if (ret != RETURN_OK) {
13092 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
13093 return RETURN_ERR;
13094 }
13095 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
developer613892e2023-09-21 16:33:35 +080013096
13097 ret = wifi_getApWpsEnable(vap_index, &enabled);
13098 if (ret != RETURN_OK) {
13099 fprintf(stderr, "%s: wifi_getApWpsEnable\n", __func__);
13100 return RETURN_ERR;
13101 }
13102
13103 map->vap_array[i].u.bss_info.wps.enable = enabled;
13104
developera77d84b2023-02-22 16:10:50 +080013105 map->num_vaps++;
developerc086fb72022-10-04 10:18:22 +080013106 // TODO: wps, noack
developer06a01d92022-09-07 16:32:39 +080013107 }
developerefb790a2023-12-26 18:58:32 +080013108
13109 if (!tflag) {
13110 result = pthread_create(&pthread_id, NULL, wifi_Syncthread,NULL);
13111 if (result != 0)
13112 printf("%s %d fail create sync thread\n", __func__, __LINE__);
13113 else
13114 tflag = 1;
13115 }
13116
developer06a01d92022-09-07 16:32:39 +080013117 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13118 return RETURN_OK;
13119}
13120
developer431128d2022-12-16 15:30:41 +080013121
developerd946fd62022-12-08 18:03:28 +080013122static int prepareInterface(UINT apIndex, char *new_interface)
13123{
13124 char cur_interface[16] = {0};
13125 char config_file[128] = {0};
13126 char cmd[128] = {0};
13127 char buf[16] = {0};
13128 int max_radio_num = 0;
13129 int radioIndex = -1;
13130 int phyIndex = -1;
13131
13132 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
13133 wifi_hostapdRead(config_file, "interface", cur_interface, sizeof(cur_interface));
13134
13135 if (strncmp(cur_interface, new_interface, sizeof(cur_interface)) != 0) {
13136 wifi_getMaxRadioNumber(&max_radio_num);
13137 radioIndex = apIndex % max_radio_num;
13138 phyIndex = radio_index_to_phy(radioIndex);
13139 // disable and del old interface, then add new interface
13140 wifi_setApEnable(apIndex, FALSE);
developer2f18b9f2023-03-17 19:32:57 +080013141 if (!(apIndex/max_radio_num)) {
13142 snprintf(cmd, sizeof(cmd), "iw %s del && iw phy%d interface add %s type __ap", cur_interface, phyIndex, new_interface);
13143 _syscmd(cmd, buf, sizeof(buf));
13144 }
developerd946fd62022-12-08 18:03:28 +080013145 }
developer431128d2022-12-16 15:30:41 +080013146 // update the vap status file
13147 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=1' %s", cur_interface, new_interface, VAP_STATUS_FILE);
13148 _syscmd(cmd, buf, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +080013149 return RETURN_OK;
13150}
13151
developer06a01d92022-09-07 16:32:39 +080013152INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
13153{
developerd946fd62022-12-08 18:03:28 +080013154 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080013155 unsigned int i;
13156 wifi_vap_info_t *vap_info = NULL;
13157 int acl_mode;
developer1d57d002022-10-12 18:03:15 +080013158 int ret = 0;
developer06a01d92022-09-07 16:32:39 +080013159 char *sec_str = NULL;
developer1d57d002022-10-12 18:03:15 +080013160 char buf[256] = {0};
13161 char cmd[128] = {0};
13162 char config_file[64] = {0};
13163 char bssid[32] = {0};
13164 char psk_file[64] = {0};
developer431128d2022-12-16 15:30:41 +080013165 bool enable = FALSE;
developer06a01d92022-09-07 16:32:39 +080013166
13167 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13168 printf("Entering %s index = %d\n", __func__, (int)index);
13169 for (i = 0; i < map->num_vaps; i++)
13170 {
developer1d57d002022-10-12 18:03:15 +080013171 multiple_set = TRUE;
developer06a01d92022-09-07 16:32:39 +080013172 vap_info = &map->vap_array[i];
developer431128d2022-12-16 15:30:41 +080013173
13174 // Check vap status file to enable multiple ap if the system boot.
13175 checkVapStatus(vap_info->vap_index, &enable);
13176 if (vap_info->u.bss_info.enabled == FALSE && enable == FALSE)
developer1d57d002022-10-12 18:03:15 +080013177 continue;
developer06a01d92022-09-07 16:32:39 +080013178
developer1d57d002022-10-12 18:03:15 +080013179 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
13180
developer431128d2022-12-16 15:30:41 +080013181 if (wifi_getApEnable(vap_info->vap_index, &enable) != RETURN_OK)
13182 enable = FALSE;
13183
13184 // multi-ap first up need to copy current radio config
13185 if (vap_info->radio_index != vap_info->vap_index && enable == FALSE) {
developer1d57d002022-10-12 18:03:15 +080013186 snprintf(cmd, sizeof(cmd), "cp %s%d.conf %s%d.conf", CONFIG_PREFIX, vap_info->radio_index, CONFIG_PREFIX, vap_info->vap_index);
13187 _syscmd(cmd, buf, sizeof(buf));
developer431128d2022-12-16 15:30:41 +080013188 if (strlen(vap_info->vap_name) == 0) // default name of the interface is wifiX
13189 snprintf(vap_info->vap_name, 16, "wifi%d", vap_info->vap_index);
13190 } else {
13191 // Check whether the interface name is valid or this ap change it.
13192 int apIndex = -1;
13193 wifi_getApIndexFromName(vap_info->vap_name, &apIndex);
13194 if (apIndex != -1 && apIndex != vap_info->vap_index)
13195 continue;
13196 prepareInterface(vap_info->vap_index, vap_info->vap_name);
developer06a01d92022-09-07 16:32:39 +080013197 }
developer06a01d92022-09-07 16:32:39 +080013198
developer1d57d002022-10-12 18:03:15 +080013199 struct params params[3];
developer1d57d002022-10-12 18:03:15 +080013200 params[0].name = "interface";
13201 params[0].value = vap_info->vap_name;
13202 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
13203 params[1].name = "bssid";
13204 params[1].value = bssid;
developer431128d2022-12-16 15:30:41 +080013205 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", vap_info->vap_index);
developer1d57d002022-10-12 18:03:15 +080013206 params[2].name = "wpa_psk_file";
13207 params[2].value = psk_file;
13208
13209 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
13210 wifi_hostapdWrite(config_file, params, 3);
13211
13212 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
13213 _syscmd(cmd, buf, sizeof(buf));
13214
13215 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
13216 if (ret != RETURN_OK) {
13217 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
13218 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080013219 }
developer1d57d002022-10-12 18:03:15 +080013220
13221 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
13222 if (ret != RETURN_OK) {
13223 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
13224 return RETURN_ERR;
13225 }
13226
13227 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
13228 if (ret != RETURN_OK) {
13229 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
13230 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080013231 }
13232
developer1d57d002022-10-12 18:03:15 +080013233 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
13234 if (ret != RETURN_OK) {
13235 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
13236 return RETURN_ERR;
13237 }
developer06a01d92022-09-07 16:32:39 +080013238
developer1d57d002022-10-12 18:03:15 +080013239 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
13240 if (ret != RETURN_OK) {
13241 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
13242 return RETURN_ERR;
13243 }
developer06a01d92022-09-07 16:32:39 +080013244
developer1d57d002022-10-12 18:03:15 +080013245 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
13246 if (ret != RETURN_OK) {
13247 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
13248 return RETURN_ERR;
13249 }
13250
developer804c64f2022-10-19 13:54:40 +080013251 if (vap_info->u.bss_info.mac_filter_enable == false){
developer1d57d002022-10-12 18:03:15 +080013252 acl_mode = 0;
developer804c64f2022-10-19 13:54:40 +080013253 }else {
13254 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
developer1d57d002022-10-12 18:03:15 +080013255 acl_mode = 2;
developer804c64f2022-10-19 13:54:40 +080013256 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
13257 _syscmd(cmd, buf, sizeof(buf));
13258 }else{
developer1d57d002022-10-12 18:03:15 +080013259 acl_mode = 1;
developer804c64f2022-10-19 13:54:40 +080013260 }
developer1d57d002022-10-12 18:03:15 +080013261 }
13262
13263 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
13264 if (ret != RETURN_OK) {
13265 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
13266 return RETURN_ERR;
13267 }
13268
13269 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
13270 if (ret != RETURN_OK) {
13271 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
13272 return RETURN_ERR;
13273 }
13274
13275 memset(buf, 0, sizeof(buf));
13276 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
13277 // fprintf(stderr, "%s: beaconrate: %d, buf: %s\n", __func__, vap_info->u.bss_info.beaconRate, buf);
13278 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
13279 if (ret != RETURN_OK) {
13280 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
13281 return RETURN_ERR;
13282 }
13283
developer1d57d002022-10-12 18:03:15 +080013284 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
13285 if (ret != RETURN_OK) {
13286 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
13287 return RETURN_ERR;
13288 }
13289
13290 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
13291 if (ret != RETURN_OK) {
13292 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
13293 return RETURN_ERR;
13294 }
developer06a01d92022-09-07 16:32:39 +080013295
developer894affa2023-05-10 18:13:19 +080013296 ret = wifi_setApWpsEnable(vap_info->vap_index, vap_info->u.bss_info.wps.enable);
13297 if (ret != RETURN_OK) {
13298 fprintf(stderr, "%s: wifi_setApWpsEnable return error\n", __func__);
13299 return RETURN_ERR;
13300 }
13301
developer2f995fb2023-02-24 10:40:44 +080013302 wifi_setApEnable(vap_info->vap_index, FALSE);
developer74ed4192023-09-21 17:15:17 +080013303 if (vap_info->u.bss_info.enabled == TRUE)
13304 wifi_setApEnable(vap_info->vap_index, TRUE);
13305
developer2f995fb2023-02-24 10:40:44 +080013306 multiple_set = FALSE;
13307
13308 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
developer900e2b72023-05-23 10:23:48 +080013309 if (vap_info->u.bss_info.wps.enable && vap_info->u.bss_info.wps.methods && WIFI_ONBOARDINGMETHODS_PUSHBUTTON) {
developer894affa2023-05-10 18:13:19 +080013310 // The set wps methods function should check whether wps is configured.
13311 ret = wifi_setApWpsButtonPush(vap_info->vap_index);
13312 if (ret != RETURN_OK) {
13313 fprintf(stderr, "%s: wifi_setApWpsButtonPush return error\n", __func__);
13314 return RETURN_ERR;
13315 }
13316 // wifi_setApWpsConfigMethodsEnabled only write to config.
13317 ret = wifi_setApWpsConfigMethodsEnabled(vap_info->vap_index, "PushButton");
13318 if (ret != RETURN_OK) {
13319 fprintf(stderr, "%s: wifi_setApWpsConfigMethodsEnabled return error\n", __func__);
13320 return RETURN_ERR;
13321 }
13322 }
developer2f995fb2023-02-24 10:40:44 +080013323
developer894affa2023-05-10 18:13:19 +080013324 // TODO mgmtPowerControl, interworking
developer06a01d92022-09-07 16:32:39 +080013325 }
developerfb09ba62023-06-09 17:03:21 +080013326
13327 // IGMP Snooping enable should be placed after all hostapd_reload.
13328 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
13329 if (ret != RETURN_OK) {
13330 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable return error\n", __func__);
13331 return RETURN_ERR;
13332 }
13333
developer06a01d92022-09-07 16:32:39 +080013334 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13335 return RETURN_OK;
13336}
13337
13338int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
13339{
13340 char *token, *next;
13341 const char s[2] = ",";
13342 int count =0;
13343
13344 /* get the first token */
13345 token = strtok_r(pchannels, s, &next);
13346
13347 /* walk through other tokens */
13348 while( token != NULL && count < MAX_CHANNELS) {
13349 chlistptr->channels_list[count++] = atoi(token);
13350 token = strtok_r(NULL, s, &next);
13351 }
13352
13353 return count;
13354}
13355
13356static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
13357{
13358 INT status;
13359 wifi_channels_list_t *chlistp;
13360 CHAR output_string[64];
13361 CHAR pchannels[128];
developer7930d352022-12-21 17:55:42 +080013362 CHAR interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +080013363 wifi_band band;
developer06a01d92022-09-07 16:32:39 +080013364
13365 if(rcap == NULL)
13366 {
13367 return RETURN_ERR;
13368 }
13369
13370 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080013371 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080013372
developer1e5aa162022-09-13 16:06:24 +080013373 if (band == band_2_4)
13374 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
13375 else if (band == band_5)
13376 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
13377 else if (band == band_6)
13378 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080013379
13380 chlistp = &(rcap->channel_list[0]);
13381 memset(pchannels, 0, sizeof(pchannels));
13382
13383 /* possible number of radio channels */
13384 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
13385 {
13386 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
13387 }
13388 /* Number of channels and list*/
13389 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
13390
13391 /* autoChannelSupported */
13392 /* always ON with wifi_getRadioAutoChannelSupported */
13393 rcap->autoChannelSupported = TRUE;
13394
13395 /* DCSSupported */
13396 /* always ON with wifi_getRadioDCSSupported */
13397 rcap->DCSSupported = TRUE;
13398
13399 /* zeroDFSSupported - TBD */
13400 rcap->zeroDFSSupported = FALSE;
13401
13402 /* Supported Country List*/
13403 memset(output_string, 0, sizeof(output_string));
13404 status = wifi_getRadioCountryCode(radioIndex, output_string);
13405 if( status != 0 ) {
13406 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
13407 return RETURN_ERR;
13408 } else {
13409 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
13410 }
13411 if(!strcmp(output_string,"US")){
13412 rcap->countrySupported[0] = wifi_countrycode_US;
13413 rcap->countrySupported[1] = wifi_countrycode_CA;
13414 } else if (!strcmp(output_string,"CA")) {
13415 rcap->countrySupported[0] = wifi_countrycode_CA;
13416 rcap->countrySupported[1] = wifi_countrycode_US;
13417 } else {
13418 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
13419 }
13420
13421 rcap->numcountrySupported = 2;
13422
13423 /* csi */
13424 rcap->csi.maxDevices = 8;
13425 rcap->csi.soudingFrameSupported = TRUE;
13426
developer7930d352022-12-21 17:55:42 +080013427 wifi_GetInterfaceName(radioIndex, interface_name);
13428 snprintf(rcap->ifaceName, sizeof(interface_name), "%s",interface_name);
developer06a01d92022-09-07 16:32:39 +080013429
13430 /* channelWidth - all supported bandwidths */
13431 int i=0;
13432 rcap->channelWidth[i] = 0;
developer7c4cd202023-03-01 10:56:29 +080013433
13434 /* mode - all supported variants */
13435 // rcap->mode[i] = WIFI_80211_VARIANT_H;
13436 wifi_getRadioSupportedStandards(radioIndex, output_string);
13437
developer06a01d92022-09-07 16:32:39 +080013438 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
13439 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13440 WIFI_CHANNELBANDWIDTH_40MHZ);
developer7c4cd202023-03-01 10:56:29 +080013441 rcap->mode[i] = ( WIFI_80211_VARIANT_B | WIFI_80211_VARIANT_G);
developer06a01d92022-09-07 16:32:39 +080013442
developer7c4cd202023-03-01 10:56:29 +080013443 if (strstr(output_string, "n") != NULL)
13444 rcap->mode[i] |= WIFI_80211_VARIANT_N;
13445 if (strstr(output_string, "ax") != NULL)
13446 rcap->mode[i] |= WIFI_80211_VARIANT_AX;
13447 if (strstr(output_string, "be") != NULL)
13448 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13449 } else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND) {
developer06a01d92022-09-07 16:32:39 +080013450 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13451 WIFI_CHANNELBANDWIDTH_40MHZ |
13452 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
developer7c4cd202023-03-01 10:56:29 +080013453 rcap->mode[i] = ( WIFI_80211_VARIANT_A);
developer06a01d92022-09-07 16:32:39 +080013454
developer7c4cd202023-03-01 10:56:29 +080013455 if (strstr(output_string, "n") != NULL)
13456 rcap->mode[i] |= WIFI_80211_VARIANT_N;
13457 if (strstr(output_string, "ac") != NULL)
13458 rcap->mode[i] |= WIFI_80211_VARIANT_AC;
13459 if (strstr(output_string, "ax") != NULL)
13460 rcap->mode[i] |= WIFI_80211_VARIANT_AX;
13461 if (strstr(output_string, "be") != NULL)
13462 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13463 } else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
13464 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13465 WIFI_CHANNELBANDWIDTH_40MHZ |
13466 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
developer1e5aa162022-09-13 16:06:24 +080013467 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer7c4cd202023-03-01 10:56:29 +080013468
13469 if (strstr(output_string, "be") != NULL) {
13470 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13471 rcap->channelWidth[i] |= WIFI_CHANNELBANDWIDTH_320_1MHZ | WIFI_CHANNELBANDWIDTH_320_2MHZ;
13472 }
developer06a01d92022-09-07 16:32:39 +080013473 }
developer7c4cd202023-03-01 10:56:29 +080013474
developer06a01d92022-09-07 16:32:39 +080013475 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
13476 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
13477
13478 /* supportedBitRate - all supported bitrates */
13479 rcap->supportedBitRate[i] = 0;
13480 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
13481 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13482 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
13483 }
developer1e5aa162022-09-13 16:06:24 +080013484 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080013485 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13486 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
13487 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
13488 }
13489
13490
13491 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
13492 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
13493 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
13494 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
13495 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
13496 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
13497 rcap->cipherSupported = 0;
13498 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
13499 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
13500
13501 return RETURN_OK;
13502}
13503
13504INT wifi_getHalCapability(wifi_hal_capability_t *cap)
13505{
developer30423732022-12-01 16:17:49 +080013506 INT status = 0, radioIndex = 0;
13507 char cmd[MAX_BUF_SIZE] = {0}, output[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +080013508 int iter = 0;
developer30423732022-12-01 16:17:49 +080013509 unsigned int j = 0;
developer7930d352022-12-21 17:55:42 +080013510 int max_num_radios;
developer30423732022-12-01 16:17:49 +080013511 wifi_interface_name_idex_map_t *iface_info = NULL;
developer06a01d92022-09-07 16:32:39 +080013512
13513 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13514
13515 memset(cap, 0, sizeof(wifi_hal_capability_t));
13516
13517 /* version */
13518 cap->version.major = WIFI_HAL_MAJOR_VERSION;
13519 cap->version.minor = WIFI_HAL_MINOR_VERSION;
13520
13521 /* number of radios platform property */
developer7930d352022-12-21 17:55:42 +080013522 wifi_getMaxRadioNumber(&max_num_radios);
13523 cap->wifi_prop.numRadios = max_num_radios;
developer06a01d92022-09-07 16:32:39 +080013524
13525 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
13526 {
13527 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
13528 if (status != 0) {
13529 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
13530 return RETURN_ERR;
13531 }
13532
13533 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
13534 {
developer804c64f2022-10-19 13:54:40 +080013535 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
developer06a01d92022-09-07 16:32:39 +080013536 {
13537 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
13538 return RETURN_ERR;
13539 }
13540 iface_info = &cap->wifi_prop.interface_map[iter];
13541 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
13542 iface_info->rdk_radio_index = radioIndex;
13543 memset(output, 0, sizeof(output));
13544 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
13545 {
13546 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
13547 }
13548 // TODO: bridge name
13549 // TODO: vlan id
13550 // TODO: primary
13551 iface_info->index = array_index_to_vap_index(radioIndex, j);
13552 memset(output, 0, sizeof(output));
developer7930d352022-12-21 17:55:42 +080013553 if (wifi_getApName(iface_info->index, output) == RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080013554 {
13555 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
13556 }
13557 iter++;
13558 }
13559 }
13560
13561 cap->BandSteeringSupported = FALSE;
13562 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13563 return RETURN_OK;
13564}
13565
developer9df4e652022-10-11 11:27:38 +080013566INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
13567{
13568 struct params h_config={0};
13569 char config_file[64] = {0};
13570
13571 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13572
13573 h_config.name = "okc";
13574 h_config.value = okc_enable?"1":"0";
13575
13576 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13577 wifi_hostapdWrite(config_file, &h_config, 1);
13578 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13579
13580 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13581 return RETURN_OK;
13582}
13583
13584INT wifi_setSAEMFP(int ap_index, BOOL enable)
13585{
13586 struct params h_config={0};
13587 char config_file[64] = {0};
13588 char buf[128] = {0};
13589
13590 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13591
13592 h_config.name = "sae_require_mfp";
13593 h_config.value = enable?"1":"0";
13594
13595 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13596 wifi_hostapdWrite(config_file, &h_config, 1);
13597 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13598
13599 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13600 return RETURN_OK;
13601}
13602
13603INT wifi_setSAEpwe(int ap_index, int sae_pwe)
13604{
13605 struct params h_config={0};
13606 char config_file[64] = {0};
13607 char buf[128] = {0};
13608
13609 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13610
13611 h_config.name = "sae_pwe";
13612 snprintf(buf, sizeof(buf), "%d", sae_pwe);
13613 h_config.value = buf;
13614
13615 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13616 wifi_hostapdWrite(config_file, &h_config, 1);
13617 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13618
13619 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13620 return RETURN_OK;
13621}
13622
13623INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
13624{
13625 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
13626 struct params h_config={0};
13627 char config_file[64] = {0};
13628
13629 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13630
13631 h_config.name = "wpa_disable_eapol_key_retries";
13632 h_config.value = disable_EAPOL_retries?"1":"0";
13633
13634 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13635 wifi_hostapdWrite(config_file, &h_config, 1);
13636 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13637
13638 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13639 return RETURN_OK;
13640}
13641
developer06a01d92022-09-07 16:32:39 +080013642INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
13643{
developer587c1b62022-09-27 15:58:59 +080013644 char buf[128] = {0};
13645 char config_file[128] = {0};
developer4b102122023-02-15 10:53:03 +080013646 char cmd[128] = {0};
developer587c1b62022-09-27 15:58:59 +080013647 char password[64] = {0};
13648 char mfp[32] = {0};
13649 char wpa_mode[32] = {0};
developer9df4e652022-10-11 11:27:38 +080013650 BOOL okc_enable = FALSE;
13651 BOOL sae_MFP = FALSE;
13652 BOOL disable_EAPOL_retries = TRUE;
13653 int sae_pwe = 0;
developer587c1b62022-09-27 15:58:59 +080013654 struct params params = {0};
developer9df4e652022-10-11 11:27:38 +080013655 wifi_band band = band_invalid;
developer587c1b62022-09-27 15:58:59 +080013656
13657 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13658
13659 multiple_set = TRUE;
13660 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13661 if (security->mode == wifi_security_mode_none) {
13662 strcpy(wpa_mode, "None");
13663 } else if (security->mode == wifi_security_mode_wpa_personal)
13664 strcpy(wpa_mode, "WPA-Personal");
13665 else if (security->mode == wifi_security_mode_wpa2_personal)
13666 strcpy(wpa_mode, "WPA2-Personal");
13667 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
13668 strcpy(wpa_mode, "WPA-WPA2-Personal");
13669 else if (security->mode == wifi_security_mode_wpa_enterprise)
13670 strcpy(wpa_mode, "WPA-Enterprise");
13671 else if (security->mode == wifi_security_mode_wpa2_enterprise)
13672 strcpy(wpa_mode, "WPA2-Enterprise");
13673 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
13674 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
developer9df4e652022-10-11 11:27:38 +080013675 else if (security->mode == wifi_security_mode_wpa3_personal) {
developer587c1b62022-09-27 15:58:59 +080013676 strcpy(wpa_mode, "WPA3-Personal");
developer9df4e652022-10-11 11:27:38 +080013677 okc_enable = TRUE;
13678 sae_MFP = TRUE;
13679 sae_pwe = 2;
13680 disable_EAPOL_retries = FALSE;
13681 } else if (security->mode == wifi_security_mode_wpa3_transition) {
developer4a359672022-10-13 15:30:46 +080013682 strcpy(wpa_mode, "WPA3-Personal-Transition");
developer9df4e652022-10-11 11:27:38 +080013683 okc_enable = TRUE;
13684 sae_MFP = TRUE;
13685 sae_pwe = 2;
13686 disable_EAPOL_retries = FALSE;
13687 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
developer587c1b62022-09-27 15:58:59 +080013688 strcpy(wpa_mode, "WPA3-Enterprise");
developer9df4e652022-10-11 11:27:38 +080013689 sae_MFP = TRUE;
13690 sae_pwe = 2;
13691 disable_EAPOL_retries = FALSE;
developerae432c62023-04-24 11:07:20 +080013692 } else if (security->mode == wifi_security_mode_enhanced_open) {
developer5c9fee82023-01-13 14:44:16 +080013693 strcpy(wpa_mode, "OWE");
13694 sae_MFP = TRUE;
13695 sae_pwe = 2;
13696 disable_EAPOL_retries = FALSE;
developer9df4e652022-10-11 11:27:38 +080013697 }
13698
13699 band = wifi_index_to_band(ap_index);
13700 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
13701 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
13702 return RETURN_ERR;
13703 }
developer587c1b62022-09-27 15:58:59 +080013704
13705 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
developer9df4e652022-10-11 11:27:38 +080013706 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
developerc0830312022-10-13 13:22:36 +080013707 wifi_setSAEMFP(ap_index, sae_MFP);
13708 wifi_setSAEpwe(ap_index, sae_pwe);
developer9df4e652022-10-11 11:27:38 +080013709 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
developer587c1b62022-09-27 15:58:59 +080013710
developerae432c62023-04-24 11:07:20 +080013711 if (security->mode != wifi_security_mode_none && security->mode != wifi_security_mode_enhanced_open) {
developer4b102122023-02-15 10:53:03 +080013712 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) {
13713 int key_len = strlen(security->u.key.key);
13714 // wpa_psk and wpa_passphrase cann;t use at the same time, the command replace one with the other.
13715 if (key_len == 64) { // set wpa_psk
13716 strncpy(password, security->u.key.key, 64); // 64 characters
13717 password[64] = '\0';
13718 wifi_setApSecurityPreSharedKey(ap_index, password);
13719 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_passphrase=/!p' %s", config_file);
13720 } else if (key_len >= 8 && key_len < 64) { // set wpa_passphrase
13721 strncpy(password, security->u.key.key, 63);
13722 password[63] = '\0';
13723 wifi_setApSecurityKeyPassphrase(ap_index, password);
13724 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_psk=/!p' %s", config_file);
13725 } else
13726 return RETURN_ERR;
13727 _syscmd(cmd, buf, sizeof(buf));
developer9df4e652022-10-11 11:27:38 +080013728 }
13729 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
13730 params.name = "sae_password";
13731 params.value = security->u.key.key;
13732 wifi_hostapdWrite(config_file, &params, 1);
developer4b102122023-02-15 10:53:03 +080013733 } else { // remove sae_password
13734 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^sae_password=/!p' %s", config_file);
13735 _syscmd(cmd, buf, sizeof(buf));
developer9df4e652022-10-11 11:27:38 +080013736 }
13737 }
developer587c1b62022-09-27 15:58:59 +080013738
13739 if (security->mode != wifi_security_mode_none) {
13740 memset(&params, 0, sizeof(params));
13741 params.name = "wpa_pairwise";
13742 if (security->encr == wifi_encryption_tkip)
13743 params.value = "TKIP";
13744 else if (security->encr == wifi_encryption_aes)
13745 params.value = "CCMP";
13746 else if (security->encr == wifi_encryption_aes_tkip)
13747 params.value = "TKIP CCMP";
13748 wifi_hostapdWrite(config_file, &params, 1);
13749 }
13750
13751 if (security->mfp == wifi_mfp_cfg_disabled)
developerc0830312022-10-13 13:22:36 +080013752 strcpy(mfp, "Disabled");
developer587c1b62022-09-27 15:58:59 +080013753 else if (security->mfp == wifi_mfp_cfg_optional)
13754 strcpy(mfp, "Optional");
13755 else if (security->mfp == wifi_mfp_cfg_required)
13756 strcpy(mfp, "Required");
13757 wifi_setApSecurityMFPConfig(ap_index, mfp);
13758
13759 memset(&params, 0, sizeof(params));
13760 params.name = "transition_disable";
13761 if (security->wpa3_transition_disable == TRUE)
13762 params.value = "0x01";
13763 else
13764 params.value = "0x00";
13765 wifi_hostapdWrite(config_file, &params, 1);
13766
13767 memset(&params, 0, sizeof(params));
13768 params.name = "wpa_group_rekey";
13769 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
13770 params.value = buf;
13771 wifi_hostapdWrite(config_file, &params, 1);
13772
13773 memset(&params, 0, sizeof(params));
13774 params.name = "wpa_strict_rekey";
13775 params.value = security->strict_rekey?"1":"0";
13776 wifi_hostapdWrite(config_file, &params, 1);
13777
13778 memset(&params, 0, sizeof(params));
13779 params.name = "wpa_pairwise_update_count";
developer4b102122023-02-15 10:53:03 +080013780 if (security->eapol_key_retries == 0)
13781 security->eapol_key_retries = 4; // 0 is invalid, set to default value.
developer587c1b62022-09-27 15:58:59 +080013782 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
13783 params.value = buf;
13784 wifi_hostapdWrite(config_file, &params, 1);
13785
13786 memset(&params, 0, sizeof(params));
13787 params.name = "disable_pmksa_caching";
13788 params.value = security->disable_pmksa_caching?"1":"0";
13789 wifi_hostapdWrite(config_file, &params, 1);
13790
developer23e71282023-01-18 10:25:19 +080013791 if (multiple_set == FALSE) {
13792 wifi_setApEnable(ap_index, FALSE);
13793 wifi_setApEnable(ap_index, TRUE);
13794 }
developer587c1b62022-09-27 15:58:59 +080013795
13796 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13797
developer06a01d92022-09-07 16:32:39 +080013798 return RETURN_OK;
13799}
13800
13801INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
13802{
developer9df4e652022-10-11 11:27:38 +080013803 char buf[256] = {0};
developer587c1b62022-09-27 15:58:59 +080013804 char config_file[128] = {0};
13805 int disable = 0;
developer4b102122023-02-15 10:53:03 +080013806 bool set_sae = FALSE;
developer587c1b62022-09-27 15:58:59 +080013807
13808 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13809 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13810 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
13811 security->mode = wifi_security_mode_none;
13812 if (strlen(buf) != 0) {
developer517a9792022-10-05 19:37:42 +080013813 if (!strcmp(buf, "WPA-Personal"))
developer587c1b62022-09-27 15:58:59 +080013814 security->mode = wifi_security_mode_wpa_personal;
developer517a9792022-10-05 19:37:42 +080013815 else if (!strcmp(buf, "WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080013816 security->mode = wifi_security_mode_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080013817 else if (!strcmp(buf, "WPA-WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080013818 security->mode = wifi_security_mode_wpa_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080013819 else if (!strcmp(buf, "WPA-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013820 security->mode = wifi_security_mode_wpa_enterprise;
developer517a9792022-10-05 19:37:42 +080013821 else if (!strcmp(buf, "WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013822 security->mode = wifi_security_mode_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080013823 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013824 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080013825 else if (!strcmp(buf, "WPA3-Personal"))
developer587c1b62022-09-27 15:58:59 +080013826 security->mode = wifi_security_mode_wpa3_personal;
developer4a359672022-10-13 15:30:46 +080013827 else if (!strcmp(buf, "WPA3-Personal-Transition"))
developer587c1b62022-09-27 15:58:59 +080013828 security->mode = wifi_security_mode_wpa3_transition;
developer517a9792022-10-05 19:37:42 +080013829 else if (!strcmp(buf, "WPA3-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013830 security->mode = wifi_security_mode_wpa3_enterprise;
developer5c9fee82023-01-13 14:44:16 +080013831 else if (!strcmp(buf, "OWE"))
developerae432c62023-04-24 11:07:20 +080013832 security->mode = wifi_security_mode_enhanced_open;
developer587c1b62022-09-27 15:58:59 +080013833 }
13834
13835 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
13836 if (security->mode == wifi_security_mode_none)
13837 security->encr = wifi_encryption_none;
13838 else {
13839 if (strcmp(buf, "TKIP") == 0)
13840 security->encr = wifi_encryption_tkip;
13841 else if (strcmp(buf, "CCMP") == 0)
13842 security->encr = wifi_encryption_aes;
13843 else
13844 security->encr = wifi_encryption_aes_tkip;
13845 }
13846
developer9df4e652022-10-11 11:27:38 +080013847 if (security->mode != wifi_encryption_none) {
13848 memset(buf, 0, sizeof(buf));
13849 // wpa3 can use one or both configs as password, so we check sae_password first.
13850 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
developer4b102122023-02-15 10:53:03 +080013851 if (strlen(buf) != 0) {
13852 if (security->mode == wifi_security_mode_wpa3_personal || security->mode == wifi_security_mode_wpa3_transition)
13853 security->u.key.type = wifi_security_key_type_sae;
13854 set_sae = TRUE;
13855 strncpy(security->u.key.key, buf, sizeof(buf));
13856 }
13857 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
13858 if (strlen(buf) != 0){
13859 if (set_sae == TRUE)
13860 security->u.key.type = wifi_security_key_type_psk_sae;
13861 else if (strlen(buf) == 64)
13862 security->u.key.type = wifi_security_key_type_psk;
13863 else
13864 security->u.key.type = wifi_security_key_type_pass;
13865 strncpy(security->u.key.key, buf, sizeof(security->u.key.key));
developer9df4e652022-10-11 11:27:38 +080013866 }
developer9df4e652022-10-11 11:27:38 +080013867 security->u.key.key[255] = '\0';
13868 }
13869
developer587c1b62022-09-27 15:58:59 +080013870 memset(buf, 0, sizeof(buf));
13871 wifi_getApSecurityMFPConfig(ap_index, buf);
13872 if (strcmp(buf, "Disabled") == 0)
13873 security->mfp = wifi_mfp_cfg_disabled;
13874 else if (strcmp(buf, "Optional") == 0)
13875 security->mfp = wifi_mfp_cfg_optional;
13876 else if (strcmp(buf, "Required") == 0)
13877 security->mfp = wifi_mfp_cfg_required;
13878
13879 memset(buf, 0, sizeof(buf));
13880 security->wpa3_transition_disable = FALSE;
13881 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
13882 disable = strtol(buf, NULL, 16);
13883 if (disable != 0)
13884 security->wpa3_transition_disable = TRUE;
13885
13886 memset(buf, 0, sizeof(buf));
13887 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
13888 if (strlen(buf) == 0)
13889 security->rekey_interval = 86400;
13890 else
13891 security->rekey_interval = strtol(buf, NULL, 10);
13892
13893 memset(buf, 0, sizeof(buf));
13894 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
13895 if (strlen(buf) == 0)
developer894d8222023-06-15 13:40:44 +080013896 security->strict_rekey = 0;
developer587c1b62022-09-27 15:58:59 +080013897 else
13898 security->strict_rekey = strtol(buf, NULL, 10);
13899
13900 memset(buf, 0, sizeof(buf));
13901 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
13902 if (strlen(buf) == 0)
13903 security->eapol_key_retries = 4;
13904 else
13905 security->eapol_key_retries = strtol(buf, NULL, 10);
13906
13907 memset(buf, 0, sizeof(buf));
13908 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
13909 if (strlen(buf) == 0)
13910 security->disable_pmksa_caching = FALSE;
13911 else
13912 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
13913
13914 /* TODO
13915 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
13916 */
13917 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
13918 security->eap_identity_req_timeout = 0;
13919 security->eap_identity_req_retries = 0;
13920 security->eap_req_timeout = 0;
13921 security->eap_req_retries = 0;
13922 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080013923 return RETURN_OK;
13924}
13925
13926#endif /* WIFI_HAL_VERSION_3 */
13927
13928#ifdef WIFI_HAL_VERSION_3_PHASE2
13929INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
13930{
developerd946fd62022-12-08 18:03:28 +080013931 char interface_name[16] = {0};
developer13df9332022-09-27 16:53:22 +080013932 char cmd[128] = {0};
13933 char buf[128] = {0};
13934 char *mac_addr = NULL;
13935 BOOL status = FALSE;
13936 size_t len = 0;
13937
13938 if(ap_index > MAX_APS)
13939 return RETURN_ERR;
13940
13941 *output_numDevices = 0;
13942 wifi_getApEnable(ap_index, &status);
13943 if (status == FALSE)
13944 return RETURN_OK;
13945
developerac6f1142022-12-20 19:26:35 +080013946 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080013947 return RETURN_ERR;
13948 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
developer13df9332022-09-27 16:53:22 +080013949 _syscmd(cmd, buf, sizeof(buf));
13950
13951 mac_addr = strtok(buf, "\n");
13952 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
13953 *output_numDevices = i + 1;
13954 fprintf(stderr, "mac_addr: %s\n", mac_addr);
13955 addr_ptr = output_deviceMacAddressArray[i];
13956 mac_addr_aton(addr_ptr, mac_addr);
13957 mac_addr = strtok(NULL, "\n");
13958 }
13959
13960 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080013961}
13962#else
13963INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
13964{
developerd946fd62022-12-08 18:03:28 +080013965 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080013966 char cmd[128];
13967 BOOL status = false;
13968
13969 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
13970 return RETURN_ERR;
13971
13972 output_buf[0] = '\0';
13973
13974 wifi_getApEnable(ap_index,&status);
13975 if (!status)
13976 return RETURN_OK;
13977
developerac6f1142022-12-20 19:26:35 +080013978 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080013979 return RETURN_ERR;
13980 sprintf(cmd, "hostapd_cli -i %s list_sta | tr '\\n' ',' | sed 's/.$//'", interface_name);
developer06a01d92022-09-07 16:32:39 +080013981 _syscmd(cmd, output_buf, output_buf_size);
13982
13983 return RETURN_OK;
13984}
13985#endif
developer2f513ab2022-09-13 14:26:06 +080013986
13987INT wifi_getProxyArp(INT apIndex, BOOL *enable)
13988{
13989 char output[16]={'\0'};
13990 char config_file[MAX_BUF_SIZE] = {0};
13991
13992 if (!enable)
13993 return RETURN_ERR;
13994
13995 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
13996 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
13997
13998 if (strlen(output) == 0)
13999 *enable = FALSE;
14000 else if (strncmp(output, "1", 1) == 0)
14001 *enable = TRUE;
14002 else
14003 *enable = FALSE;
14004
14005 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
14006 return RETURN_OK;
14007}
developer2d9c30f2022-09-13 15:06:14 +080014008
14009INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
14010{
developer804c64f2022-10-19 13:54:40 +080014011 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
developer2d9c30f2022-09-13 15:06:14 +080014012 return RETURN_ERR;
14013 *output_enable=TRUE;
14014 return RETURN_OK;
14015}
developerfd7d2892022-09-13 16:44:53 +080014016
14017INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
14018{
14019 char cmd[128] = {0};
14020 char buf[128] = {0};
14021 char line[128] = {0};
14022 size_t len = 0;
developerfd7d2892022-09-13 16:44:53 +080014023 FILE *f = NULL;
14024 int index = 0;
14025 int exp = 0;
14026 int mantissa = 0;
14027 int duration = 0;
14028 int radio_index = 0;
14029 int max_radio_num = 0;
14030 uint twt_wake_interval = 0;
developer033b37b2022-10-18 11:27:46 +080014031 int phyId = 0;
developerfd7d2892022-09-13 16:44:53 +080014032 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
14033
14034 wifi_getMaxRadioNumber(&max_radio_num);
developer033b37b2022-10-18 11:27:46 +080014035
developerfd7d2892022-09-13 16:44:53 +080014036 radio_index = ap_index % max_radio_num;
developer033b37b2022-10-18 11:27:46 +080014037
14038 phyId = radio_index_to_phy(radio_index);
developer439baa32024-05-02 15:54:58 +080014039 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", single_wiphy ? radio_index : phyId);
developerfd7d2892022-09-13 16:44:53 +080014040 _syscmd(cmd, buf, sizeof(buf));
14041 *numSessionReturned = strtol(buf, NULL, 10) - 1;
14042 if (*numSessionReturned > maxNumberSessions)
14043 *numSessionReturned = maxNumberSessions;
14044 else if (*numSessionReturned < 1) {
14045 *numSessionReturned = 0;
14046 return RETURN_OK;
14047 }
14048
developer439baa32024-05-02 15:54:58 +080014049 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | tail -n %d | tr '|' ' ' | tr -s ' '", single_wiphy ? radio_index : phyId, *numSessionReturned);
developerfd7d2892022-09-13 16:44:53 +080014050 if ((f = popen(cmd, "r")) == NULL) {
14051 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
14052 return RETURN_ERR;
14053 }
14054
14055 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
developer30423732022-12-01 16:17:49 +080014056 while((fgets(line, sizeof(line), f)) != NULL) {
developerfd7d2892022-09-13 16:44:53 +080014057 char *tmp = NULL;
14058 strcpy(buf, line);
14059 tmp = strtok(buf, " ");
14060 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
14061 tmp = strtok(NULL, " ");
14062 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
14063 tmp = strtok(NULL, " ");
14064 if (strstr(tmp, "t")) {
14065 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
14066 }
14067 if (strstr(tmp, "a")) {
14068 twtSessions[index].twtParameters.operation.announced = TRUE;
14069 }
14070 tmp = strtok(NULL, " ");
14071 exp = strtol(tmp, NULL, 10);
14072 tmp = strtok(NULL, " ");
14073 mantissa = strtol(tmp, NULL, 10);
14074 tmp = strtok(NULL, " ");
14075 duration = strtol(tmp, NULL, 10);
14076
14077 // only implicit supported
14078 twtSessions[index].twtParameters.operation.implicit = TRUE;
14079 // only individual agreement supported
14080 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
14081
14082 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
14083 twt_wake_interval = mantissa * (1 << exp);
developer30423732022-12-01 16:17:49 +080014084 if (mantissa == 0 || twt_wake_interval/mantissa != (1 << exp)) {
developerfd7d2892022-09-13 16:44:53 +080014085 // Overflow handling
14086 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
14087 } else {
14088 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
14089 }
14090 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
14091 index++;
14092 }
14093
14094 pclose(f);
14095 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
14096 return RETURN_OK;
14097}